Refactor the code that updates the vpn-to-dpn list 48/48548/4
authorMiguel Perez <francisco.miguel.perez@ericsson.com>
Wed, 16 Nov 2016 14:30:59 +0000 (15:30 +0100)
committerSam Hague <shague@redhat.com>
Tue, 22 Nov 2016 22:08:09 +0000 (22:08 +0000)
 + This is a prerrequisite for fixing bug 6833 [1]

 + Code that updates the vpn-to-dpn data is being taking out
   of VpnInterfaceManager so that it can also be invoked from
   other places.

 + It is now implemented by the VpnFootprintService

 + It is also offered to other modules, like cloud-servicechain,
   via IVpnManager

 + It is the first step of refactoring this gerrit change that
   had grown too big and complex [2]

 [1] Bug 6833: InterVpnLink FIB routes not populated when no VM on VPN
 [2] https://git.opendaylight.org/gerrit/#/c/45979/

Change-Id: I069c539e5b958f958665b51142404de8f1be7b10
Signed-off-by: Miguel Perez <francisco.miguel.perez@ericsson.com>
15 files changed:
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/VPNServiceChainHandler.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/utils/VpnServiceChainUtils.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/resources/org/opendaylight/blueprint/cloud-servicechain-impl.xml
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/test/java/org/opendaylight/netvirt/cloudservicechain/VPNServiceChainHandlerTest.java
vpnservice/vpnmanager/vpnmanager-api/src/main/java/org/opendaylight/netvirt/vpnmanager/api/IVpnManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnFootprintService.java [new file with mode: 0644]
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceOpListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkNodeAddTask.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkNodeListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/resources/org/opendaylight/blueprint/vpnmanager.xml

index 7c3270686968bfac2acefe6b25c5d5a3c1347226..713f332d4c0dfabccc92f6fc21acb62b4c8482ef 100755 (executable)
@@ -25,10 +25,10 @@ import org.opendaylight.netvirt.cloudservicechain.jobs.AddVpnPseudoPortDataJob;
 import org.opendaylight.netvirt.cloudservicechain.jobs.RemoveVpnPseudoPortDataJob;
 import org.opendaylight.netvirt.cloudservicechain.utils.VpnPseudoPortCache;
 import org.opendaylight.netvirt.cloudservicechain.utils.VpnServiceChainUtils;
+import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
@@ -45,12 +45,14 @@ public class VPNServiceChainHandler implements AutoCloseable {
 
     private final IMdsalApiManager mdsalManager;
     private final DataBroker broker;
-    private final FibRpcService fibRpcService;
+    private final IVpnManager vpnManager;
 
-    public VPNServiceChainHandler(final DataBroker db, IMdsalApiManager mdsalManager, FibRpcService fibRpcSrv) {
+
+    public VPNServiceChainHandler(final DataBroker db, final IMdsalApiManager mdsalManager,
+                                  final IVpnManager vpnManager) {
         this.broker = db;
         this.mdsalManager = mdsalManager;
-        this.fibRpcService = fibRpcSrv;
+        this.vpnManager = vpnManager;
     }
 
     public void init() {
@@ -140,21 +142,6 @@ public class VPNServiceChainHandler implements AutoCloseable {
                                                                    tableIdToGoTo, addOrRemove);
     }
 
-    /**
-     * Get fake VPNPseudoPort interface name.
-     *
-     * @param dpId Dpn Id
-     * @param scfTag Service Function tag
-     * @param scsTag Service Chain tag
-     * @param lportTag Lport tag
-     * @return the fake VpnPseudoPort interface name
-     */
-    private String buildVpnPseudoPortIfName(Long dpId, long scfTag, int scsTag, int lportTag) {
-        return new StringBuilder("VpnPseudo.").append(dpId).append(NwConstants.FLOWID_SEPARATOR)
-                                              .append(lportTag).append(NwConstants.FLOWID_SEPARATOR)
-                                              .append(scfTag).append(NwConstants.FLOWID_SEPARATOR)
-                                              .append(scsTag).toString();
-    }
 
     /**
      * L3VPN Service chaining: It moves traffic from a ServiceChain to a L3VPN.
@@ -219,16 +206,10 @@ public class VPNServiceChainHandler implements AutoCloseable {
             // We need to keep a fake VpnInterface in the DPN where the last vSF (before the VpnPseudoPort) is
             // located, because in case the last real VpnInterface is removed from that DPN, we still need
             // the Fib table programmed there
-            String intfName = buildVpnPseudoPortIfName(dpnId, scfTag, servChainTag, vpnPseudoLportTag);
-            if (addOrRemove == NwConstants.ADD_FLOW ) {
-                // Including this DPN in the VPN footprint even if there is no VpnInterface here.
-                // This is needed so that FibManager maintains the FIB table in this DPN
-                VpnServiceChainUtils.updateMappingDbs(broker, fibRpcService, vpnInstance.getVpnId(),
-                                                      BigInteger.valueOf(dpnId), intfName, vpnName);
-            } else {
-                VpnServiceChainUtils.removeFromMappingDbs(broker, fibRpcService, vpnInstance.getVpnId(),
-                                                          BigInteger.valueOf(dpnId), intfName, vpnName);
-            }
+            String intfName = VpnServiceChainUtils.buildVpnPseudoPortIfName(dpnId, scfTag, servChainTag,
+                                                                            vpnPseudoLportTag);
+            vpnManager.updateVpnFootprint(BigInteger.valueOf(dpnId), vpnName, intfName,
+                                          (addOrRemove == NwConstants.ADD_FLOW) );
         }
         LOG.info("L3VPN: Service Chaining programScfToVpnPipeline [End]");
     }
index 4f90a49f6e9ae4ddfb005b2768706b0511644cdf..8bc432765ebf6011fed2e58e393a2c65096dd45d 100755 (executable)
@@ -37,11 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.VpnToPseudoPortList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.vpn.to.pseudo.port.list.VpnToPseudoPortData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.vpn.to.pseudo.port.list.VpnToPseudoPortDataKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CleanupDpnForVpnInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CleanupDpnForVpnInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.PopulateFibOnDpnInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.PopulateFibOnDpnInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
@@ -49,15 +44,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -101,10 +90,7 @@ public class VpnServiceChainUtils {
     }
 
     public static InstanceIdentifier<VrfTables> buildVrfId(String rd) {
-        InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder = InstanceIdentifier.builder(FibEntries.class)
-                .child(VrfTables.class, new VrfTablesKey(rd));
-        InstanceIdentifier<VrfTables> id = idBuilder.build();
-        return id;
+        return InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
     }
 
     public static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
@@ -120,10 +106,7 @@ public class VpnServiceChainUtils {
 
     public static InstanceIdentifier<VpnToPseudoPortData> getVpnToPseudoPortTagIid(String rd) {
         VpnToPseudoPortDataKey key = new VpnToPseudoPortDataKey(rd);
-        InstanceIdentifier<VpnToPseudoPortData> result = InstanceIdentifier.builder(VpnToPseudoPortList.class)
-                                                                           .child(VpnToPseudoPortData.class, key)
-                                                                           .build();
-        return result;
+        return InstanceIdentifier.builder(VpnToPseudoPortList.class).child(VpnToPseudoPortData.class, key).build();
     }
 
     public static Optional<VpnToPseudoPortData> getVpnPseudoPortData(DataBroker broker, String rd) {
@@ -138,6 +121,21 @@ public class VpnServiceChainUtils {
         return all.isPresent() ? all.get().getVpnToPseudoPortData() : new ArrayList<>();
     }
 
+    /**
+     * Get fake VPNPseudoPort interface name.
+     *
+     * @param dpId Dpn Id
+     * @param scfTag Service Function tag
+     * @param scsTag Service Chain tag
+     * @param lportTag Lport tag
+     * @return the fake VpnPseudoPort interface name
+     */
+    public static String buildVpnPseudoPortIfName(Long dpId, long scfTag, int scsTag, int lportTag) {
+        return new StringBuilder("VpnPseudo.").append(dpId).append(NwConstants.FLOWID_SEPARATOR)
+                                              .append(lportTag).append(NwConstants.FLOWID_SEPARATOR)
+                                              .append(scfTag).append(NwConstants.FLOWID_SEPARATOR)
+                                              .append(scsTag).toString();
+    }
 
     /**
      * Retrieves the VpnId (datapath id) searching by VpnInstanceName.
@@ -188,9 +186,7 @@ public class VpnServiceChainUtils {
         InstanceIdentifier<VrfTables> vpnVrfTables =
             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
         Optional<VrfTables> vrfTable = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTables);
-        List<VrfEntry> vpnVrfEntries = vrfTable.isPresent() ? vrfTable.get().getVrfEntry()
-                                                                : new ArrayList<>();
-        return vpnVrfEntries;
+        return vrfTable.isPresent() ? vrfTable.get().getVrfEntry() : new ArrayList<>();
     }
 
     /**
@@ -388,11 +384,10 @@ public class VpnServiceChainUtils {
         }));
         instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { gotoTableId }));
         String flowRef = getL3VpnToScfLportDispatcherFlowRef(lportTag);
-        FlowEntity flowEntity =
-            MDSALUtil.buildFlowEntity(dpId, NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
-                                      CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef, 0, 0,
-                                      getCookieSCHop(scfTag), matches, instructions);
-        return flowEntity;
+
+        return MDSALUtil.buildFlowEntity(dpId, NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+                                         CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef, 0, 0,
+                                         getCookieSCHop(scfTag), matches, instructions);
 
     }
 
@@ -415,103 +410,14 @@ public class VpnServiceChainUtils {
                                                                          NwConstants.L3VPN_SERVICE_INDEX));
         List<Instruction> instructions = buildSetVrfTagAndGotoFibInstructions(vpnTag);
         String flowRef = getL3VpnToL3VpnLportDispFlowRef(dstLportTag, vpnTag);
-        Flow result = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
-                                             CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
-                                             0, 0, VpnServiceChainUtils.getCookieL3(vpnTag),
-                                             matches, instructions);
-        return result;
-    }
-
-    /**
-     * Updates the VPN footprint by adding a 'fake' interface for the
-     * VpnPseudoPort. The objective of this operation is that the FibManager,
-     * on one hand, maintains the FIB table even in DPNs where there are no
-     * real VpnInterfaces and, on other hand, keeps maintaining the FIB table
-     * even after the last real VpnInterface is removed.
-     *
-     */
-    public static void updateMappingDbs(DataBroker broker, FibRpcService fibRpcService, long vpnId,
-                                        BigInteger dpnId, String intfName, String vpnName) {
-        if (vpnName != null) {
-            synchronized (vpnName.intern()) {
-                String routeDistinguisher = getVpnRd(broker, vpnName);
-                String rd = routeDistinguisher == null ? vpnName : routeDistinguisher;
-                InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
-                Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-                VpnInterfaces vpnInterface =
-                    new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-                if (dpnInVpn.isPresent()) {
-                    MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
-                                        id.child(VpnInterfaces.class, new VpnInterfacesKey(intfName)), vpnInterface);
-                } else {
-                    VpnInstanceOpDataEntry vpnOpData = new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId)
-                                                                                          .setVpnInstanceName(vpnName)
-                                                                                          .build();
-                    MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,getVpnInstanceOpDataIdentifier(rd),
-                                       vpnOpData);
-                    VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
-                    List<VpnInterfaces> vpnInterfaces =  new ArrayList<>();
-                    vpnInterfaces.add(vpnInterface);
-                    MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
-                                      vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
-                    PopulateFibOnDpnInput populateFibInput =
-                            new PopulateFibOnDpnInputBuilder().setDpid(dpnId).setVpnId(vpnId)
-                                                              .setRd(rd == null ? vpnName : rd)
-                                                              .build();
-                    fibRpcService.populateFibOnDpn(populateFibInput);
-                }
-            }
-        } else {
-            LOG.debug("vpnName is null");
-        }
-    }
 
