NETVIRT-1201 Upstream fixes to master --- 8 05/73705/4
authoreupakir <kiran.n.upadhyaya@ericsson.com>
Tue, 10 Apr 2018 07:23:04 +0000 (12:53 +0530)
committerSam Hague <shague@redhat.com>
Wed, 4 Jul 2018 18:15:15 +0000 (18:15 +0000)
This fix does not associate subnet to vpn,
if another subnet with the same cidr is already associated
to any configured vpn with the same route-targets.
This is currently handled only for network association
to vpn.

Change-Id: I035b2d1854f5bc5f8880ff35eea63ab861ac1a56
Signed-off-by: eupakir <kiran.n.upadhyaya@ericsson.com>
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronBgpvpnChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronSubnetChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java
vpnmanager/api/src/main/java/org/opendaylight/netvirt/vpnmanager/api/IVpnManager.java
vpnmanager/api/src/main/yang/odl-l3vpn.yang
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetmapChangeListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/TunnelInterfaceStateListener.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java

index 0074135e1a5295f1dac3eed3965d72531e9b290a..de2cd4cfaaac816d610d9c201c768d378fd9eb64 100644 (file)
@@ -237,24 +237,39 @@ public class NeutronBgpvpnChangeListener extends AsyncDataTreeChangeListenerBase
                     //clear removed networks
                     if (!oldNetworks.isEmpty()) {
                         LOG.trace("Removing old networks {} ", oldNetworks);
-                        nvpnManager.dissociateNetworksFromVpn(vpnId, oldNetworks);
+                        List<String> errorMessages = nvpnManager.dissociateNetworksFromVpn(vpnId, oldNetworks);
+                        if (!errorMessages.isEmpty()) {
+                            LOG.error("handleNetworksUpdate: dissociate old Networks not part of bgpvpn update,"
+                                    + " from vpn {} failed due to {}", vpnId.getValue(), errorMessages);
+                        }
                     }
 
                     //add new (Delta) Networks
                     if (!newNetworks.isEmpty()) {
                         LOG.trace("Adding delta New networks {} ", newNetworks);
-                        nvpnManager.associateNetworksToVpn(vpnId, newNetworks);
+                        List<String> errorMessages = nvpnManager.associateNetworksToVpn(vpnId, newNetworks);
+                        if (!errorMessages.isEmpty()) {
+                            LOG.error("handleNetworksUpdate: associate new Networks not part of original bgpvpn,"
+                                    + " to vpn {} failed due to {}", vpnId.getValue(), errorMessages);
+                        }
                     }
                 }
             } else {
                 //add new Networks
                 LOG.trace("Adding New networks {} ", newNetworks);
-                nvpnManager.associateNetworksToVpn(vpnId, newNetworks);
+                List<String> errorMessages = nvpnManager.associateNetworksToVpn(vpnId, newNetworks);
+                if (!errorMessages.isEmpty()) {
+                    LOG.error("handleNetworksUpdate: associate new Networks to vpn {} failed due to {}",
+                            vpnId.getValue(), errorMessages);
+                }
             }
         } else if (oldNetworks != null && !oldNetworks.isEmpty()) {
             LOG.trace("Removing old networks {} ", oldNetworks);
-            nvpnManager.dissociateNetworksFromVpn(vpnId, oldNetworks);
-
+            List<String> errorMessages = nvpnManager.dissociateNetworksFromVpn(vpnId, oldNetworks);
+            if (!errorMessages.isEmpty()) {
+                LOG.error("handleNetworksUpdate: dissociate old Networks from vpn {} failed due to {}",
+                        vpnId.getValue(), errorMessages);
+            }
         }
     }
 
index a0fefa4acef748272e5ce8ad2cd2784a324bd447..ba6758f77c6414b53b17120de41c778ba0f08329 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.netvirt.neutronvpn;
 import com.google.common.base.Optional;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -19,12 +20,15 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
 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.natservice.rev160111.ProviderTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
@@ -40,15 +44,18 @@ public class NeutronSubnetChangeListener extends AsyncDataTreeChangeListenerBase
     private final NeutronvpnManager nvpnManager;
     private final NeutronExternalSubnetHandler externalSubnetHandler;
     private final NeutronvpnUtils neutronvpnUtils;
+    private final IVpnManager vpnManager;
 
     @Inject
     public NeutronSubnetChangeListener(final DataBroker dataBroker, final NeutronvpnManager neutronvpnManager,
-            final NeutronExternalSubnetHandler externalSubnetHandler, final NeutronvpnUtils neutronvpnUtils) {
+            final NeutronExternalSubnetHandler externalSubnetHandler, final NeutronvpnUtils neutronvpnUtils,
+                                       final IVpnManager vpnManager) {
         super(Subnet.class, NeutronSubnetChangeListener.class);
         this.dataBroker = dataBroker;
         this.nvpnManager = neutronvpnManager;
         this.externalSubnetHandler = externalSubnetHandler;
         this.neutronvpnUtils = neutronvpnUtils;
+        this.vpnManager = vpnManager;
     }
 
     @Override
