Support for multiple route paths 10/49010/29
authorKency Kurian <kency.kurian@ericsson.com>
Wed, 8 Feb 2017 06:03:02 +0000 (11:33 +0530)
committerSam Hague <shague@redhat.com>
Fri, 24 Feb 2017 21:49:02 +0000 (21:49 +0000)
- Modified odl-fib.yang to support multiple route-paths for the same
  destination prefix.
- Added a FibHelper which provides util methods to construct VrfEntry.

Change-Id: I7bcd3b77ac452476b4190286c1f3e8815a1b8819
Signed-off-by: Kency Kurian <kency.kurian@ericsson.com>
19 files changed:
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpConfigurationManager.java
vpnservice/bgpmanager/bgpmanager-impl/src/main/java/org/opendaylight/netvirt/bgpmanager/FibDSWriter.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/listeners/VrfListener.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/main/java/org/opendaylight/netvirt/cloudservicechain/utils/VpnServiceChainUtils.java
vpnservice/cloud-servicechain/cloud-servicechain-impl/src/test/java/org/opendaylight/netvirt/cloudservicechain/VPNServiceChainHandlerTest.java
vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/FibHelper.java [new file with mode: 0644]
vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/IFibManager.java
vpnservice/fibmanager/fibmanager-api/src/main/yang/odl-fib.yang
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibConstants.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibManagerImpl.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/FibUtil.java
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java
vpnservice/fibmanager/fibmanager-impl/src/test/java/org/opendaylight/netvirt/fibmanager/test/FibManagerTest.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/FibEntriesListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/TunnelInterfaceStateListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.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/InterVpnLinkUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/populator/impl/L3vpnOverMplsGrePopulator.java

index a18b96ce56af19a4651ff211a14256885299bbce..d2ac14f919b361db13b3f6489f4a8b97915644b0 100755 (executable)
@@ -1992,9 +1992,12 @@ public class BgpConfigurationManager {
                         }
                         totalStaledCount++;
                         //Create MAP from staleVrfTables.
-                        for (String nextHop : vrfEntry.getNextHopAddressList()) {
-                            staleFibEntMap.put(vrfEntry.getDestPrefix(), nextHop + "/" + vrfEntry.getLabel());
-                        }
+                        vrfEntry.getRoutePaths()
+                                .forEach(
+                                    routePath -> staleFibEntMap.put(
+                                            vrfEntry.getDestPrefix(),
+                                            routePath.getNexthopAddress() + "/"
+                                                    + routePath.getLabel()));
                     }
                     staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
                 }
index 22c18830552a4123dd8f4d7b5418b30a6fb0f376..378de64b750cc60baa8d10b22d3c7eddcff9ca40 100644 (file)
@@ -8,9 +8,13 @@
 package org.opendaylight.netvirt.bgpmanager;
 
 import com.google.common.base.Preconditions;
+
 import java.util.List;
+import java.util.stream.Collectors;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 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;
@@ -18,6 +22,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePaths;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
@@ -40,7 +45,6 @@ public class FibDSWriter {
         }
 
         Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
-
         for (String nextHop : nextHopList) {
             if (nextHop == null || nextHop.isEmpty()) {
                 LOG.error("nextHop list contains null element");
@@ -56,20 +60,27 @@ public class FibDSWriter {
                         .child(VrfTables.class, new VrfTablesKey(rd))
                         .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
 
-        VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix)
-                .setNextHopAddressList(nextHopList).setLabel((long)label).setOrigin(origin.getValue());
-        buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, (long)label, l3vni, macAddress, gatewayMacAddress);
-        BgpUtil.write(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
+        VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
+        buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, (long)label, l3vni, macAddress,
+                gatewayMacAddress, nextHopList);
+        BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
     }
 
-    private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder, VrfEntry.EncapType encapType, long label,
-                                                  long l3vni, String macAddress, String gatewayMac) {
-        if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
-            builder.setLabel(label);
-        } else {
-            builder.setL3vni(l3vni).setGatewayMacAddress(gatewayMac);
+    private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder,
+            VrfEntry.EncapType encapType, long label, long l3vni, String macAddress,
+            String gatewayMac, List<String> nextHopList) {
+        if (!encapType.equals(VrfEntry.EncapType.Mplsgre)) {
+            builder.setL3vni(l3vni);
         }
         builder.setEncapType(encapType);
+        builder.setGatewayMacAddress(gatewayMac);
+        Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
+        List<RoutePaths> routePaths = nextHopList.stream()
+                        .filter(nextHop -> nextHop != null && !nextHop.isEmpty())
+                        .map(nextHop -> {
+                            return FibHelper.buildRoutePath(nextHop, lbl);
+                        }).collect(Collectors.toList());
+        builder.setRoutePaths(routePaths);
     }
 
     public synchronized void removeFibEntryFromDS(String rd, String prefix) {
index 902e588180fd74fa0742ebcc8acc93045208d021..4ef2620d0b9ad95a3f25bfd9984038f0b2b82b62 100644 (file)
@@ -8,10 +8,12 @@
 package org.opendaylight.netvirt.cloudservicechain.listeners;
 
 import com.google.common.base.Optional;
+
 import java.math.BigInteger;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Objects;
+import java.util.List;
+import java.util.stream.Collectors;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
@@ -79,18 +81,19 @@ public class VrfListener extends AbstractDataChangeListener<VrfEntry> implements
 
     @Override
     protected void remove(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntryDeleted) {
-        LOG.debug("VrfEntry removed: id={}  vrfEntry=[ destination={}, nexthops=[{}],  label={} ]",
-                  identifier, vrfEntryDeleted.getDestPrefix(), vrfEntryDeleted.getNextHopAddressList(),
-                  vrfEntryDeleted.getLabel());
+        LOG.debug("VrfEntry removed: id={}  vrfEntry=[ destination={}, route-paths=[{}]]",
+                  identifier, vrfEntryDeleted.getDestPrefix(), vrfEntryDeleted.getRoutePaths());
         String vpnRd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
         programLabelInAllVpnDpns(vpnRd, vrfEntryDeleted, NwConstants.DEL_FLOW);
     }
 
     @Override
     protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
-        LOG.debug("VrfEntry updated: id={}  vrfEntry=[ destination={}, nexthops=[{}],  label={} ]",
-                  identifier, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
-        if (!Objects.equals(original.getLabel(), update.getLabel())) {
+        LOG.debug("VrfEntry updated: id={}  vrfEntry=[ destination={}, route-paths=[{}]]",
+                  identifier, update.getDestPrefix(), update.getRoutePaths());
+        List<Long> originalLabels = getUniqueLabelList(original);
+        List<Long> updateLabels = getUniqueLabelList(update);
+        if (!updateLabels.equals(originalLabels)) {
             remove(identifier, original);
             add(identifier, update);
         }
@@ -98,9 +101,8 @@ public class VrfListener extends AbstractDataChangeListener<VrfEntry> implements
 
     @Override
     protected void add(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntryAdded) {
-        LOG.debug("VrfEntry added: id={}  vrfEntry=[ destination={}, nexthops=[{}],  label={} ]",
-                  identifier, vrfEntryAdded.getDestPrefix(), vrfEntryAdded.getNextHopAddressList(),
-                  vrfEntryAdded.getLabel());
+        LOG.debug("VrfEntry added: id={}  vrfEntry=[ destination={}, route-paths=[{}]]",
+                  identifier, vrfEntryAdded.getDestPrefix(), vrfEntryAdded.getRoutePaths());
         String vpnRd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
         programLabelInAllVpnDpns(vpnRd, vrfEntryAdded, NwConstants.ADD_FLOW);
     }
@@ -132,4 +134,9 @@ public class VrfListener extends AbstractDataChangeListener<VrfEntry> implements
                                                           (int) vpnPseudoLPortTag.longValue(), addOrRemove);
         }
     }
+
+    private List<Long> getUniqueLabelList(VrfEntry original) {
+        return original.getRoutePaths().stream().map(routePath -> routePath.getLabel()).distinct()
+                .sorted().collect(Collectors.toList());
+    }
 }