-    /**
-     * Updates the VPN footprint by removing a 'fake' interface that represents
-     * the VpnPseudoPort.
-     *
-     */
-    public static void removeFromMappingDbs(DataBroker broker, FibRpcService fibRpcService, long vpnId,
-                                            BigInteger dpnId, String intfName, String vpnName) {
-        //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
-        if (vpnName != null) {
-            synchronized (vpnName.intern()) {
-                String rd = getVpnRd(broker, vpnName);
-                InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
-                Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-                if (dpnInVpn.isPresent()) {
-                    List<VpnInterfaces> vpnInterfaces =
-                        dpnInVpn.get().getVpnInterfaces();
-                    VpnInterfaces currVpnInterface =
-                        new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
-                    if (vpnInterfaces.remove(currVpnInterface)) {
-                        if (vpnInterfaces.isEmpty()) {
-                            List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
-                            if (ipAddresses == null || ipAddresses.isEmpty()) {
-                                LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
-                                MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
-                                CleanupDpnForVpnInput cleanupVpnInDpnInput =
-                                    new CleanupDpnForVpnInputBuilder().setDpid(dpnId).setVpnId(vpnId)
-                                                                      .setRd(rd == null ? vpnName : rd).build();
-                                fibRpcService.cleanupDpnForVpn(cleanupVpnInDpnInput);
-                            } else {
-                                LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} "
-                                          + "in dpn {}", vpnName, dpnId);
-                            }
-                        } else {
-                            MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
-                                VpnInterfaces.class,
-                                    new VpnInterfacesKey(intfName)));
-                        }
-                    }
-                }
-            }
-        }
+        return MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+                                      CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
+                                      0, 0, VpnServiceChainUtils.getCookieL3(vpnTag),
+                                      matches, instructions);
     }
 
 
