Dualstack support for L3VPN-two router design 21/63421/107
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 16 Oct 2017 15:35:20 +0000 (16:35 +0100)
committerSam Hague <shague@redhat.com>
Sat, 30 Jun 2018 01:55:23 +0000 (01:55 +0000)
According to dualstack specification [0], this commit introduces
following changes:

* neutronvpn.yang: Use "router-ids" leaf-list instead of "router-ids"
  leaf in grouping "vpn-instance" and "vpnMaps" container. Two neutron
  routers can be attached to one L3 BGPVPN instance at the same time:
  the first one with only IPv4 ports and the second one with only IPv6
  ports.

* NeutronvpnManager, NeutronvpnUtils: Support routerIds list in all
  basic methods. Control the number of associated routers in "add" and
  "handleRoutersUpdate" methods. Consequently assign each router
  accordingly.

* IVpnLinkServiceImpl: Appropriate changes, due to support of routerIds
  list in neutronvpn.yang.

* NatUtil:

  * "getRouterIdfromVpnInstance": control, that we get routerId from
    appropriate IPv4 Subnetmap, which is corresponding to given vpnId;
  * "getVpnForRouter" support routerIdsList, due to  changes in
    neutronvpn.yang.

* neutronvpn: rpc L3VPN support for assoc/disassoc routers list

Change yang model to associate or dissociate two routers with a vpnid in
the same curl query.

Change-Id: Iade14e52baee2da4a82f01231c7ea6f8051e520b
Signed-off-by: Noel de Prandières <prandieres@6wind.com>
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Karthikeyan Krishnan <karthikeyangceb007@gmail.com>
natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
neutronvpn/api/src/main/java/org/opendaylight/netvirt/neutronvpn/api/utils/NeutronConstants.java
neutronvpn/api/src/main/java/org/opendaylight/netvirt/neutronvpn/api/utils/NeutronUtils.java
neutronvpn/api/src/main/yang/neutronvpn.yang
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronBgpvpnChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/IVpnLinkServiceImpl.java