@@ -98,7 +105,7 @@ public class NeutronSubnetChangeListener extends AsyncDataTreeChangeListenerBase
                     subnetId.getValue(), network);
             return;
         }
-        handleNeutronSubnetDeleted(subnetId, networkId);
+        handleNeutronSubnetDeleted(subnetId, networkId, String.valueOf(input.getCidr().getValue()));
         externalSubnetHandler.handleExternalSubnetRemoved(network, subnetId);
         neutronvpnUtils.removeFromSubnetCache(input);
     }
@@ -121,10 +128,22 @@ public class NeutronSubnetChangeListener extends AsyncDataTreeChangeListenerBase
         createSubnetToNetworkMapping(subnetId, networkId);
     }
 
-    private void handleNeutronSubnetDeleted(Uuid subnetId, Uuid networkId) {
+    private void handleNeutronSubnetDeleted(Uuid subnetId, Uuid networkId, String subnetCidr) {
         Uuid vpnId = neutronvpnUtils.getVpnForNetwork(networkId);
         if (vpnId != null) {
-            nvpnManager.removeSubnetFromVpn(vpnId, subnetId, null /* internet-vpn-id */);
+            LOG.warn("Subnet {} deleted without disassociating network {} from VPN {}. Ideally, please disassociate "
+                    + "network from VPN before deleting neutron subnet.", subnetId.getValue(), networkId.getValue(),
+                    vpnId.getValue());
+            Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
+            if (subnetmap != null) {
+                nvpnManager.removeSubnetFromVpn(vpnId, subnetId, null /* internet-vpn-id */);
+            } else {
+                LOG.error("Subnetmap for subnet {} not found", subnetId.getValue());
+            }
+            Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+            if (!routeTargets.isEmpty()) {
+                vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetCidr, subnetId.getValue());
+            }
         }
         if (networkId != null) {
             deleteSubnetToNetworkMapping(subnetId, networkId);
index 1f01ddeb0117a46b7e4bf826d258efc174bae65a..48752cfd5d50d151669c77b714e30888ee32a2f0 100644 (file)
@@ -201,6 +201,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     private final NeutronEvpnUtils neutronEvpnUtils;
     private final JobCoordinator jobCoordinator;
     private final NeutronvpnUtils neutronvpnUtils;
+    private final IVpnManager vpnManager;
     private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
     private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
     private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
@@ -224,6 +225,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
         this.jobCoordinator = jobCoordinator;
         this.neutronvpnUtils = neutronvpnUtils;
+        this.vpnManager = vpnManager;
 
         configureFeatures();
     }
@@ -2348,6 +2350,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                                + "associated with", vpnId.getValue()));
                 return failedNwList;
             }
+            Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
             for (Uuid nw : networkList) {
                 Network network = neutronvpnUtils.getNeutronNetwork(nw);
                 if (network == null) {
@@ -2379,29 +2382,35 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                             nw.getValue(), vpnId.getValue()));
                     continue;
                 }
-                List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
-                if (networkSubnets == null) {
+                List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
+                if (subnetmapList == null || subnetmapList.isEmpty()) {
                     passedNwList.add(nw);
                     continue;
                 }
-                for (Uuid subnet : networkSubnets) {
-                    Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnet);
+                if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
+                    continue;
+                }
+                for (Subnetmap subnetmap : subnetmapList) {
+                    Uuid subnetId = subnetmap.getId();
+                    Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
                     if (subnetVpnId != null) {
-                        LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {} as it is already "
-                                  + "associated", subnet.getValue(), subnetVpnId.getValue());
-                        failedNwList.add(String.format("Failed to associate subnet %s with VPN %s as it is already "
-                                                       + "associated", subnet.getValue(), vpnId.getValue()));
+                        LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
+                                + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
+                        failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
+                                + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
                         continue;
                     }
-                    Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
-                    if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sm, vpnId)) {
+                    if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(subnetmap, vpnId)) {
                         neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                                NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()), true);
+                                NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()), true);
                     }
                     if (!neutronvpnUtils.getIsExternal(network)) {
-                        LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnet.getValue(),
+                        LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
                                 vpnId.getValue());
-                        addSubnetToVpn(vpnId, subnet, null);
+                        addSubnetToVpn(vpnId, subnetId, null);
+                        vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
+                                vpnId.getValue());
+                        passedNwList.add(nw);
                     }
                 }
                 passedNwList.add(nw);