-
     private static BigInteger getCookieSCHop(long scfInstanceTag) {
         return CloudServiceChainConstants.COOKIE_SCF_BASE.add(new BigInteger("0610000", 16))
                 .add(BigInteger.valueOf(scfInstanceTag));
index 31aab34a5efc4ee6afcd0f0a994d031ab87620fa..300137eb84e68a12badbb78b8f04a55ff8c6f9ca 100644 (file)
@@ -6,15 +6,13 @@
     <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
                odl:type="pingpong" />
     <reference id="mdsalManager" interface="org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager" />
-
-    <odl:rpc-service id="fibRpcService"
-                     interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService"/>
+    <reference id="vpnManager" interface="org.opendaylight.netvirt.vpnmanager.api.IVpnManager" />
 
     <bean id="vpnServiceChainHandler" class="org.opendaylight.netvirt.cloudservicechain.VPNServiceChainHandler"
           init-method="init" destroy-method="close">
         <argument ref="dataBroker" />
         <argument ref="mdsalManager" />
-        <argument ref="fibRpcService" />
+        <argument ref="vpnManager" />
     </bean>
 
     <bean id="elanServiceChainHandler" class="org.opendaylight.netvirt.cloudservicechain.ElanServiceChainHandler">
index 919a2966b0aaeb714694bedc0d042abf03211f66..45098ea0530857be92142f6e38af03d174cee9f6 100755 (executable)
@@ -17,7 +17,6 @@ import static org.mockito.Mockito.when;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
-
 import java.math.BigInteger;
 import java.util.Collections;
 import java.util.List;
@@ -46,6 +45,7 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.cloudservicechain.matchers.FlowEntityMatcher;
 import org.opendaylight.netvirt.cloudservicechain.matchers.FlowMatcher;
 import org.opendaylight.netvirt.cloudservicechain.utils.VpnServiceChainUtils;
+import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
@@ -96,6 +96,7 @@ public class VPNServiceChainHandlerTest {
     @Mock ReadOnlyTransaction readTx;
     @Mock WriteTransaction writeTx;
     @Mock IMdsalApiManager mdsalMgr;
+    @Mock IVpnManager vpnManager;
 
 
     @BeforeClass
@@ -113,7 +114,9 @@ public class VPNServiceChainHandlerTest {
         when(broker.newWriteOnlyTransaction()).thenReturn(writeTx);
         CheckedFuture chkdFuture = mock(CheckedFuture.class);
         when(writeTx.submit()).thenReturn(chkdFuture);
-        vpnsch = new VPNServiceChainHandler(broker, mdsalMgr, fibRpcService);
+
+        // SUT
+        vpnsch = new VPNServiceChainHandler(broker, mdsalMgr, vpnManager);
     }
 
     @After
@@ -296,12 +299,10 @@ public class VPNServiceChainHandlerTest {
             VpnServiceChainUtils.buildLPortDispFromScfToL3VpnFlow(VPN_ID, DPN_ID, LPORT_TAG, NwConstants.ADD_FLOW);
         assert (new FlowMatcher(expectedLportDispatcherFlowEntity).matches(installedFlowsCaptured.get(0)));
 
-        LOG.info("second call = {}", installedFlowsCaptured.get(1));
-
         // Verifying VpnToDpn update
-        verify(writeTx, times(1)).put(eq(LogicalDatastoreType.OPERATIONAL),
-                                      argThat(isIIdType(VpnInterfaces.class)),
-                                      anyObject(), eq(Boolean.TRUE));
+        String vpnPseudoPortIfaceName =
+            VpnServiceChainUtils.buildVpnPseudoPortIfName(DPN_ID.longValue(), SCF_TAG, SERV_CHAIN_TAG, LPORT_TAG);
+        verify(vpnManager).updateVpnFootprint(eq(DPN_ID), eq(VPN_NAME), eq(vpnPseudoPortIfaceName), eq(Boolean.TRUE));
     }
 
 
index 98346f3e496dfb8ee85fe34638c539370471e607..9ab40b87d87985d03c121db94f94eb48210c529e 100644 (file)
@@ -37,6 +37,19 @@ public interface IVpnManager {
      * @return The list of DPNs
      */
     List<BigInteger> getDpnsOnVpn(String vpnInstanceName);
+
+    /**
+     * Updates the footprint that a VPN has on a given DPN by adding/removing
+     * the specified interface
+     *
+     * @param dpId DPN where the VPN interface belongs to
+     * @param vpnName Name of the VPN whose footprint is being modified
+     * @param interfaceName Name of the VPN interface to be added/removed
+     *          to/from the specified DPN
+     * @param add true for addition, false for removal
+     */
+    void updateVpnFootprint(BigInteger dpId, String vpnName, String interfaceName, boolean add);
+
     void setupSubnetMacIntoVpnInstance(String vpnName, String srcMacAddress,
             BigInteger dpnId, WriteTransaction writeTx, int addOrRemove);
 }
diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnFootprintService.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnFootprintService.java
new file mode 100644 (file)
index 0000000..5a8f62e
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.vpnmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VpnFootprintService {
+
+    // TODO: Should this class have its own interface instead of being under IVpnManager's umbrella?
+
+    private static final Logger LOG = LoggerFactory.getLogger(VpnFootprintService.class);
+
+    private final DataBroker dataBroker;
+    private final IFibManager fibManager;
+    private final OdlInterfaceRpcService ifaceMgrRpcService;
+    private final NotificationPublishService notificationPublishService;
+
+    public VpnFootprintService(final DataBroker dataBroker,
+                               final IFibManager fibManager,
+                               final OdlInterfaceRpcService ifaceRpcService,
+                               final NotificationPublishService notificationPublishService) {
+        this.dataBroker = dataBroker;
+        this.fibManager = fibManager;
+        this.ifaceMgrRpcService = ifaceRpcService;
+        this.notificationPublishService = notificationPublishService;
+    }
+
+    public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+        long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+        if (dpId == null) {
+            dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
+        }
+        if(!dpId.equals(BigInteger.ZERO)) {
+            if(add) {
+                createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
+            } else {
+                removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
+            }
+        }
+    }
+
+    private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+        String routeDistinguisher = VpnUtil.getVpnRdFromVpnInstanceConfig(dataBroker, vpnName);
+        String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+        Boolean newDpnOnVpn = Boolean.FALSE;
+
+        synchronized (vpnName.intern()) {
+            WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
+            InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+            Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+            VpnInterfaces vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+            if (dpnInVpn.isPresent()) {
+                VpnToDpnList vpnToDpnList = dpnInVpn.get();
+                List<VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
+                if (vpnInterfaces == null) {
+                    vpnInterfaces = new ArrayList<>();
+                }
+                vpnInterfaces.add(vpnInterface);
+                VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
+                vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
+
+                writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
+                /* If earlier state was inactive, it is considered new DPN coming back to the
+                 * same VPN
+                 */
+                if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
+                    newDpnOnVpn = Boolean.TRUE;
+                }
+            } else {
+                List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
+                vpnInterfaces.add(vpnInterface);
+                VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
+                vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
+
+                writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
+                newDpnOnVpn = Boolean.TRUE;
+            }
+            CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+            try {
+                futures.get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+        /*
+         * Informing the Fib only after writeTxn is submitted successfuly.
+         */
+        if (newDpnOnVpn) {
+            LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
+            fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
+                                                                                       true /* entered */));
+        }
+    }
+
+    private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+        Boolean lastDpnOnVpn = Boolean.FALSE;
+        String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
+        synchronized (vpnName.intern()) {
+            InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+            Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+            WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
+            if (dpnInVpn.isPresent()) {
+                List<VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+                VpnInterfaces currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+                if (vpnInterfaces.remove(currVpnInterface)) {
+                    if (vpnInterfaces.isEmpty()) {
+                        List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
+                        if (ipAddresses == null || ipAddresses.isEmpty()) {
+                            VpnToDpnListBuilder dpnInVpnBuilder =
+                                new VpnToDpnListBuilder(dpnInVpn.get()).setDpnState(VpnToDpnList.DpnState.Inactive)
+                                                                       .setVpnInterfaces(null);
+                            writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
+                            lastDpnOnVpn = Boolean.TRUE;
+                        } else {
+                            LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}",
+                                     vpnName, dpnId);
+                        }
+                    } else {
+                        writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(VpnInterfaces.class,
+                                                                                   new VpnInterfacesKey(intfName)));
+                    }
+                }
+            }
+            CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
+            try {
+                futures.get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+        if (lastDpnOnVpn) {
+            LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
+            fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
+                                                                                    false /* exited */));
+        }
+    }
+
+    void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
+        LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
+        AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
+        AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
+        final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
+        Futures.addCallback(eventFuture, new FutureCallback<Object>() {
+            @Override
+            public void onFailure(Throwable error) {
+                LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
+            }
+
+            @Override
+            public void onSuccess(Object arg) {
+                LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
+            }
+        });
+    }
+
+    void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
+        LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
+        RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
+        RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
+        final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
+        Futures.addCallback(eventFuture, new FutureCallback<Object>() {
+            @Override
+            public void onFailure(Throwable error) {
+                LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
+            }
+
+            @Override
+            public void onSuccess(Object arg) {
+                LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
+            }
+        });
+    }
+
+
+    /**
+     * JobCallback class is used as a future callback for
+     * main and rollback workers to handle success and failure.
+     */
+    private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
+        BigInteger dpnId;
+        String vpnName;
+        String rd;
+        boolean entered;
+
+        public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
+            this.entered = entered;
+            this.dpnId = dpnId;
+            this.vpnName = vpnName;
+            this.rd = rd;
+        }
+
+        /**
+         * @param voids
+         * This implies that all the future instances have returned success. -- TODO: Confirm this
+         */
+        @Override
+        public void onSuccess(List<Void> voids) {
+            if (entered) {
+                publishAddNotification(dpnId, vpnName, rd);
+            } else {
+                publishRemoveNotification(dpnId, vpnName, rd);
+            }
+        }
+
+        /**
+         *
+         * @param throwable
+         * This method is used to handle failure callbacks.
+         * If more retry needed, the retrycount is decremented and mainworker is executed again.
+         * After retries completed, rollbackworker is executed.
+         * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+         */
+        @Override
+        public void onFailure(Throwable throwable) {
+            LOG.warn("Job: failed with exception: ", throwable);
+        }
+    }
+
+}
index 4a6fc7b9aafad53d7ac67726cdd1b50c62f9feec..356bb6a19216e72a72eb7d432297d548b06f8b24 100755 (executable)
@@ -14,7 +14,6 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterators;
-import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.JdkFutureAdapters;
@@ -25,10 +24,8 @@ import java.util.concurrent.*;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
@@ -73,14 +70,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
@@ -93,15 +84,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neu
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -113,7 +97,11 @@ import org.slf4j.LoggerFactory;
 
 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager>
         implements AutoCloseable {
+
     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
+    private static final int vpnInfUpdateTimerTaskDelay = 1000;
+    private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
+
     private final DataBroker dataBroker;
     private final IBgpManager bgpManager;
     private final IFibManager fibManager;
@@ -121,13 +109,12 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
     private final IdManagerService idManager;
     private final OdlArputilService arpManager;
     private final OdlInterfaceRpcService ifaceMgrRpcService;
-    private final NotificationPublishService notificationPublishService;
+    private final VpnFootprintService vpnFootprintService;
+
     private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
     private ConcurrentHashMap<String, List<Runnable>> vpnInstanceToIdSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
     private ConcurrentHashMap<String, List<Runnable>> vpnInstanceOpDataSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
-    private ExecutorService executorService = Executors.newSingleThreadExecutor();
-    private static final int vpnInfUpdateTimerTaskDelay = 1000;
-    private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
+
     private BlockingQueue<UpdateData> vpnInterfacesUpdateQueue = new LinkedBlockingQueue<>();
     private ScheduledThreadPoolExecutor vpnInfUpdateTaskExecutor = (ScheduledThreadPoolExecutor) Executors
             .newScheduledThreadPool(1);
@@ -139,7 +126,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                final IMdsalApiManager mdsalManager,
                                final IFibManager fibManager,
                                final OdlInterfaceRpcService ifaceMgrRpcService,
-                               final NotificationPublishService notificationPublishService) {
+                               final VpnFootprintService vpnFootprintService) {
         super(VpnInterface.class, VpnInterfaceManager.class);
         this.dataBroker = dataBroker;
         this.bgpManager = bgpManager;
@@ -148,7 +135,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         this.mdsalManager = mdsalManager;
         this.fibManager = fibManager;
         this.ifaceMgrRpcService = ifaceMgrRpcService;
-        this.notificationPublishService = notificationPublishService;
+        this.vpnFootprintService = vpnFootprintService;
         vpnInfUpdateTaskExecutor.scheduleWithFixedDelay(new VpnInterfaceUpdateTimerTask(),
                 0, vpnInfUpdateTimerTaskDelay, TIME_UNIT);
     }