index 2ce1b571a615219609dfb4f7db7372c47bf9f633..ab8ecfbfb636fdb93745b6747d25d1c0454592bb 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.netvirt.natservice.internal;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.CheckedFuture;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.math.BigInteger;
@@ -64,6 +65,7 @@ import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.natservice.ha.NatDataUtil;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
+import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
@@ -213,6 +215,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
@@ -227,6 +230,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -578,15 +582,35 @@ public final class NatUtil {
     }
 
     public static String getRouterIdfromVpnInstance(DataBroker broker, String vpnName) {
+        // returns only router, attached to IPv4 networks
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
             .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
         Optional<VpnMap> optionalVpnMap =
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                         LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
-        if (optionalVpnMap.isPresent()) {
-            Uuid routerId = optionalVpnMap.get().getRouterId();
-            if (routerId != null) {
-                return routerId.getValue();
+        if (!optionalVpnMap.isPresent()) {
+            LOG.error("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
+            return null;
+        }
+        List<Uuid> routerIdsList = NeutronUtils.getVpnMapRouterIdsListUuid(optionalVpnMap.get().getRouterIds());
+        if (routerIdsList != null && !routerIdsList.isEmpty()) {
+            for (Uuid routerUuid : routerIdsList) {
+                InstanceIdentifier<Router> routerIdentifier = buildNeutronRouterIdentifier(routerUuid);
+                Optional<Router> optRouter = SingleTransactionDataBroker
+                    .syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
+                            LogicalDatastoreType.CONFIGURATION, routerIdentifier);
+                if (!optRouter.isPresent()) {
+                    continue;
+                }
+                List<Routes> routes = optRouter.get().getRoutes();
+                if (routes == null || routes.isEmpty()) {
+                    continue;
+                }
+                for (Routes r : routes) {
+                    if (r.getDestination().getIpv4Prefix() != null) {
+                        return routerUuid.getValue();
+                    }
+                }
             }
         }
         LOG.info("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
@@ -594,19 +618,23 @@ public final class NatUtil {
     }
 
     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
+        Preconditions.checkNotNull(routerId, "dissociateRouter: routerId not found!");
         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
         Optional<VpnMaps> optionalVpnMaps =
                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
                         LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
-            if (routerId != null) {
-                for (VpnMap vpnMap : allMaps) {
-                    if (vpnMap.getRouterId() != null
-                        && routerId.equals(vpnMap.getRouterId().getValue())
-                        && !routerId.equals(vpnMap.getVpnId().getValue())) {
-                        return vpnMap.getVpnId();
-                    }
+            for (VpnMap vpnMap: allMaps) {
+                if (routerId.equals(vpnMap.getVpnId().getValue())) {
+                    continue;
+                }
+                List<Uuid> routerIdsList = NeutronUtils.getVpnMapRouterIdsListUuid(vpnMap.getRouterIds());
+                if (routerIdsList == null || routerIdsList.isEmpty()) {
+                    return null;
+                }
+                if (routerIdsList.contains(new Uuid(routerId))) {
+                    return vpnMap.getVpnId();
                 }
             }
         }
index 94dc8223b1e77d640da59b5a62e4c654050667c6..1a044284e72f8d921633a564f244094f55bdad99 100644 (file)
@@ -35,6 +35,7 @@ public interface NeutronConstants {
     String VNIC_TYPE_DIRECT = "direct";
     String BINDING_PROFILE_CAPABILITIES = "capabilities";
     String SWITCHDEV = "switchdev";
+    int MAX_ROUTERS_PER_BGPVPN = 2;
 
     Predicate<Port> IS_DHCP_PORT = port -> port != null
             && DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
index b9bf682f0bfe91c50425de2103047da0942dc5ef..92ca17d78ba2caaf878ceaceccbbcf529cc232d3 100644 (file)
@@ -9,15 +9,18 @@
 package org.opendaylight.netvirt.neutronvpn.api.utils;
 
 import com.google.common.base.Preconditions;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
 import java.util.regex.Pattern;
+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.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
@@ -215,4 +218,13 @@ public final class NeutronUtils {
             return Boolean.FALSE;
         }
     }
+
+    public static List<Uuid> getVpnMapRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
 }
index 125dfd9f988deb8b3b5d9107ab266c7bc18b3abc..76c55e0d5ef39309d6602ac690182c156b5df08d 100644 (file)
@@ -125,9 +125,12 @@ module neutronvpn {
              Format is ASN:nn or IP-address:nn.";
         }
 
-        leaf router-id {
-          type    yang:uuid;
-          description "UUID of router ";
+        list router-ids {
+           key "router-id";
+           leaf router-id {
+               type yang:uuid;
+               description "UUID of router ";
+          }
         }
 
         leaf-list network-ids {
@@ -178,9 +181,12 @@ module neutronvpn {
                 description "The UUID of the tenant that will own the subnet.";
             }
 
-            leaf router-id {
-              type    yang:uuid;
-              description "UUID of router ";
+            list router-ids {
+               key "router-id";
+               leaf router-id {
+                   type yang:uuid;
+                   description "UUID of router ";
+              }
             }
             leaf-list network_ids {
               type    yang:uuid;
@@ -306,10 +312,13 @@ module neutronvpn {
                 mandatory "true";
                 description "vpn-id";
             }
-            leaf router-id {
-                type    yang:uuid;
-                mandatory "true";
-                description "vpn-id";
+            list router-ids {
+               key "router-id";
+               min-elements "1";
+               description "list of router-ids to be associated with the vpn";
+               leaf router-id {
+                   type yang:uuid;
+              }
             }
         }
     }
@@ -322,10 +331,13 @@ module neutronvpn {
                 mandatory "true";
                 description "vpn-id";
             }
-            leaf router-id {
-                type    yang:uuid;
-                mandatory "true";
-                description "router-id";
+            list router-ids {
+               key "router-id";
+               min-elements "1";
+               description "list of router-ids to be dissociated from the vpn";
+               leaf router-id {
+                   type yang:uuid;
+              }
             }
         }
     }
index 0813cd744436a2810b956a4f571e349ab5e7c634..0074135e1a5295f1dac3eed3965d72531e9b290a 100644 (file)
@@ -29,7 +29,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.BgpvpnTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.BgpvpnTypeL3;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.bgpvpns.attributes.Bgpvpns;
@@ -139,15 +138,20 @@ public class NeutronBgpvpnChangeListener extends AsyncDataTreeChangeListenerBase
                             rd);
                     return;
                 }
-                Uuid router = null;
+                List<Uuid> routersList = null;
                 if (input.getRouters() != null && !input.getRouters().isEmpty()) {
-                    // currently only one router
-                    router = input.getRouters().get(0);
+                    // try to take all routers
+                    routersList = input.getRouters();
+                }
+                if (routersList != null && routersList.size() > NeutronConstants.MAX_ROUTERS_PER_BGPVPN) {
+                    LOG.error("Creation of BGPVPN for rd {} failed: maximum allowed number of associated "
+                             + "routers is {}.", rd, NeutronConstants.MAX_ROUTERS_PER_BGPVPN);
+                    return;
                 }
                 if (!rd.isEmpty()) {
                     try {
                         nvpnManager.createVpn(input.getUuid(), input.getName(), input.getTenantId(), rd,
-                                importRouteTargets, exportRouteTargets, router, input.getNetworks(),
+                                importRouteTargets, exportRouteTargets, routersList, input.getNetworks(),
                                 vpnInstanceType, 0 /*l3vni*/);
                     } catch (Exception e) {
                         LOG.error("Creation of BGPVPN {} failed", vpnName, e);
@@ -255,23 +259,37 @@ public class NeutronBgpvpnChangeListener extends AsyncDataTreeChangeListenerBase
     }
 
     protected void handleRoutersUpdate(Uuid vpnId, List<Uuid> oldRouters, List<Uuid> newRouters) {
+        // for dualstack case we can associate with one VPN instance maximum 2 routers: one with
+        // only IPv4 ports and one with only IPv6 ports, or only one router with IPv4/IPv6 ports
+        // TODO: check router ports ethertype to follow this restriction
+        if (oldRouters != null && !oldRouters.isEmpty()) {
+            //remove to oldRouters the newRouters if existing
+            List<Uuid> oldRoutersCopy = new ArrayList<>();
+            oldRoutersCopy.addAll(oldRouters);
+            if (newRouters != null) {
+                newRouters.forEach(r -> oldRoutersCopy.remove(r));
+            }
+            /* dissociate old router */
+            oldRoutersCopy.forEach(r -> {
+                nvpnManager.dissociateRouterFromVpn(vpnId, r);
+            });
+        }
         if (newRouters != null && !newRouters.isEmpty()) {
-            if (oldRouters != null && !oldRouters.isEmpty()) {
-                if (oldRouters.size() > 1 || newRouters.size() > 1) {
-                    VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
-                    if (vpnMap != null && vpnMap.getRouterId() != null) {
-                        LOG.warn("Only single router association to a given bgpvpn is allowed. Kindly disassociate "
-                                + "router {} from vpn {} before proceeding with associate",
-                                vpnMap.getRouterId().getValue(), vpnId.getValue());
+            if (newRouters.size() > NeutronConstants.MAX_ROUTERS_PER_BGPVPN) {
+                LOG.debug("In handleRoutersUpdate: maximum allowed number of associated routers is 2. VPN: {} "
+                        + "is already associated with router: {} and with router: {}",
+                        vpnId, newRouters.get(0).getValue(), newRouters.get(1).getValue());
+                return;
+            } else {
+                for (Uuid routerId : newRouters) {
+                    if (oldRouters != null && oldRouters.contains(routerId)) {
+                        continue;
+                    }
+                    if (validateRouteInfo(routerId)) {
+                        nvpnManager.associateRouterToVpn(vpnId, routerId);
                     }
                 }
-            } else if (validateRouteInfo(newRouters.get(0))) {
-                nvpnManager.associateRouterToVpn(vpnId, newRouters.get(0));
             }
-        } else if (oldRouters != null && !oldRouters.isEmpty()) {
-                /* dissociate old router */
-            Uuid oldRouter = oldRouters.get(0);
-            nvpnManager.dissociateRouterFromVpn(vpnId, oldRouter);
         }
     }
 
index df175d95bf093a813a2d56b413b178f7f801acee..468285ceaaefe78088250176c50d6456639abc5d 100644 (file)
@@ -37,6 +37,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.PreDestroy;
@@ -150,6 +151,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
@@ -491,7 +494,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void deleteSubnetMapNode(Uuid subnetId) {
         InstanceIdentifier<Subnetmap> subnetMapIdentifier =
-                InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
+                InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
         LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
         try {
             synchronized (subnetId.getValue().intern()) {
@@ -657,7 +660,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 builder.setTenantId(tenantId);
             }
             if (router != null) {
-                builder.setRouterId(router);
+                RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
+                List<RouterIds> rtrIds = builder.getRouterIds();
+                if (rtrIds == null) {
+                    rtrIds = Collections.singletonList(vpnRouterId);
+                } else {
+                    rtrIds.add(vpnRouterId);
+                }
+                builder.setRouterIds(rtrIds);
             }
             if (networks != null) {
                 List<Uuid> nwList = builder.getNetworkIds();
@@ -699,8 +709,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (optionalVpnMap.isPresent()) {
             VpnMap vpnMap = optionalVpnMap.get();
             VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
+            List<RouterIds> rtrIds = vpnMap.getRouterIds();
+            if (rtrIds == null) {
+                rtrIds = new ArrayList<>();
+            }
             if (routerId != null) {
                 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
+                    rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
+                    vpnMapBuilder.setRouterIds(rtrIds);
                     try {
                         // remove entire node in case of internal VPN
                         isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
@@ -715,8 +731,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         }
                     }
                     return;
+                } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
+                    rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
+                    vpnMapBuilder.setRouterIds(rtrIds);
+                    LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
                 }
-                vpnMapBuilder.setRouterId(null);
             }
             if (networkIds != null) {
                 List<Uuid> vpnNw = vpnMap.getNetworkIds();
@@ -832,11 +851,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
         Optional<VpnInterface> optionalVpnInterface = null;
         LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
-                   vpnId, internetVpnId, infName);
+                  vpnId, internetVpnId, infName);
         try {
             optionalVpnInterface = SingleTransactionDataBroker
-                .syncReadOptional(dataBroker, LogicalDatastoreType
-                .CONFIGURATION, vpnIfIdentifier);
+                    .syncReadOptional(dataBroker, LogicalDatastoreType
+                    .CONFIGURATION, vpnIfIdentifier);
         } catch (ReadFailedException e) {
             LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
             return;
@@ -863,15 +882,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                       adjString, vpnId);
                 if (vpnId != null) {
                     neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
-                          String.valueOf(adjString), wrtConfigTxn);
+                            String.valueOf(adjString), wrtConfigTxn);
                 }
                 if (internetVpnId != null) {
                     neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
-                            String.valueOf(adjString), wrtConfigTxn);
+                          String.valueOf(adjString), wrtConfigTxn);
                 }
             } else {
                 if (port.getDeviceOwner()
-                    .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null)  {
+                    .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
                     Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
                     if (rtr != null && rtr.getRoutes() != null) {
                         List<Routes> extraRoutesToRemove = new ArrayList<>();
@@ -1050,7 +1069,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     listVpn.add(vpnInstance);
                 }
                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
-                         .setVpnInstanceNames(listVpn);
+                        .setVpnInstanceNames(listVpn);
                 LOG.debug("Updating vpn interface {}", infName);
                 if (!isBeingAssociated) {
                     Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
@@ -1139,21 +1158,23 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * @param rdList Route-distinguisher for the VPN
      * @param irtList A list of Import Route Targets
      * @param ertList A list of Export Route Targets
-     * @param routerId neutron router Id to associate with created VPN
+     * @param routerIdsList ist of neutron router Id to associate with created VPN
      * @param networkList UUID of the neutron network the VPN may be associated to
      * @param type Type of the VPN Instance
      * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
      * @throws Exception if association of L3VPN failed
      */
     public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
-                          List<String> ertList, Uuid routerId, List<Uuid> networkList, VpnInstance.Type type,
-                          long l3vni) throws Exception {
+                    List<String> ertList,  @Nullable List<Uuid> routerIdsList, List<Uuid> networkList,
+                    VpnInstance.Type type, long l3vni) throws Exception {
 
         IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
 
-        if (routerId != null) {
-            IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
-            ipVersChoices = ipVersChoices.addVersion(vers);
+        if (routerIdsList != null && !routerIdsList.isEmpty()) {
+            for (Uuid routerId : routerIdsList) {
+                IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
+                ipVersChoices = ipVersChoices.addVersion(vers);
+            }
         }
         updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
 
@@ -1161,12 +1182,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         // by subsequent calls here to associateRouterToVpn and
         // associateNetworksToVpn
         updateVpnMaps(vpnId, name, null, tenantId, null);
-        LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerID {}, "
-                        + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerId,
+        LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
+                        + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
                 networkList);
 
-        if (routerId != null) {
-            associateRouterToVpn(vpnId, routerId);
+        if (routerIdsList != null && !routerIdsList.isEmpty()) {
+            for (Uuid routerId : routerIdsList) {
+                associateRouterToVpn(vpnId, routerId);
+            }
         }
         if (networkList != null) {
             List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
@@ -1193,6 +1216,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         int warningcount = 0;
 
         List<L3vpn> vpns = input.getL3vpn();
+        if (vpns == null) {
+            vpns = Collections.emptyList();
+        }
         for (L3vpn vpn : vpns) {
             if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
                 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
@@ -1237,23 +1263,27 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 warningcount++;
                 continue;
             }
-            if (vpn.getRouterId() != null) {
-                if (neutronvpnUtils.getNeutronRouter(vpn.getRouterId()) == null) {
-                    errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
-                            formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router not found {}",
-                                    vpn.getId().getValue(), vpn.getRouterId().getValue())));
-                    warningcount++;
-                    continue;
-                }
-                Uuid vpnId = neutronvpnUtils.getVpnForRouter(vpn.getRouterId(), true);
-                if (vpnId != null) {
-                    errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
-                            formatAndLog(LOG::warn,
-                                    "Creation of L3VPN failed for VPN {} due to router {} already associated to "
-                                            + "another VPN {}", vpn.getId().getValue(), vpn.getRouterId().getValue(),
-                                    vpnId.getValue())));
-                    warningcount++;
-                    continue;
+            if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
+                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
+                        routerIdsList = vpn.getRouterIds();
+                for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
+                        routerId : routerIdsList) {
+                    if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
+                        errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
+                                formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
+                                        + "{}", vpn.getId(), routerId.getRouterId())));
+                        warningcount++;
+                        continue;
+                    }
+                    Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
+                    if (vpnId != null) {
+                        errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
+                                formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
+                                                + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
+                                        vpnId.getValue())));
+                        warningcount++;
+                        continue;
+                    }
                 }
             }
             if (vpn.getNetworkIds() != null) {
@@ -1280,13 +1310,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     continue;
                 }
             }
