Bug 6536: Allow propagation of SB notifications on slaves
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / LispMappingService.java
index a091da97b21513b2ea32392604c88cfc0cbb2ba3..f3e57b3a669de7124b940629222ba1fac3df9190 100644 (file)
@@ -8,87 +8,92 @@
 
 package org.opendaylight.lispflowmapping.implementation;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
 import org.apache.commons.lang3.tuple.MutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
 import org.opendaylight.lispflowmapping.implementation.lisp.MapResolver;
 import org.opendaylight.lispflowmapping.implementation.lisp.MapServer;
 import org.opendaylight.lispflowmapping.implementation.util.LispNotificationHelper;
-import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IFlowMapping;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapNotifyHandler;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapRequestResultHandler;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapServerAsync;
 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
+import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.AddMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.GotMapNotify;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.GotMapReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.LispProtoListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapNotify;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapRegister;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapRequest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.RequestMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.XtrReplyMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.XtrRequestMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.lispaddress.LispAddressContainer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.mapnotifymessage.MapNotifyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.mapreplymessage.MapReplyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.maprequestmessage.MapRequestBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.transportaddress.TransportAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.transportaddress.TransportAddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.LispSbService;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.AddMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapNotify;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRegister;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MappingKeepAlive;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.OdlLispProtoListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.RequestMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrReplyMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrRequestMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.MapRegisterCacheMetadata;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.map.register.cache.metadata.EidLispAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapnotifymessage.MapNotifyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestmessage.MapRequestBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.OdlLispSbService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapNotifyInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapReplyInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapRequestInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class LispMappingService implements IFlowMapping, BindingAwareProvider, IMapRequestResultHandler,
-        IMapNotifyHandler, LispProtoListener, AutoCloseable {
-    protected static final Logger LOG = LoggerFactory.getLogger(LispMappingService.class);
+public class LispMappingService implements IFlowMapping, IMapRequestResultHandler,
+        IMapNotifyHandler, OdlLispProtoListener, AutoCloseable, ClusterSingletonService {
+    public static final String LISPFLOWMAPPING_ENTITY_NAME = "lispflowmapping";
+    public static final ServiceGroupIdentifier SERVICE_GROUP_IDENTIFIER = ServiceGroupIdentifier.create(
+            LISPFLOWMAPPING_ENTITY_NAME);
 
-    private volatile boolean shouldAuthenticate = true;
 
-    private static final ConfigIni configIni = new ConfigIni();
-    private volatile boolean smr = configIni.smrIsSet();
-    private volatile String elpPolicy = configIni.getElpPolicy();
+    protected static final Logger LOG = LoggerFactory.getLogger(LispMappingService.class);
+    private final ClusterSingletonServiceProvider clusterSingletonService;
+
+    private volatile boolean smr = ConfigIni.getInstance().smrIsSet();
+    private volatile String elpPolicy = ConfigIni.getInstance().getElpPolicy();
 
     private ThreadLocal<MapReply> tlsMapReply = new ThreadLocal<MapReply>();
-    private ThreadLocal<MapNotify> tlsMapNotify = new ThreadLocal<MapNotify>();
-    private ThreadLocal<Pair<MapRequest, TransportAddress>> tlsMapRequest = new ThreadLocal<Pair<MapRequest, TransportAddress>>();
+    private ThreadLocal<Pair<MapNotify, List<TransportAddress>>> tlsMapNotify =
+            new ThreadLocal<Pair<MapNotify, List<TransportAddress>>>();
+    private ThreadLocal<Pair<MapRequest, TransportAddress>> tlsMapRequest =
+            new ThreadLocal<Pair<MapRequest, TransportAddress>>();
 
-    private LispSbService lispSB = null;
+    private final OdlLispSbService lispSB;
     private IMapResolverAsync mapResolver;
     private IMapServerAsync mapServer;
 
-    private IMappingService mapService;
-    private NotificationService notificationService;
-    private BindingAwareBroker broker;
-    private ProviderContext session;
-
-    public LispMappingService() {
-        LOG.debug("LispMappingService Module constructed!");
-    }
-
-    public void setBindingAwareBroker(BindingAwareBroker broker) {
-        this.broker = broker;
-    }
+    private final IMappingService mapService;
+    private final NotificationService notificationService;
 
-    public void setNotificationService(NotificationService ns) {
-        this.notificationService = ns;
-    }
+    public LispMappingService(final NotificationService notificationService,
+            final IMappingService mappingService,
+            final OdlLispSbService odlLispService, final ClusterSingletonServiceProvider clusterSingletonService) {
 
-    public void setMappingService(IMappingService ms) {
-        LOG.trace("MappingService set in LispMappingService");
-        this.mapService = ms;
+        this.notificationService = notificationService;
+        this.mapService = mappingService;
+        this.lispSB = odlLispService;
+        this.clusterSingletonService = clusterSingletonService;
+        LOG.debug("LispMappingService Module constructed!");
     }
 
     public boolean shouldUseSmr() {
@@ -103,6 +108,7 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
         if (mapResolver != null) {
             mapResolver.setSubscriptionService(smr);
         }
+        ConfigIni.getInstance().setSmr(smr);
     }
 
     public NotificationService getNotificationService() {
@@ -110,27 +116,22 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
     }
 
     public void initialize() {
-        broker.registerProvider(this);
-        notificationService.registerNotificationListener(this);
         mapResolver = new MapResolver(mapService, smr, elpPolicy, this);
-        mapServer = new MapServer(mapService, shouldAuthenticate, smr, this, notificationService);
+        mapServer = new MapServer(mapService, smr, this, notificationService);
+        this.clusterSingletonService.registerClusterSingletonService(this);
+        LOG.info("LISP (RFC6830) Mapping Service init finished");
     }
 
     public void basicInit() {
         mapResolver = new MapResolver(mapService, smr, elpPolicy, this);
-        mapServer = new MapServer(mapService, shouldAuthenticate, smr, this, notificationService);
-    }
-
-    @Override
-    public void onSessionInitiated(ProviderContext session) {
-        LOG.info("Lisp Consumer session initialized!");
-        this.session = session;
-        LOG.info("LISP (RFC6830) Mapping Service init finished");
+        mapServer = new MapServer(mapService, smr, this, notificationService);
     }
 
     public MapReply handleMapRequest(MapRequest request) {
-        LOG.debug("DAO: Retrieving mapping for {}",
-                LispAddressStringifier.getString(request.getEidRecord().get(0).getLispAddressContainer()));
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("DAO: Retrieving mapping for {}",
+                    LispAddressStringifier.getString(request.getEidItem().get(0).getEid()));
+        }
 
         tlsMapReply.set(null);
         tlsMapRequest.set(null);
@@ -138,7 +139,6 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
         // After this invocation we assume that the thread local is filled with the reply
         if (tlsMapRequest.get() != null) {
             SendMapRequestInputBuilder smrib = new SendMapRequestInputBuilder();
-            new MapRequestBuilder(tlsMapRequest.get().getLeft());
             smrib.setMapRequest(new MapRequestBuilder(tlsMapRequest.get().getLeft()).build());
             smrib.setTransportAddress(tlsMapRequest.get().getRight());
             getLispSB().sendMapRequest(smrib.build());
@@ -148,19 +148,12 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
         }
     }
 
-    public MapNotify handleMapRegister(MapRegister mapRegister) {
-        LOG.debug("DAO: Adding mapping for {}",
-                LispAddressStringifier.getString(mapRegister.getEidToLocatorRecord().get(0).getLispAddressContainer()));
-
-        tlsMapNotify.set(null);
-        mapServer.handleMapRegister(mapRegister);
-        // After this invocation we assume that the thread local is filled with the reply
-        return tlsMapNotify.get();
-    }
-
-    public MapNotify handleMapRegister(MapRegister mapRegister, boolean smr) {
-        LOG.debug("DAO: Adding mapping for {}",
-                LispAddressStringifier.getString(mapRegister.getEidToLocatorRecord().get(0).getLispAddressContainer()));
+    public Pair<MapNotify, List<TransportAddress>> handleMapRegister(MapRegister mapRegister) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("DAO: Adding mapping for {}",
+                    LispAddressStringifier.getString(mapRegister.getMappingRecordItem().get(0)
+                            .getMappingRecord().getEid()));
+        }
 
         tlsMapNotify.set(null);
         mapServer.handleMapRegister(mapRegister);
@@ -169,28 +162,34 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
     }
 
     public void setShouldAuthenticate(boolean shouldAuthenticate) {
-        this.shouldAuthenticate = shouldAuthenticate;
         this.mapResolver.setShouldAuthenticate(shouldAuthenticate);
-        this.mapServer.setShouldAuthenticate(shouldAuthenticate);
     }
 
-    public boolean shouldAuthenticate() {
-        return shouldAuthenticate;
+    private void sendMapNotify(MapNotify mapNotify, TransportAddress address) {
+        SendMapNotifyInputBuilder smnib = new SendMapNotifyInputBuilder();
+        smnib.setMapNotify(new MapNotifyBuilder(mapNotify).build());
+        smnib.setTransportAddress(address);
+        getLispSB().sendMapNotify(smnib.build());
     }
 
     @Override
     public void onAddMapping(AddMapping mapRegisterNotification) {
-        MapNotify mapNotify = handleMapRegister(mapRegisterNotification.getMapRegister());
-        if (mapNotify != null) {
-            TransportAddressBuilder tab = new TransportAddressBuilder();
-            tab.setIpAddress(mapRegisterNotification.getTransportAddress().getIpAddress());
-            tab.setPort(new PortNumber(LispMessage.PORT_NUM));
-            SendMapNotifyInputBuilder smnib = new SendMapNotifyInputBuilder();
-            smnib.setMapNotify(new MapNotifyBuilder(mapNotify).build());
-            smnib.setTransportAddress(tab.build());
-            getLispSB().sendMapNotify(smnib.build());
+        Pair<MapNotify, List<TransportAddress>> result = handleMapRegister(mapRegisterNotification.getMapRegister());
+        if (result != null && result.getLeft() != null) {
+            MapNotify mapNotify = result.getLeft();
+            List<TransportAddress> rlocs = result.getRight();
+            if (rlocs == null) {
+                TransportAddressBuilder tab = new TransportAddressBuilder();
+                tab.setIpAddress(mapRegisterNotification.getTransportAddress().getIpAddress());
+                tab.setPort(new PortNumber(LispMessage.PORT_NUM));
+                sendMapNotify(mapNotify, tab.build());
+            } else {
+                for (TransportAddress ta : rlocs) {
+                    sendMapNotify(mapNotify, ta);
+                }
+            }
         } else {
-            LOG.warn("got null map notify");
+            LOG.debug("Not sending Map-Notify");
         }
     }
 
@@ -203,7 +202,7 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
             smrib.setTransportAddress(mapRequestNotification.getTransportAddress());
             getLispSB().sendMapReply(smrib.build());
         } else {
-            LOG.warn("got null map reply");
+            LOG.debug("handleMapRequest: Got null MapReply");
         }
     }
 
@@ -227,10 +226,19 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
         LOG.debug("Received XtrReplyMapping notification, ignoring");
     }
 