@@ -333,7 +320,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             }
             if (!waitForVpnInterfaceOpRemoval) {
                 // Add the VPNInterface and quit
-                updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
+                vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
                 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
                 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
                 return;
@@ -361,7 +348,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 return;
             }
             // VPNInterface got removed, proceed with Add
-            updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
+            vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
             bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
             processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
         } else {
@@ -541,20 +528,6 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
-    public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
-        long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
-        if (dpId == null) {
-            dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
-        }
-        if(!dpId.equals(BigInteger.ZERO)) {
-            if(add) {
-                createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
-            } else {
-                removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
-            }
-        }
-    }
-
     private void bindService(BigInteger dpId, final String vpnInstanceName, final String vpnInterfaceName,
                              int lPortTag, WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
         final int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
@@ -838,174 +811,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         return rd;
     }
 
-    /**
-     * JobCallback class is used as a future callback for
-     * main and rollback workers to handle success and failure.
-     */
-    private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
-        BigInteger dpnId;
-        String vpnName;
-        String rd;
-        boolean entered;
-
-        public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
-            this.entered = entered;
-            this.dpnId = dpnId;
-            this.vpnName = vpnName;
-            this.rd = rd;
-        }
-
-        /**
-         * @param voids
-         * This implies that all the future instances have returned success. -- TODO: Confirm this
-         */
-        @Override
-        public void onSuccess(List<Void> voids) {
-            if (entered) {
-                publishAddNotification(dpnId, vpnName, rd);
-            } else {
-                publishRemoveNotification(dpnId, vpnName, rd);
-            }
-        }
-
-        /**
-         *
-         * @param throwable
-         * This method is used to handle failure callbacks.
-         * If more retry needed, the retrycount is decremented and mainworker is executed again.
-         * After retries completed, rollbackworker is executed.
-         * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
-         */
-        @Override
-        public void onFailure(Throwable throwable) {
-            LOG.warn("Job: failed with exception: ", throwable);
-        }
-    }
 