+            List<Uuid> rtrIdsList = new ArrayList<>();
+            if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
+                for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
+                        rtrId : vpn.getRouterIds()) {
+                    rtrIdsList.add(rtrId.getRouterId());
+                }
+            }
             try {
                 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
-                                + "routerID {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
+                                + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
                         vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
-                        vpn.getExportRT().toString(), vpn.getRouterId(), vpn.getNetworkIds());
+                        vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
                 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
-                        vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
+                        vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
                         vpnInstanceType, l3vni);
             } catch (Exception ex) {
                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
@@ -1342,6 +1379,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
                             vpns.add(vpn);
                         }
+                        if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
+                            vpns.add(vpn);
+                        }
                     }
                 } else {
                     // No VPN present
@@ -1359,7 +1399,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 vpnIdentifier);
                 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
                 // getL3VPN output
-                if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
+                if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null)
+                        || (optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
                     vpns.add(optionalVpn.get());
                 } else {
                     result.set(
@@ -1372,22 +1413,35 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
                 // create VpnMaps id
                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
-                List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
+                List<String> rd = Collections.EMPTY_LIST;
+                if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
+                    rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
+                } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
+                    rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
+                }
                 List<String> ertList = new ArrayList<>();
                 List<String> irtList = new ArrayList<>();
 
