support to get fib service in vpn manager
[vpnservice.git] / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / vpnservice / VpnInterfaceManager.java
index f8e04be665a623d6cdf28b56eefa7efb683a4f18..fa81708e6e4208cb57d966e446febf58445a1bbd 100644 (file)
@@ -8,18 +8,25 @@
 package org.opendaylight.vpnservice;
 
 import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.FutureCallback;
 
 import org.opendaylight.bgpmanager.api.IBgpManager;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.fibmanager.api.IFibManager;
 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
@@ -67,9 +74,12 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     private ListenerRegistration<DataChangeListener> listenerRegistration;
     private final DataBroker broker;
     private final IBgpManager bgpManager;
+    private IFibManager fibManager;
     private IMdsalApiManager mdsalManager;
     private IInterfaceManager interfaceManager;
     private IdManagerService idManager;
+    private Map<Long, Collection<Long>> vpnToDpnsDb;
+    private Map<Long, Collection<String>> dpnToInterfaceDb;
 
     private static final FutureCallback<Void> DEFAULT_CALLBACK =
             new FutureCallback<Void>() {
@@ -92,6 +102,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         super(VpnInterface.class);
         broker = db;
         this.bgpManager = bgpManager;
+        vpnToDpnsDb = new ConcurrentHashMap<>();
+        dpnToInterfaceDb = new ConcurrentHashMap<>();
         registerListener(db);
     }
 
@@ -103,6 +115,10 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         this.interfaceManager = interfaceManager;
     }
 
+    public void setFibManager(IFibManager fibManager) {
+        this.fibManager = fibManager;
+    }
+
     public void setIdManager(IdManagerService idManager) {
         this.idManager = idManager;
     }
@@ -133,7 +149,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     @Override
     protected void add(final InstanceIdentifier<VpnInterface> identifier,
             final VpnInterface vpnInterface) {
-        LOG.info("key: {} , value: {}", identifier, vpnInterface );
+        LOG.trace("key: {} , value: {}", identifier, vpnInterface );
         addInterface(identifier, vpnInterface);
     }
 
@@ -147,7 +163,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
         if (port.isPresent()) {
             Interface interf = port.get();
-            bindServiceOnInterface(interf, getVpnId(vpnInterface.getVpnInstanceName()));
+            bindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
             updateNextHops(identifier, vpnInterface);
         }
     }
@@ -168,20 +184,23 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             long dpnId = interfaceManager.getDpnForInterface(intfName);
             String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
 
-            if (!nextHops.isEmpty()) {
-                LOG.info("NextHops are {}", nextHops);
-                for (Adjacency nextHop : nextHops) {
-                    String key = nextHop.getIpAddress();
-                    long label = getUniqueId(key);
 
-                    updatePrefixToBGP(rd, nextHop, nextHopIp, label);
-                    value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
-                }
+            LOG.trace("NextHops are {}", nextHops);
+            for (Adjacency nextHop : nextHops) {
+                String key = nextHop.getIpAddress();
+                long label = getUniqueId(key);
+                value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
             }
+
             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
             VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
             InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
             asyncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
+            for (Adjacency nextHop : nextHops) {
+                String key = nextHop.getIpAddress();
+                long label = getUniqueId(key);
+                updatePrefixToBGP(rd, nextHop, nextHopIp, label);
+            }
         }
     }
 
@@ -205,10 +224,12 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
     }
 
     private long getVpnId(String vpnName) {
+        //TODO: This should be a Util function
         InstanceIdentifier<VpnInstance1> id = InstanceIdentifier.builder(VpnInstances.class)
                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).augmentation(VpnInstance1.class).build();
-        Optional<VpnInstance1> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
-        long vpnId = -1;
+        Optional<VpnInstance1> vpnInstance = read(LogicalDatastoreType.OPERATIONAL, id);
+
+        long vpnId = VpnConstants.INVALID_ID;
         if(vpnInstance.isPresent()) {
             vpnId = vpnInstance.get().getVpnId();
         }
@@ -228,13 +249,54 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         return rd;
     }
 