-    private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
-        String routeDistinguisher = getRouteDistinguisher(vpnName);
-        String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
-        Boolean newDpnOnVpn = Boolean.FALSE;
-
-        synchronized (vpnName.intern()) {
-            WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-            InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
-            Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
-            org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
-                    .entry.vpn.to.dpn.list.VpnInterfaces
-                    vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
-            if (dpnInVpn.isPresent()) {
-                VpnToDpnList vpnToDpnList = dpnInVpn.get();
-                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                        .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
-                if (vpnInterfaces == null) {
-                    vpnInterfaces = new ArrayList<>();
-                }
-                vpnInterfaces.add(vpnInterface);
-                VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
-                vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
 
-                if (writeTxn != null) {
-                    writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
-                } else {
-                    VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
-                }
-                /* If earlier state was inactive, it is considered new DPN coming back to the
-                 * same VPN
-                 */
-                if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
-                    newDpnOnVpn = Boolean.TRUE;
-                }
-            } else {
-                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                        .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
-                vpnInterfaces.add(vpnInterface);
-                VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
-                vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
-
-                if (writeTxn != null) {
-                    writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
-                } else {
-                    VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
-                }
-                newDpnOnVpn = Boolean.TRUE;
-            }
-            CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
-            try {
-                futures.get();
-            } catch (InterruptedException | ExecutionException e) {
-                LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
-                throw new RuntimeException(e.getMessage());
-            }
-        }
-        /*
-         * Informing the Fib only after writeTxn is submitted successfuly.
-         */
-        if (newDpnOnVpn) {
-            LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
-            fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, true /* entered */));
-        }
-    }
-
-    private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
-        Boolean lastDpnOnVpn = Boolean.FALSE;
-        String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
-        synchronized (vpnName.intern()) {
-            InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
-            Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
-            WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
-            if (dpnInVpn.isPresent()) {
-                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                        .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
-                org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
-                        currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
-                if (vpnInterfaces.remove(currVpnInterface)) {
-                    if (vpnInterfaces.isEmpty()) {
-                        List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
-                        if (ipAddresses == null || ipAddresses.isEmpty()) {
-                            VpnToDpnListBuilder dpnInVpnBuilder =
-                                    new VpnToDpnListBuilder(dpnInVpn.get())
-                                            .setDpnState(VpnToDpnList.DpnState.Inactive)
-                                            .setVpnInterfaces(null);
-                            if (writeTxn != null) {
-                                writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
-                            } else {
-                                VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build());
-                            }
-                            lastDpnOnVpn = Boolean.TRUE;
-                        } else {
-                            LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
-                        }
-                    } else {
-                        if (writeTxn != null) {
-                            writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
-                                    org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                                            .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
-                                    new VpnInterfacesKey(intfName)));
-                        } else {
-                            VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
-                                    org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
-                                            .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
-                                    new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
-                        }
-                    }
-                }
-            }
-            CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
-            try {
-                futures.get();
-            } catch (InterruptedException | ExecutionException e) {
-                LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
-                throw new RuntimeException(e.getMessage());
-            }
-        }
-        if (lastDpnOnVpn) {
-            LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
-            fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
-        }
-    }
 
     void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
         List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
@@ -1721,41 +1528,6 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         }
     }
 
-    void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
-        LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
-        AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
-        AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
-        final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
-        Futures.addCallback(eventFuture, new FutureCallback<Object>() {
-            @Override
-            public void onFailure(Throwable error) {
-                LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
-            }
-
-            @Override
-            public void onSuccess(Object arg) {
-                LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
-            }
-        });
-    }
-
-    void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
-        LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
-        RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
-        RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
-        final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
-        Futures.addCallback(eventFuture, new FutureCallback<Object>() {
-            @Override
-            public void onFailure(Throwable error) {
-                LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
-            }
-
-            @Override
-            public void onSuccess(Object arg) {
-                LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
-            }
-        });
-    }
 
     InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
         return InstanceIdentifier.builder(NeutronRouterDpns.class)
index 4f0a61a6f58623fd55ffb112e54d775d7ba61929..b17d7bfccd83c7ed36a1deb069060f1825be0afa 100644 (file)
@@ -38,6 +38,7 @@ public class VpnInterfaceOpListener extends AsyncDataTreeChangeListenerBase<VpnI
     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceOpListener.class);
     private final DataBroker dataBroker;
     private final VpnInterfaceManager vpnInterfaceManager;
+    private final VpnFootprintService vpnFootprintService;
     private ExecutorService executorService = Executors.newSingleThreadExecutor();
 
     /*public VpnInterfaceOpListener(final DataBroker dataBroker) {
@@ -45,10 +46,12 @@ public class VpnInterfaceOpListener extends AsyncDataTreeChangeListenerBase<VpnI
         this.dataBroker = dataBroker;
     }*/
 
-    public VpnInterfaceOpListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager) {
+    public VpnInterfaceOpListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager,
+                                  final VpnFootprintService vpnFootprintService) {
         super(VpnInterface.class, VpnInterfaceOpListener.class);
         this.dataBroker = dataBroker;
         this.vpnInterfaceManager = vpnInterfaceManager;
+        this.vpnFootprintService = vpnFootprintService;
     }
 
     public void start() {
@@ -141,8 +144,8 @@ public class VpnInterfaceOpListener extends AsyncDataTreeChangeListenerBase<VpnI
                                 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
                                 VpnUtil.DEFAULT_CALLBACK);
                     }
-                    vpnInterfaceManager.updateVpnToDpnMapping(pref.getDpnId(), del.getVpnInstanceName(),
-                            interfaceName, false /* delete */);
+                    vpnFootprintService.updateVpnToDpnMapping(pref.getDpnId(), del.getVpnInstanceName(),
+                                                              interfaceName, false /* delete */);
                 }
             }
         } else {
@@ -197,8 +200,7 @@ public class VpnInterfaceOpListener extends AsyncDataTreeChangeListenerBase<VpnI
                 = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, origId);
 
         if (origVpnInstance.isPresent()) {
-            String rd = null;
-            rd = origVpnInstance.get().getVrfId();
+            String rd = origVpnInstance.get().getVrfId();
 
             vpnInstOp = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
             LOG.trace("VpnInterfaceOpListener updated: interface name {} original rd {} original vpnName {}",
@@ -226,8 +228,8 @@ public class VpnInterfaceOpListener extends AsyncDataTreeChangeListenerBase<VpnI
                     }
                 }
                 for (Prefixes prefix : prefixToInterfaceList) {
-                    vpnInterfaceManager.updateVpnToDpnMapping(prefix.getDpnId(), original.getVpnInstanceName(),
-                            interfaceName, false /* delete */);
+                    vpnFootprintService.updateVpnToDpnMapping(prefix.getDpnId(), original.getVpnInstanceName(),
+                                                              interfaceName, false /* delete */);
                 }
             }
         }
index 674b1b3ee8de5ac3eabd7f1946399bba2bc7d9e5..fdcd4768b8bd98b00176f36fa9612c5c67fa9425 100644 (file)
@@ -34,17 +34,20 @@ public class VpnManagerImpl implements IVpnManager {
     private final VpnInstanceListener vpnInstanceListener;
     private final IdManagerService idManager;
     private final IMdsalApiManager mdsalManager;
+    private final VpnFootprintService vpnFootprintService;
 
     public VpnManagerImpl(final DataBroker dataBroker,
                           final IdManagerService idManagerService,
                           final VpnInstanceListener vpnInstanceListener,
                           final VpnInterfaceManager vpnInterfaceManager,
-                          final IMdsalApiManager mdsalManager) {
+                          final IMdsalApiManager mdsalManager,
+                          final VpnFootprintService vpnFootprintService) {
         this.dataBroker = dataBroker;
         this.vpnInterfaceManager = vpnInterfaceManager;
         this.vpnInstanceListener = vpnInstanceListener;
         this.idManager = idManagerService;
         this.mdsalManager = mdsalManager;
+        this.vpnFootprintService = vpnFootprintService;
     }
 
     public void start() {
@@ -100,7 +103,7 @@ public class VpnManagerImpl implements IVpnManager {
                               RouteOrigin origin) {
         LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}",
                  destination, nextHop, label, origin);
-        vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, origin, /*intfName*/ null, 
+        vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, origin, /*intfName*/ null,
                                           null, null);
     }
 