-                if (vpnInstance.getIpv4Family().getVpnTargets() != null) {
-                    List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
-                    for (VpnTarget vpnTarget : vpnTargetList) {
-                        if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
-                            ertList.add(vpnTarget.getVrfRTValue());
-                        }
-                        if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
-                            irtList.add(vpnTarget.getVrfRTValue());
-                        }
-                        if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
-                            ertList.add(vpnTarget.getVrfRTValue());
-                            irtList.add(vpnTarget.getVrfRTValue());
+                if (vpnInstance.getIpv4Family().getVpnTargets() != null
+                        || vpnInstance.getIpv6Family().getVpnTargets() != null) {
+                    List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
+                    if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
+                        vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
+                    } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
+                        vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
+                    }
+                    if (!vpnTargetList.isEmpty()) {
+                        for (VpnTarget vpnTarget : vpnTargetList) {
+                            if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+                                ertList.add(vpnTarget.getVrfRTValue());
+                            }
+                            if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+                                irtList.add(vpnTarget.getVrfRTValue());
+                            }
+                            if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+                                ertList.add(vpnTarget.getVrfRTValue());
+                                irtList.add(vpnTarget.getVrfRTValue());
+                            }
                         }
                     }
                 }
@@ -1404,8 +1458,16 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 vpnMapIdentifier);
                 if (optionalVpnMap.isPresent()) {
                     VpnMap vpnMap = optionalVpnMap.get();
-                    l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
-                        .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
+                    List<Uuid> rtrIds = new ArrayList<>();
+                    if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
+                        for (RouterIds rtrId : vpnMap.getRouterIds()) {
+                            rtrIds.add(rtrId.getRouterId());
+                        }
+                    }
+                    l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
+                            .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
+                            .setName(vpnMap.getName());
+
                 }
                 l3vpnList.add(l3vpn.build());
             }