index b73d9e4883b189fc8242220f051320c2679783ba..8b428f2cb5243d2a2ae8ff26e37198eed146e0d1 100755 (executable)
@@ -342,21 +342,28 @@ public class VpnServiceChainUtils {
      *
      */
     public static void programLFibEntriesForSCF(IMdsalApiManager mdsalMgr, BigInteger dpId, List<VrfEntry> vrfEntries,
-                                                int lportTag, int addOrRemove) {
-        for (VrfEntry vrfEntry : vrfEntries) {
-            Long label = vrfEntry.getLabel();
-            for (String nexthop : vrfEntry.getNextHopAddressList()) {
-                FlowEntity flowEntity = buildLFibVpnPseudoPortFlow(dpId, label, nexthop, lportTag);
-                if (addOrRemove == NwConstants.ADD_FLOW) {
-                    mdsalMgr.installFlow(flowEntity);
-                } else {
-                    mdsalMgr.removeFlow(flowEntity);
-                }
-                LOG.debug("LFIB Entry for label={}, destination={}, nexthop={} {} successfully in dpn={}",
-                          label, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(),
-                          addOrRemove == NwConstants.DEL_FLOW ? "removed" : "installed", dpId);
-            }
-        }
+            int lportTag, int addOrRemove) {
+        java.util.Optional.ofNullable(vrfEntries).ifPresent(entries -> {
+            entries.stream()
+                    .forEach(vrfEntry -> vrfEntry.getRoutePaths()
+                            .stream()
+                            .forEach(routePath -> {
+                                Long label = routePath.getLabel();
+                                String nextHop = routePath.getNexthopAddress();
+                                FlowEntity flowEntity =
+                                        buildLFibVpnPseudoPortFlow(dpId, label, nextHop, lportTag);
+                                if (addOrRemove == NwConstants.ADD_FLOW) {
+                                    mdsalMgr.installFlow(flowEntity);
+                                } else {
+                                    mdsalMgr.removeFlow(flowEntity);
+                                }
+                                LOG.debug(
+                                        "LFIBEntry for label={}, destination={}, nexthop={} {} successfully in dpn={}",
+                                        label, vrfEntry.getDestPrefix(), nextHop,
+                                        addOrRemove == NwConstants.DEL_FLOW ? "removed"
+                                                : "installed", dpId);
+                            }));
+        });
     }
 
     /**
index be2e20b1ea97d4bc6eb4b8bce3b7621d50f2ce07..9bdab2eeda13e98773ead1577e6b6357900b40ab 100755 (executable)
@@ -18,10 +18,12 @@ 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;
 import java.util.stream.Collectors;
+
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.TypeSafeMatcher;
@@ -47,6 +49,8 @@ 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.fibmanager.api.FibHelper;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 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.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
@@ -55,8 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePaths;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
@@ -194,12 +197,6 @@ public class VPNServiceChainHandlerTest {
                          eq(VpnServiceChainUtils.getVpnInstanceOpDataIdentifier(rd)))).thenReturn(chkdFuture);
     }
 
-
-    private VrfEntry buildVrfEntry(long label, String prefix, String nextop) {
-        return new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix).setLabel(label)
-                                    .setNextHopAddressList(Collections.singletonList(nextop)).build();
-    }
-
     private void stubGetVrfEntries(String rd, List<VrfEntry> vrfEntryList)
         throws Exception {
 
@@ -302,7 +299,8 @@ public class VPNServiceChainHandlerTest {
         /////////////////////
         stubGetRouteDistinguisher(VPN_NAME, RD);
         stubGetVpnInstance(RD, "1.2.3.4", "eth0");
-        stubGetVrfEntries(RD, Collections.singletonList(buildVrfEntry(2000L, "11.12.13.14", DC_GW_IP)));
+        VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder("11.12.13.14", 2000L, DC_GW_IP, RouteOrigin.STATIC).build();
+        stubGetVrfEntries(RD, Collections.singletonList(vrfEntry));
         stubReadVpnToDpnList(RD, DPN_ID, Collections.singletonList("iface1"));
         /////////
         // SUT //
@@ -339,7 +337,7 @@ public class VPNServiceChainHandlerTest {
         String ifaceName = "eth0";
         stubGetRouteDistinguisher(VPN_NAME, RD);
         stubGetVpnInstance(RD, "1.2.3.4", ifaceName);
-        VrfEntry vrfEntry = buildVrfEntry(2000L, "11.12.13.14", DC_GW_IP);
+        VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder("11.12.13.14", 2000L, DC_GW_IP, RouteOrigin.STATIC).build();
         stubGetVrfEntries(RD, Collections.singletonList(vrfEntry));
         stubReadVpnToDpnList(RD, DPN_ID, Collections.singletonList(ifaceName));
         stubScfIsBoundOnIface(SCF_TAG, ifaceName);
@@ -358,9 +356,10 @@ public class VPNServiceChainHandlerTest {
         List<FlowEntity> installedFlowsCaptured = argumentCaptor.getAllValues();
         assert (installedFlowsCaptured.size() == 2);
 
+        RoutePaths routePath = vrfEntry.getRoutePaths().get(0);
         FlowEntity expectedLFibFlowEntity =
-            VpnServiceChainUtils.buildLFibVpnPseudoPortFlow(DPN_ID, vrfEntry.getLabel(),
-                                                            vrfEntry.getNextHopAddressList().get(0), LPORT_TAG);
+            VpnServiceChainUtils.buildLFibVpnPseudoPortFlow(DPN_ID, routePath.getLabel(),
+                    routePath.getNexthopAddress(), LPORT_TAG);
         assert (new FlowEntityMatcher(expectedLFibFlowEntity).matches(installedFlowsCaptured.get(0)));
 
         FlowEntity expectedLPortDispatcher =
@@ -378,7 +377,7 @@ public class VPNServiceChainHandlerTest {
         String ifaceName = "eth0";
         stubGetRouteDistinguisher(VPN_NAME, RD);
         stubGetVpnInstance(RD, "1.2.3.4", ifaceName);
-        VrfEntry vrfEntry = buildVrfEntry(2000L, "11.12.13.14", DC_GW_IP);
+        VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder("11.12.13.14", 2000L, DC_GW_IP, RouteOrigin.STATIC).build();
         stubGetVrfEntries(RD, Collections.singletonList(vrfEntry));
         stubReadVpnToDpnList(RD, DPN_ID, Collections.singletonList(ifaceName));
         stubScfIsNotBoundOnIface(SCF_TAG, ifaceName);
@@ -398,9 +397,10 @@ public class VPNServiceChainHandlerTest {
         List<FlowEntity> installedFlowsCaptured = argumentCaptor.getAllValues();
         assert (installedFlowsCaptured.size() == 2);
 
+        RoutePaths routePath = vrfEntry.getRoutePaths().get(0);
         FlowEntity expectedLFibFlowEntity =
-            VpnServiceChainUtils.buildLFibVpnPseudoPortFlow(DPN_ID, vrfEntry.getLabel(),
-                                                            vrfEntry.getNextHopAddressList().get(0), LPORT_TAG);
+            VpnServiceChainUtils.buildLFibVpnPseudoPortFlow(DPN_ID, routePath.getLabel(),
+                    routePath.getNexthopAddress(), LPORT_TAG);
         assert (new FlowEntityMatcher(expectedLFibFlowEntity).matches(installedFlowsCaptured.get(0)));
 
         FlowEntity expectedLPortDispatcher =
diff --git a/vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/FibHelper.java b/vpnservice/fibmanager/fibmanager-api/src/main/java/org/opendaylight/netvirt/fibmanager/api/FibHelper.java
new file mode 100644 (file)
index 0000000..c40d429
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 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.fibmanager.api;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePaths;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePathsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePathsKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+
+public class FibHelper {
+
+    public static RoutePaths buildRoutePath(String nextHop, Long label) {
+        return Optional.ofNullable(label).map(lbl -> {
+            return new RoutePathsBuilder().setKey(new RoutePathsKey(nextHop)).setLabel(lbl)
+                    .setNexthopAddress(nextHop).build();
+        }).orElseGet(() -> {
+            return new RoutePathsBuilder().setKey(new RoutePathsKey(nextHop))
+                    .setNexthopAddress(nextHop).build();
+        });
+    }
+
+    public static VrfEntryBuilder getVrfEntryBuilder(String prefix, List<RoutePaths> routePaths,
+            RouteOrigin origin) {
+        return new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
+                .setRoutePaths(routePaths).setOrigin(origin.getValue());
+    }
+
+    public static VrfEntryBuilder getVrfEntryBuilder(String prefix, long label, String nextHop, RouteOrigin origin) {
+        RoutePaths routePath = buildRoutePath(nextHop, label);
+        return getVrfEntryBuilder(prefix, Arrays.asList(routePath), origin);
+    }
+
+    public static VrfEntryBuilder getVrfEntryBuilder(VrfEntry vrfEntry, long label,
+            List<String> nextHopList, RouteOrigin origin) {
+        List<RoutePaths> routePaths =
+                nextHopList.stream().map(nextHop -> buildRoutePath(nextHop, label))
+                        .collect(Collectors.toList());
+        return getVrfEntryBuilder(vrfEntry.getDestPrefix(), routePaths, origin);
+    }
+
+    public static InstanceIdentifier<RoutePaths> buildRoutePathId(String rd, String prefix, String nextHop) {
+        InstanceIdentifierBuilder<RoutePaths> idBuilder =
+                InstanceIdentifier.builder(FibEntries.class)
+                        .child(VrfTables.class, new VrfTablesKey(rd))
+                        .child(VrfEntry.class, new VrfEntryKey(prefix))
+                        .child(RoutePaths.class, new RoutePathsKey(nextHop));
+        return idBuilder.build();
+    }
+}
\ No newline at end of file
index 65ae54112cf1fc5da9f8a8fac57e6e218cb190e1..2de386c710088d3fcdabaec194e20670a04164d6 100644 (file)
@@ -61,10 +61,11 @@ public interface IFibManager {
                                 long vpnId,
                                 String rd,
                                 String destPrefix,
-                                String destTepIp);
+                                String destTepIp,
+                                long label);
 
     void addOrUpdateFibEntry(DataBroker broker, String rd, String macAddress, String prefix, List<String> nextHopList,
-                             VrfEntry.EncapType encapType, int label, long l3vni, String gwMacAddress,
+                             VrfEntry.EncapType encapType, long label, long l3vni, String gwMacAddress,
                              RouteOrigin origin, WriteTransaction writeConfigTxn);
 
     void addFibEntryForRouterInterface(DataBroker broker, String rd, String prefix,
@@ -76,7 +77,7 @@ public interface IFibManager {
     void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn);
 
     void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                        String gwMacAddress, WriteTransaction writeConfigTxn);
+                        String gwMacAddress, long label, WriteTransaction writeConfigTxn);
 
     void addVrfTable(DataBroker broker, String rd, WriteTransaction writeConfigTxn);
 
index 7735cc3c0589230511554aa0dd35e32697d5eea2..33b32f798e302d0c01032dffe7b7febe10908a21 100644 (file)
@@ -23,13 +23,6 @@ module odl-fib {
                 type string;
                 mandatory true;
             }
-            leaf label {
-                type uint32;
-            }
-            leaf-list nextHopAddressList {
-                type string;
-                min-elements "1";
-            }
             leaf origin {
                 type string;
                 mandatory true;
@@ -37,7 +30,7 @@ module odl-fib {
             leaf encap-type {
                description
                   "This flag indicates how to interpret the existing label field.
-                   A value of mplsgre indicates that the label will continue to be considered as an MPLS Label.
+                   A value of mplsgre indicates that the label within route paths will continue to be considered as an MPLS Label.
                    A value of vxlan indicates that l3vni should be used to advertise to bgp and label will be ignored.";
 
                type enumeration {
@@ -59,6 +52,15 @@ module odl-fib {
             leaf gateway_mac_address {
                type string;
             }
+            list route-paths {
+                key "nexthop-address";
+                leaf nexthop-address {
+                    type string;
+                }
+                leaf label {
+                    type uint32;
+                }
+            }
         }
     }
 
index f67fdf126bfa83eae2bed83b2090d91f06df443b..5418f580b9fd121bceb47f3f46d4342cb0f68ae7 100644 (file)
@@ -16,4 +16,5 @@ public class FibConstants {
     static final String FLOWID_PREFIX = "L3.";
     static final String VPN_IDPOOL_NAME = "vpnservices";
     static final String SEPARATOR = ".";
+    static final String DEFAULT_NEXTHOP_IP = "0.0.0.0";
 }
index a95d8b5a48fe8bbe6ecccc7c978fd1c1c68b2441..86fcdd0e7f84e708d18457f6e3b8ff6e6cdec641 100755 (executable)
@@ -142,13 +142,14 @@ public class FibManagerImpl implements IFibManager {
                                        long vpnId,
                                        String rd,
                                        String destPrefix,
-                                       String destTepIp) {
-        vrfEntryListener.manageRemoteRouteOnDPN(action, dpnId, vpnId, rd, destPrefix, destTepIp);
+                                       String destTepIp,
+                                       long label) {
+        vrfEntryListener.manageRemoteRouteOnDPN(action, dpnId, vpnId, rd, destPrefix, destTepIp, label);
     }
 
     @Override
     public void addOrUpdateFibEntry(DataBroker broker, String rd, String macAddress, String prefix,
-                                    List<String> nextHopList, VrfEntry.EncapType encapType, int label,
+                                    List<String> nextHopList, VrfEntry.EncapType encapType, long label,
                                     long l3vni, String gwMacAddress, RouteOrigin origin,
                                     WriteTransaction writeConfigTxn) {
         FibUtil.addOrUpdateFibEntry(broker, rd, macAddress, prefix , nextHopList, encapType, label, l3vni,
@@ -174,8 +175,8 @@ public class FibManagerImpl implements IFibManager {
     }
 
     public void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                               String gwMacAddress, WriteTransaction writeConfigTxn) {
-        FibUtil.updateFibEntry(broker, rd, prefix, nextHopList, gwMacAddress, writeConfigTxn);
+                               String gwMacAddress, long label, WriteTransaction writeConfigTxn) {
+        FibUtil.updateFibEntry(broker, rd, prefix, nextHopList, gwMacAddress, label, writeConfigTxn);
     }
 
     @Override
index f37e7732e3299b965d2471c288b244bf3917a4cb..9b12915ba4087cd0289166668c76ee1752953d73 100644 (file)
@@ -13,18 +13,22 @@ import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 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.MDSALUtil;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
@@ -41,6 +45,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePaths;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
@@ -353,7 +358,7 @@ public class FibUtil {
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     public static void addOrUpdateFibEntry(DataBroker broker, String rd, String macAddress, String prefix,
-                                           List<String> nextHopList, VrfEntry.EncapType encapType, int label,
+                                           List<String> nextHopList, VrfEntry.EncapType encapType, long label,
                                            long l3vni, String gwMacAddress, RouteOrigin origin,
                                            WriteTransaction writeConfigTxn) {
         if (rd == null || rd.isEmpty()) {
@@ -368,23 +373,10 @@ public class FibUtil {
                 InstanceIdentifier.builder(FibEntries.class)
                     .child(VrfTables.class, new VrfTablesKey(rd))
                     .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
-            Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-
-            if (! entry.isPresent()) {
-                writeFibEntryToDs(vrfEntryId, prefix, nextHopList, label, l3vni, encapType, origin, macAddress,
-                        gwMacAddress, writeConfigTxn, broker);
-                LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHopList, label);
-            } else { // Found in MDSAL database
-                List<String> nh = entry.get().getNextHopAddressList();
-                for (String nextHop : nextHopList) {
-                    if (!nh.contains(nextHop)) {
-                        nh.add(nextHop);
-                    }
-                }
-                writeFibEntryToDs(vrfEntryId, prefix, nh, label, l3vni, encapType, origin, macAddress,
-                        gwMacAddress, writeConfigTxn, broker);
-                LOG.debug("Updated vrfEntry for {} nexthop {} label {}", prefix, nh, label);
-            }
+
+            writeFibEntryToDs(vrfEntryId, prefix, nextHopList, label, l3vni, encapType, origin, macAddress,
+                    gwMacAddress, writeConfigTxn, broker);
+            LOG.debug("Created/Updated vrfEntry for {} nexthop {} label {}", prefix, nextHopList, label);
         } catch (Exception e) {
             LOG.error("addFibEntryToDS: error ", e);
         }
@@ -397,9 +389,8 @@ public class FibUtil {
                                          VrfEntry.EncapType encapType, RouteOrigin origin, String macAddress,
                                          String gatewayMacAddress, WriteTransaction writeConfigTxn,
                                          DataBroker broker) {
-        VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nextHopList)
-                .setOrigin(origin.getValue());
-        buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress, gatewayMacAddress);
+        VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
+        buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress, gatewayMacAddress, nextHopList);
         if (writeConfigTxn != null) {
             writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build(), true);
         } else {
@@ -425,10 +416,9 @@ public class FibUtil {
                     .child(VrfTables.class, new VrfTablesKey(rd))
                     .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
 
-            VrfEntry vrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
-                .setNextHopAddressList(Collections.singletonList(""))
-                .setLabel(label)
-                .setOrigin(RouteOrigin.LOCAL.getValue())
+            // Filling the nextHop with dummy nextHopAddress
+            VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label,
+                    FibConstants.DEFAULT_NEXTHOP_IP, RouteOrigin.LOCAL)
                 .addAugmentation(RouterInterface.class, routerInterface).build();
 
             if (writeConfigTxn != null) {
@@ -443,13 +433,19 @@ public class FibUtil {
     }
 
     private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder, VrfEntry.EncapType encapType, long label,
-                                                 long l3vni, String macAddress, String gatewayMac) {
-        if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
-            builder.setLabel(label);
-        } else {
-            builder.setL3vni(l3vni).setGatewayMacAddress(gatewayMac);
+                                         long l3vni, String macAddress, String gatewayMac, List<String> nextHopList) {
+        if (!encapType.equals(VrfEntry.EncapType.Mplsgre)) {
+            builder.setL3vni(l3vni);
         }
         builder.setEncapType(encapType);
+        builder.setGatewayMacAddress(gatewayMac);
+        Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
+        List<RoutePaths> routePaths = nextHopList.stream()
+                        .filter(nextHop -> nextHop != null && !nextHop.isEmpty())
+                        .map(nextHop -> {
+                            return FibHelper.buildRoutePath(nextHop, lbl);
+                        }).collect(Collectors.toList());
+        builder.setRoutePaths(routePaths);
     }
 
     public static void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn) {
@@ -493,15 +489,21 @@ public class FibUtil {
         Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
 
         if (entry.isPresent()) {
-            List<String> nhListRead = new ArrayList<>();
-            if (nextHopToRemove != null && !nextHopToRemove.isEmpty()) {
-                nhListRead = entry.get().getNextHopAddressList();
-                if (nhListRead.contains(nextHopToRemove)) {
-                    nhListRead.remove(nextHopToRemove);
-                }
+            final List<RoutePaths> routePaths = entry.get().getRoutePaths();
+            if (routePaths == null || routePaths.isEmpty()) {
+                LOG.warn("routePaths is null/empty for given rd {}, prefix {}", rd, prefix);
+                return;
             }
-
-            if (nhListRead.isEmpty()) {
+            java.util.Optional<RoutePaths> optRoutePath =
+                    routePaths.stream()
+                              .filter(routePath -> routePath.getNexthopAddress().equals(
+                                    nextHopToRemove)).findFirst();
+            if (!optRoutePath.isPresent()) {
+                LOG.error("Unable to find a routePath that contains the given nextHop to remove {}", nextHopToRemove);
+                return;
+            }
+            RoutePaths routePath = optRoutePath.get();
+            if (routePaths.size() == 1) {
                 // Remove the whole entry
                 if (writeConfigTxn != null) {
                     writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
@@ -510,16 +512,16 @@ public class FibUtil {
                 }
                 LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
             } else {
-                // An update must be done, not including the current next hop
-                VrfEntry vrfEntry =
-                    new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
-                        .setKey(new VrfEntryKey(prefix)).build();
+                InstanceIdentifier<RoutePaths> routePathsId =
+                        FibHelper.buildRoutePathId(rd, prefix, routePath.getNexthopAddress());
+                // Remove route
                 if (writeConfigTxn != null) {
-                    writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
+                    writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, routePathsId);
                 } else {
-                    MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+                    MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routePathsId);
                 }
-                LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
+                LOG.info("Removed Route Path rd {} prefix {}, nextHop {}, label {}", rd, prefix,
+                        routePath.getNexthopAddress(), routePath.getLabel());
             }
         } else {
             LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
@@ -527,7 +529,7 @@ public class FibUtil {
     }
 
     public static void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
-                                      String gwMacAddress, WriteTransaction writeConfigTxn) {
+                                      String gwMacAddress, long label, WriteTransaction writeConfigTxn) {
 
         LOG.debug("Updating fib entry for prefix {} with nextHopList {} for rd {}", prefix, nextHopList, rd);
 
@@ -538,10 +540,11 @@ public class FibUtil {
         Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
 
         if (entry.isPresent()) {
+            RouteOrigin routeOrigin = RouteOrigin.value(entry.get().getOrigin());
             // Update the VRF entry with nextHopList
-            VrfEntry vrfEntry =
-                new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nextHopList)
-                    .setGatewayMacAddress(gwMacAddress).setKey(new VrfEntryKey(prefix)).build();
+            VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(entry.get(), label, nextHopList, routeOrigin)
+                    .setGatewayMacAddress(gwMacAddress).build();
+
             if (nextHopList.isEmpty()) {
                 if (writeConfigTxn != null) {
                     writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
@@ -602,4 +605,30 @@ public class FibUtil {
             || routeOrigin == RouteOrigin.CONNECTED
             || routeOrigin == RouteOrigin.LOCAL;
     }
+
+    public static List<String> getNextHopListFromRoutePaths(final VrfEntry vrfEntry) {
+        List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+        if (routePaths == null || routePaths.isEmpty()) {
+            return Collections.EMPTY_LIST;
+        }
+        return routePaths.stream()
+                .map(routePath -> routePath.getNexthopAddress())
+                .collect(Collectors.toList());
+    }
+
+    public static java.util.Optional<Long> getLabelFromRoutePaths(final VrfEntry vrfEntry) {
+        List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+        if (routePaths == null || routePaths.isEmpty()) {
+            return java.util.Optional.empty();
+        }
+        return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getLabel());
+    }
+
+    public static java.util.Optional<String> getFirstNextHopAddress(final VrfEntry vrfEntry) {
+        List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+        if (routePaths == null || routePaths.isEmpty()) {
+            return java.util.Optional.empty();
+        }
+        return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getNexthopAddress());
+    }
 }
index 777f180b59009a87b32cf9616c0eced93eef9463..65f2d8001b46e64373a5d2d59e606b6066b26f47 100755 (executable)
@@ -27,6 +27,8 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
@@ -74,6 +76,7 @@ import org.opendaylight.genius.utils.batching.ResourceHandler;
 import org.opendaylight.genius.utils.batching.SubTransaction;
 import org.opendaylight.genius.utils.batching.SubTransactionImpl;
 import org.opendaylight.netvirt.fibmanager.NexthopManager.AdjacencyResult;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
@@ -110,8 +113,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePaths;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
@@ -212,8 +215,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
     protected void add(final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
         Preconditions.checkNotNull(vrfEntry, "VrfEntry should not be null or empty.");
         String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
-        LOG.debug("ADD: Adding Fib Entry rd {} prefix {} nexthop {} label {}",
-            rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
+        LOG.debug("ADD: Adding Fib Entry rd {} prefix {} route-paths {}",
+            rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
         if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
             createFibEntries(identifier, vrfEntry);
         } else {
@@ -224,16 +227,16 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             vrfEntryBufferQ.add(actResource);
         }
         leakRouteIfNeeded(identifier, vrfEntry, NwConstants.ADD_FLOW);
-        LOG.info("ADD: Added Fib Entry rd {} prefix {} nexthop {} label {}",
-            rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
+        LOG.info("ADD: Added Fib Entry rd {} prefix {} route-paths {}",
+            rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
     }
 
     @Override
     protected void remove(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry) {
         Preconditions.checkNotNull(vrfEntry, "VrfEntry should not be null or empty.");
         String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
-        LOG.debug("REMOVE: Removing Fib Entry rd {} prefix {} nexthop {} label {}",
-            rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
+        LOG.debug("REMOVE: Removing Fib Entry rd {} prefix {} route-paths {}",
+            rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
         if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
             deleteFibEntries(identifier, vrfEntry);
         } else {
@@ -244,8 +247,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             vrfEntryBufferQ.add(actResource);
         }
         leakRouteIfNeeded(identifier, vrfEntry, NwConstants.DEL_FLOW);
-        LOG.info("REMOVE: Removed Fib Entry rd {} prefix {} nexthop {} label {}",
-            rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
+        LOG.info("REMOVE: Removed Fib Entry rd {} prefix {} route-paths {}",
+            rd, vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths());
     }
 
     @Override
@@ -254,8 +257,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
 
         final String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
         final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
-        LOG.debug("UPDATE: Updating Fib Entries to rd {} prefix {} nexthop {} label {}",
-            rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
+        LOG.debug("UPDATE: Updating Fib Entries to rd {} prefix {} route-paths {}",
+            rd, update.getDestPrefix(), update.getRoutePaths());
         // Handle BGP Routes first
         if (RouteOrigin.value(update.getOrigin()) == RouteOrigin.BGP) {
             ActionableResource actResource = new ActionableResourceImpl(rd + update.getDestPrefix());
@@ -264,8 +267,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             actResource.setInstance(update);
             actResource.setOldInstance(original);
             vrfEntryBufferQ.add(actResource);
-            LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} nexthop {} label {}",
-                rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
+            LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} route-paths {}",
+                rd, update.getDestPrefix(), update.getRoutePaths());
             return;
         }
 
@@ -274,15 +277,15 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             SubnetRoute subnetRoute = update.getAugmentation(SubnetRoute.class);
             /* Ignore SubnetRoute entry, as it will be driven by createFibEntries call down below */
             if (subnetRoute == null) {
-                List<String> origNhList = original.getNextHopAddressList();
-                List<String> updateNhList = update.getNextHopAddressList();
+                List<RoutePaths> originalRoutePath = original.getRoutePaths();
+                List<RoutePaths> updateRoutePath = update.getRoutePaths();
                 //final SubnetRoute subnetRoute = update.getAugmentation(SubnetRoute.class);
-                LOG.info("UPDATE: Original nexthop {} updateNextHop {} ", origNhList, updateNhList);
+                LOG.info("UPDATE: Original route-path {} update route-path {} ", originalRoutePath, updateRoutePath);
 
                 // If original VRF Entry had nexthop null , but update VRF Entry
                 // has nexthop , route needs to be created on remote Dpns
-                if (((origNhList == null) || (origNhList.isEmpty())
-                    && (updateNhList != null) && (!updateNhList.isEmpty()))) {
+                if (((originalRoutePath == null) || (originalRoutePath.isEmpty())
+                    && (updateRoutePath != null) && (!updateRoutePath.isEmpty()))) {
                     // TODO(vivek): Though ugly, Not handling this code now, as each
                     // tep add event will invoke flow addition
                     LOG.trace("Original VRF entry NH is null for destprefix {}. This event is IGNORED here.",
@@ -292,24 +295,24 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
 
                 // If original VRF Entry had valid nexthop , but update VRF Entry
                 // has nexthop empty'ed out, route needs to be removed from remote Dpns
-                if (((updateNhList == null) || (updateNhList.isEmpty())
-                    && (origNhList != null) && (!origNhList.isEmpty()))) {
+                if (((updateRoutePath == null) || (updateRoutePath.isEmpty())
+                    && (originalRoutePath != null) && (!originalRoutePath.isEmpty()))) {
                     LOG.trace("Original VRF entry had valid NH for destprefix {}. This event is IGNORED here.",
                         update.getDestPrefix());
                     return;
                 }
             }
             createFibEntries(identifier, update);
-            LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} nexthop {} label {}",
-                rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
+            LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} route-paths {}",
+                rd, update.getDestPrefix(), update.getRoutePaths());
             return;
         }
 
         /* Handl all other route origins */
         createFibEntries(identifier, update);
 
-        LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} nexthop {} label {}",
-            rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
+        LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} route-paths {}",
+            rd, update.getDestPrefix(), update.getRoutePaths());
     }
 
     @Override