-    private void bindServiceOnInterface(Interface intf, long vpnId) {
-        LOG.info("Bind service on interface {} for VPN: {}", intf, vpnId);
+    private synchronized void updateMappingDbs(long vpnId, long dpnId, String intfName, String rd) {
+        Collection<Long> dpnIds = vpnToDpnsDb.get(vpnId);
+        if(dpnIds == null) {
+            dpnIds = new HashSet<>();
+        }
+        if(dpnIds.add(dpnId)) {
+            vpnToDpnsDb.put(vpnId, dpnIds);
+            fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
+        }
+
+        Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
+        if(intfNames == null) {
+            intfNames = new ArrayList<>();
+        }
+        intfNames.add(intfName);
+        dpnToInterfaceDb.put(dpnId, intfNames);
+    }
+
+    private synchronized void remoteFromMappingDbs(long vpnId, long dpnId, String inftName, String rd) {
+        Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
+        if(intfNames == null) {
+            return;
+        }
+        intfNames.remove(inftName);
+        dpnToInterfaceDb.put(dpnId, intfNames);
+        //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
+        if(intfNames.isEmpty()) {
+            Collection<Long> dpnIds = vpnToDpnsDb.get(vpnId);
+            if(dpnIds == null) {
+                return;
+            }
+            dpnIds.remove(dpnId);
+            vpnToDpnsDb.put(vpnId, dpnIds);
+            fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+        }
+    }
+
+    private void bindServiceOnInterface(Interface intf, String vpnName) {
+        LOG.trace("Bind service on interface {} for VPN: {}", intf, vpnName);
 
+        long vpnId = getVpnId(vpnName);
         long dpId = interfaceManager.getDpnForInterface(intf.getName()); 
         if(dpId == 0L) {
             LOG.warn("DPN for interface {} not found. Bind service on this interface aborted.", intf.getName());
             return;
+        } else {
+            String rd = getRouteDistinguisher(vpnName);
+            updateMappingDbs(vpnId, dpId, intf.getName(), rd);
         }
 
         long portNo = interfaceManager.getPortForInterface(intf.getName());
@@ -296,7 +358,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
 
     @Override
     protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
-        LOG.info("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
+        LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
         String interfaceName = key.getName();
         InstanceIdentifierBuilder<Interface> idBuilder = 
@@ -305,10 +367,12 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
         if (port.isPresent()) {
             Interface interf = port.get();
-            unbindServiceOnInterface(interf, getVpnId(vpnInterface.getVpnInstanceName()));
             removeNextHops(identifier, vpnInterface);
+            unbindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
+            //InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+            delete(LogicalDatastoreType.OPERATIONAL, identifier);
         } else {
-            LOG.info("No nexthops were available to handle remove event {}", interfaceName);
+            LOG.warn("No nexthops were available to handle remove event {}", interfaceName);
         }
     }
 
@@ -328,8 +392,8 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                 }
             }
         }
-        InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
-        delete(LogicalDatastoreType.OPERATIONAL, interfaceId);
+//        InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
+//        delete(LogicalDatastoreType.OPERATIONAL, interfaceId);
     }
 
     private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
@@ -338,13 +402,17 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
     }
 
-    private void unbindServiceOnInterface(Interface intf, long vpnId) {
-        LOG.info("Unbind service on interface {} for VPN: {}", intf, vpnId);
+    private void unbindServiceOnInterface(Interface intf, String vpnName) {
+        LOG.trace("Unbind service on interface {} for VPN: {}", intf, vpnName);
 
+        long vpnId = getVpnId(vpnName);
         long dpId = interfaceManager.getDpnForInterface(intf.getName());
         if(dpId == 0L) {
             LOG.warn("DPN for interface {} not found. Unbind service on this interface aborted.", intf.getName());
             return;
+        } else {
+            String rd = getRouteDistinguisher(vpnName);
+            remoteFromMappingDbs(vpnId, dpId, intf.getName(), rd);
         }
 
         long portNo = interfaceManager.getPortForInterface(intf.getName());
@@ -386,4 +454,13 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         tx.put(datastoreType, path, data, true);
         Futures.addCallback(tx.submit(), callback);
     }
+
+    synchronized Collection<Long> getDpnsForVpn(long vpnId) {
+        Collection<Long> dpnIds = vpnToDpnsDb.get(vpnId);
+        if(dpnIds != null) {
+            return ImmutableList.copyOf(dpnIds);
+        } else {
+            return Collections.emptyList();
+        }
+    }
 }