@@ -120,6 +123,11 @@ public class VpnManagerImpl implements IVpnManager {
         return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
     }
 
+    @Override
+    public void updateVpnFootprint(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+        vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, interfaceName, add);
+    }
+
     @Override
     public boolean existsVpn(String vpnName) {
         return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
index 84181f271a443088c05e307e04c7f30e81d53cf1..dc2ef6ff002175e0d7c61a96dbc56a50b4064158 100644 (file)
@@ -919,75 +919,6 @@ public class VpnUtil {
                         .build();
     }
 
-    /**
-     * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
-     * This method is preferably over mergeDpnInVpnToDpnMap(DataBroker, String, String, BigInteger, List)
-     * when there are several DPNs to be merged since it saves some readings from MDSAL.
-     *
-     * @param broker     dataBroker service reference
-     * @param vpnOpData  Reference to the object that holds the Operational data of the VpnInstance
-     * @param dpnId      Id of the DPN where the interfaces to be added to Operational data are located
-     * @param ifaceNames List of interface names
-     */
-    public static void mergeDpnInVpnToDpnMap(DataBroker broker, VpnInstanceOpDataEntry vpnOpData, BigInteger dpnId,
-                                             List<String> ifaceNames) {
-        Preconditions.checkNotNull(vpnOpData);
-        Preconditions.checkNotNull(ifaceNames);
-
-        for (String ifaceName : ifaceNames) {
-            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
-                    .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnDpnIfaceIid =
-                    getVpnToDpnInterfacePath(vpnOpData.getKey().getVrfId(), dpnId, ifaceName);
-
-            org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
-                    .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnDpnIface =
-                    new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
-                            .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list
-                            .VpnInterfacesBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
-                            .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
-                            .setInterfaceName(ifaceName)
-                            .build();
-
-            syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vpnDpnIfaceIid, vpnDpnIface);
-        }
-    }
-
-    /**
-     * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
-     *
-     * @param broker dataBroker service reference
-     * @param vpnName Name of the VPN
-     * @param rd Route-Distinguisher
-     * @param dpnId Id of the DPN that includes the list of Ifaces to be
-     *           included in the Map
-     * @param ifaceNames List of interfaces to be included in the Map
-     */
-    public static void mergeDpnInVpnToDpnMap(DataBroker broker, String vpnName, String rd, BigInteger dpnId,
-                                             List<String> ifaceNames) {
-        InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
-                .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
-                .build();
-
-        Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
-            MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-        if (vpnInstanceOpData.isPresent()) {
-            mergeDpnInVpnToDpnMap(broker, vpnInstanceOpData.get(), dpnId, ifaceNames);
-        }
-    }
-
-    /**
-     * Removes a specific interface from the VpnToDpn operative map.
-     *
-     * @param broker    dataBroker service reference
-     * @param rd        Route-distinguisher of the VPN
-     * @param dpnId     Id of the DPN where the interface is
-     * @param ifaceName interface name.
-     */
-    public static void removeIfaceFromVpnToDpnMap(DataBroker broker, String rd, BigInteger dpnId, String ifaceName) {
-        tryDelete(broker, LogicalDatastoreType.OPERATIONAL, getVpnToDpnInterfacePath(rd, dpnId, ifaceName));
-        // Note: tryDelete is a best-effort. Sometimes we want to update the VpnToDpnMap ifaces when the
-        // DPN has gone down (and the VpnToDpnMap has been removed in a different Thread)
-    }
 
     public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
         try {
index 760ede38eb6a3db6767956cd592f42b2942c517a..e1af1709e988f7742ed094a3fd344a26874e7588 100755 (executable)
@@ -38,6 +38,7 @@ import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
@@ -100,6 +101,7 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
     private final IBgpManager bgpManager;
     private final IFibManager fibManager;
     private final NotificationPublishService notificationsService;
+    private final VpnFootprintService vpnFootprintService;
 
     // A couple of listener in order to maintain the InterVpnLink cache
     private InterVpnLinkCacheFeeder iVpnLinkCacheFeeder;
@@ -108,7 +110,8 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
 
     public InterVpnLinkListener(final DataBroker dataBroker, final IdManagerService idManager,
                                 final IMdsalApiManager mdsalManager, final IBgpManager bgpManager,
-                                final IFibManager fibManager, final NotificationPublishService notifService) {
+                                final IFibManager fibManager, final NotificationPublishService notifService,
+                                final VpnFootprintService vpnFootprintService) {
         super(InterVpnLink.class, InterVpnLinkListener.class);
         this.dataBroker = dataBroker;
         this.idManager = idManager;
@@ -116,6 +119,7 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
         this.bgpManager = bgpManager;
         this.fibManager = fibManager;
         this.notificationsService = notifService;
+        this.vpnFootprintService = vpnFootprintService;
     }
 
     public void start() {
@@ -136,10 +140,6 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
         return InterVpnLinkListener.this;
     }
 
-    private String getInterVpnLinkIfaceName(String vpnUuid, BigInteger dpnId ) {
-        return String.format("InterVpnLink.%s.%s", vpnUuid, dpnId.toString());
-    }
-
     @Override
     protected void add(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink add) {
 
@@ -153,32 +153,34 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid, vpnLinkState);
 
         InterVpnLinkKey key = add.getKey();
-        Uuid firstEndpointVpnUuid = add.getFirstEndpoint().getVpnUuid();
-        Uuid secondEndpointVpnUuid = add.getSecondEndpoint().getVpnUuid();
+        Uuid vpn1Uuid = add.getFirstEndpoint().getVpnUuid();
+        String vpn1Name = vpn1Uuid.getValue();
+        Uuid vpn2Uuid = add.getSecondEndpoint().getVpnUuid();
+        String vpn2Name = vpn2Uuid.getValue();
         // First VPN
-        if ( VpnUtil.getVpnInstance(this.dataBroker, firstEndpointVpnUuid.getValue()) == null ) {
+        if ( VpnUtil.getVpnInstance(this.dataBroker, vpn1Name) == null ) {
             String errMsg = "InterVpnLink " + add.getName() + " creation error: could not find 1st endpoint Vpn "
-                    + firstEndpointVpnUuid.getValue();
+                            + vpn1Name;
             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
             return;
         }
-        if (!checkVpnAvailability(key, firstEndpointVpnUuid)) {
-            String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + firstEndpointVpnUuid.getValue()
-                    + " is already associated to an inter-vpn-link ";
+        if (!checkVpnAvailability(key, vpn1Uuid)) {
+            String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + vpn1Name
+                            + " is already associated to an inter-vpn-link ";
             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
             return;
         }
 
         // Second VPN
-        if ( VpnUtil.getVpnInstance(this.dataBroker, secondEndpointVpnUuid.getValue()) == null ) {
+        if ( VpnUtil.getVpnInstance(this.dataBroker, vpn2Name) == null ) {
             String errMsg = "InterVpnLink " + add.getName() + " creation error: could not find 2nd endpoint Vpn "
-                    + secondEndpointVpnUuid.getValue();
+                             + vpn2Name;
             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
             return;
         }
-        if (!checkVpnAvailability(key, secondEndpointVpnUuid)) {
-            String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + secondEndpointVpnUuid.getValue()
-                    + " is already associated with an inter-vpn-link";
+        if (!checkVpnAvailability(key, vpn2Uuid)) {
+            String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + vpn2Name
+                            + " is already associated with an inter-vpn-link";
             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
             return;
         }
@@ -190,13 +192,13 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
         if (firstDpnList != null && !firstDpnList.isEmpty()) {
             List<BigInteger> secondDpnList = firstDpnList;
 
-            Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
-            Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
+            Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn1Name);
+            Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn2Name);
             FirstEndpointState firstEndPointState =
-                new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid).setDpId(firstDpnList)
+                new FirstEndpointStateBuilder().setVpnUuid(vpn1Uuid).setDpId(firstDpnList)
                                                .setLportTag(firstVpnLportTag).build();
             SecondEndpointState secondEndPointState =
-                new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid).setDpId(secondDpnList)
+                new SecondEndpointStateBuilder().setVpnUuid(vpn2Uuid).setDpId(secondDpnList)
                                                 .setLportTag(secondVpnLportTag).build();
 
             InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Active,
@@ -206,16 +208,16 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
 
             // Note that in the DPN of the firstEndpoint we install the lportTag of the secondEndpoint and viceversa
             InterVpnLinkUtil.installLPortDispatcherTableFlow(dataBroker, mdsalManager, add, firstDpnList,
-                                                             secondEndpointVpnUuid, secondVpnLportTag.intValue());
+                                                             vpn2Uuid, secondVpnLportTag.intValue());
             InterVpnLinkUtil.installLPortDispatcherTableFlow(dataBroker, mdsalManager, add, secondDpnList,
-                                                             firstEndpointVpnUuid, firstVpnLportTag.intValue());
+                                                             vpn1Uuid, firstVpnLportTag.intValue());
             // Update the VPN -> DPNs Map.
             // Note: when a set of DPNs is calculated for Vpn1, these DPNs are added to the VpnToDpn map of Vpn2. Why?
             // because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
             // to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
             // Vpn2 is not physically present there.