@@ -1539,7 +1601,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
                         Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
-                                vpnIface);
+                                    vpnIface);
                         if (vpnIface == null) {
                             LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
                             Set<Uuid> listVpn = new HashSet<>();
@@ -1550,9 +1612,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 listVpn.add(internetId);
                             }
                             writeVpnInterfaceToDs(listVpn,
-                                     vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
+                                    vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
                             if (sn.getRouterId() != null) {
-                                addToNeutronRouterInterfacesMap(sn.getRouterId(),portId.getValue());
+                                addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
                             }
                         } else {
                             LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
@@ -1662,14 +1724,14 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
             txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
                 if (isBeingAssociated) {
-                    updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
-                                    true, true, wrtConfigTxn);
+                    updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
+                            sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
                 } else {
                     removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
                                         wrtConfigTxn, sm);
                 }
-            }
-        )));
+                }
+            )));
 
         // Check for ports on this subnet and update association of
         // corresponding vpn-interfaces to internet vpn
@@ -1677,7 +1739,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (portList != null) {
             for (Uuid port : portList) {
                 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
-                    port.getValue(), isBeingAssociated);
+                        port.getValue(), isBeingAssociated);
                 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
                     () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
                         if (isBeingAssociated) {
@@ -1923,7 +1985,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     .withKey(new AdjacencyKey(destination)).build();
             adjList.add(erAdj);
         }
-        return  adjList;
+        return adjList;
     }
 
     protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
@@ -2045,7 +2107,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
 
             // 2. Router ID
-            Uuid routerUuid = neutronvpnUtils.getRouterforVpn(vpnId);
+            List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
+            Uuid routerUuid = routerUuidList.get(0);
             StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
             detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
 
@@ -2162,14 +2225,18 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     public void removeVpn(Uuid vpnId) {
         // read VPNMaps
         VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
-        Uuid router = vpnMap != null ? vpnMap.getRouterId() : null;
+        List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
         // dissociate router
-        if (router != null) {
-            dissociateRouterFromVpn(vpnId, router);
-        }
-        // dissociate networks
-        if (!vpnId.equals(router) && vpnMap.getNetworkIds() != null) {
-            dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
+        if (routerIdsList != null && !routerIdsList.isEmpty()) {
+            for (RouterIds routerId : routerIdsList) {
+                dissociateRouterFromVpn(vpnId, routerId.getRouterId());
+            }
+            List<Uuid> rtrIdsList = routerIdsList.stream().map(routerId -> routerId.getRouterId())
+                    .collect(Collectors.toList());
+            if (rtrIdsList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
+                // dissociate networks
+                dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
+            }
         }
         // remove entire vpnMaps node
         deleteVpnMapsNode(vpnId);
@@ -2268,7 +2335,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (networkList.isEmpty()) {
             LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
             failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
-                                           vpnId.getValue()));
+                    vpnId.getValue()));
             return failedNwList;
         }
         VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
@@ -2406,7 +2473,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (network == null) {
                 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
                 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
-                                               nw.getValue()));
+                        nw.getValue()));
                 continue;
             }
             Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
@@ -2420,8 +2487,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
                           nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
                 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
-                                               + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
-                                               vpnId.getValue()));
+                                + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
+                                vpnId.getValue()));
                 continue;
             }
             if (NeutronvpnUtils.getIsExternal(network)) {
@@ -2471,7 +2538,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             for (Uuid netId : vpnNets) {
                 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
                     LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
-                              + "{}", vpnId.getValue(), netId.getValue());
+                            + "{}", vpnId.getValue(), netId.getValue());
                     return true;
                 }
             }
@@ -2541,55 +2608,55 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
      * It handles the invocations to the neutronvpn:associateRouter RPC method.
      */
     @Override
-    // TODO Clean up the exception handling
-    @SuppressWarnings("checkstyle:IllegalCatch")
     public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
 
         SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
         LOG.debug("associateRouter {}", input);
         StringBuilder returnMsg = new StringBuilder();
         Uuid vpnId = input.getVpnId();
-        Uuid routerId = input.getRouterId();
-        try {
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
+                routerIds = input.getRouterIds();
+        Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
+        Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
+        Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
+        for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
+                .RouterIds routerId : routerIds) {
             VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
-            Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
+            Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
             if (vpnMap != null) {
                 if (rtr != null) {
-                    Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
-                    if (vpnMap.getRouterId() != null) {
+                    Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
+                    if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
                         returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
-                                .append(vpnMap.getRouterId().getValue());
+                                .append(routerId.getRouterId());
                     } else if (extVpnId != null) {
-                        returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
-                            + "another VPN ").append(extVpnId.getValue());
+                        returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
+                                + "another VPN ").append(extVpnId.getValue());
                     } else {
                         LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
-                                input.getRouterId().getValue());
-                        associateRouterToVpn(vpnId, routerId);
+                                routerId.getRouterId());
+                        associateRouterToVpn(vpnId, routerId.getRouterId());
                     }
                 } else {
-                    returnMsg.append("router not found : ").append(routerId.getValue());
+                    returnMsg.append("router not found : ").append(routerId.getRouterId());
                 }
             } else {
                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
             }
             if (returnMsg.length() != 0) {
                 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
-                        "invalid-value", formatAndLog(LOG::error,
-                                "associate router to vpn {} failed due to {}", routerId.getValue(),returnMsg)).build());
+                        "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
+                                + "due to {}", routerId.getRouterId(), returnMsg)).build());
             } else {
                 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
             }