@@ -2464,6 +2473,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             return failedNwList;
         }
         for (Uuid nw : networkList) {
+            List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
+            if (networkSubnets == null) {
+                passedNwList.add(nw);
+                continue;
+            }
             Network network = neutronvpnUtils.getNeutronNetwork(nw);
             if (network == null) {
                 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
@@ -2498,22 +2512,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     continue;
                 }
             }
-            List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
-            if (networkSubnets == null) {
-                passedNwList.add(nw);
-                continue;
-            }
+            Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
             for (Uuid subnet : networkSubnets) {
-                Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
-                if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sm, vpnId)) {
+                Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
+                if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(subnetmap, vpnId)) {
                     IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
-                    IpVersionChoice ipVersion = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
+                    IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
                     neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
                         ipVersionsToRemove.addVersion(ipVersion), false);
                 }
                 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
                           vpnId.getValue());
                 removeSubnetFromVpn(vpnId, subnet, null);
+                vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
+                        vpnId.getValue());
                 passedNwList.add(nw);
             }
         }
index e0755843f78f00381f2f237e88cf680b64193dd1..4d9763ed8d1c3abf9dc248601dd9cc7916c3e9ce 100644 (file)
@@ -773,6 +773,7 @@ public class NeutronvpnUtils {
 
         if (sn.isPresent()) {
             subnet = sn.get();
+            addToSubnetCache(subnet);
         }
         return subnet;
     }
@@ -1784,4 +1785,24 @@ public class NeutronvpnUtils {
              .child(Routers.class).child(Router.class, new RouterKey(routerUuid));
         return routerInstanceIdentifier;
     }
+
+    List<Subnetmap> getSubnetmapListFromNetworkId(Uuid networkId) {
+        List<Uuid> subnetIdList = getSubnetIdsFromNetworkId(networkId);
+        if (subnetIdList != null) {
+            List<Subnetmap> subnetmapList = new ArrayList<>();
+            for (Uuid subnetId : subnetIdList) {
+                Subnetmap subnetmap = getSubnetmap(subnetId);
+                if (subnetmap != null) {
+                    subnetmapList.add(subnetmap);
+                } else {
+                    LOG.error("getSubnetmapListFromNetworkId: subnetmap is null for subnet {} belonging to network {}",
+                            subnetId.getValue(), networkId.getValue());
+                }
+            }
+            return subnetmapList;
+        }
+        LOG.error("getSubnetmapListFromNetworkId: Failed as subnetIdList is null for network {}",
+                networkId.getValue());
+        return null;
+    }
 }
index 1779fa49c468a47c5ab62f517688a4195bedb151..03a43ab7a08beb57b76ff0bf3736237bf5c89519 100644 (file)
@@ -11,10 +11,13 @@ package org.opendaylight.netvirt.vpnmanager.api;
 import java.math.BigInteger;
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
 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.fibmanager.rev150330.vrfentries.VrfEntry;
@@ -93,4 +96,13 @@ public interface IVpnManager {
     String getVpnRd(DataBroker broker, String vpnName);
 
     VpnPortipToPort getNeutronPortFromVpnPortFixedIp(DataBroker broker, String vpnName, String fixedIp);
+
+    void updateRouteTargetsToSubnetAssociation(Set<VpnTarget> routeTargets, String cidr, String vpnName);
+
+    void removeRouteTargetsToSubnetAssociation(Set<VpnTarget> routeTargets, String cidr, String vpnName);
+
+    boolean checkForOverlappingSubnets(Uuid network, List<Subnetmap> subnetmapList, Uuid vpn,
+                                       Set<VpnTarget> routeTargets, List<String> failedNwList);
+
+    Set<VpnTarget> getRtListForVpn(String vpnName);
 }
index a9c2b9ebbf86bbf7c3616be5a3f7550540f89986..dc927e7cd1f7fef4b51eec0330d86b51f4f2f546 100644 (file)
@@ -740,4 +740,31 @@ module odl-l3vpn {
             leaf learnt-vpn-vip-event-id { type string; }
         }
     }
+
+    /* rt to subnets map */
+    container subnets-associated-to-route-targets {
+        config false;
+        list route-target {
+            key "rt rt-type";
+            leaf rt { type string; }
+            leaf rt-type {
+                type enumeration {
+                    enum iRT {
+                        value "0";
+                    }
+                    enum eRT {
+                        value "1";
+                    }
+                }
+            }
+            list associated-subnet {
+                key cidr;
+                leaf cidr { type string; }
+                list associated-vpn {
+                    key "name";
+                    leaf name  { type string; }
+                }
+            }
+        }
+    }
 }