@@ -421,13 +424,14 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             if (optInterVpnLink.isPresent()) {
                 InterVpnLinkDataComposite interVpnLink = optInterVpnLink.get();
                 String vpnUuid = optVpnUuid.get();
-                String routeNexthop = vrfEntry.getNextHopAddressList().get(0);
-                if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
-                    // This is an static route that points to the other endpoint of an InterVpnLink
-                    // In that case, we should add another entry in FIB table pointing to LPortDispatcher table.
-                    installIVpnLinkSwitchingFlows(interVpnLink, vpnUuid, vrfEntry, vpnId);
-                    installInterVpnRouteInLFib(rd, vrfEntry);
-                }
+                FibUtil.getFirstNextHopAddress(vrfEntry).ifPresent(routeNexthop -> {
+                    if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
+                        // This is an static route that points to the other endpoint of an InterVpnLink
+                        // In that case, we should add another entry in FIB table pointing to LPortDispatcher table.
+                        installIVpnLinkSwitchingFlows(interVpnLink, vpnUuid, vrfEntry, vpnId);
+                        installInterVpnRouteInLFib(rd, vrfEntry);
+                    }
+                });
             }
         }
     }
@@ -465,8 +469,10 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
 
         String prefix = vrfEntry.getDestPrefix();
-        List<String> nextHopsList = vrfEntry.getNextHopAddressList();
-        Long label = vrfEntry.getLabel();
+        List<String> nextHopsList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+        // Label is used only for logging in subsequent method calls.
+        //TODO : This label is not needed here. Can be removed. Hence using a default value.
+        Long label = FibUtil.getLabelFromRoutePaths(vrfEntry).orElse(0L);
         String rd = vrfTableKey.getRouteDistinguisher();
         LOG.trace("leakRouteIfNeeded: srcVpnRd={}  prefix={}  nhList={}  label={}", rd, prefix, nextHopsList, label);
 