-        } catch (Exception ex) {
-            result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withError(ErrorType.APPLICATION,
-                    formatAndLog(LOG::error, "associate router {} to vpn {} failed due to {}", routerId.getValue(),
-                            vpnId.getValue(), ex.getMessage(), ex)).build());
         }
         LOG.debug("associateRouter returns..");
         return result;
     }
 
-    /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
+    /**
+     * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
      */
     @Override
     // TODO Clean up the exception handling
@@ -2662,7 +2729,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (returnMsg.length() != 0) {
                 opBuilder.setResponse(
                         "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
-                                "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
+                                "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
+                                returnMsg));
                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
             } else {
                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
@@ -2689,48 +2757,54 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.debug("dissociateRouter {}", input);
         StringBuilder returnMsg = new StringBuilder();
         Uuid vpnId = input.getVpnId();
-        Uuid routerId = input.getRouterId();
-        try {
-            if (neutronvpnUtils.getVpnMap(vpnId) != null) {
-                if (routerId != null) {
-                    Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
-                    if (rtr != null) {
-                        Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
-                        if (vpnId.equals(routerVpnId)) {
-                            LOG.debug("dissociateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
-                                    input.getRouterId().getValue());
-                            dissociateRouterFromVpn(vpnId, routerId);
-                        } else {
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
+                .RouterIds> routerIdList = input.getRouterIds();
+        String routerIdsString = "";
+        Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
+        Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
+        Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
+        if (neutronvpnUtils.getVpnMap(vpnId) != null) {
+            for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
+                    .RouterIds routerId : routerIdList) {
+                try {
+                    if (routerId != null) {
+                        routerIdsString += routerId.getRouterId() + ", ";
+                        Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
+                        if (rtr != null) {
+                            Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
                             if (routerVpnId == null) {
-                                returnMsg.append("input router ").append(routerId.getValue())
-                                    .append(" not associated to any vpn yet");
+                                returnMsg.append("input router ").append(routerId.getRouterId())
+                                        .append(" not associated to any vpn yet");
+                            } else if (vpnId.equals(routerVpnId)) {
+                                dissociateRouterFromVpn(vpnId, routerId.getRouterId());
                             } else {
-                                returnMsg.append("input router ").append(routerId.getValue())
-                                    .append(" associated to vpn ")
-                                    .append(routerVpnId.getValue()).append("instead of the vpn given as input");
+                                returnMsg.append("input router ").append(routerId.getRouterId())
+                                        .append(" associated to vpn ")
+                                        .append(routerVpnId.getValue()).append("instead of the vpn given as input");
                             }
+                        } else {
+                            returnMsg.append("router not found : ").append(routerId.getRouterId());
                         }
+                    }
+                    if (returnMsg.length() != 0) {
+                        result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
+                                "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
+                                                + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
+                                        returnMsg)).build());
                     } else {
-                        returnMsg.append("router not found : ").append(routerId.getValue());
+                        result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
                     }
+                } catch (Exception ex) {
+                    result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
+                            formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
+                                    routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
                 }
-            } else {
-                returnMsg.append("VPN not found : ").append(vpnId.getValue());
-            }
-            if (returnMsg.length() != 0) {
-                result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
-                        "invalid-value", formatAndLog(LOG::error, "dissociate router {} to vpn {} failed due to {}",
-                                routerId.getValue(), vpnId.getValue(), returnMsg)).build());
-            } else {
-                result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
             }
-        } catch (Exception ex) {
-            result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
-                    formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}", routerId.getValue(),
-                            vpnId.getValue(), ex.getMessage(), ex)).build());
+        } else {
+            returnMsg.append("VPN not found : ").append(vpnId.getValue());
         }
-        LOG.debug("dissociateRouter returns..");
 
+        LOG.debug("dissociateRouter returns..");
         return result;
     }
 
@@ -2861,7 +2935,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             result.add("");
             List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
             for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
-                        .rev150602.VpnInstance vpn : vpnList) {
+                    .rev150602.VpnInstance vpn : vpnList) {
                 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
                         : "\"                 " + "                  \"";
                 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
@@ -3016,7 +3090,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
                         optionalVpnInterface.get().getVpnInstanceNames());
                     if (listVpnInstances.isEmpty() || !VpnHelper
-                        .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),listVpnInstances)) {
+                        .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
                         VpnInstanceNames vpnInstance = VpnHelper
                              .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
                         listVpnInstances.add(vpnInstance);
@@ -3085,7 +3159,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
         Uuid extNetId = extNet.getUuid();
         InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
-            .child(Networks.class, new NetworksKey(extNetId)).build();
+                .child(Networks.class, new NetworksKey(extNetId)).build();
 
         try {
             Optional<Networks> optionalExtNets =
@@ -3125,7 +3199,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 builder = new NetworksBuilder(optionalNets.get());
             } else {
                 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
-                          extNetId.getValue());
+                        extNetId.getValue());
                 return false;
             }
             builder.setVpnid(null);
@@ -3136,7 +3210,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return true;
         } catch (TransactionCommitFailedException | ReadFailedException ex) {
             LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
-                      extNetId.getValue(), ex);
+                    extNetId.getValue(), ex);
         }
         return false;
     }
index 2c629a0aa1a8b1ebccfcc0d5153bb0c9f9afb985..e0755843f78f00381f2f237e88cf680b64193dd1 100644 (file)
@@ -29,9 +29,12 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
 import javax.annotation.Nonnull;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+
 import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
@@ -118,6 +121,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension;
@@ -263,7 +268,7 @@ public class NeutronvpnUtils {
     }
 
     // @param external vpn - true if external vpn being fetched, false for internal vpn