index 196528dfaeefb6d5aa21fd4c61cd65a01b1c721e..57ff3485fceba15f80139f49ccccb14819aad2e3 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Optional;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -20,6 +21,8 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
 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.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
@@ -38,14 +41,16 @@ public class SubnetmapChangeListener extends AsyncDataTreeChangeListenerBase<Sub
     private final DataBroker dataBroker;
     private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
     private final VpnUtil vpnUtil;
+    private final IVpnManager vpnManager;
 
     @Inject
     public SubnetmapChangeListener(final DataBroker dataBroker, final VpnSubnetRouteHandler vpnSubnetRouteHandler,
-                                   VpnUtil vpnUtil) {
+                                   VpnUtil vpnUtil, IVpnManager vpnManager) {
         super(Subnetmap.class, SubnetmapChangeListener.class);
         this.dataBroker = dataBroker;
         this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
         this.vpnUtil = vpnUtil;
+        this.vpnManager = vpnManager;
     }
 
     @PostConstruct
@@ -96,11 +101,21 @@ public class SubnetmapChangeListener extends AsyncDataTreeChangeListenerBase<Sub
                       elanInstanceName, subnetId.getValue());
             return;
         }
-        if (subnetmap.getVpnId() != null) {
-            boolean isBgpVpn = !subnetmap.getVpnId().equals(subnetmap.getRouterId());
+        Uuid vpnId = subnetmap.getVpnId();
+        if (vpnId != null) {
+            boolean isBgpVpn = !vpnId.equals(subnetmap.getRouterId());
             LOG.info("SubnetMapChangeListener:add: subnetmap {} with elanTag {} to VPN {}", subnetmap, elanTag,
-                     subnetmap.getVpnId());
+                     vpnId);
             vpnSubnetRouteHandler.onSubnetAddedToVpn(subnetmap, isBgpVpn, elanTag);
+            if (isBgpVpn && subnetmap.getRouterId() == null) {
+                Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+                if (!routeTargets.isEmpty()) {
+                    synchronized (subnetmap.getSubnetIp().intern()) {
+                        vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
+                                vpnId.getValue());
+                    }
+                }
+            }
         }
     }
 
index d8928d8cac29958da28406ca9ed0db5151f33347..e315adc33668270676fecd085f929187b70c7235 100644 (file)
@@ -348,7 +348,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                 interfaces = interfacelistIter.next();
                 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
                     LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
-                    return;
+                    continue;
                 }
                 intfName = interfaces.getInterfaceName();
                 VpnInterface vpnInterface =
@@ -371,7 +371,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                 interfaces = interfacelistIter.next();
                 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
                     LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
-                    return;
+                    continue;
                 }
                 intfName = interfaces.getInterfaceName();
                 VpnInterface vpnInterface =
index 564d045a4820ac6a0eade50a536a5350d3567805..7c0325c87e7eeab2c749401820312b4bf95d5087 100644 (file)
@@ -13,13 +13,16 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 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.ReadFailedException;
@@ -54,6 +57,7 @@ import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComp
 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -66,8 +70,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpc
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetsAssociatedToRouteTargets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.RouteTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.RouteTargetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.AssociatedSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.associated.subnet.AssociatedVpn;
 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.to.extraroutes.vpn.extra.routes.Routes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
@@ -730,4 +739,243 @@ public class VpnManagerImpl implements IVpnManager {
     public VpnPortipToPort getNeutronPortFromVpnPortFixedIp(DataBroker broker, String vpnName, String fixedIp) {
         return vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, fixedIp);
     }