@@ -517,25 +523,27 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             wrTxPresent = false;
             tx = dataBroker.newWriteOnlyTransaction();
         }
-        synchronized (vrfEntry.getLabel().toString().intern()) {
-            LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-            if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
+        FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
+            List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+            synchronized (label.toString().intern()) {
+                LabelRouteInfo lri = getLabelRouteInfo(label);
+                if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
 
-                if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
-                    Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
-                        FibUtil.getVpnInstanceOpData(dataBroker, rd);
-                    if (vpnInstanceOpDataEntryOptional.isPresent()) {
-                        String vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
-                        if (!lri.getVpnInstanceList().contains(vpnInstanceName)) {
-                            updateVpnReferencesInLri(lri, vpnInstanceName, false);
+                    if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
+                        Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
+                                FibUtil.getVpnInstanceOpData(dataBroker, rd);
+                        if (vpnInstanceOpDataEntryOptional.isPresent()) {
+                            String vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
+                            if (!lri.getVpnInstanceList().contains(vpnInstanceName)) {
+                                updateVpnReferencesInLri(lri, vpnInstanceName, false);
+                            }
                         }
                     }
+                    LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
+                            label, lri.getVpnInterfaceName(), lri.getDpnId());
                 }
-                LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
-                    vrfEntry.getLabel(), lri.getVpnInterfaceName(), lri.getDpnId());
             }
-        }
+        });
         final List<InstructionInfo> instructions = new ArrayList<>();
         BigInteger subnetRouteMeta = ((BigInteger.valueOf(elanTag)).shiftLeft(32))
             .or((BigInteger.valueOf(vpnId).shiftLeft(1)));
@@ -543,19 +551,21 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         instructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
         makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
 
-        if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
-            List<ActionInfo> actionsInfos = new ArrayList<>();
-            // reinitialize instructions list for LFIB Table
-            final List<InstructionInfo> LFIBinstructions = new ArrayList<>();
-
-            actionsInfos.add(new ActionPopMpls());
-            LFIBinstructions.add(new InstructionApplyActions(actionsInfos));
-            LFIBinstructions.add(new InstructionWriteMetadata(subnetRouteMeta,
-                MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
-            LFIBinstructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
-
-            makeLFibTableEntry(dpnId, vrfEntry.getLabel(), LFIBinstructions, DEFAULT_FIB_FLOW_PRIORITY,
-                NwConstants.ADD_FLOW, tx);
+        for (RoutePaths routePath : vrfEntry.getRoutePaths()) {
+            if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
+                List<ActionInfo> actionsInfos = new ArrayList<>();
+                // reinitialize instructions list for LFIB Table
+                final List<InstructionInfo> LFIBinstructions = new ArrayList<>();
+
+                actionsInfos.add(new ActionPopMpls());
+                LFIBinstructions.add(new InstructionApplyActions(actionsInfos));
+                LFIBinstructions.add(new InstructionWriteMetadata(subnetRouteMeta,
+                        MetaDataUtil.METADATA_MASK_SUBNET_ROUTE));
+                LFIBinstructions.add(new InstructionGotoTable(NwConstants.L3_SUBNET_ROUTE_TABLE));
+
+                makeLFibTableEntry(dpnId, routePath.getLabel(), LFIBinstructions, DEFAULT_FIB_FLOW_PRIORITY,
+                        NwConstants.ADD_FLOW, tx);
+            }
         }
         if (!wrTxPresent) {
             tx.submit();
@@ -615,13 +625,16 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                                 MetaDataUtil.getMetaDataMaskForLPortDispatcher()),
                             new InstructionGotoTable(NwConstants.L3_INTERFACE_TABLE));
 
-                    LOG.debug("Installing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for "
-                        + "InterVpnLink {} in LFIB",
-                        vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(),
-                        dpId, interVpnLink.getName());
+                    FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(interVpnRoutePathLabel -> {
+                        List<String> interVpnNextHopList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+                        LOG.debug("Installing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for "
+                                + "InterVpnLink {} in LFIB",
+                                vrfEntry.getDestPrefix(), interVpnRoutePathLabel, interVpnNextHopList,
+                                dpId, interVpnLink.getName());
 
-                    makeLFibTableEntry(dpId, vrfEntry.getLabel(), instructions, LFIB_INTERVPN_PRIORITY,
-                        NwConstants.ADD_FLOW, null);
+                        makeLFibTableEntry(dpId, interVpnRoutePathLabel, instructions, LFIB_INTERVPN_PRIORITY,
+                                NwConstants.ADD_FLOW, null);
+                    });
                 }
 
                 break;
@@ -629,9 +642,9 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         }
 
         if (!interVpnLinkFound) {
-            LOG.warn("VrfEntry=[prefix={} label={} nexthop={}] for VPN {} has origin INTERVPN but "
+            LOG.warn("VrfEntry=[prefix={} route-paths={}] for VPN {} has origin INTERVPN but "
                 + "no InterVpnLink could be found",
-                vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), rd);
+                vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), rd);
         }
     }
 
@@ -642,10 +655,10 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
     private void installIVpnLinkSwitchingFlows(final InterVpnLinkDataComposite interVpnLink, final String vpnUuid,
                                                final VrfEntry vrfEntry, long vpnTag) {
         Preconditions.checkNotNull(interVpnLink, "InterVpnLink cannot be null");
-        Preconditions.checkArgument(vrfEntry.getNextHopAddressList() != null
-            && vrfEntry.getNextHopAddressList().size() == 1);
+        Preconditions.checkArgument(vrfEntry.getRoutePaths() != null
+            && vrfEntry.getRoutePaths().size() == 1);
         String destination = vrfEntry.getDestPrefix();
-        String nextHop = vrfEntry.getNextHopAddressList().get(0);
+        String nextHop = vrfEntry.getRoutePaths().get(0).getNexthopAddress();
         String interVpnLinkName = interVpnLink.getInterVpnLinkName();
 
         // After having received a static route, we should check if the vpn is part of an inter-vpn-link.
@@ -701,8 +714,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
 
         for (BigInteger dpId : targetDpns) {
 
-            LOG.debug("Installing flow: VrfEntry=[prefix={} label={} nextHop={}] dpn {} for InterVpnLink {} in FIB",
-                vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(),
+            LOG.debug("Installing flow: VrfEntry=[prefix={} route-paths={}] dpn {} for InterVpnLink {} in FIB",
+                vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(),
                 dpId, interVpnLink.getInterVpnLinkName());
 
             mdsalManager.installFlow(dpId, flowEntity);
@@ -774,29 +787,33 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             }
             if (localNextHopInfo == null) {
             /* imported routes case */
-                synchronized (vrfEntry.getLabel().toString().intern()) {
-                    LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-                    if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                        && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
-                        if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
-                            Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
-                                FibUtil.getVpnInstanceOpData(dataBroker, rd);
-                            if (vpnInstanceOpDataEntryOptional.isPresent()) {
-                                String vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
-                                if (lri.getVpnInstanceList().contains(vpnInstanceName)) {
-                                    localNextHopInfo = updateVpnReferencesInLri(lri, vpnInstanceName, true);
-                                    localNextHopIP = lri.getPrefix();
-                                } else {
-                                    localNextHopInfo = updateVpnReferencesInLri(lri, vpnInstanceName, false);
-                                    localNextHopIP = lri.getPrefix();
+                if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
+                    java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+                    if (optionalLabel.isPresent()) {
+                        Long label = optionalLabel.get();
+                        List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+                        synchronized (label.toString().intern()) {
+                            LabelRouteInfo lri = getLabelRouteInfo(label);
+                            if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
+                                Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
+                                        FibUtil.getVpnInstanceOpData(dataBroker, rd);
+                                if (vpnInstanceOpDataEntryOptional.isPresent()) {
+                                    String vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
+                                    if (lri.getVpnInstanceList().contains(vpnInstanceName)) {
+                                        localNextHopInfo = updateVpnReferencesInLri(lri, vpnInstanceName, true);
+                                        localNextHopIP = lri.getPrefix();
+                                    } else {
+                                        localNextHopInfo = updateVpnReferencesInLri(lri, vpnInstanceName, false);
+                                        localNextHopIP = lri.getPrefix();
+                                    }
+                                }
+                                if (localNextHopInfo != null) {
+                                    LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
+                                            label, localNextHopInfo.getVpnInterfaceName(), lri.getDpnId());
+                                    BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfo, localNextHopIP,
+                                            vpnId, rd, vrfEntry, lri.getParentVpnid());
+                                    returnLocalDpnId.add(dpnId);
                                 }
-                            }
-                            if (localNextHopInfo != null) {
-                                LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
-                                    vrfEntry.getLabel(), localNextHopInfo.getVpnInterfaceName(), lri.getDpnId());
-                                BigInteger dpnId = checkCreateLocalFibEntry(localNextHopInfo, localNextHopIP,
-                                    vpnId, rd, vrfEntry, lri.getParentVpnid());
-                                returnLocalDpnId.add(dpnId);
                             }
                         }
                     }
@@ -840,25 +857,28 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             final List<InstructionInfo> lfibinstructions = Collections.singletonList(
                 new InstructionApplyActions(
                     Arrays.asList(new ActionPopMpls(), new ActionGroup(groupId))));
+            java.util.Optional<Long> optLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+            List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
             if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
                 LOG.debug("Installing tunnel table entry on dpn {} for interface {} with label {}",
-                    dpnId, localNextHopInfo.getVpnInterfaceName(), vrfEntry.getLabel());
+                    dpnId, localNextHopInfo.getVpnInterfaceName(), optLabel);
             } else {
                 LOG.debug("Route with rd {} prefix {} label {} nexthop {} for vpn {} is an imported route. "
                     + "LFib and Terminating table entries will not be created.",
-                    rd, vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpnId);
+                    rd, vrfEntry.getDestPrefix(), optLabel, nextHopAddressList, vpnId);
             }
             DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
             dataStoreCoordinator.enqueueJob("FIB-" + vpnId.toString()
-                    + "-" + dpnId.toString() + "-" + vrfEntry.getDestPrefix(),
-                () -> {
+                    + "-" + dpnId.toString() + "-" + vrfEntry.getDestPrefix(), () -> {
                     WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
                     makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx);
-                    if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
-                        makeLFibTableEntry(dpnId, vrfEntry.getLabel(), lfibinstructions,
-                            DEFAULT_FIB_FLOW_PRIORITY, NwConstants.ADD_FLOW, tx);
-                        makeTunnelTableEntry(dpnId, vrfEntry.getLabel(), groupId, tx);
-                    }
+                    optLabel.ifPresent(label -> {
+                        if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
+                            makeLFibTableEntry(dpnId, label, lfibinstructions,
+                                    DEFAULT_FIB_FLOW_PRIORITY, NwConstants.ADD_FLOW, tx);
+                            makeTunnelTableEntry(dpnId, label, groupId, tx);
+                        }
+                    });
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
                     futures.add(tx.submit());
                     return futures;
