BUG 6487: Extra routes to IVpnLink endpoint not in FIB 30/44430/2
authorSuraj Ranjan <suraj.ranjan@ericsson.com>
Sat, 20 Aug 2016 07:34:10 +0000 (13:04 +0530)
committerSam Hague <shague@redhat.com>
Sun, 21 Aug 2016 00:07:15 +0000 (00:07 +0000)
 + LportTag range for InterVpnLink endpoints has changed to a range of
   [170001..270000]. Those values does not fit in a uint16 attribute

 + Also applies a bit of refactoring to reduce the duplication of code
   as much as possible

 + It also aligns the system properties names to the ones defined
   in sdnc repository

 Apart from above bug fix this commit also deals with:

 1> Fixes in metadata writing
 2> InterVpnLink Active even if VPN not exists

Change-Id: Iafe72a651153a7ca48e68748c6b7b271541e835c
Signed-off-by: Suraj Ranjan <suraj.ranjan@ericsson.com>
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/CloudServiceChainConstants.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/utils/ElanServiceChainUtils.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/utils/VpnServiceChainUtils.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java
vpnservice/vpnmanager/vpnmanager-api/src/main/yang/inter-vpn-link.yang
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnConstants.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.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/InterVpnLinkUtil.java

index 6889a080b625a94376dbf72792b11ecef82a8398..101ec8485b682721fa8d31584d5c5e1fd9c80efa 100644 (file)
@@ -29,10 +29,6 @@ public class CloudServiceChainConstants {
     public static final String VPN_PSEUDO_SCF2VPN_FLOWID_PREFIX = "VpnPseudoPort.Scf2Vpn";
     public static final String ELAN_TO_SCF_L2_FLOWID_PREFIX = "ElanPseudoPort.Elan2Scf";
     public static final String SCF_TO_ELAN_L2_FLOWID_PREFIX = "ElanPseudoPort.Scf2Elan";
-    public static final String SCF_L3VPN_IDPOOL_NAME = "l3vpnscf";
-    public static final long SCF_L3VPN_ID_POOL_START = 20000;
-    public static final long SCF_L3VPN_ID_POOL_END = 65535;
-    public static final long ETHERTYPE_IPV4 = 0x0800L;
     public static final long INVALID_VPN_TAG = -1;
 
 }
index 5a319b9749ad33c88fa840affcbace5a91072223..0042d63dfc28fada7230c135689a2c389c325f66 100644 (file)
@@ -83,20 +83,16 @@ public class ElanServiceChainUtils {
         return (BigInteger.valueOf(elanTag)).shiftLeft(24);
     }
 
-    public static BigInteger getElanMetadataMask() {
-        return MetaDataUtil.METADATA_MASK_SERVICE.or(MetaDataUtil.METADATA_MASK_LPORT_TAG);
-    }
-
-
-    /* This flow is in charge of handling packets coming from ExtTunnelTable
+    /**
+     * This flow is in charge of handling packets coming from ExtTunnelTable
      * that must be redirected to the SCF Pipeline.
      *  + Matches on lportTag=ElanPseudoLportTag + SI=1
      *  + Sets scfTag and sends to the DlSubsFilter table.
      *
-     * @param dpnId
-     * @param elanLportTag
-     * @param elanTag
-     * @param addOrRemove
+     * @param dpnId  Dpn Id where the LPortDispatcher table must be modified
+     * @param elanLportTag Dataplane identifier of the ElanPseudoPort
+     * @param elanTag Dataplane identifier of the ELAN
+     * @param addOrRemove  States if flows must be added or removed
      */
     public static void programLPortDispatcherToScf(IMdsalApiManager mdsalManager, BigInteger dpnId, int elanTag,
             int elanLportTag, short tableId, int scfTag, int addOrRemove) {
@@ -128,42 +124,44 @@ public class ElanServiceChainUtils {
         }
     }
 