-    protected Uuid getVpnForRouter(Uuid routerId, Boolean externalVpn) {
+    protected Uuid getVpnForRouter(Uuid routerId, boolean externalVpn) {
         if (routerId == null) {
             return null;
         }
@@ -273,7 +278,14 @@ public class NeutronvpnUtils {
         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
             for (VpnMap vpnMap : allMaps) {
-                if (routerId.equals(vpnMap.getRouterId())) {
+                List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap
+                    .RouterIds> routerIdsList = vpnMap.getRouterIds();
+                if (routerIdsList == null || routerIdsList.isEmpty()) {
+                    continue;
+                }
+                List<Uuid> rtrIdsList = routerIdsList.stream().map(routerIds -> routerIds.getRouterId())
+                        .collect(Collectors.toList());
+                if (rtrIdsList.contains(routerId)) {
                     if (externalVpn) {
                         if (!routerId.equals(vpnMap.getVpnId())) {
                             return vpnMap.getVpnId();
@@ -290,15 +302,15 @@ public class NeutronvpnUtils {
         return null;
     }
 
-    protected Uuid getRouterforVpn(Uuid vpnId) {
+    protected List<Uuid> getRouterIdListforVpn(Uuid vpnId) {
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap.class,
                 new VpnMapKey(vpnId)).build();
         Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
         if (optionalVpnMap.isPresent()) {
             VpnMap vpnMap = optionalVpnMap.get();
-            return vpnMap.getRouterId();
+            return NeutronUtils.getVpnMapRouterIdsListUuid(vpnMap.getRouterIds());
         }
-        LOG.error("getRouterforVpn: Failed as VPNMaps DS is absent for VPN {}", vpnId.getValue());
+        LOG.error("getRouterIdListforVpn: Failed as VPNMaps DS is absent for VPN {}", vpnId.getValue());
         return null;
     }
 
@@ -1590,44 +1602,52 @@ public class NeutronvpnUtils {
         if (extNetVpnId == null) {
             return subList;
         }
-        Router router = getNeutronRouter(getRouterforVpn(extNetVpnId));
-        ExternalGatewayInfo info = router.getExternalGatewayInfo();
-        if (info == null) {
-            LOG.error("getPrivateSubnetsToExport: can not get info about external gateway for router {}",
-                      router.getUuid().getValue());
-            return subList;
-        }
-        // check that router really has given provider network as its external gateway port
-        if (!extNet.getUuid().equals(info.getExternalNetworkId())) {
-            LOG.error("getPrivateSubnetsToExport: router {} is not attached to given provider network {}",
-                      router.getUuid().getValue(), extNet.getUuid().getValue());
-            return subList;
+        for (Uuid rtrId: getRouterIdListforVpn(extNetVpnId)) {
+            Router router = getNeutronRouter(rtrId);
+            ExternalGatewayInfo info = router.getExternalGatewayInfo();
+            if (info == null) {
+                LOG.error("getPrivateSubnetsToExport: can not get info about external gateway for router {}",
+                          router.getUuid().getValue());
+                continue;
+            }
+            // check that router really has given provider network as its external gateway port
+            if (!extNet.getUuid().equals(info.getExternalNetworkId())) {
+                LOG.error("getPrivateSubnetsToExport: router {} is not attached to given provider network {}",
+                          router.getUuid().getValue(), extNet.getUuid().getValue());
+                continue;
+            }
+            subList.addAll(getSubnetsforVpn(rtrId));
         }
-        return getSubnetsforVpn(router.getUuid());
+        return subList;
     }
 
     public void updateVpnInstanceWithFallback(String vpnName, boolean add) {
         VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName);
         if (vpnInstanceOpDataEntry == null) {
-            // BGPVPN context not found
+            LOG.error("updateVpnInstanceWithFallback: vpnInstanceOpDataEntry not found for vpn {}", vpnName);
             return;
         }
-        String routerIdUuid = getRouterIdfromVpnInstance(vpnInstanceOpDataEntry.getVrfId());
-        if (routerIdUuid != null) {
-            List<BigInteger> dpnIds = getDpnsForRouter(routerIdUuid);
-            if (!dpnIds.isEmpty()) {
-                Long vpnId = vpnInstanceOpDataEntry.getVpnId();
-                VpnInstanceOpDataEntry vpnOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(routerIdUuid);
-                Long routerIdAsLong = vpnOpDataEntry.getVpnId();
-                if (routerIdAsLong == null) {
-                    return;
-                }
-                for (BigInteger dpnId : dpnIds) {
-                    if (add) {
-                        ipV6InternetDefRt.installDefaultRoute(dpnId, vpnId, routerIdAsLong);
-                    } else {
-                        ipV6InternetDefRt.removeDefaultRoute(dpnId, vpnId, routerIdAsLong);
-                    }
+        Long vpnId = vpnInstanceOpDataEntry.getVpnId();
+        List<Uuid> routerIds = getRouterIdsfromVpnInstance(vpnInstanceOpDataEntry.getVrfId());
+        if ((routerIds == null) || (routerIds.isEmpty())) {
+            LOG.error("updateVpnInstanceWithFallback: router not found for vpn {}", vpnName);
+            return;
+        }
+        for (Uuid rtrId: routerIds) {
+            if (rtrId == null) {
+                continue;
+            }
+            List<BigInteger> dpnIds = getDpnsForRouter(rtrId.getValue());
+            if (dpnIds.isEmpty()) {
+                continue;
+            }
+            VpnInstanceOpDataEntry vpnOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(rtrId.getValue());
+            Long routerIdAsLong = vpnOpDataEntry.getVpnId();
+            for (BigInteger dpnId : dpnIds) {
+                if (add) {
+                    ipV6InternetDefRt.installDefaultRoute(dpnId, vpnId, routerIdAsLong);
+                } else {
+                    ipV6InternetDefRt.removeDefaultRoute(dpnId, vpnId, routerIdAsLong);
                 }
             }
         }
@@ -1664,6 +1684,67 @@ public class NeutronvpnUtils {
         }), LOG, "Error updating VPN instance op {} with type {}", vpn, choice);
     }
 
+    public List<Uuid> getAssociateRouterInputRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
+    public List<Uuid> getDisassociateRouterInputRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
+    public RouterIds getvpnMapRouterIds(Uuid routerId) {
+        return new RouterIdsBuilder().setRouterId(routerId).build();
+    }
+
+    public void removeVpnMapRouterIdsFromList(Uuid routerId, List<RouterIds> vpnRouterIds) {
+        Iterator<RouterIds> vpnRouterIdIter = vpnRouterIds.iterator();
+        while (vpnRouterIdIter.hasNext()) {
+            RouterIds vpnRouterId = vpnRouterIdIter.next();
+            if (vpnRouterId.getRouterId().getValue().equals(routerId.getValue())) {
+                vpnRouterIdIter.remove();
+                return;
+            }
+        }
+        return;
+    }
+
+    public boolean vpnMapRouterIdsContainsRouterId(Uuid routerId, List<RouterIds> vpnRouterIds) {
+        if (routerId == null) {
+            return false;
+        }
+        return vpnRouterIds.stream().anyMatch(vpnRouterId ->
+              vpnRouterId.getRouterId().getValue().equals(routerId.getValue()));
+    }
+
+    public List<Uuid> getVpnInstanceRouterIdsListUuid(List<RouterIds> routerIds) {
+        if (routerIds == null) {
+            return Collections.emptyList();
+        }
+        return routerIds.stream().map(
+            routerId -> routerId.getRouterId()).collect(Collectors.toList());
+    }
+
+    public static RouterIds getvpnInstanceRouterIds(Uuid routerId) {
+        return new RouterIdsBuilder().setRouterId(routerId).build();
+    }
+
+    public static List<RouterIds> getVpnInstanceRouterIdsList(List<Uuid> routerIds) {
+        List<RouterIds> listRouterIds = new ArrayList<>();
+        for (Uuid routerId : routerIds) {
+            final RouterIds routerIdInstance = getvpnInstanceRouterIds(routerId);
+            listRouterIds.add(routerIdInstance);
+        }
+        return listRouterIds;
+    }
+
     @Nonnull
     public List<BigInteger> getDpnsForRouter(String routerUuid) {
         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class)
@@ -1681,7 +1762,7 @@ public class NeutronvpnUtils {
         return dpns;
     }
 
-    public String getRouterIdfromVpnInstance(String vpnName) {
+    public List<Uuid> getRouterIdsfromVpnInstance(String vpnName) {
         // returns only router, attached to IPv4 networks
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
             .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
@@ -1689,15 +1770,13 @@ public class NeutronvpnUtils {
                 .syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
                         LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
         if (!optionalVpnMap.isPresent()) {
-            LOG.error("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
+            LOG.error("getRouterIdsfromVpnInstance : Router not found for vpn : {}", vpnName);
             return null;
         }
-        Uuid routerId = optionalVpnMap.get().getRouterId();
-        if (routerId != null) {
-            return routerId.getValue();
-        }
-        LOG.info("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
-        return null;
+        List<Uuid> rtrIds = optionalVpnMap.get().getRouterIds().stream().map(routerIds -> routerIds.getRouterId())
+                .collect(Collectors.toList());
+        return rtrIds;
+
     }
 
     public InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
index fea4029cc0d373d64f19b660c57701afb076bd4a..d451c969f2df203442495108af677e3f09cdaacb 100755 (executable)
@@ -15,7 +15,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
@@ -32,6 +31,7 @@ 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.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
@@ -39,6 +39,7 @@ import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 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;
@@ -346,14 +347,21 @@ public class IVpnLinkServiceImpl implements IVpnLinkService, AutoCloseable {
             LOG.info("Could not retrieve VpnMaps object from Configurational DS");
             return new HashMap<>();
         }
-        Predicate<VpnMap> isExternalVpn =
-            (vpnMap) -> vpnMap.getRouterId() != null
-                        && ! vpnMap.getVpnId().getValue().equalsIgnoreCase(vpnMap.getRouterId().getValue());
-
-        return optVpnMaps.get().getVpnMap().stream()
-                                           .filter(isExternalVpn)
-                                           .collect(Collectors.toMap(v -> v.getRouterId().getValue(),
-                                               v -> v.getVpnId().getValue()));
+        Map<String,String> vmap = new HashMap<String,String>();
+        final List<VpnMap> VpnMapList = optVpnMaps.get().getVpnMap();
+        for (VpnMap map : VpnMapList) {
+            if (map.getRouterIds() == null) {
+                continue;
+            }
+            final List<Uuid> vpnRouterIds = NeutronUtils.getVpnMapRouterIdsListUuid(map.getRouterIds());
+            for (Uuid routerId : vpnRouterIds) {
+                if (map.getVpnId().getValue().equalsIgnoreCase(routerId.getValue())) {
+                    break; // VPN is internal
+                }
+                vmap.put(routerId.getValue(), map.getVpnId().getValue());
+            }
+        }
+        return vmap;
     }