@@ -1000,16 +1020,20 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             }
 
             if (localNextHopInfo == null) {
-              /* Imported VRF entry */
-                LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-                if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                    && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
-                    VpnNexthopBuilder vpnNexthopBuilder = new VpnNexthopBuilder();
-                    vpnNexthopBuilder.setDpnId(lri.getDpnId());
-                    BigInteger dpnId = checkDeleteLocalFibEntry(vpnNexthopBuilder.build(), localNextHopIP,
-                        vpnId, rd, vrfEntry, false /*isExtraRoute*/);
-                    if (!dpnId.equals(BigInteger.ZERO)) {
-                        returnLocalDpnId.add(dpnId);
+                /* Imported VRF entry */
+                java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+                if (optionalLabel.isPresent()) {
+                    Long label = optionalLabel.get();
+                    List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+                    LabelRouteInfo lri = getLabelRouteInfo(label);
+                    if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
+                        VpnNexthopBuilder vpnNexthopBuilder = new VpnNexthopBuilder();
+                        vpnNexthopBuilder.setDpnId(lri.getDpnId());
+                        BigInteger dpnId = checkDeleteLocalFibEntry(vpnNexthopBuilder.build(), localNextHopIP,
+                                vpnId, rd, vrfEntry, false /*isExtraRoute*/);
+                        if (!dpnId.equals(BigInteger.ZERO)) {
+                            returnLocalDpnId.add(dpnId);
+                        }
                     }
                 }
             }
@@ -1038,9 +1062,11 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                     makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null /* instructions */,
                         NwConstants.DEL_FLOW, tx);
                     if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
-                        makeLFibTableEntry(dpnId, vrfEntry.getLabel(), null /* instructions */,
-                            DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx);
-                        removeTunnelTableEntry(dpnId, vrfEntry.getLabel(), tx);
+                        FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
+                            makeLFibTableEntry(dpnId, label, null /* instructions */,
+                                    DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx);
+                            removeTunnelTableEntry(dpnId, label, tx);
+                        });
                     }
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
                     futures.add(tx.submit());
@@ -1101,8 +1127,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
 
         List<AdjacencyResult> adjacencyResults = resolveAdjacency(remoteDpnId, vpnId, vrfEntry, rd);
         if (adjacencyResults.isEmpty()) {
-            LOG.error("Could not get interface for nexthop: {} in vpn {}",
-                vrfEntry.getNextHopAddressList(), rd);
+            LOG.error("Could not get interface for route-paths: {} in vpn {}",
+                vrfEntry.getRoutePaths(), rd);
             LOG.warn("Failed to add Route: {} in vpn: {}",
                 vrfEntry.getDestPrefix(), rd);
             return;
@@ -1119,9 +1145,9 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             List<ActionInfo> egressActions = nextHopManager.getEgressActionsForInterface(egressInterface,
                     actionInfos.size());
             if (egressActions.isEmpty()) {
-                LOG.error("Failed to retrieve egress action for prefix {} nextHop {} interface {}. "
+                LOG.error("Failed to retrieve egress action for prefix {} route-paths {} interface {}. "
                     + "Aborting remote FIB entry creation.",
-                    vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), egressInterface);
+                    vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), egressInterface);
                 return;
             }
             actionInfos.addAll(egressActions);
@@ -1161,13 +1187,18 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
     private void addTunnelInterfaceActions(String tunnelInterface, long vpnId, VrfEntry vrfEntry,
                                            List<ActionInfo> actionInfos) {
         Class<? extends TunnelTypeBase> tunnelType = getTunnelType(tunnelInterface);
+        java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+        if (!optionalLabel.isPresent()) {
+            LOG.warn("RoutePaths not available");
+            return;
+        }
+        long label = optionalLabel.get();
         if (tunnelType.equals(TunnelTypeMplsOverGre.class)) {
             LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
             actionInfos.add(new ActionPushMpls());
-            actionInfos.add(new ActionSetFieldMplsLabel(vrfEntry.getLabel()));
+            actionInfos.add(new ActionSetFieldMplsLabel(label));
             actionInfos.add(new ActionNxLoadInPort(BigInteger.ZERO));
         } else {
-            int label = vrfEntry.getLabel().intValue();
             BigInteger tunnelId;
             // FIXME vxlan vni bit set is not working properly with OVS.need to
             // revisit
@@ -1230,17 +1261,21 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                 }
             }
             if (prefixInfo == null) {
-                LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-                if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                    && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
-                    PrefixesBuilder prefixBuilder = new PrefixesBuilder();
-                    prefixBuilder.setDpnId(lri.getDpnId());
-                    prefixBuilder.setVpnInterfaceName(lri.getVpnInterfaceName());
-                    prefixBuilder.setIpAddress(lri.getPrefix());
-                    prefixInfo = prefixBuilder.build();
-                    LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
-                        vrfEntry.getLabel(), prefixInfo.getVpnInterfaceName(), lri.getDpnId());
-                    checkCleanUpOpDataForFib(prefixInfo, vpnId, rd, vrfEntry, extraRoute);
+                java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+                if (optionalLabel.isPresent()) {
+                    Long label = optionalLabel.get();
+                    List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+                    LabelRouteInfo lri = getLabelRouteInfo(label);
+                    if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
+                        PrefixesBuilder prefixBuilder = new PrefixesBuilder();
+                        prefixBuilder.setDpnId(lri.getDpnId());
+                        prefixBuilder.setVpnInterfaceName(lri.getVpnInterfaceName());
+                        prefixBuilder.setIpAddress(lri.getPrefix());
+                        prefixInfo = prefixBuilder.build();
+                        LOG.debug("Fetched labelRouteInfo for label {} interface {} and got dpn {}",
+                                label, prefixInfo.getVpnInterfaceName(), lri.getDpnId());
+                        checkCleanUpOpDataForFib(prefixInfo, vpnId, rd, vrfEntry, extraRoute);
+                    }
                 }
             }
         } else {
@@ -1291,27 +1326,30 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
 
             //First Cleanup LabelRouteInfo
-            synchronized (vrfEntry.getLabel().toString().intern()) {
-                LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-                if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                    && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
-                    Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
-                        FibUtil.getVpnInstanceOpData(dataBroker, rd);
-                    String vpnInstanceName = "";
-                    if (vpnInstanceOpDataEntryOptional.isPresent()) {
-                        vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
-                    }
-                    boolean lriRemoved = deleteLabelRouteInfo(lri, vpnInstanceName, writeOperTxn);
-                    if (lriRemoved) {
-                        String parentRd = lri.getParentVpnRd();
+            FibUtil.getLabelFromRoutePaths(vrfEntry).ifPresent(label -> {
+                List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+                synchronized (label.toString().intern()) {
+                    LabelRouteInfo lri = getLabelRouteInfo(label);
+                    if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
+                            && nextHopAddressList.contains(lri.getNextHopIpList().get(0))) {
+                        Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
+                                FibUtil.getVpnInstanceOpData(dataBroker, rd);
+                        String vpnInstanceName = "";
+                        if (vpnInstanceOpDataEntryOptional.isPresent()) {
+                            vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
+                        }
+                        boolean lriRemoved = deleteLabelRouteInfo(lri, vpnInstanceName, writeOperTxn);
+                        if (lriRemoved) {
+                            String parentRd = lri.getParentVpnRd();
+                            FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
+                                    FibUtil.getNextHopLabelKey(parentRd, vrfEntry.getDestPrefix()));
+                        }
+                    } else {
                         FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
-                            FibUtil.getNextHopLabelKey(parentRd, vrfEntry.getDestPrefix()));
+                                FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
                     }
-                } else {
-                    FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
-                        FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
                 }
-            }
+            });
             String ifName = prefixInfo.getVpnInterfaceName();
             Optional<VpnInterface> optvpnInterface = FibUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
                 FibUtil.getVpnInterfaceIdentifier(ifName));
@@ -1381,6 +1419,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
         long elanTag = 0L;
         SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
+        final java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+        List<String> nextHopAddressList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
         if (subnetRoute != null) {
             elanTag = subnetRoute.getElantag();
             LOG.trace("SubnetRoute augmented vrfentry found for rd {} prefix {} with elantag {}",
@@ -1396,8 +1436,10 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                             makeConnectedRoute(curDpn.getDpnId(), vpnInstance.getVpnId(), vrfEntry,
                                 vrfTableKey.getRouteDistinguisher(), null, NwConstants.DEL_FLOW, tx);
                             if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.SELF_IMPORTED) {
-                                makeLFibTableEntry(curDpn.getDpnId(), vrfEntry.getLabel(), null,
-                                    DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx);
+                                optionalLabel.ifPresent(label -> {
+                                    makeLFibTableEntry(curDpn.getDpnId(), label, null,
+                                            DEFAULT_FIB_FLOW_PRIORITY, NwConstants.DEL_FLOW, tx);
+                                });
                             }
                         }
                         List<ListenableFuture<Void>> futures = new ArrayList<>();
@@ -1405,32 +1447,33 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                         return futures;
                     });
             }
-            synchronized (vrfEntry.getLabel().toString().intern()) {
-                LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-                if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                    && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
-                    Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
-                        FibUtil.getVpnInstanceOpData(dataBroker, rd);
-                    String vpnInstanceName = "";
-                    if (vpnInstanceOpDataEntryOptional.isPresent()) {
-                        vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
-                    }
-                    boolean lriRemoved = this.deleteLabelRouteInfo(lri, vpnInstanceName, null);
-                    if (lriRemoved) {
-                        String parentRd = lri.getParentVpnRd();
+            optionalLabel.ifPresent(label -> {
+                synchronized (label.toString().intern()) {
+                    LabelRouteInfo lri = getLabelRouteInfo(label);
+                    if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopAddressList, lri)) {
+                        Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional =
+                                FibUtil.getVpnInstanceOpData(dataBroker, rd);
+                        String vpnInstanceName = "";
+                        if (vpnInstanceOpDataEntryOptional.isPresent()) {
+                            vpnInstanceName = vpnInstanceOpDataEntryOptional.get().getVpnInstanceName();
+                        }
+                        boolean lriRemoved = this.deleteLabelRouteInfo(lri, vpnInstanceName, null);
+                        if (lriRemoved) {
+                            String parentRd = lri.getParentVpnRd();
+                            FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
+                                    FibUtil.getNextHopLabelKey(parentRd, vrfEntry.getDestPrefix()));
+                            LOG.trace("deleteFibEntries: Released subnetroute label {} for rd {} prefix {} as "
+                                    + "labelRouteInfo cleared", label, rd,
+                                    vrfEntry.getDestPrefix());
+                        }
+                    } else {
                         FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
-                            FibUtil.getNextHopLabelKey(parentRd, vrfEntry.getDestPrefix()));
-                        LOG.trace("deleteFibEntries: Released subnetroute label {} for rd {} prefix {} as "
-                            + "labelRouteInfo cleared", vrfEntry.getLabel(), rd,
-                            vrfEntry.getDestPrefix());
+                                FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
+                        LOG.trace("deleteFibEntries: Released subnetroute label {} for rd {} prefix {}",
+                                label, rd, vrfEntry.getDestPrefix());
                     }
-                } else {
-                    FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
-                        FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
-                    LOG.trace("deleteFibEntries: Released subnetroute label {} for rd {} prefix {}",
-                        vrfEntry.getLabel(), rd, vrfEntry.getDestPrefix());
                 }