-            InterVpnLinkUtil.updateVpnToDpnMap(dataBroker, firstDpnList, secondEndpointVpnUuid);
-            InterVpnLinkUtil.updateVpnToDpnMap(dataBroker, secondDpnList, firstEndpointVpnUuid);
+            InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, vpn2Name, firstDpnList);
+            InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, vpn1Name, secondDpnList);
 
             // Program static routes if needed
             handleStaticRoutes(iVpnLink.get());
@@ -225,14 +227,12 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
         } else {
             // If there is no connection to DPNs, the InterVpnLink is created and the InterVpnLinkState is also created
             // with the corresponding LPortTags but no DPN is assigned since there is no DPN operative.
-            Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
-            Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
+            Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn1Name);
+            Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn2Name);
             FirstEndpointState firstEndPointState =
-                new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid)
-                                               .setLportTag(firstVpnLportTag).build();
+                new FirstEndpointStateBuilder().setVpnUuid(vpn1Uuid).setLportTag(firstVpnLportTag).build();
             SecondEndpointState secondEndPointState =
-                new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid)
-                                                .setLportTag(secondVpnLportTag).build();
+                new SecondEndpointStateBuilder().setVpnUuid(vpn2Uuid).setLportTag(secondVpnLportTag).build();
             InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Error,
                                                      firstEndPointState, secondEndPointState);
         }