-    /* This flow is in charge of handling packets coming from the SCF Pipeline
+    /**
+     * This flow is in charge of handling packets coming from the SCF Pipeline
      * when there is no matching ServiceChain.
      *
      *  + Matches on ElanPseudoPortTag and SI=3 (ELAN)
      *  + Sets elanTag and sends to DMAC table
      *
-     * @param dpnId
-     * @param elanLportTag
-     * @param elanTag
-     * @param addOrRemove
+     * @param dpnId Dpn Id where the LPortDispatcher table must be modified
+     * @param elanLportTag Dataplane identifier of the ElanPseudoPort
+     * @param elanTag Dataplane identifier of the ELAN
+     * @param addOrRemove States if flows must be added or removed
      */
     public static void programLPortDispatcherFromScf(IMdsalApiManager mdsalManager, BigInteger dpnId,
-            int elanLportTag, int elanTag, int addOrRemove) {
+                                                     int elanLportTag, int elanTag, int addOrRemove) {
         logger.info("L2-ServiceChaining: programLPortDispatcherFromScf dpId={} elanLportTag={} elanTag={} addOrRemove={} ",
                 dpnId, elanLportTag, elanTag, addOrRemove);
         String flowRef = buildLportDispFromScfFlowRef(elanTag, elanLportTag );
         if (addOrRemove == NwConstants.ADD_FLOW) {
             List<MatchInfo> matches = Arrays.asList(
                     new MatchInfo(MatchFieldType.metadata,
-                                  new BigInteger[] { MetaDataUtil.getMetaDataForLPortDispatcher(elanLportTag,
-                                                                             NwConstants.ELAN_SERVICE_INDEX)
-                                                                  .or(BigInteger.ONE),  // SH FLag
-                                                     MetaDataUtil.getMetaDataMaskForLPortDispatcher()
-                                                                 .or(BigInteger.ONE) })); // Bit mask for SH Flag
+                            new BigInteger[] { MetaDataUtil.getMetaDataForLPortDispatcher(elanLportTag,
+                                    NwConstants.ELAN_SERVICE_INDEX),
+                                    MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
             int instructionKey = 0;
             List<Instruction> instructions = Arrays.asList(
-                    MDSALUtil.buildAndGetWriteMetadaInstruction(ElanServiceChainUtils.getElanMetadataLabel(elanTag),
-                            ElanServiceChainUtils.getElanMetadataMask(),
+                    // BigInter.ONE is for setting also the Split-Horizon flag since it could have been cleared
+                    // while going through the SCF Pipeline
+                    MDSALUtil.buildAndGetWriteMetadaInstruction(getElanMetadataLabel(elanTag).or(BigInteger.ONE),
+                            MetaDataUtil.METADATA_MASK_SERVICE.or(BigInteger.ONE),
                             instructionKey++),
-                    MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_DMAC_TABLE, instructionKey++) );
+                    MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_SMAC_TABLE,
+                            instructionKey++) );
 
-            Flow flow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
-                    CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY,
-                    flowRef, 0, 0,
-                    ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
-                    matches, instructions);
+            Flow flow =
+                    MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+                            CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY,
+                            flowRef, 0, 0, ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
+                            matches, instructions);
             mdsalManager.installFlow(dpnId, flow);
         } else {
             Flow flow = new FlowBuilder().setTableId(NwConstants.LPORT_DISPATCHER_TABLE)
@@ -173,7 +171,8 @@ public class ElanServiceChainUtils {
     }
 
 
-    /* This flow is in charge of receiving packets from the TOR and sending
+    /**
+     *  This flow is in charge of receiving packets from the TOR and sending
      * them to the SCF Pipeline by setting the LportTag of ElanPseudoPort.
      * Note that ELAN already has a flow in this table that redirects packets
      * to the ELAN Pipeline. However, the flow for the SCF Pipeline will have
@@ -181,14 +180,14 @@ public class ElanServiceChainUtils {
      * using this ElanPseudoPort.
      *
      *  + Matches on the VNI
-     *  + Sets the ElanPseudoPort tag in the Metadata and sends to
+     *  + Sets SI=1 and ElanPseudoPort tag in the Metadata and sends to
      *    LPortDispatcher via table 80.
      *
-     * @param dpnId
-     * @param elanLportTag
-     * @param vni
-     * @param elanTag
-     * @param addOrRemove
+     * @param dpnId Dpn Id where the ExtTunnel table must be modified
+     * @param elanLportTag Dataplane identifier of the ElanPseudoPort
+     * @param vni Virtual Network Identifier
+     * @param elanTag Dataplane identifier of the ELAN
+     * @param addOrRemove States if flows must be added or removed
      */
     public static void programExternalTunnelTable(IMdsalApiManager mdsalManager, BigInteger dpnId, int elanLportTag,
             Long vni, int elanTag, int addOrRemove) {
@@ -214,14 +213,16 @@ public class ElanServiceChainUtils {
      * Builds a List of Instructions that set the ElanPseudoPort Tag in
      * metadata and sends to LPortDispatcher table (via Table 80)
      *
-     * @param lportTag LPortTag of the ElanPseudoPort
+     * @param lportTag Dataplane identifier of the ElanPseudoPort
      *
      * @return the List of Instructions
      */
     public static List<Instruction> buildSetLportTagAndGotoLportDispInstructions(long lportTag) {
         int instructionKey = 0;
+        BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher((int) lportTag,
+                NwConstants.SCF_SERVICE_INDEX);
         List<Instruction> result =
-                Arrays.asList(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getLportTagMetaData((int) lportTag),
+                Arrays.asList(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata,
                         MetaDataUtil.getMetaDataMaskForLPortDispatcher(),
                         ++instructionKey),
                         MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_INTERFACE_TABLE, ++instructionKey));
@@ -246,11 +247,11 @@ public class ElanServiceChainUtils {
     /**
      * Stores the relation between elanInstanceName and ElanLport and scfTag.
      *
-     * @param broker
-     * @param elanInstanceName
-     * @param lportTag
-     * @param scfTag
-     * @param addOrRemove
+     * @param broker dataBroker service reference
+     * @param elanInstanceName Name of the ELAN. Typically its UUID
+     * @param lportTag Dataplane identifier of the ElanPseudoPort
+     * @param scfTag Dataplane identifier of the SCF
+     * @param addOrRemove States if flows must be added or removed
      */
     public static void updateElanToLportTagMap(final DataBroker broker, final String elanInstanceName,
                                                 final int lportTag, final int scfTag, final int addOrRemove) {
@@ -273,9 +274,10 @@ public class ElanServiceChainUtils {
     /**
      * Read from ElanToLportTagMap the PsuedoLogicalPort related with a given elan.
      *
-     * @param broker
+     * @param broker dataBroker service reference
      * @param elanInstanceName
-     * @return Optional containing ElanToPseudoPortData
+     * @return the ElanToPseudoPortData object or Optional.absent() if it
+     *     cannot be found
      */
     public static Optional<ElanToPseudoPortData> getElanToLportTagList(final DataBroker broker, final String elanInstanceName) {
         ElanToPseudoPortDataKey key = new ElanToPseudoPortDataKey(elanInstanceName);
index f6dba1d553d192a6cefc89b316e0fd95946e5c04..a725f94c4e0812ed0637c35bf89185dd038c5782 100644 (file)
@@ -433,9 +433,16 @@ public class VpnServiceChainUtils {
                 if ( addOrRemove == NwConstants.ADD_FLOW ) {
                     VpnToPseudoPortTag newValue =
                         new VpnToPseudoPortTagBuilder().setKey(key).setVrfId(rd).setLportTag((long) lportTag).build();
+                    logger.debug("Adding lportTag={} to VpnToLportTag map for VPN with rd={}", lportTag, rd);
                     MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, path, newValue);
                 } else {
-                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, path);
+                    logger.debug("Removing VpnToLportTag map entry for VPN with rd={}", rd);
+                    try {
+                        MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, path);
+                    } catch ( Exception e ) {
+                        // It may throw Exception if 'path' does not exist, but we dont care
+                        logger.debug("Error when removing {}", path, e);
+                    }
                 }
 
             }
index 80f256701bea38e2925c06b17ed3cfeca6d32631..44ed2aba8447f177d280b7b1c42a9acebc405d6c 100644 (file)
@@ -574,7 +574,7 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
                 List<BigInteger> targetDpns =
                         ( vpnIs1stEndpoint ) ? vpnLinkState.get().getFirstEndpointState().getDpId()
                                 : vpnLinkState.get().getSecondEndpointState().getDpId();
-                int lportTag =
+                Long lportTag =
                         ( vpnIs1stEndpoint ) ? vpnLinkState.get().getSecondEndpointState().getLportTag()
                                 : vpnLinkState.get().getFirstEndpointState().getLportTag();
 
@@ -582,7 +582,7 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
                     List<ActionInfo> actionsInfos = Arrays.asList(new ActionInfo(ActionType.pop_mpls, new String[]{}));
 
                     BigInteger[] metadata = new BigInteger[] {
-                            MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
+                            MetaDataUtil.getMetaDataForLPortDispatcher(lportTag.intValue(), ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
                             MetaDataUtil.getMetaDataMaskForLPortDispatcher()
                     };
                     List<InstructionInfo> instructions =
@@ -636,12 +636,12 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
                 vpnIsFirstEndpoint ? interVpnLinkState.get().getFirstEndpointState().getDpId()
                         : interVpnLinkState.get().getSecondEndpointState().getDpId();
 
-        Integer otherEndpointlportTag =
+        Long otherEndpointlportTag =
                 vpnIsFirstEndpoint ? interVpnLinkState.get().getSecondEndpointState().getLportTag()
                         : interVpnLinkState.get().getFirstEndpointState().getLportTag();
 
         BigInteger[] metadata = new BigInteger[] {
-                MetaDataUtil.getMetaDataForLPortDispatcher(otherEndpointlportTag,
+                MetaDataUtil.getMetaDataForLPortDispatcher(otherEndpointlportTag.intValue(),
                         ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
                 MetaDataUtil.getMetaDataMaskForLPortDispatcher()
         };
index ffb32a781dfe5f3c072639add2604b2f5b00a923..14a6b0506c79fcaacc6812059f4a3fdc46994fad 100644 (file)
@@ -45,7 +45,7 @@ module inter-vpn-link {
       }
 
       leaf lport-tag {
-          type uint16;
+          type uint32;
 
       }
   }
index e63dbb33cdf7ae9487ee9dc5531cf8949513e796..237659c711e47bd7fcc3c2fa131bb4f67b34f56d 100644 (file)
@@ -26,12 +26,11 @@ public class VpnConstants {
     public static final int ELAN_GID_MIN = 200000;
 
     // An IdPool for Pseudo LPort tags, that is, lportTags that are no related to an interface.
-    // These lportTags must be higher than 65535 to avoid collision with interface LportTags
-    // TODO: This pool details and creation... should it be located in InterfaceManager?
-    public static final String PSEUDO_LPORT_TAG_ID_POOL_NAME = System.getProperty("lporttag.idpool.name", "lporttag");
-    public static final long LOWER_PSEUDO_LPORT_TAG = Long.getLong("lporttag.range.lower", 170001);
-    // The max value for LPortTag is 1F FF FF => 2097151
-    public static final long UPPER_PSEUDO_LPORT_TAG = Long.getLong("lporttag.range.upper", 2097151);
+    // These lportTags must be higher than 170000 to avoid collision with interface LportTags and
+    // also VPN related IDs (vrfTags and labels)
+    public static final String PSEUDO_LPORT_TAG_ID_POOL_NAME = System.getProperty("lport.gid.name", "lporttag");
+    public static final long LOWER_PSEUDO_LPORT_TAG = Long.getLong("lower.lport.gid", 170001);
+    public static final long UPPER_PSEUDO_LPORT_TAG = Long.getLong("upper.lport.gid", 270000);
 
     public static byte[] EthernetDestination_Broadcast = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
             (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
index 2a17909dd73f7aee732aace3ef5ef4add2697626..44cb63717b577cdbe3349601659308414f79530d 100644 (file)
@@ -31,7 +31,7 @@ public class VpnRpcServiceImpl implements VpnRpcService {
     private final DataBroker dataBroker;
     private final IdManagerService idManager;
     private final VpnInterfaceManager vpnInterfaceMgr;
-    private final IFibManager fibManager;
+    private IFibManager fibManager;
 
     public VpnRpcServiceImpl(final DataBroker dataBroker, final IdManagerService idManager,
                              final VpnInterfaceManager vpnIfaceMgr, final IFibManager fibManager) {
@@ -41,6 +41,11 @@ public class VpnRpcServiceImpl implements VpnRpcService {
         this.fibManager = fibManager;
     }
 
+    public void setFibManager(IFibManager fibMgr) {
+        this.fibManager = fibMgr;
+    }
+
+
     /**
      * to generate label for the given ip prefix from the associated VPN
      *
index 9b6c282bd52233d27d512c244d257e67b7e23ecb..324e89ce643bb6f6e7caac3a092c058fdbc3f24b 100644 (file)
@@ -274,7 +274,7 @@ public class VpnUtil {
     }
 
     //FIXME: Implement caches for DS reads
-    static VpnInstance getVpnInstance(DataBroker broker, String vpnInstanceName) {
+    public static VpnInstance getVpnInstance(DataBroker broker, String vpnInstanceName) {
         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
                 new VpnInstanceKey(vpnInstanceName)).build();
         Optional<VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
index 38d3de3dd9e6902c6a2daf0b47b4880a19646bf1..60f17bf2cfdf58fa4f643f78b6172532bbbcc614 100644 (file)
@@ -71,7 +71,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
     private final IBgpManager bgpManager;
     private final NotificationPublishService notificationsService;
     private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
-    private static final int INVALID_ID = 0;
+    private static final long INVALID_ID = 0;
 
     public InterVpnLinkListener(final DataBroker dataBroker, final IdManagerService idManager,
                                 final IMdsalApiManager mdsalManager, final IBgpManager bgpManager,
@@ -110,6 +110,10 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
     @Override
     protected void add(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink add) {
 
+        LOG.debug("Reacting to IVpnLink {} creation. Vpn1=[name={}  EndpointIp={}]  Vpn2=[name={} endpointIP={}]",
+                add.getName(), add.getFirstEndpoint().getVpnUuid(), add.getFirstEndpoint().getIpAddress(),
+                add.getSecondEndpoint().getVpnUuid(), add.getSecondEndpoint().getIpAddress());
+
         int numberOfDpns = Integer.getInteger(NBR_OF_DPNS_PROPERTY_NAME, 1);
         // Create VpnLink state
         InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(add.getName());
@@ -120,19 +124,29 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
         Uuid firstEndpointVpnUuid = add.getFirstEndpoint().getVpnUuid();
         Uuid secondEndpointVpnUuid = add.getSecondEndpoint().getVpnUuid();
         // First VPN
+        if ( VpnUtil.getVpnInstance(this.dataBroker, firstEndpointVpnUuid.getValue()) == null ) {
+            String errMsg = "InterVpnLink " + add.getName() + " creation error: could not find 1st endpoint Vpn "
+                    + firstEndpointVpnUuid.getValue();
+            setInError(vpnLinkStateIid, vpnLinkState, errMsg);
+            return;
+        }
         if (!checkVpnAvailability(key, firstEndpointVpnUuid)) {
-            String errMsg = String.format("Vpn already associated with a previous inter-vpn-link {}",
-                                          firstEndpointVpnUuid);
-            LOG.error(errMsg);
+            String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + firstEndpointVpnUuid.getValue()
+                    + " is already associated to an inter-vpn-link ";
             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
             return;
         }
 
         // Second VPN
+        if ( VpnUtil.getVpnInstance(this.dataBroker, secondEndpointVpnUuid.getValue()) == null ) {
+            String errMsg = "InterVpnLink " + add.getName() + " creation error: could not find 2nd endpoint Vpn "
+                    + secondEndpointVpnUuid.getValue();
+            setInError(vpnLinkStateIid, vpnLinkState, errMsg);
+            return;
+        }
         if (!checkVpnAvailability(key, secondEndpointVpnUuid)) {
-            String errMsg = String.format("Vpn already associated with a previous inter-vpn-link {}",
-                                          secondEndpointVpnUuid);
-            LOG.error(errMsg);
+            String errMsg = "InterVpnLink " + add.getName() + " creation error: Vpn " + secondEndpointVpnUuid.getValue()
+                    + " is already associated with an inter-vpn-link";
             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
             return;
         }
@@ -144,8 +158,8 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
             // List<BigInteger> secondDpnList = VpnUtil.pickRandomDPNs(dataBroker, numberOfDpns, firstDpnList);
             List<BigInteger> secondDpnList = firstDpnList;
 
-            Integer firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
-            Integer secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
+            Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
+            Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
             FirstEndpointState firstEndPointState =
                 new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid).setDpId(firstDpnList)
                                                .setLportTag(firstVpnLportTag).build();
@@ -174,8 +188,8 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
         } 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.
-            Integer firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
-            Integer secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
+            Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
+            Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
             FirstEndpointState firstEndPointState =
                 new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid)
                                                .setLportTag(firstVpnLportTag).build();
@@ -216,9 +230,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
             leakRoutes(vpnLink, vpn1Uuid, vpn2Uuid, originsToConsider);
 
             // 2nd Endpoint ==> 1st endpoint
-            leakRoutes(vpnLink, vpnLink.getSecondEndpoint().getVpnUuid().getValue(),
-                       vpnLink.getFirstEndpoint().getVpnUuid().getValue(),
-                       originsToConsider);
+            leakRoutes(vpnLink, vpn2Uuid, vpn1Uuid, originsToConsider);
         }
 
         // Static routes in Vpn1 pointing to Vpn2's endpoint
@@ -289,6 +301,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
     @Override
     protected void remove(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink del) {
 
+        LOG.debug("Reacting to InterVpnLink {} removal", del.getName());
         // Remove learnt routes
         // Remove entries in the LPortDispatcher table
         // Remove the corresponding entries in InterVpnLinkState
@@ -296,46 +309,27 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
         // For each endpoint, remove all routes that have been learnt by intervpnLink
         String vpn1Uuid = del.getFirstEndpoint().getVpnUuid().getValue();
         String rd1 = VpnUtil.getVpnRdFromVpnInstanceConfig(dataBroker, vpn1Uuid);
+        LOG.debug("Removing leaked routes in VPN {}  rd={}", vpn1Uuid, rd1);
         VpnUtil.removeVrfEntriesByOrigin(dataBroker, rd1, RouteOrigin.INTERVPN);
         VpnUtil.removeVrfEntriesByNexthop(dataBroker, rd1, del.getSecondEndpoint().getIpAddress().getValue());
 
         String vpn2Uuid = del.getSecondEndpoint().getVpnUuid().getValue();
         String rd2 = VpnUtil.getVpnRdFromVpnInstanceConfig(dataBroker, vpn2Uuid);
+        LOG.debug("Removing leaked routes in VPN {}  rd={}", vpn2Uuid, rd2);
         VpnUtil.removeVrfEntriesByOrigin(dataBroker, rd2, RouteOrigin.INTERVPN);
         VpnUtil.removeVrfEntriesByNexthop(dataBroker, rd2, del.getFirstEndpoint().getIpAddress().getValue());
 
         InterVpnLinkState interVpnLinkState = VpnUtil.getInterVpnLinkState(dataBroker, del.getName());
-        Integer firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
-
-        Integer secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
-
-        // Remmoving the flow entries in LPortDispatcher table in 1st Endpoint DPNs
-        for ( BigInteger dpnId : interVpnLinkState.getFirstEndpointState().getDpId() ) {
-            String flowRef = InterVpnLinkUtil.getLportDispatcherFlowRef(del.getName(), secondEndpointLportTag);
-            FlowKey flowKey = new FlowKey(new FlowId(flowRef));
-            Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
-                                         .setTableId(NwConstants.LPORT_DISPATCHER_TABLE).setFlowName(flowRef)
-                                         .build();
-            mdsalManager.removeFlow(dpnId, flow);
-
-            // Also remove the 'fake' iface from the VpnToDpn map
-            VpnUtil.removeIfaceFromVpnToDpnMap(dataBroker, rd1, dpnId, getInterVpnLinkIfaceName(vpn1Uuid, dpnId));
-        }
-
-        // Removing the flow entries in 2nd Endpoint DPNs
-        for ( BigInteger dpnId : interVpnLinkState.getSecondEndpointState().getDpId() ) {
-            String flowRef = InterVpnLinkUtil.getLportDispatcherFlowRef(del.getName(), firstEndpointLportTag);
-            FlowKey flowKey = new FlowKey(new FlowId(flowRef));
-            Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
-                                         .setTableId(NwConstants.LPORT_DISPATCHER_TABLE).setFlowName(flowRef)
-                                         .build();
-            mdsalManager.removeFlow(dpnId, flow);
-
-            // Also remove the 'fake' iface from the VpnToDpn map
-            VpnUtil.removeIfaceFromVpnToDpnMap(dataBroker, rd2, dpnId, getInterVpnLinkIfaceName(vpn2Uuid, dpnId));
-        }
-
-        // Release idManager wit LPortTag associated to endpoints
+        Long firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
+        Long secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
+        removeVpnLinkEndpointFlows(del.getName(), rd1, vpn1Uuid, interVpnLinkState.getFirstEndpointState().getDpId(),
+                secondEndpointLportTag.intValue(),
+                del.getSecondEndpoint().getIpAddress().getValue());
+        removeVpnLinkEndpointFlows(del.getName(), rd2, vpn2Uuid, interVpnLinkState.getSecondEndpointState().getDpId(),
+                firstEndpointLportTag.intValue(), del.getFirstEndpoint().getIpAddress().getValue());
+
+        // Release idManager with LPortTag associated to endpoints
+        LOG.debug("Releasing InterVpnLink {} endpoints LportTags", del.getName());
         InterVpnLinkKey key = del.getKey();
         Uuid firstEndpointVpnUuid = del.getFirstEndpoint().getVpnUuid();
         Uuid secondEndpointVpnUuid = del.getSecondEndpoint().getVpnUuid();
@@ -347,21 +341,50 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
         // At this point. we need to check if is there any entry in FIB table pointing to LPortDispatcher table.
         // Remove it in that case.
 
-        // 1stEndPoint dpns
-        for ( BigInteger dpnId : interVpnLinkState.getFirstEndpointState().getDpId() ) {
-            removeRouteFromInterVpnLink(dpnId, del.getName(), del.getSecondEndpoint().getIpAddress().getValue());
-        }
-
-        // 2ndtEndPoint dpns
-        for ( BigInteger dpnId : interVpnLinkState.getSecondEndpointState().getDpId() ) {
-            removeRouteFromInterVpnLink(dpnId, del.getName(), del.getFirstEndpoint().getIpAddress().getValue());
-        }
-
         // Removing the InterVpnLinkState
         InstanceIdentifier<InterVpnLinkState> interVpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(del.getName());
         VpnUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
     }
 
+    private void removeVpnLinkEndpointFlows( String interVpnLinkName, String rd, String vpnUuid, List<BigInteger> dpns,
+                                             int otherEndpointLportTag, String otherEndpointIpAddr ) {
+        LOG.debug("Removing endpoint flows for vpn {}.  InterVpnLink={}.  OtherEndpointLportTag={}",
+                vpnUuid, interVpnLinkName, otherEndpointLportTag);
+        if ( dpns == null ) {
+            LOG.debug("VPN {} endpoint is not instantiated in any DPN for InterVpnLink {}",
+                    vpnUuid, interVpnLinkName);
+            return;
+        }
+
+        for ( BigInteger dpnId : dpns ) {
+            try {
+                // Removing flow from LportDispatcher table
+                String flowRef = InterVpnLinkUtil.getLportDispatcherFlowRef(interVpnLinkName, otherEndpointLportTag);
+                FlowKey flowKey = new FlowKey(new FlowId(flowRef));
+                Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
+                        .setTableId(NwConstants.LPORT_DISPATCHER_TABLE).setFlowName(flowRef)
+                        .build();
+                mdsalManager.removeFlow(dpnId, flow);
+
+                // Removing flow from Fib table
+                String fibFlowRef = getInterVpnFibFlowRef(dpnId, NwConstants.L3_FIB_TABLE, interVpnLinkName,
+                        otherEndpointIpAddr);
+                FlowKey fibFlowKey = new FlowKey(new FlowId(fibFlowRef));
+                Flow fibFlow = new FlowBuilder().setKey(fibFlowKey).setId(new FlowId(fibFlowRef))
+                        .setTableId(NwConstants.L3_FIB_TABLE).setFlowName(fibFlowRef).build();
+                mdsalManager.removeFlow(dpnId, fibFlow);
+
+                // Also remove the 'fake' iface from the VpnToDpn map
+                VpnUtil.removeIfaceFromVpnToDpnMap(dataBroker, rd, dpnId, getInterVpnLinkIfaceName(vpnUuid, dpnId));
+
+            } catch ( Exception e ) {
+                // Whatever happens it should not stop it from trying to remove as much as possible
+                LOG.warn("Error while removing InterVpnLink {} Endpoint flows on dpn {}. Reason: {}",
+                        interVpnLinkName, dpnId, e);
+            }
+        }
+    }
+
     private void releaseVpnLinkLPortTag(String idKey) {
         ReleaseIdInput releaseIdInput =
                 new ReleaseIdInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME).setIdKey(idKey).build();
@@ -373,24 +396,15 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
      // TODO
     }
 
-    private String getInterVpnFibFlowRef(BigInteger dpnId, short tableId, String interVpnLinkName, String nextHop ) {
-        return new StringBuilder(64).append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
-            .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
-            .append(interVpnLinkName).append(NwConstants.FLOWID_SEPARATOR)
-            .append(nextHop).toString();
+    private String getInterVpnFibFlowRef(BigInteger dpnId, short tableId, String interVpnLinkName,  String nextHop ) {
+        return new StringBuilder(64).append(VpnConstants.FLOWID_PREFIX).append(dpnId)
+                .append(NwConstants.FLOWID_SEPARATOR).append(tableId)
+                .append(NwConstants.FLOWID_SEPARATOR).append(interVpnLinkName)
+                .append(NwConstants.FLOWID_SEPARATOR).append(nextHop)
+                .toString();
     }
 
-    private void removeRouteFromInterVpnLink(BigInteger dpnId, String interVpnLinkName, final String nextHop) {
-        String flowRef = getInterVpnFibFlowRef(dpnId, NwConstants.L3_FIB_TABLE, interVpnLinkName, nextHop);
-        FlowKey flowKey = new FlowKey(new FlowId(flowRef));
-        Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
-                .setTableId(NwConstants.L3_FIB_TABLE).setFlowName(flowRef)
-                .build();
-        mdsalManager.removeFlow(dpnId, flow);
-    }
-
-
-    private Integer allocateVpnLinkLportTag(String idKey) {
+    private Long allocateVpnLinkLportTag(String idKey) {
         AllocateIdInput getIdInput =
                 new AllocateIdInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME)
                         .setIdKey(idKey)
@@ -399,7 +413,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
             RpcResult<AllocateIdOutput> rpcResult = result.get();
             if (rpcResult.isSuccessful()) {
-                return rpcResult.getResult().getIdValue().intValue();
+                return rpcResult.getResult().getIdValue();
             } else {
                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
             }
@@ -412,6 +426,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
     protected void setInError(final InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid,
                               final InterVpnLinkState vpnLinkState,
                               String errorMsg) {
+        LOG.error("Setting InterVpnLink {} in error. Reason: {}", vpnLinkState.getInterVpnLinkName(), errorMsg);
         // Setting InterVPNLink in error state in MDSAL
         InterVpnLinkState vpnLinkErrorState =
             new InterVpnLinkStateBuilder(vpnLinkState).setState(InterVpnLinkState.State.Error)
index 6a6db38c3e716fef62d9edb616163f4b12765d53..711bb463ebf71ffb2b196f4e541e9267269e9cb4 100644 (file)
@@ -121,11 +121,12 @@ public class InterVpnLinkUtil {
      */
     public static void installLPortDispatcherTableFlow(DataBroker broker, IMdsalApiManager mdsalManager,
                                                        InterVpnLink interVpnLink, List<BigInteger> dpnList,
-                                                       Uuid vpnUuidOtherEndpoint, Integer lPortTagOfOtherEndpoint) {
+                                                       Uuid vpnUuidOtherEndpoint, Long lPortTagOfOtherEndpoint) {
         long vpnId = VpnUtil.getVpnId(broker, vpnUuidOtherEndpoint.getValue());
         for ( BigInteger dpnId : dpnList ) {
             // insert into LPortDispatcher table
-            Flow lPortDispatcherFlow = buildLPortDispatcherFlow(interVpnLink.getName(), vpnId, lPortTagOfOtherEndpoint);
+            Flow lPortDispatcherFlow = buildLPortDispatcherFlow(interVpnLink.getName(), vpnId,
+                    lPortTagOfOtherEndpoint.intValue());
             mdsalManager.installFlow(dpnId, lPortDispatcherFlow);
         }
     }
@@ -139,7 +140,7 @@ public class InterVpnLinkUtil {
     * @param lportTag DataPlane identifier of the LogicalPort.
     * @return the Flow ready to be installed
     */
-   public static Flow buildLPortDispatcherFlow(String interVpnLinkName, long vpnId, Integer lportTag) {
+   public static Flow buildLPortDispatcherFlow(String interVpnLinkName, long vpnId, int lportTag) {
        LOG.info("Inter-vpn-link : buildLPortDispatcherFlow. vpnId {}   lportTag {} ", vpnId, lportTag);
        List<MatchInfo> matches = Arrays.asList(new MatchInfo(MatchFieldType.metadata,
                                                               new BigInteger[] {