-            }
+            });
             return;
         }
         if (installRouterFibEntries(vrfEntry, vpnToDpnList, vpnInstance.getVpnId(), NwConstants.DEL_FLOW)) {
@@ -1489,23 +1532,21 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         Optional<String> optVpnUuid = FibUtil.getVpnNameFromRd(this.dataBroker, rd);
         if (optVpnUuid.isPresent()) {
             String vpnUuid = optVpnUuid.get();
-            List<String> routeNexthoplist = vrfEntry.getNextHopAddressList();
-            if (routeNexthoplist.isEmpty()) {
-                LOG.trace("NextHopList is empty for VrfEntry {}", vrfEntry);
-                return;
-            }
-            String routeNexthop = routeNexthoplist.get(0);
-            Optional<InterVpnLinkDataComposite> optInterVpnLink = InterVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid);
-            if (optInterVpnLink.isPresent()) {
-                InterVpnLinkDataComposite interVpnLink = optInterVpnLink.get();
-                if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
-                    // This is route that points to the other endpoint of an InterVpnLink
-                    // In that case, we should look for the FIB table pointing to LPortDispatcher table and remove it.
-                    removeInterVPNLinkRouteFlows(interVpnLink.getInterVpnLinkName(),
-                        interVpnLink.isFirstEndpointVpnName(rd),
-                        vrfEntry);
+            FibUtil.getFirstNextHopAddress(vrfEntry).ifPresent(routeNexthop -> {
+                Optional<InterVpnLinkDataComposite> optInterVpnLink =
+                        InterVpnLinkCache.getInterVpnLinkByVpnId(vpnUuid);
+                if (optInterVpnLink.isPresent()) {
+                    InterVpnLinkDataComposite interVpnLink = optInterVpnLink.get();
+                    if (interVpnLink.isIpAddrTheOtherVpnEndpoint(routeNexthop, vpnUuid)) {
+                        // This is route that points to the other endpoint of an InterVpnLink
+                        // In that case, we should look for the FIB table pointing to
+                        // LPortDispatcher table and remove it.
+                        removeInterVPNLinkRouteFlows(interVpnLink.getInterVpnLinkName(),
+                                interVpnLink.isFirstEndpointVpnName(rd),
+                                vrfEntry);
+                    }
                 }
-            }
+            });
         }
 
     }
@@ -1776,12 +1817,15 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                         }
                         //Handle local flow creation for imports
                         if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.SELF_IMPORTED) {
-                            LabelRouteInfo lri = getLabelRouteInfo(vrfEntry.getLabel());
-                            if (lri != null && lri.getPrefix().equals(vrfEntry.getDestPrefix())
-                                && vrfEntry.getNextHopAddressList().contains(lri.getNextHopIpList().get(0))) {
-                                if (lri.getDpnId().equals(dpnId)) {
-                                    createLocalFibEntry(vpnId, rd, vrfEntry);
-                                    continue;
+                            java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+                            if (optionalLabel.isPresent()) {
+                                List<String> nextHopList = FibUtil.getNextHopListFromRoutePaths(vrfEntry);
+                                LabelRouteInfo lri = getLabelRouteInfo(optionalLabel.get());
+                                if (isPrefixAndNextHopPresentInLri(vrfEntry.getDestPrefix(), nextHopList, lri)) {
+                                    if (lri.getDpnId().equals(dpnId)) {
+                                        createLocalFibEntry(vpnId, rd, vrfEntry);
+                                        continue;
+                                    }
                                 }
                             }
                         }
@@ -1815,19 +1859,12 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
                     synchronized (vpnInstance.getVpnInstanceName().intern()) {
                         WriteTransaction writeCfgTxn = dataBroker.newWriteOnlyTransaction();
-                        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-                            if (!vrfEntry.getNextHopAddressList().isEmpty()) {
-                                if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
-                                    if (remoteNextHopIp.trim()
-                                        .equals(vrfEntry.getNextHopAddressList().get(0).trim())) {
-                                        LOG.trace(" creating remote FIB entry for prefix {} rd {}",
-                                            vrfEntry.getDestPrefix(), rd);
-                                        createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getKey(),
-                                            vrfEntry, writeCfgTxn);
-                                    }
-                                }
-                            }
-                        }
+                        vrfTable.get().getVrfEntry().stream()
+                            .filter(vrfEntry -> RouteOrigin.BGP == RouteOrigin.value(vrfEntry.getOrigin()))
+                            .forEach(
+                                getConsumerForCreatingRemoteFib(dpnId, vpnId,
+                                        rd, remoteNextHopIp, vrfTable,
+                                        writeCfgTxn));
                         futures.add(writeCfgTxn.submit());
                     }
                     return futures;
@@ -1849,24 +1886,18 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
                     synchronized (vpnInstance.getVpnInstanceName().intern()) {
                         WriteTransaction writeCfgTxn = dataBroker.newWriteOnlyTransaction();
-                        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-                            // Handle Internal Routes only (i.e., STATIC for now)
-                            if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.STATIC) {
-                                SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
-                                    /* Ignore SubnetRoute entry */
-                                if (subnetRoute == null) {
-                                    if (!vrfEntry.getNextHopAddressList().isEmpty()) {
-                                        if (remoteNextHopIp.trim()
-                                            .equals(vrfEntry.getNextHopAddressList().get(0).trim())) {
-                                            LOG.trace(" creating remote FIB entry for prefix {} rd {} on Dpn {}",
-                                                vrfEntry.getDestPrefix(), rd, dpnId);
-                                            createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry,
-                                                writeCfgTxn);
-                                        }
-                                    }
-                                }
-                            }
-                        }
+                        // Handle Internal Routes only (i.e., STATIC for now)
+                        vrfTable.get().getVrfEntry().stream()
+                            .filter(vrfEntry -> {
+                                SubnetRoute subnetRoute =
+                                        vrfEntry.getAugmentation(SubnetRoute.class);
+                                /* Ignore SubnetRoute entry */
+                                return (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.STATIC)
+                                        && (subnetRoute == null);
+                            })
+                            .forEach(getConsumerForCreatingRemoteFib(dpnId, vpnId,
+                                       rd, remoteNextHopIp, vrfTable,
+                                       writeCfgTxn));
                         futures.add(writeCfgTxn.submit());
                     }
                     return futures;
@@ -1879,7 +1910,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                                        final long vpnId,
                                        final String rd,
                                        final String destPrefix,
-                                       final String destTepIp) {
+                                       final String destTepIp,
+                                       final long label) {
         final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
 
         if (vpnInstance == null) {
@@ -1899,11 +1931,13 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                     }
                     LOG.trace("manageRemoteRouteOnDPN :: action {}, DpnId {}, vpnId {}, rd {}, destPfx {}",
                         action, localDpnId, vpnId, rd, destPrefix);
-                    List<String> nextHopAddressList = vrfEntry.getNextHopAddressList();
+                    List<RoutePaths> routePathList = vrfEntry.getRoutePaths();
                     VrfEntry modVrfEntry;
-                    if (nextHopAddressList == null || (nextHopAddressList.isEmpty())) {
-                        List<String> nhList = Collections.singletonList(destTepIp);
-                        modVrfEntry = new VrfEntryBuilder(vrfEntry).setNextHopAddressList(nhList).build();
+                    if (routePathList == null || (routePathList.isEmpty())) {
+                        modVrfEntry = FibHelper.getVrfEntryBuilder(vrfEntry, label,
+                                Collections.singletonList(destTepIp),
+                                RouteOrigin.value(vrfEntry.getOrigin()))
+                                .build();
                     } else {
                         modVrfEntry = vrfEntry;
                     }
@@ -1939,14 +1973,18 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                             SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
                             if (subnetRoute != null) {
                                 LOG.trace("Cleaning subnetroute {} on dpn {} for vpn {} : cleanUpDpnForVpn",
-                                    vrfEntry.getDestPrefix(),
-                                    dpnId, rd);
+                                        vrfEntry.getDestPrefix(),
+                                        dpnId, rd);
                                 makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW, tx);
-                                makeLFibTableEntry(dpnId, vrfEntry.getLabel(), null, DEFAULT_FIB_FLOW_PRIORITY,
-                                    NwConstants.DEL_FLOW, tx);
-                                LOG.trace("cleanUpDpnForVpn: Released subnetroute label {} for rd {} prefix {}",
-                                    vrfEntry.getLabel(), rd,
-                                    vrfEntry.getDestPrefix());
+                                java.util.Optional.ofNullable(vrfEntry.getRoutePaths()).ifPresent(routePaths -> {
+                                    routePaths.stream().forEach(routePath -> {
+                                        makeLFibTableEntry(dpnId, routePath.getLabel(), null, DEFAULT_FIB_FLOW_PRIORITY,
+                                                NwConstants.DEL_FLOW, tx);
+                                        LOG.trace("cleanUpDpnForVpn: Released subnetroute label {} for rd {} prefix {}",
+                                                routePath.getLabel(), rd,
+                                                vrfEntry.getDestPrefix());
+                                    });
+                                });
                                 continue;
                             }
                             // ping responder for router interfaces
@@ -1988,20 +2026,12 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                 () -> {
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
                     synchronized (vpnInstance.getVpnInstanceName().intern()) {
-                        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
-                        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-                            if (!vrfEntry.getNextHopAddressList().isEmpty()) {
-                                if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
-                                    if (remoteNextHopIp.trim()
-                                        .equals(vrfEntry.getNextHopAddressList().get(0).trim())) {
-                                        LOG.trace(" deleting remote FIB entry {}", vrfEntry);
-                                        deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(),
-                                            vrfEntry, writeTransaction);
-                                    }
-                                }
-                            }
-                        }
-                        futures.add(writeTransaction.submit());
+                        WriteTransaction writeCfgTxn = dataBroker.newWriteOnlyTransaction();
+                        vrfTable.get().getVrfEntry().stream()
+                            .filter(vrfEntry -> RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP)
+                            .forEach(getConsumerForDeletingRemoteFib(dpnId, vpnId, rd,
+                                remoteNextHopIp, vrfTable, writeCfgTxn));
+                        futures.add(writeCfgTxn.submit());
                     }
                     return futures;
                 });
@@ -2022,25 +2052,17 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                 () -> {
                     List<ListenableFuture<Void>> futures = new ArrayList<>();
                     synchronized (vpnInstance.getVpnInstanceName().intern()) {
-                        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
-                        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-                            // Handle Internal Routes only (i.e, STATIC for now)
-                            if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.STATIC) {
+                        WriteTransaction writeCfgTxn = dataBroker.newWriteOnlyTransaction();
+                        vrfTable.get().getVrfEntry().stream()
+                            .filter(vrfEntry -> {
                                 SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class);
-                                    /* Ignore SubnetRoute entry */
-                                if (subnetRoute == null) {
-                                    if (!vrfEntry.getNextHopAddressList().isEmpty()) {
-                                        if (remoteNextHopIp.trim()
-                                            .equals(vrfEntry.getNextHopAddressList().get(0).trim())) {
-                                            LOG.trace(" deleting remote FIB entry {}", vrfEntry);
-                                            deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(),
-                                                vrfEntry, writeTransaction);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        futures.add(writeTransaction.submit());
+                                /* Ignore SubnetRoute entry */
+                                return (subnetRoute == null)
+                                        && (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.STATIC);
+                            })
+                            .forEach(getConsumerForDeletingRemoteFib(dpnId, vpnId,
+                                rd, remoteNextHopIp, vrfTable, writeCfgTxn));
+                        futures.add(writeCfgTxn.submit());
                     }
                     return futures;
                 });
@@ -2091,14 +2113,16 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             }
 
             for (String prefixIp : prefixIpList) {
-                for (String nextHopIp : vrfEntry.getNextHopAddressList()) {
-                    LOG.debug("NextHop IP for destination {} is {}", prefixIp, nextHopIp);
-                    AdjacencyResult adjacencyResult = nextHopManager.getRemoteNextHopPointer(remoteDpnId, vpnId,
-                        prefixIp, nextHopIp);
-                    if (adjacencyResult != null && !adjacencyList.contains(adjacencyResult)) {
-                        adjacencyList.add(adjacencyResult);
-                    }
-                }
+                adjacencyList.addAll(vrfEntry.getRoutePaths().stream()
+                        .map(routePath -> {
+                            LOG.debug("NextHop IP for destination {} is {}", prefixIp,
+                                    routePath.getNexthopAddress());
+                            return nextHopManager.getRemoteNextHopPointer(remoteDpnId, vpnId,
+                                    prefixIp, routePath.getNexthopAddress());
+                        })
+                        .filter(adjacencyResult -> adjacencyResult != null && !adjacencyList.contains(adjacencyResult))
+                        .distinct()
+                        .collect(Collectors.toList()));
             }
         } catch (NullPointerException e) {
             LOG.trace("", e);
@@ -2158,15 +2182,17 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
             for (VrfTables vrfTable : vrfTables) {
                 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
-                    for (String nextHop : vrfEntry.getNextHopAddressList()) {
+                    List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+                    for (RoutePaths routePath : routePaths) {
                         result.add(String.format("   %-7s  %-20s  %-20s  %-7s  %-7s",
                             vrfTable.getRouteDistinguisher(),
-                            vrfEntry.getDestPrefix(), nextHop, vrfEntry.getLabel(), vrfEntry.getOrigin()));
+                            vrfEntry.getDestPrefix(), routePath.getNexthopAddress(),
+                            routePath.getLabel(), vrfEntry.getOrigin()));
                     }
-                    if (vrfEntry.getNextHopAddressList().isEmpty()) {
-                        result.add(String.format("   %-7s  %-20s  %-20s  %-7s  %-7s",
+                    if (routePaths.isEmpty()) {
+                        result.add(String.format("   %-7s  %-20s  %-20s  %-7s",
                             vrfTable.getRouteDistinguisher(),
-                            vrfEntry.getDestPrefix(), "local", vrfEntry.getLabel(), vrfEntry.getOrigin()));
+                            vrfEntry.getDestPrefix(), "local", vrfEntry.getOrigin()));
                     }
                 }
             }