-    private LispSbService getLispSB() {
-        if (lispSB == null) {
-            lispSB = session.getRpcService(LispSbService.class);
+    @Override
+    public void onMappingKeepAlive(MappingKeepAlive notification) {
+        final MapRegisterCacheMetadata cacheMetadata = notification.getMapRegisterCacheMetadata();
+        for (EidLispAddress eidLispAddress : cacheMetadata.getEidLispAddress()) {
+            final Eid eid = eidLispAddress.getEid();
+            final Long timestamp = cacheMetadata.getTimestamp();
+            LOG.debug("Update map registration for eid {} with timestamp {}", LispAddressStringifier.getString(eid),
+                    timestamp);
+            mapService.updateMappingRegistration(MappingOrigin.Southbound, eid, timestamp);
         }
+    }
+
+    private OdlLispSbService getLispSB() {
         return lispSB;
     }
 
@@ -240,19 +248,21 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
     }
 
     @Override
-    public void handleMapNotify(MapNotify notify) {
-        tlsMapNotify.set(notify);
+    public void handleMapNotify(MapNotify notify, List<TransportAddress> rlocs) {
+        tlsMapNotify.set(new MutablePair<MapNotify, List<TransportAddress>>(notify, rlocs));
     }
 
     @Override
-    public void handleSMR(MapRequest smr, LispAddressContainer subscriber) {
-        LOG.debug("Sending SMR to {} with Source-EID {} and EID Record {}",
-                LispAddressStringifier.getString(subscriber),
-                LispAddressStringifier.getString(smr.getSourceEid().getLispAddressContainer()),
-                LispAddressStringifier.getString(smr.getEidRecord().get(0).getLispAddressContainer()));
+    public void handleSMR(MapRequest smr, Rloc subscriber) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Sending SMR to {} with Source-EID {} and EID Record {}",
+                    LispAddressStringifier.getString(subscriber),
+                    LispAddressStringifier.getString(smr.getSourceEid().getEid()),
+                    LispAddressStringifier.getString(smr.getEidItem().get(0).getEid()));
+        }
         SendMapRequestInputBuilder smrib = new SendMapRequestInputBuilder();
         smrib.setMapRequest(new MapRequestBuilder(smr).build());
-        smrib.setTransportAddress(LispNotificationHelper.getTransportAddressFromContainer(subscriber));
+        smrib.setTransportAddress(LispNotificationHelper.getTransportAddressFromRloc(subscriber));
         getLispSB().sendMapRequest(smrib.build());
 
     }
@@ -271,5 +281,24 @@ public class LispMappingService implements IFlowMapping, BindingAwareProvider, I
     @Override
     public void close() throws Exception {
         destroy();
+        clusterSingletonService.close();
+    }
+
+    @Override
+    public void instantiateServiceInstance() {
+        mapService.setIsMaster(true);
+    }
+
+    @Override
+    public ListenableFuture<Void> closeServiceInstance() {
+        if (mapService != null) {
+            mapService.setIsMaster(false);
+        }
+        return Futures.<Void>immediateFuture(null);
+    }
+
+    @Override
+    public ServiceGroupIdentifier getIdentifier() {
+        return SERVICE_GROUP_IDENTIFIER;
     }
 }