Add Map-Request source RLOC to DAO (needed for SMR)
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / lisp / MapResolver.java
index 13a162ba103243953223af516f821ce65d92643c..9d0f41678f9b9bc650731b0f49e307a6d3406eb7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Contextream, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,27 +8,39 @@
 
 package org.opendaylight.lispflowmapping.implementation.lisp;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashSet;
 import java.util.Map;
+import java.net.InetAddress;
 
+import org.opendaylight.lispflowmapping.implementation.dao.MappingServiceKeyUtil;
+import org.opendaylight.lispflowmapping.implementation.util.LispNotificationHelper;
+import org.opendaylight.lispflowmapping.implementation.util.MapRequestUtil;
+import org.opendaylight.lispflowmapping.implementation.util.MaskUtil;
 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
 import org.opendaylight.lispflowmapping.interfaces.dao.IMappingServiceKey;
-import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceKeyUtil;
-import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceRLOC;
-import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceValue;
-import org.opendaylight.lispflowmapping.interfaces.lisp.IMapReplyHandler;
+import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
+import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceRLOCGroup;
+import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceSubscriberRLOC;
+import org.opendaylight.lispflowmapping.interfaces.lisp.IMapRequestResultHandler;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
-import org.opendaylight.lispflowmapping.type.lisp.EidRecord;
-import org.opendaylight.lispflowmapping.type.lisp.EidToLocatorRecord;
-import org.opendaylight.lispflowmapping.type.lisp.MapReply;
-import org.opendaylight.lispflowmapping.type.lisp.MapRequest;
-import org.opendaylight.lispflowmapping.type.lisp.address.IMaskable;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.MapRequest;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.eidrecords.EidRecord;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.eidtolocatorrecords.EidToLocatorRecord;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.eidtolocatorrecords.EidToLocatorRecord.Action;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.eidtolocatorrecords.EidToLocatorRecordBuilder;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.lispaddress.LispAddressContainerBuilder;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.locatorrecords.LocatorRecord;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.locatorrecords.LocatorRecordBuilder;
+import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.mapreplymessage.MapReplyBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class MapResolver implements IMapResolverAsync {
-    private ILispDAO dao;
-    private volatile boolean shouldAuthenticate;
-    private volatile boolean shouldIterateMask;
+public class MapResolver extends AbstractLispComponent implements IMapResolverAsync {
+
+    private static final int TTL_RLOC_TIMED_OUT = 1;
+    private static final int TTL_NO_RLOC_KNOWN = 15;
     protected static final Logger logger = LoggerFactory.getLogger(MapResolver.class);
 
     public MapResolver(ILispDAO dao) {
@@ -36,43 +48,118 @@ public class MapResolver implements IMapResolverAsync {
     }
 
     public MapResolver(ILispDAO dao, boolean authenticate, boolean iterateMask) {
-        this.dao = dao;
-        this.shouldAuthenticate = authenticate;
-        this.shouldIterateMask = iterateMask;
+        super(dao, authenticate, iterateMask);
     }
 
-    public void handleMapRequest(MapRequest request, IMapReplyHandler callback) {
+    public void handleMapRequest(MapRequest request, IMapRequestResultHandler callback) {
         if (dao == null) {
             logger.warn("handleMapRequest called while dao is uninitialized");
+            return;
+        }
+        InetAddress itrRloc = MapRequestUtil.selectItrRloc(request);
+        logger.trace("Map-Request itrRloc is " + ((itrRloc == null) ? "MISSING" : itrRloc.toString()));
+        if (request.isPitr()) {
+            if (request.getEidRecord().size() > 0) {
+                EidRecord eid = request.getEidRecord().get(0);
+                Object result = getLocatorsSpecific(eid, ADDRESS_SUBKEY);
+                if (result != null && result instanceof MappingServiceRLOCGroup) {
+                    MappingServiceRLOCGroup locatorsGroup = (MappingServiceRLOCGroup) result;
+                    if (locatorsGroup != null && locatorsGroup.getRecords().size() > 0) {
+                        callback.handleNonProxyMapRequest(request,
+                                LispNotificationHelper.getInetAddressFromContainer(locatorsGroup.getRecords().get(0).getLispAddressContainer()));
+                    }
+                }
+            }
+
         } else {
-            MapReply mapReply = new MapReply();
-            mapReply.setNonce(request.getNonce());
-            for (EidRecord eid : request.getEids()) {
-                EidToLocatorRecord eidToLocators = new EidToLocatorRecord();
-                eidToLocators.setMaskLength(eid.getMaskLength())//
-                        .setPrefix(eid.getPrefix());
-                IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(eid.getPrefix(), eid.getMaskLength());
-                Map<String, ?> locators = dao.get(key);
-                if (shouldIterateMask() && locators == null && key.getEID() instanceof IMaskable) {
-                    locators = findMaskLocators(key);
+            MapReplyBuilder builder = new MapReplyBuilder();
+            builder.setEchoNonceEnabled(false);
+            builder.setProbe(false);
+            builder.setSecurityEnabled(false);
+            builder.setNonce(request.getNonce());
+            builder.setEidToLocatorRecord(new ArrayList<EidToLocatorRecord>());
+            for (EidRecord eid : request.getEidRecord()) {
+                EidToLocatorRecordBuilder recordBuilder = new EidToLocatorRecordBuilder();
+                recordBuilder.setRecordTtl(0);
+                recordBuilder.setAction(Action.NoAction);
+                recordBuilder.setAuthoritative(false);
+                recordBuilder.setMapVersion((short) 0);
+                recordBuilder.setMaskLength(eid.getMask());
+                recordBuilder.setLispAddressContainer(eid.getLispAddressContainer());
+                recordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
+                List<MappingServiceRLOCGroup> locators = getLocators(eid);
+                if (locators != null && locators.size() > 0) {
+                    addLocatorGroups(recordBuilder, locators);
+                    if (itrRloc != null) {
+                        MappingServiceSubscriberRLOC subscriberRloc = new MappingServiceSubscriberRLOC(itrRloc);
+                        HashSet<MappingServiceSubscriberRLOC> subscribers = getSubscribers(eid.getLispAddressContainer(), eid.getMask());
+                        if (subscribers == null) {
+                            subscribers = new HashSet<MappingServiceSubscriberRLOC>();
+                        } else if (subscribers.contains(subscriberRloc)) {
+                            /* If there is an entry already for this subscriberRloc, remove it, so that it gets the new timestamp */
+                            subscribers.remove(subscriberRloc);
+                        }
+                        IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(eid.getLispAddressContainer(), eid.getMask());
+                        subscribers.add(subscriberRloc);
+                        dao.put(key, new MappingEntry<HashSet<MappingServiceSubscriberRLOC>>(SUBSCRIBERS_SUBKEY, subscribers));
+                    }
+                } else {
+                    recordBuilder
+                            .setAction(org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.eidtolocatorrecords.EidToLocatorRecord.Action.NativelyForward);
+                    if (getPassword(eid.getLispAddressContainer(), eid.getMask()) != null) {
+                        recordBuilder.setRecordTtl(TTL_RLOC_TIMED_OUT);
+                    } else {
+                        recordBuilder.setRecordTtl(TTL_NO_RLOC_KNOWN);
+
+                    }
                 }
-                if (locators != null) {
-                    addLocators(eidToLocators, locators);
+                builder.getEidToLocatorRecord().add(recordBuilder.build());
+            }
+
+            callback.handleMapReply(builder.build());
+        }
+    }
+
+    private List<MappingServiceRLOCGroup> getLocators(EidRecord eid) {
+        IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(eid.getLispAddressContainer(), eid.getMask());
+        Map<String, ?> locators = dao.get(key);
+        List<MappingServiceRLOCGroup> result = aggregateLocators(locators);
+        if (shouldIterateMask() && result.isEmpty() && MaskUtil.isMaskable(key.getEID().getAddress())) {
+            result = findMaskLocators(key);
+        }
+        return result;
+    }
+
+    private List<MappingServiceRLOCGroup> aggregateLocators(Map<String, ?> locators) {
+        List<MappingServiceRLOCGroup> result = new ArrayList<MappingServiceRLOCGroup>();
+        if (locators != null) {
+            for (Object value : locators.values()) {
+                if (value != null && value instanceof MappingServiceRLOCGroup) {
+                    if (!((MappingServiceRLOCGroup) value).getRecords().isEmpty()) {
+                        result.add((MappingServiceRLOCGroup) value);
+                    }
                 }
-                mapReply.addEidToLocator(eidToLocators);
             }
-            callback.handleMapReply(mapReply);
         }
+        return result;
+    }
+
+    private Object getLocatorsSpecific(EidRecord eid, String subkey) {
+        IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(eid.getLispAddressContainer(), eid.getMask());
+        Object locators = dao.getSpecific(key, subkey);
+        if (shouldIterateMask() && locators == null && MaskUtil.isMaskable(key.getEID().getAddress())) {
+            locators = findMaskLocatorsSpecific(key, subkey);
+        }
+        return locators;
     }
 
-    private Map<String, ?> findMaskLocators(IMappingServiceKey key) {
+    private Object findMaskLocatorsSpecific(IMappingServiceKey key, String subkey) {
         int mask = key.getMask();
         while (mask > 0) {
-            key = MappingServiceKeyUtil.generateMappingServiceKey(key.getEID(), (byte) mask);
-
-            ((IMaskable) key.getEID()).normalize(mask);
+            key = MappingServiceKeyUtil.generateMappingServiceKey(
+                    new LispAddressContainerBuilder().setAddress(MaskUtil.normalize(key.getEID().getAddress(), mask)).build(), mask);
             mask--;
-            Map<String, ?> locators = dao.get(key);
+            Object locators = dao.getSpecific(key, subkey);
             if (locators != null) {
                 return locators;
             }
@@ -80,44 +167,47 @@ public class MapResolver implements IMapResolverAsync {
         return null;
     }
 
-    private void addLocators(EidToLocatorRecord eidToLocators, Map<String, ?> locators) {
-        try {
-            MappingServiceValue value = (MappingServiceValue) locators.get("value");
-            for (MappingServiceRLOC rloc : value.getRlocs()) {
-                addLocator(eidToLocators, rloc);
-
+    private List<MappingServiceRLOCGroup> findMaskLocators(IMappingServiceKey key) {
+        int mask = key.getMask();
+        while (mask > 0) {
+            key = MappingServiceKeyUtil.generateMappingServiceKey(
+                    new LispAddressContainerBuilder().setAddress(MaskUtil.normalize(key.getEID().getAddress(), mask)).build(), mask);
+            mask--;
+            Map<String, ?> locators = dao.get(key);
+            if (locators != null) {
+                List<MappingServiceRLOCGroup> result = aggregateLocators(locators);
+                if (result != null && !result.isEmpty()) {
+                    return result;
+                }
             }
-        } catch (ClassCastException cce) {
+        }
+        return null;
+    }
+
+    private void addLocatorGroups(EidToLocatorRecordBuilder recordBuilder, List<MappingServiceRLOCGroup> rlocs) {
+        for (MappingServiceRLOCGroup rloc : rlocs) {
+            addLocators(recordBuilder, rloc);
+            recordBuilder.setRecordTtl(rloc.getTtl());
         }
     }
 
-    private void addLocator(EidToLocatorRecord eidToLocators, MappingServiceRLOC locatorObject) {
+    private void addLocators(EidToLocatorRecordBuilder recordBuilder, MappingServiceRLOCGroup locatorObject) {
         if (locatorObject == null) {
             return;
         }
         try {
-            eidToLocators.addLocator(locatorObject.getRecord().clone().setRouted(true));
-            eidToLocators.setAction(locatorObject.getAction());
-            eidToLocators.setAuthoritative(locatorObject.isAuthoritative());
-            eidToLocators.setRecordTtl(locatorObject.getTtl());
+            for (LocatorRecord record : locatorObject.getRecords()) {
+                recordBuilder.getLocatorRecord().add(
+                        new LocatorRecordBuilder().setLocalLocator(record.isLocalLocator()).setRlocProbed(record.isRlocProbed())
+                                .setWeight(record.getWeight()).setPriority(record.getPriority()).setMulticastWeight(record.getMulticastWeight())
+                                .setMulticastPriority(record.getMulticastPriority()).setRouted(true)
+                                .setLispAddressContainer(record.getLispAddressContainer()).build());
+            }
+            recordBuilder.setAction(locatorObject.getAction());
+            recordBuilder.setAuthoritative(locatorObject.isAuthoritative());
+            recordBuilder.setRecordTtl(locatorObject.getTtl());
         } catch (ClassCastException cce) {
         }
     }
 
-    public boolean shouldIterateMask() {
-        return shouldIterateMask;
-    }
-
-    public boolean shouldAuthenticate() {
-        return shouldAuthenticate;
-    }
-
-    public void setShouldIterateMask(boolean shouldIterateMask) {
-        this.shouldIterateMask = shouldIterateMask;
-    }
-
-    public void setShouldAuthenticate(boolean shouldAuthenticate) {
-        this.shouldAuthenticate = shouldAuthenticate;
-    }
-
 }