@@ -2234,6 +2260,11 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             return;
         }
 
+        java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
+        if (!optionalLabel.isPresent()) {
+            LOG.warn("Routes paths not present. Exiting installRouterFibEntry");
+            return;
+        }
         String addRemoveStr = (addOrRemove == NwConstants.ADD_FLOW) ? "ADD_FLOW" : "DELETE_FLOW";
         LOG.trace("{}: bulding Echo Flow entity for dpid:{}, router_ip:{}, vpnId:{}, subSplit:{} ", addRemoveStr,
             dpnId, routerInternalIp, vpnId, subSplit[0]);
@@ -2268,7 +2299,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
         instructions.add(new InstructionApplyActions(actionsInfos));
 
         int priority = FibConstants.DEFAULT_FIB_FLOW_PRIORITY + FibConstants.DEFAULT_PREFIX_LENGTH;
-        String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, vrfEntry.getLabel(), priority);
+        String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, optionalLabel.get(),
+                priority);
 
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_FIB_TABLE, flowRef, priority, flowRef,
             0, 0, NwConstants.COOKIE_VM_FIB_TABLE, matches, instructions);
@@ -2283,8 +2315,8 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
     public void removeInterVPNLinkRouteFlows(final String interVpnLinkName,
                                              final boolean isVpnFirstEndPoint,
                                              final VrfEntry vrfEntry) {
-        Preconditions.checkArgument(vrfEntry.getNextHopAddressList() != null
-            && vrfEntry.getNextHopAddressList().size() == 1);
+        Preconditions.checkArgument(vrfEntry.getRoutePaths() != null
+            && vrfEntry.getRoutePaths().size() == 1);
         Optional<InterVpnLinkState> interVpnLinkState = FibUtil.getInterVpnLinkState(dataBroker, interVpnLinkName);
 
         if (!interVpnLinkState.isPresent()) {
@@ -2296,38 +2328,78 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
             isVpnFirstEndPoint ? interVpnLinkState.get().getFirstEndpointState().getDpId()
                 : interVpnLinkState.get().getSecondEndpointState().getDpId();
 
-        String nextHop = vrfEntry.getNextHopAddressList().get(0);
+        java.util.Optional<String> optionalNextHop = FibUtil.getFirstNextHopAddress(vrfEntry);
+        java.util.Optional<Long> optionalLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
 
         // delete from FIB
         //
-        String flowRef = getInterVpnFibFlowRef(interVpnLinkName, vrfEntry.getDestPrefix(), 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();
+        optionalNextHop.ifPresent(nextHop -> {
+            String flowRef = getInterVpnFibFlowRef(interVpnLinkName, vrfEntry.getDestPrefix(), 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();
 
-        LOG.trace("Removing flow in FIB table for interVpnLink {} key {}",
-            interVpnLinkName, flowRef);
+            LOG.trace("Removing flow in FIB table for interVpnLink {} key {}",
+                    interVpnLinkName, flowRef);
 
-        for (BigInteger dpId : targetDpns) {
-            LOG.debug("Removing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for InterVpnLink {} in FIB",
-                vrfEntry.getDestPrefix(), vrfEntry.getLabel(), nextHop,
-                dpId, interVpnLinkName);
+            for (BigInteger dpId : targetDpns) {
+                LOG.debug("Removing flow: VrfEntry=[prefix={} nexthop={}] dpn {} for InterVpnLink {} in FIB",
+                        vrfEntry.getDestPrefix(), nextHop,
+                        dpId, interVpnLinkName);
 
-            mdsalManager.removeFlow(dpId, flow);
-        }
+                mdsalManager.removeFlow(dpId, flow);
+            }
+        });
 
         // delete from LFIB
         //
-        LOG.trace("Removing flow in FIB table for interVpnLink {}", interVpnLinkName);
+        optionalLabel.ifPresent(label -> {
+            LOG.trace("Removing flow in FIB table for interVpnLink {}", interVpnLinkName);
+
+            WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+            for (BigInteger dpId : targetDpns) {
+                LOG.debug("Removing flow: VrfEntry=[prefix={} label={}] dpn {} for InterVpnLink {} in LFIB",
+                        vrfEntry.getDestPrefix(), label,
+                        dpId, interVpnLinkName);
+                makeLFibTableEntry(dpId, label, null /* no instructions */,
+                        LFIB_INTERVPN_PRIORITY, NwConstants.DEL_FLOW, tx);
+            }
+            tx.submit();
+        });
+    }
+
+    private Consumer<? super VrfEntry> getConsumerForCreatingRemoteFib(
+            final BigInteger dpnId, final long vpnId, final String rd,
+            final String remoteNextHopIp, final Optional<VrfTables> vrfTable,
+            WriteTransaction writeCfgTxn) {
+        return vrfEntry -> vrfEntry.getRoutePaths().stream()
+                .filter(routes -> !routes.getNexthopAddress().isEmpty()
+                        && remoteNextHopIp.trim().equals(routes.getNexthopAddress().trim()))
+                .findFirst()
+                .ifPresent(routes -> {
+                    LOG.trace("creating remote FIB entry for prefix {} rd {} on Dpn {}",
+                            vrfEntry.getDestPrefix(), rd, dpnId);
+                    createRemoteFibEntry(dpnId, vpnId, vrfTable.get().getKey(), vrfEntry, writeCfgTxn);
+                });
+    }
 
-        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-        for (BigInteger dpId : targetDpns) {
-            LOG.debug("Removing flow: VrfEntry=[prefix={} label={} nexthop={}] dpn {} for InterVpnLink {} in LFIB",
-                vrfEntry.getDestPrefix(), vrfEntry.getLabel(), nextHop,
-                dpId, interVpnLinkName);
-            makeLFibTableEntry(dpId, vrfEntry.getLabel(), null /* no instructions */,
-                LFIB_INTERVPN_PRIORITY, NwConstants.DEL_FLOW, tx);
-        }
-        tx.submit();
+    private Consumer<? super VrfEntry> getConsumerForDeletingRemoteFib(
+            final BigInteger dpnId, final long vpnId, final String rd,
+            final String remoteNextHopIp, final Optional<VrfTables> vrfTable,
+            WriteTransaction writeCfgTxn) {
+        return vrfEntry -> vrfEntry.getRoutePaths().stream()
+                .filter(routes -> !routes.getNexthopAddress().isEmpty()
+                        && remoteNextHopIp.trim().equals(routes.getNexthopAddress().trim()))
+                .findFirst()
+                .ifPresent(routes -> {
+                    LOG.trace(" deleting remote FIB entry {}", vrfEntry);
+                    deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry, writeCfgTxn);
+                });
+    }
+
+    private boolean isPrefixAndNextHopPresentInLri(String prefix,
+            List<String> nextHopAddressList, LabelRouteInfo lri) {
+        return lri != null && lri.getPrefix().equals(prefix)
+                && nextHopAddressList.contains(lri.getNextHopIpList().get(0));
     }
 }
index 600936cf78b5eca1187acc173703f37dbcf4d429..81719c68da4c075952eab9f5b48eeb82dea065ef 100644 (file)
@@ -11,8 +11,7 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.when;
 
 import java.math.BigInteger;
-import java.util.Collections;
-import java.util.List;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -26,13 +25,13 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataCh
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.fibmanager.VrfEntryListener;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -61,7 +60,6 @@ public class FibManagerTest {
     private static final Long EGRESS_POINTER = 11L;
     VrfEntry vrfEntry;
     InstanceIdentifier<VrfEntry> identifier;
-    VrfEntryBuilder vrfbuilder;
     private static final String TEST_VPN_INSTANCE_NAME = "95486250-4ad7-418f-9030-2df37f98ad24";
     private static final String TEST_RD = "100:1";
     private static final String PREFIX = "1.1.2.3";
@@ -76,7 +74,7 @@ public class FibManagerTest {
     private void setupMocks() {
         dpn = BigInteger.valueOf(100000L);
         identifier = buildVrfEntryId(TEST_RD, PREFIX);
-        vrfEntry = buildVrfEntry(TEST_RD, PREFIX, Collections.singletonList(NEXTHOP), LABEL, origin);
+        vrfEntry = FibHelper.getVrfEntryBuilder(PREFIX, LABEL, NEXTHOP, origin).build();
         when(vrfTableKey.getRouteDistinguisher()).thenReturn(TEST_RD);
     }
 
@@ -87,7 +85,6 @@ public class FibManagerTest {
                 any(InstanceIdentifier.class), any(DataChangeListener.class),
                 any(DataChangeScope.class))).thenReturn(dataChangeListenerRegistration);
         dataChangeEvent = new MockDataChangedEvent();
-        vrfbuilder = new VrfEntryBuilder();
         setupMocks();
     }
 
@@ -98,12 +95,6 @@ public class FibManagerTest {
         //Mockito.verify(mdsalManager, Mockito.times(2)).installFlow(any(FlowEntity.class));
     }
 
-    private VrfEntry buildVrfEntry(String rd, String prefix, List<String> nextHopList, int label, RouteOrigin origin) {
-
-        return new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nextHopList)
-            .setLabel((long) label).setOrigin(origin.getValue()).build();
-    }
-
     public static InstanceIdentifier<VrfTables> buildVrfTableId(String rd) {
         InstanceIdentifierBuilder<VrfTables> idBuilder =
             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
index a4bdd9e5db2d5b335e5503906b267c1db79c5c5d..b142abdeb30e4ac619909c4abd8e4febcea2c927 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.netvirt.vpnmanager;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
@@ -16,6 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.vrfentry.RoutePaths;
 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.yangtools.yang.binding.InstanceIdentifier;
@@ -56,30 +60,24 @@ public class FibEntriesListener extends AsyncDataTreeChangeListenerBase<VrfEntry
         LOG.trace("Remove Fib event - Key : {}, value : {} ", identifier, del);
         final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
         String rd = key.getRouteDistinguisher();
-        Long label = del.getLabel();
-        VpnInstanceOpDataEntry vpnInstanceOpData = vpnInstanceListener.getVpnInstanceOpData(rd);
-        if (vpnInstanceOpData != null) {
-            List<Long> routeIds = vpnInstanceOpData.getRouteEntryId();
-            if (routeIds == null) {
-                LOG.debug("Fib Route entry is empty.");
-                return;
-            }
-            LOG.debug("Removing label from vpn info - {}", label);
-            routeIds.remove(label);
-            TransactionUtil.asyncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
-                VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-                new VpnInstanceOpDataEntryBuilder(vpnInstanceOpData).setRouteEntryId(routeIds).build(),
-                TransactionUtil.DEFAULT_CALLBACK);
-        } else {
-            LOG.warn("No VPN Instance found for RD: {}", rd);
-        }
+        List<RoutePaths> routePaths = del.getRoutePaths();
+        removeLabelFromVpnInstance(rd, routePaths);
     }
 
     @Override
     protected void update(InstanceIdentifier<VrfEntry> identifier,
         VrfEntry original, VrfEntry update) {
-        // TODO Auto-generated method stub
-
+        final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
+        String rd = key.getRouteDistinguisher();
+        List<RoutePaths> originalRoutePaths = new ArrayList<>(original.getRoutePaths());
+        List<RoutePaths> updateRoutePaths = new ArrayList<>(update.getRoutePaths());
+        if (originalRoutePaths.size() < updateRoutePaths.size()) {
+            updateRoutePaths.removeAll(originalRoutePaths);
+            addLabelToVpnInstance(rd, updateRoutePaths);
+        } else if (originalRoutePaths.size() > updateRoutePaths.size()) {
+            originalRoutePaths.removeAll(updateRoutePaths);
+            removeLabelFromVpnInstance(rd, originalRoutePaths);
+        }
     }
 
     @Override