@@ -453,7 +453,7 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
             boolean isVpnFirstEndPoint = true;
             if (interVpnLinkState.getFirstEndpointState() != null) {
                 Long firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
-                removeVpnLinkEndpointFlows(del, rd2, vpn2Uuid,
+                removeVpnLinkEndpointFlows(del, vpn2Uuid,
                                            interVpnLinkState.getSecondEndpointState().getDpId(),
                                            firstEndpointLportTag.intValue(),
                                            del.getFirstEndpoint().getIpAddress().getValue(),
@@ -465,7 +465,7 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
             isVpnFirstEndPoint = false;
             if (interVpnLinkState.getSecondEndpointState() != null) {
                 Long secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
-                removeVpnLinkEndpointFlows(del, rd1, vpn1Uuid,
+                removeVpnLinkEndpointFlows(del, vpn1Uuid,
                                            interVpnLinkState.getFirstEndpointState().getDpId(),
                                            secondEndpointLportTag.intValue(),
                                            del.getSecondEndpoint().getIpAddress().getValue(),
@@ -497,7 +497,7 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
         VpnUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
     }
 
-    private void removeVpnLinkEndpointFlows(InterVpnLink del, String rd, String vpnUuid, List<BigInteger> dpns,
+    private void removeVpnLinkEndpointFlows(InterVpnLink del, String vpnUuid, List<BigInteger> dpns,
                                             int otherEndpointLportTag, String otherEndpointIpAddr, List<VrfEntry> vrfEntries,
                                             final boolean isVpnFirstEndPoint) {
 
@@ -521,7 +521,7 @@ public class InterVpnLinkListener extends AsyncDataTreeChangeListenerBase<InterV
                 mdsalManager.removeFlow(dpnId, flow);
 
                 // Also remove the 'fake' iface from the VpnToDpn map
-                VpnUtil.removeIfaceFromVpnToDpnMap(dataBroker, rd, dpnId, getInterVpnLinkIfaceName(vpnUuid, dpnId));
+                InterVpnLinkUtil.removeIVpnLinkIfaceFromVpnFootprint(vpnFootprintService, vpnUuid, dpnId);
 
             } catch ( Exception e ) {
                 // Whatever happens it should not stop it from trying to remove as much as possible
index 3000a4952906e741afd329bb1ee5ac267ae5d112..c29e6dd60e0d83ced5ed615558988d0f68270302 100755 (executable)
@@ -15,6 +15,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
@@ -42,13 +43,18 @@ public class InterVpnLinkNodeAddTask implements Callable<List<ListenableFuture<V
     private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
 
     private DataBroker broker;
+    private final IMdsalApiManager mdsalManager;
+    private final VpnFootprintService vpnFootprintService;
+
     private BigInteger dpnId;
-    final IMdsalApiManager mdsalManager;
 
-    public InterVpnLinkNodeAddTask(final DataBroker broker, final IMdsalApiManager mdsalMgr, final BigInteger dpnId) {
+    public InterVpnLinkNodeAddTask(final DataBroker broker, final IMdsalApiManager mdsalMgr,
+                                   final VpnFootprintService vpnFootprintService, final BigInteger dpnId) {
         this.broker = broker;
-        this.dpnId = dpnId;
         this.mdsalManager = mdsalMgr;
+        this.vpnFootprintService = vpnFootprintService;
+
+        this.dpnId = dpnId;
     }
 
     @Override
@@ -130,8 +136,8 @@ public class InterVpnLinkNodeAddTask implements Callable<List<ListenableFuture<V
             // because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
             // to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
             // Vpn2 is not physically present there.
-            InterVpnLinkUtil.updateVpnToDpnMap(broker, firstDpnList, secondEndpointVpnUuid);
-            InterVpnLinkUtil.updateVpnToDpnMap(broker, secondDpnList, firstEndpointVpnUuid);
+            InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, secondEndpointVpnUuid.getValue(), firstDpnList);
+            InterVpnLinkUtil.updateVpnFootprint(vpnFootprintService, firstEndpointVpnUuid.getValue(), secondDpnList);
         }
     }
 
index b96aee096affd6fdd6a0b342c50198f96e211178..66b143e65ab15ab076ce7a4a15e373bb53104636 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
@@ -52,12 +53,15 @@ public class InterVpnLinkNodeListener extends AsyncDataTreeChangeListenerBase<No
 
     private final DataBroker dataBroker;
     private final IMdsalApiManager mdsalManager;
+    private final VpnFootprintService vpnFootprintService;
 
 
-    public InterVpnLinkNodeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalMgr) {
+    public InterVpnLinkNodeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalMgr,
+                                    final VpnFootprintService vpnFootprintService) {
         super(Node.class, InterVpnLinkNodeListener.class);
         this.dataBroker = dataBroker;
-        mdsalManager = mdsalMgr;
+        this.mdsalManager = mdsalMgr;
+        this.vpnFootprintService = vpnFootprintService;
     }
 
     public void start() {
@@ -88,7 +92,7 @@ public class InterVpnLinkNodeListener extends AsyncDataTreeChangeListenerBase<No
         BigInteger dpId = new BigInteger(node[1]);
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
         coordinator.enqueueJob("IVpnLink" + dpId.toString(),
-                               new InterVpnLinkNodeAddTask(dataBroker, mdsalManager, dpId));
+                               new InterVpnLinkNodeAddTask(dataBroker, mdsalManager, vpnFootprintService, dpId));
     }
 
     @Override
index a90e82614c434f4818245ecf9aa195b2f2536adb..d53839d4c973356f7ba7754312dac38009d69e26 100755 (executable)
@@ -22,6 +22,7 @@ import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
+import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
@@ -95,27 +96,45 @@ public class InterVpnLinkUtil {
                 .build();
     }
 
+    public static String buildInterVpnLinkIfaceName(String vpnName, BigInteger dpnId) {
+        return String.format("InterVpnLink.%s.%s", vpnName, dpnId.toString());
+    }
+
     /**
      * Updates VpnToDpn map by adding a fake VpnInterface related to an
-     * InterVpnLink in the corresponding DPNs
+     * InterVpnLink in the corresponding DPNs. If the fake iface is the
+     * first one on the any of the specified DPNs, the installation of
+     * Fib flows on that DPN will be triggered
      *
-     * @param broker dataBroker service reference
+     * @param vpnFootprintService VpnFootprintService service reference
+     * @param vpnName Name of the VPN to which the fake interfaces belong
      * @param dpnList List of DPNs where the fake InterVpnLink interface must
      *     be added
-     * @param vpnUuid UUID of the VPN to which the fake interfaces belong
      */
-    public static void updateVpnToDpnMap(DataBroker broker, List<BigInteger> dpnList, Uuid vpnUuid) {
-        String rd = VpnUtil.getVpnRd(broker, vpnUuid.getValue());
-        InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
-        Optional<VpnInstanceOpDataEntry> vpnInstOpData = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
-        if ( vpnInstOpData.isPresent() ) {
-            for (BigInteger dpnId : dpnList) {
-                String linkIfaceName = String.format("InterVpnLink.%s.%s", vpnUuid.getValue(), dpnId.toString());
-                VpnUtil.mergeDpnInVpnToDpnMap(broker, vpnInstOpData.get(), dpnId, Arrays.asList(linkIfaceName));
-            }
+    public static void updateVpnFootprint(VpnFootprintService vpnFootprintService, String vpnName,
+                                          List<BigInteger> dpnList) {
+        LOG.debug("updateVpnFootprint (add):  vpn={}  dpnList={}", vpnName, dpnList);
+        for ( BigInteger dpnId : dpnList ) {
+            String ifaceName = buildInterVpnLinkIfaceName(vpnName, dpnId);
+            vpnFootprintService.updateVpnToDpnMapping(dpnId, vpnName, ifaceName, true /* addition */);
         }
     }
 
+    /**
+     * Updates VpnToDpn map by removing the fake VpnInterface related to an
+     * InterVpnLink in the corresponding DPNs.
+     *
+     * @param vpnFootprintService VpnFootprintService service reference
+     * @param vpnName Name of the VPN to which the fake interfaces belong
+     * @param dpnId DPN where the fake InterVpnLink interface must be removed from
+     */
+    public static void removeIVpnLinkIfaceFromVpnFootprint(VpnFootprintService vpnFootprintService,
+                                                           String vpnName, BigInteger dpnId) {
+        String ifaceName = buildInterVpnLinkIfaceName(vpnName, dpnId);
+        LOG.debug("updateVpnFootprint (remove):  vpn={}  dpn={}  ifaceName={}", vpnName, dpnId, ifaceName);
+        vpnFootprintService.updateVpnToDpnMapping(dpnId, vpnName, ifaceName, false /* removal */);
+    }
+
 
     /**
      * Retrieves the InterVpnLink object searching by its name
index 166c6cc153c76624915215402d6d21b6fa950091..b3e29f0e8ebc37cd6400bba9b880197a248b4b6d 100644 (file)
            interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener" />
   <odl:notification-listener ref="dpnInVpnChangeListener" />
 
+  <bean id="vpnFootprintService" class="org.opendaylight.netvirt.vpnmanager.VpnFootprintService">
+    <argument ref="dataBroker" />
+    <argument ref="fibManager" />
+    <argument ref="odlInterfaceRpcService" />
+    <argument ref="notificationPublishService" />
+  </bean>
+
   <bean id="vpnInterfaceManager"
         class="org.opendaylight.netvirt.vpnmanager.VpnInterfaceManager"
         init-method="start" destroy-method="close">
@@ -56,7 +63,7 @@
     <argument ref="mdsalUtils" />
     <argument ref="fibManager" />
     <argument ref="odlInterfaceRpcService" />
-    <argument ref="notificationPublishService" />
+    <argument ref="vpnFootprintService" />
   </bean>
 
   <bean id="tunnelInterfaceStateListener"
@@ -80,6 +87,7 @@
         init-method="start" destroy-method="close">
     <argument ref="dataBroker" />
     <argument ref="vpnInterfaceManager" />
+    <argument ref="vpnFootprintService" />
   </bean>
 
   <bean id="arpMonitorEventListener"
     <argument ref="vpnInstanceListener" />
     <argument ref="vpnInterfaceManager" />
     <argument ref="mdsalUtils" />
+    <argument ref="vpnFootprintService" />
   </bean>
   <service ref="vpnManagerImpl"
            interface="org.opendaylight.netvirt.vpnmanager.api.IVpnManager" />
     <argument ref="vpnInstanceListener" />
   </bean>
 
-  <bean id="VpnInterfaceOpListener"
-        class="org.opendaylight.netvirt.vpnmanager.VpnInterfaceOpListener"
-        init-method="start" destroy-method="close">
-    <argument ref="dataBroker" />
-    <argument ref="vpnInterfaceManager" />
-  </bean>
-
   <odl:rpc-implementation ref="vpnRpcServiceImpl" />
   <bean id="vpnRpcServiceImpl"
         class="org.opendaylight.netvirt.vpnmanager.VpnRpcServiceImpl">
     <argument ref="bgpmanager" />
     <argument ref="fibManager" />
     <argument ref="notificationPublishService" />
+    <argument ref="vpnFootprintService" />
   </bean>
 
   <bean id="interVpnLinkNodeListener"
         init-method="start" destroy-method="close">
     <argument ref="dataBroker" />
     <argument ref="mdsalUtils" />
+    <argument ref="vpnFootprintService" />
   </bean>
 
   <bean id="tunnelEndPointChangeListener"