+
+    @Override
+    public Set<VpnTarget> getRtListForVpn(String vpnName) {
+        return vpnUtil.getRtListForVpn(vpnName);
+    }
+
+    @Override
+    public void updateRouteTargetsToSubnetAssociation(Set<VpnTarget> routeTargets, String cidr, String vpnName) {
+        ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+            for (VpnTarget rt : routeTargets) {
+                String rtValue = rt.getVrfRTValue();
+                switch (rt.getVrfRTType()) {
+                    case ImportExtcommunity:
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.IRT, cidr,  vpnName,
+                                tx, false/*isAssociationRemoved*/);
+                        break;
+                    case ExportExtcommunity:
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.ERT, cidr, vpnName,
+                                tx, false/*isAssociationRemoved*/);
+                        break;
+                    case Both:
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.IRT, cidr, vpnName,
+                                tx, false/*isAssociationRemoved*/);
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.ERT, cidr, vpnName,
+                                tx, false/*isAssociationRemoved*/);
+                        break;
+                    default:
+                        LOG.error("updateRouteTargetsToSubnetAssociation: Invalid rt-type {} for vpn {}"
+                                + " subnet-cidr {}", rt.getVrfRTType(), vpnName, cidr);
+                        break;
+                }
+            }
+        }), LOG, "updateRouteTargetsToSubnetAssociation: Failed for vpn {} subnet-cidr {}", vpnName, cidr);
+        LOG.info("updateRouteTargetsToSubnetAssociation: Updated RT to subnet association for vpn {} cidr {}",
+                vpnName, cidr);
+    }
+
+    @Override
+    public void removeRouteTargetsToSubnetAssociation(Set<VpnTarget> routeTargets, String cidr, String vpnName) {
+        ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+            for (VpnTarget rt : routeTargets) {
+                String rtValue = rt.getVrfRTValue();
+                switch (rt.getVrfRTType()) {
+                    case ImportExtcommunity:
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.IRT, cidr, vpnName, tx,
+                                true/*isAssociationRemoved*/);
+                        break;
+                    case ExportExtcommunity:
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.ERT, cidr, vpnName, tx,
+                                true/*isAssociationRemoved*/);
+                        break;
+                    case Both:
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.IRT, cidr, vpnName, tx,
+                                true/*isAssociationRemoved*/);
+                        addSubnetAssociationOperationToTx(rtValue, RouteTarget.RtType.ERT, cidr, vpnName, tx,
+                                true/*isAssociationRemoved*/);
+                        break;
+                    default:
+                        LOG.error("removeRouteTargetsToSubnetAssociation: Invalid route-target type {} for vpn {}"
+                                + " subnet-cidr {}", rt.getVrfRTType(), vpnName, cidr);
+                        break;
+                }
+            }
+        }), LOG, "removeRouteTargetsToSubnetAssociation: Failed for vpn {} subnet-cidr {}", vpnName, cidr);
+        LOG.info("removeRouteTargetsToSubnetAssociation: vpn {} cidr {}", vpnName, cidr);
+    }
+
+    private boolean doesExistingVpnsHaveConflictingSubnet(Set<VpnTarget> routeTargets, String subnetCidr) {
+        Set<RouteTarget> routeTargetSet = vpnUtil.getRouteTargetSet(routeTargets);
+        for (RouteTarget routerTarget : routeTargetSet) {
+            if (routerTarget.getAssociatedSubnet() != null) {
+                for (int i = 0; i < routerTarget.getAssociatedSubnet().size(); i++) {
+                    AssociatedSubnet associatedSubnet = routerTarget.getAssociatedSubnet().get(i);
+                    if (VpnUtil.areSubnetsOverlapping(associatedSubnet.getCidr(), subnetCidr)) {
+                        return true;
+                    }
+                    if (routerTarget.getRtType() == RouteTarget.RtType.ERT) {
+                        /* Check if there are multiple exports for the input iRT value (iRT in routeTargets)
+                         *  Example : (1) iRT=A eRT=B subnet-range=S1; OK
+                         *            (2) iRT=A eRT=B subnet-range=S1; OK
+                         *            (3) iRT=B eRT=A subnet-range=S2; NOK
+                         * Check if (1) and (2) are importing the same subnet-range routes to (3) */
+                        List<AssociatedVpn> multipleAssociatedVpn = associatedSubnet.getAssociatedVpn();
+                        if (multipleAssociatedVpn != null && multipleAssociatedVpn.size() > 1) {
+                            LOG.error("doesExistingVpnsHaveConflictingSubnet: There is an indirect complete  overlap"
+                                    + " for subnet CIDR {} for rt {} rtType {}", subnetCidr, routerTarget.getRt(),
+                                    routerTarget.getRtType());
+                            return true;
+                        }
+                        for (int j = i + 1; j < routerTarget.getAssociatedSubnet().size(); j++) {
+                            if (VpnUtil.areSubnetsOverlapping(associatedSubnet.getCidr(),
+                                    routerTarget.getAssociatedSubnet().get(j).getCidr())) {
+                                LOG.error("doesExistingVpnsHaveConflictingSubnet: There is an indirect paartial"
+                                                + " overlap for subnet CIDR {} for rt {} rtType {}", subnetCidr,
+                                        routerTarget.getRt(), routerTarget.getRtType());
+                                return true;
+                            }
+                        }
+                    }
+                }
+                /* Check if there are indirect EXPORTS for the eRT value (eRT in routeTargets)
+                 *  Example : (1) iRT=A eRT=B subnet-range=S1; OK
+                 *            (2) iRT=B eRT=A subnet-range=S2; OK
+                 *            (3) iRT=A eRT=B subnet-range=S1; NOK
+                 * If associatedSubnet is non-null for a routeTarget in (2),
+                 * it may have already imported routes from (1) */
+                if (routerTarget.getRtType() == RouteTarget.RtType.IRT) {
+                    try {
+                        Optional<RouteTarget> indirectRts = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                                LogicalDatastoreType.OPERATIONAL, VpnUtil.getRouteTargetsIdentifier(
+                                        routerTarget.getRt(), RouteTarget.RtType.ERT));
+                        if (indirectRts.isPresent() && routerTarget.getAssociatedSubnet() != null) {
+                            for (AssociatedSubnet associatedSubnet : indirectRts.get().getAssociatedSubnet()) {
+                                if (VpnUtil.areSubnetsOverlapping(associatedSubnet.getCidr(), subnetCidr)) {
+                                    LOG.error("doesExistingVpnsHaveConflictingSubnet: There is an indirect overlap for"
+                                            + " subnet CIDR {} for rt {} rtType {}", subnetCidr, routerTarget.getRt(),
+                                            routerTarget.getRtType());
+                                    return true;
+                                }
+                            }
+                        }
+                    } catch (ReadFailedException e) {
+                        LOG.error("doesExistingVpnsHaveConflictingSubnet: Failed to read route targets to subnet"
+                                + "association for rt {} type {} subnet-cidr {}", routerTarget.getRt(),
+                                RouteTarget.RtType.ERT, subnetCidr);
+                        return true; //Fail subnet association to avoid further damage to the data-stores
+                    }
+                }
+            } else {
+                LOG.info("doesExistingVpnsHaveConflictingSubnet: No prior associated subnets for rtVal {} rtType {}",
+                        routerTarget.getRt(), routerTarget.getRtType());
+            }
+        }
+        return false;
+    }
+
+    private void addSubnetAssociationOperationToTx(String rt, RouteTarget.RtType rtType, String cidr,
+                                                   String vpnName, ReadWriteTransaction tx,
+                                                   boolean isAssociationRemoved)
+            throws InterruptedException, ExecutionException {
+        if (isAssociationRemoved) {
+            //Remove RT-Subnet-Vpn Association
+            Optional<AssociatedSubnet> associatedSubnet = tx.read(LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getAssociatedSubnetIdentifier(rt, rtType, cidr)).get();
+            boolean deleteParent = false;
+            if (associatedSubnet.isPresent()) {
+                List<AssociatedVpn> associatedVpns = associatedSubnet.get().getAssociatedVpn();
+                if (associatedVpns == null || associatedVpns.isEmpty()) {
+                    deleteParent = true;
+                } else {
+                    for (Iterator<AssociatedVpn> iterator = associatedVpns.iterator(); iterator.hasNext();) {
+                        AssociatedVpn associatedVpn = (AssociatedVpn) iterator.next();
+                        if (associatedVpn.getName().equals(vpnName)) {
+                            iterator.remove();
+                            break;
+                        }
+                    }
+                    if (associatedVpns.isEmpty()) {
+                        deleteParent = true;
+                    }
+                }
+            }
+            if (deleteParent) {
+                deleteParentForSubnetToVpnAssocication(rt, rtType, cidr, tx);
+            } else {
+                //Some other VPNs are also part of this rtVal, rtType and subnetCidr combination.
+                //Delete only this AssociatedVpn Object
+                tx.delete(LogicalDatastoreType.OPERATIONAL,
+                        VpnUtil.getAssociatedSubnetAndVpnIdentifier(rt, rtType, cidr, vpnName));
+                LOG.debug("addSubnetAssocOperationToTx: Removed vpn {} from association rt {} rtType {} cidr {}",
+                        vpnName, rt, rtType, cidr);
+            }
+        } else {
+            //Add RT-Subnet-Vpn Association
+            tx.put(LogicalDatastoreType.OPERATIONAL,
+                    VpnUtil.getAssociatedSubnetAndVpnIdentifier(rt, rtType, cidr, vpnName),
+                    VpnUtil.buildAssociatedSubnetAndVpn(vpnName), true);
+        }
+    }
+
+    private void deleteParentForSubnetToVpnAssocication(String rt, RouteTarget.RtType rtType,
+                                                String cidr, ReadWriteTransaction tx)
+            throws InterruptedException, ExecutionException {
+        //Check if you need to delete rtVal+rtType or just the subnetCidr
+        InstanceIdentifier<RouteTarget> rtIdentifier = InstanceIdentifier
+                .builder(SubnetsAssociatedToRouteTargets.class).child(RouteTarget.class,
+                        new RouteTargetKey(rt, rtType)).build();
+        Optional<RouteTarget> rtToSubnetsAssociation = tx.read(LogicalDatastoreType.OPERATIONAL,
+                rtIdentifier).get();
+        if (rtToSubnetsAssociation.isPresent()) {
+            List<AssociatedSubnet> associatedSubnets = rtToSubnetsAssociation.get().getAssociatedSubnet();
+            if (associatedSubnets != null && !associatedSubnets.isEmpty()) {
+                for (Iterator<AssociatedSubnet> iterator = associatedSubnets.iterator(); iterator.hasNext(); ) {
+                    if (iterator.next().getCidr().equals(cidr)) {
+                        iterator.remove();
+                        break;
+                    }
+                }
+                if (associatedSubnets.isEmpty()) {
+                    //The entire rt to subnet association is empty
+                    //Delete the RouteTarget object
+                    tx.delete(LogicalDatastoreType.OPERATIONAL, rtIdentifier);
+                    LOG.debug("deleteParentForSubnetToVpnAssocication: Removed rt {} rtType {} from association,",
+                            rt, rtType);
+                } else {
+                    //Some other VPNs are also part of this rtVal, rtType combination
+                    //Delete only this AssociatedSubnet
+                    tx.delete(LogicalDatastoreType.OPERATIONAL, VpnUtil.getAssociatedSubnetIdentifier(rt, rtType,
+                            cidr));
+                    LOG.debug("deleteParentForSubnetToVpnAssocication: Removed cidr {} from association rt {}"
+                            + " rtType {}", cidr, rt, rtType);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean checkForOverlappingSubnets(Uuid network, List<Subnetmap> subnetmapList, Uuid vpn,
+                                       Set<VpnTarget> routeTargets, List<String> failedNwList) {
+        for (int i = 0; i < subnetmapList.size(); i++) {
+            //Check if any other subnet that is already part of a different vpn with same rt, has overlapping CIDR
+            if (checkExistingSubnetWithSameRoutTargets(routeTargets, vpn, subnetmapList.get(i), failedNwList)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkExistingSubnetWithSameRoutTargets(Set<VpnTarget> routeTargets, Uuid vpn, Subnetmap subnetmap,
+                                                   List<String> failedNwList) {
+        String cidr = String.valueOf(subnetmap.getSubnetIp());
+        boolean subnetExistsWithSameRt = doesExistingVpnsHaveConflictingSubnet(routeTargets, cidr);
+        if (subnetExistsWithSameRt) {
+            failedNwList.add(String.format("Another subnet with the same/overlapping cidr %s as subnet %s"
+                    + " is already associated to a vpn with routeTargets %s. Ignoring subnet addition to vpn"
+                    + " %s", cidr, subnetmap.getId().getValue(), routeTargets.toString(), vpn.getValue()));
+        }
+        return subnetExistsWithSameRt;
+    }
 }
index b5c71fc8d548b8cf94f12dba7c3294addcc50368..6053a56f82befc231ce370ab0492a1bc2a0b16e4 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.Iterators;
+import com.google.common.net.InetAddresses;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
@@ -153,6 +154,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Lea
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortEventData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetsAssociatedToRouteTargets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInterfaceOpData;
@@ -173,6 +175,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.pre
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.RouteTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.RouteTargetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.AssociatedSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.AssociatedSubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.associated.subnet.AssociatedVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.associated.subnet.AssociatedVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnets.associated.to.route.targets.route.target.associated.subnet.AssociatedVpnKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
@@ -2030,4 +2039,123 @@ public final class VpnUtil {
             LOG.error("Failed to send NS packet to ELAN group, input={}", input, e);
         }
     }
+
+    Set<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget>
+        getRtListForVpn(String vpnName) {
+        Set<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets
+                .VpnTarget> rtList = new HashSet<>();
+        InstanceIdentifier<VpnInstance> vpnInstanceId = InstanceIdentifier.builder(VpnInstances.class)
+                .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+        Optional<VpnInstance> vpnInstanceOptional = read(LogicalDatastoreType.CONFIGURATION, vpnInstanceId);
+        if (vpnInstanceOptional.isPresent()) {
+            org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets
+                    vpnTargets = vpnInstanceOptional.get().getIpv4Family().getVpnTargets();
+            if (vpnTargets != null && vpnTargets.getVpnTarget() != null) {
+                rtList.addAll(vpnTargets.getVpnTarget());
+            }
+        }
+        else {
+            LOG.error("getRtListForVpn: Vpn Instance {} not present in config DS", vpnName);
+        }
+        return rtList;
+    }
+
+    static InstanceIdentifier<AssociatedVpn> getAssociatedSubnetAndVpnIdentifier(String rt, RouteTarget.RtType rtType,
+                                                                                 String cidr, String vpnName) {
+        return InstanceIdentifier.builder(SubnetsAssociatedToRouteTargets.class).child(RouteTarget.class,
+                new RouteTargetKey(rt, rtType)).child(AssociatedSubnet.class, new AssociatedSubnetKey(cidr))
+                .child(AssociatedVpn.class, new AssociatedVpnKey(vpnName)).build();
+    }
+
+    static InstanceIdentifier<AssociatedSubnet> getAssociatedSubnetIdentifier(String rt, RouteTarget.RtType rtType,
+                                                                       String cidr) {
+        return InstanceIdentifier.builder(SubnetsAssociatedToRouteTargets.class).child(RouteTarget.class,
+                new RouteTargetKey(rt, rtType)).child(AssociatedSubnet.class, new AssociatedSubnetKey(cidr)).build();
+    }
+
+    static AssociatedVpn buildAssociatedSubnetAndVpn(String vpnName) {
+        return new AssociatedVpnBuilder().setName(vpnName).build();
+    }
+
+    static InstanceIdentifier<RouteTarget> getRouteTargetsIdentifier(String rt, RouteTarget.RtType rtType) {
+        return InstanceIdentifier.builder(SubnetsAssociatedToRouteTargets.class)
+                .child(RouteTarget.class, new RouteTargetKey(rt, rtType)).build();
+    }
+
+    Set<RouteTarget> getRouteTargetSet(Set<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815
+            .vpn.af.config.vpntargets.VpnTarget> vpnTargets) {
+        Set<RouteTarget> routeTargetSet = new HashSet<>();
+        for (org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets
+                .VpnTarget rt : vpnTargets) {
+            String rtValue = rt.getVrfRTValue();
+            switch (rt.getVrfRTType()) {
+                case ImportExtcommunity: {
+                    Optional<RouteTarget> exportRouteTargetOptional = read(LogicalDatastoreType.OPERATIONAL,
+                            getRouteTargetsIdentifier(rtValue, RouteTarget.RtType.ERT));
+                    if (exportRouteTargetOptional.isPresent()) {
+                        routeTargetSet.add(exportRouteTargetOptional.get());
+                    }
+                    break;
+                }
+                case ExportExtcommunity: {
+                    Optional<RouteTarget> importRouteTargetOptional = read(LogicalDatastoreType.OPERATIONAL,
+                            getRouteTargetsIdentifier(rtValue, RouteTarget.RtType.IRT));
+                    if (importRouteTargetOptional.isPresent()) {
+                        routeTargetSet.add(importRouteTargetOptional.get());
+                    }
+                    break;
+                }
+                case Both: {
+                    Optional<RouteTarget> exportRouteTargetOptional = read(LogicalDatastoreType.OPERATIONAL,
+                            getRouteTargetsIdentifier(rtValue, RouteTarget.RtType.ERT));
+                    if (exportRouteTargetOptional.isPresent()) {
+                        routeTargetSet.add(exportRouteTargetOptional.get());
+                    }
+                    Optional<RouteTarget> importRouteTargetOptional = read(LogicalDatastoreType.OPERATIONAL,
+                            getRouteTargetsIdentifier(rtValue, RouteTarget.RtType.IRT));
+                    if (importRouteTargetOptional.isPresent()) {
+                        routeTargetSet.add(importRouteTargetOptional.get());
+                    }
+                    break;
+                }
+                default:
+                    LOG.error("getRouteTargetSet: Invalid rt-type {}", rt.getVrfRTType());
+            }
+        }
+        return routeTargetSet;
+    }
+
+    /*
+    TODO: (vivek/kiran): Subnet overlap in a VPN detection logic should use subnet allocation pools if available
+           rather than only CIDR.
+           Also the Subnet overlap in a VPN detection logic to be addressed for router-based-l3vpns.
+    */
+    static boolean areSubnetsOverlapping(String cidr1, String cidr2) {
+        String[] ipaddressValues1 = cidr1.split("/");
+        int address1 = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues1[0]));
+        int cidrPart1 = Integer.parseInt(ipaddressValues1[1]);
+        String[] ipaddressValues2 = cidr2.split("/");
+        int address2 = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues2[0]));
+        int cidrPart2 = Integer.parseInt(ipaddressValues2[1]);
+        int comparedValue = 0;
+        int netmask = 0;
+        if (cidrPart1 <= cidrPart2) {
+            for (int j = 0; j < cidrPart1; ++j) {
+                netmask |= (1 << 31 - j);
+            }
+            int prefix = address2 & netmask;
+            comparedValue = address1 ^ prefix;
+        } else {
+            for (int j = 0; j < cidrPart2; ++j) {
+                netmask |= (1 << 31 - j);
+            }
+            int prefix = address1 & netmask;
+            comparedValue = address2 ^ prefix;
+        }
+        if (comparedValue == 0) {
+            return  true;
+        } else {
+            return false;
+        }
+    }
 }