@@ -88,21 +86,54 @@ public class FibEntriesListener extends AsyncDataTreeChangeListenerBase<VrfEntry
         LOG.trace("Add Vrf Entry event - Key : {}, value : {}", identifier, add);
         final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
         String rd = key.getRouteDistinguisher();
-        Long label = add.getLabel();
-        VpnInstanceOpDataEntry vpn = vpnInstanceListener.getVpnInstanceOpData(rd);
-        if (vpn != null) {
-            List<Long> routeIds = vpn.getRouteEntryId();
+        addLabelToVpnInstance(rd, add.getRoutePaths());
+    }
+
+    private void addLabelToVpnInstance(String rd, List<RoutePaths> routePaths) {
+        List<Long> labels = routePaths.stream().map(routePath -> routePath.getLabel()).distinct()
+                            .collect(Collectors.toList());
+        VpnInstanceOpDataEntry vpnInstanceOpData = vpnInstanceListener.getVpnInstanceOpData(rd);
+        Optional.ofNullable(vpnInstanceOpData).map(vpn -> {
+            List<Long> routeIds = vpn.getRouteEntryId() == null ? new ArrayList<>() : vpn.getRouteEntryId();
+            labels.stream().forEach(label -> {
+                LOG.debug("Adding label to vpn info - {}", label);
+                if (!routeIds.contains(label)) {
+                    routeIds.add(label);
+                }
+            });
+            TransactionUtil.asyncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                    new VpnInstanceOpDataEntryBuilder(vpn).setRouteEntryId(routeIds).build(),
+                    TransactionUtil.DEFAULT_CALLBACK);
+            return vpn;
+        }).orElseGet(() -> {
+            LOG.warn("No VPN Instance found for RD: {}", rd);
+            return null;
+        });
+    }
+
+    private void removeLabelFromVpnInstance(String rd, List<RoutePaths> routePaths) {
+        List<Long> labels = routePaths.stream().map(routePath -> routePath.getLabel()).distinct()
+                .collect(Collectors.toList());
+        VpnInstanceOpDataEntry vpnInstanceOpData = vpnInstanceListener.getVpnInstanceOpData(rd);
+        Optional.ofNullable(vpnInstanceOpData).map(vpn -> {
+            List<Long> routeIds = vpnInstanceOpData.getRouteEntryId();
             if (routeIds == null) {
-                routeIds = new ArrayList<>();
+                LOG.debug("Fib Route entry is empty.");
+                return vpn;
             }
-            LOG.debug("Adding label to vpn info - {}", label);
-            routeIds.add(label);
-            TransactionUtil.asyncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
-                VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-                new VpnInstanceOpDataEntryBuilder(vpn).setRouteEntryId(routeIds).build(),
-                TransactionUtil.DEFAULT_CALLBACK);
-        } else {
+            LOG.debug("Removing label from vpn info - {}", labels);
+            routeIds.removeAll(labels);
+            TransactionUtil.asyncWrite(
+                    dataBroker,
+                    LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+                    new VpnInstanceOpDataEntryBuilder(vpnInstanceOpData).setRouteEntryId(
+                            routeIds).build(), TransactionUtil.DEFAULT_CALLBACK);
+            return vpn;
+        }).orElseGet(() -> {
             LOG.warn("No VPN Instance found for RD: {}", rd);
-        }
+            return null;
+        });
     }
 }
index ab47a3a1f87055c26424c895f31c4f8eec9ecb80..d0de55018b9fcd220163fc0935b26ed073ae45d1 100644 (file)
@@ -293,14 +293,15 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                             vpnInterface);
                         for (Adjacency adj : adjList) {
                             prefix = adj.getIpAddress();
+                            long label = adj.getLabel();
                             if ((tunnelAction == TunnelAction.TUNNEL_EP_ADD)
                                 && (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue())) {
-                                fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp);
+                                fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp, label);
                             }
 
                             if ((tunnelAction == TunnelAction.TUNNEL_EP_DELETE)
                                 && (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue())) {
-                                fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp);
+                                fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp, label);
                             }
                         }
                     }
index 23efe7253a81d5ef5273cd8dd309e8958b8424cd..12d01341d46cbca67c76910af6d7d5f271c46000 100755 (executable)
@@ -45,6 +45,7 @@ import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
@@ -83,7 +84,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
@@ -639,7 +639,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 }
             }
             L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
-                    .setInterfaceName(interfaceName).setNextHopIp(nextHopIp);
+                    .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd);
             Adjacency operationalAdjacency = null;
             try {
                 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
@@ -728,7 +728,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     // Update the VRF entry with nextHop
                     String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnInterface.getVpnInstanceName());
                     fibManager.updateFibEntry(dataBroker, primaryRd, prefix, nhList,
-                        gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
+                        gwMacAddr.isPresent() ? gwMacAddr.get() : null, label, null);
 
                     //Get the list of VPN's importing this route(prefix) .
                     // Then update the VRF entry with nhList
@@ -740,7 +740,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             LOG.debug("Exporting route with rd {} prefix {} nhList {} label {} to VPN {}", vpnRd,
                                 prefix, nhList, label, vpn);
                             fibManager.updateFibEntry(dataBroker, vpnRd, prefix, nhList,
-                                gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
+                                gwMacAddr.isPresent() ? gwMacAddr.get() : null, label, null);
                         }
                     }
                     // Advertise the prefix to BGP only for external vpn
@@ -808,7 +808,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                     // Update the VRF entry with emtpy nextHop
                     String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnInterface.getVpnInstanceName());
                     fibManager.updateFibEntry(dataBroker, primaryRd, prefix, new ArrayList<>()/* empty */,
-                            gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
+                            gwMacAddr.isPresent() ? gwMacAddr.get() : null, label, null);
 
                     //Get the list of VPN's importing this route(prefix) .
                     // Then update the VRF entry with nhList
@@ -820,7 +820,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             LOG.debug("Exporting route with rd {} prefix {} nhList {} label {} to VPN {}", vpnRd,
                                 prefix, nhList, label, vpn);
                             fibManager.updateFibEntry(dataBroker, vpnRd, prefix, nhList,
-                                gwMacAddr.isPresent() ? gwMacAddr.get() : null, null);
+                                gwMacAddr.isPresent() ? gwMacAddr.get() : null, label, null);
                         }
                     }
 
@@ -946,11 +946,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                             continue;
                         }
                         String prefix = vrfEntry.getDestPrefix();
-                        long label = vrfEntry.getLabel();
-                        List<String> nextHops = vrfEntry.getNextHopAddressList();
-                        String gwMac = vrfEntry.getGatewayMacAddress();
                         SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
-                        for (String nh : nextHops) {
+                        String gwMac = vrfEntry.getGatewayMacAddress();
+                        vrfEntry.getRoutePaths().stream().forEach(routePath -> {
+                            String nh = routePath.getNexthopAddress();
+                            int label = routePath.getLabel().intValue();
                             if (route != null) {
                                 LOG.info(
                                     "Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}",
@@ -963,12 +963,12 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                         Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre,
                                         (int)label, 0 /*l3vni*/, gwMac, RouteOrigin.SELF_IMPORTED, writeConfigTxn);
                             }
-                        }
+                        });
                     } catch (Exception e) {
                         LOG.error(
-                            "Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} "
+                            "Exception occurred while importing route with prefix {} route-path {} from vpn {} "
                                 + "to vpn {}",
-                            vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(),
+                            vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(),
                             vpn.getVpnInstanceName(), vpnName);
                     }
                 }
@@ -1471,10 +1471,8 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
         SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
         RouteOrigin origin = RouteOrigin.CONNECTED; // Only case when a route is considered as directly connected
-        VrfEntry vrfEntry =
-                new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Collections.singletonList(nextHop))
-                        .setLabel((long) label).setOrigin(origin.getValue())
-                        .addAugmentation(SubnetRoute.class, route).build();
+        VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin)
+                .addAugmentation(SubnetRoute.class, route).build();
 
         LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
 
@@ -1513,9 +1511,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
 
         List<VpnInstanceOpDataEntry> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
         if (vpnsToImportRoute.size() > 0) {
-            VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(
-                    Collections.singletonList(nextHop))
-                    .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
+            VrfEntry importingVrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, RouteOrigin.SELF_IMPORTED)
                     .addAugmentation(SubnetRoute.class, route).build();
             List<VrfEntry> importingVrfEntryList = Collections.singletonList(importingVrfEntry);
             for (VpnInstanceOpDataEntry vpnInstance : vpnsToImportRoute) {
@@ -1541,9 +1537,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
         SubnetRoute route, WriteTransaction writeConfigTxn) {
 
         RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
-        VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(
-                Collections.singletonList(nextHop))
-                .setLabel((long)label).setOrigin(origin.getValue())
+        VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin)
                 .addAugmentation(SubnetRoute.class, route).build();
         LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label,
                 route.getElantag());
index ebd35e6522b5109ce3ce72d63bc38a8e1947f6ca..c2212c29cab0c2cd2ddcea453e52e68df26825d4 100755 (executable)
@@ -572,9 +572,10 @@ public class VpnUtil {
         if (vrfTablesOpc.isPresent()) {
             VrfTables vrfTables = vrfTablesOpc.get();
             for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
-                if (vrfEntry.getNextHopAddressList() != null && vrfEntry.getNextHopAddressList().contains(nexthop)) {
-                    matches.add(vrfEntry);
-                }
+                vrfEntry.getRoutePaths().stream()
+                        .filter(routePath -> routePath.getNexthopAddress() != null
+                                && routePath.getNexthopAddress().equals(nexthop))
+                        .findFirst().ifPresent(routePath -> matches.add(vrfEntry));
             }
         }
         return matches;
@@ -597,8 +598,8 @@ public class VpnUtil {
             try {
                 bgpManager.withdrawPrefix(rd, vrfEntry.getDestPrefix());
             } catch (Exception e) {
-                LOG.error("Could not withdraw route to {} with nextHop {} in VpnRd {}",
-                          vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), rd);
+                LOG.error("Could not withdraw route to {} with route-paths {} in VpnRd {}",
+                          vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), rd);
             }
         });
     }
index 878774950b7e7b87ab1740d2d8b30d85e786f6af..84887ca195917b331f00f806010e3c8faf30dfc1 100755 (executable)
@@ -10,11 +10,13 @@ package org.opendaylight.netvirt.vpnmanager.intervpnlink;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.ListenableFuture;
+
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
@@ -25,6 +27,7 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.fibmanager.api.FibHelper;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
@@ -39,7 +42,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkStates;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
@@ -462,10 +464,7 @@ public class InterVpnLinkUtil {
         String endpointIp = destinationIs1stEndpoint ? interVpnLink.getSecondEndpoint().getIpAddress().getValue()
             : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
 
-        VrfEntry newVrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
-            .setLabel(label).setNextHopAddressList(Collections.singletonList(endpointIp))
-            .setOrigin(RouteOrigin.INTERVPN.getValue())
-            .build();
+        VrfEntry newVrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, endpointIp, RouteOrigin.INTERVPN).build();
 
         String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
         InstanceIdentifier<VrfEntry> newVrfEntryIid =
index 838579d250411d73f157b7fe66f7fd119f9ba82a..a4ba2e41fbcc701f08cfa2ab3f1f534f4a7ce580 100644 (file)
@@ -92,10 +92,10 @@ public class L3vpnOverMplsGrePopulator extends L3vpnPopulator {
         String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
         List<String> adjNextHop = nextHop.getNextHopIpList();
         String rd = input.getRd();
+        String primaryRd = input.getPrimaryRd();
         String vpnName = input.getVpnName();
         long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
-                VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
-                        : rd, prefix));
+                VpnUtil.getNextHopLabelKey(primaryRd, prefix));
         if (label == VpnConstants.INVALID_LABEL) {
             String error = "Unable to fetch label from Id Manager. Bailing out processing add/update of vpn interface"
                     + input.getInterfaceName() + " for vpn " + vpnName;