Handle BGPVPN Instance Update/Swap Case Properly 57/75657/11
authorKarthikeyan Krishnan <karthikeyangceb007@gmail.com>
Mon, 3 Sep 2018 00:18:23 +0000 (05:48 +0530)
committerSam Hague <shague@redhat.com>
Tue, 18 Sep 2018 00:30:23 +0000 (00:30 +0000)
Issue:
======
Current implementation of the VPN Instance update
is always doing swap (Remove Old VPN Interface
and Add New VPN Interface) for when ever there
is an update with VPN Instance for existing VPN
interface.

This logic is suitable for only on Router is
getting associated/disassociated with
external BGP-VPN.

When Internet BGP-VPN is attached to router
all private IPv6 subnet routes needs to be
created with VPN interface onto Internet BGPVPN.

Single external BGP-VPN instance can be associated
to maximum two routers. This feature is supported
starting from fluorine release. This feature also
not working with current implementation.

Updating VPN Interface with second VPN Instance
should not consider the VPN Swap for Internet
BGP-VPN update and dual router use cases.

Solution:
==========
This fix addresses the following use cases
properly for BGP-VPN Instance update.

1) External BGP-VPN Instance is associated to
single router or disassociated from single router

2) Internet BGP-VPN Instance is attached to
single router(router-gw) for external public network
access or removed internet BGP-VPN instance from
single router.

IPv6 Internet/Public Data path traffic should work
along with review[0]

[0]https://git.opendaylight.org/gerrit/#/c/75601/

Issue: NETVIRT-1418

Change-Id: I71b495e0098d798c5a4ca51f395b0be67d51b2fe
Signed-off-by: Karthikeyan Krishnan <karthikeyangceb007@gmail.com>
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java

index 0a101f91c4f36ce2039c245b974647dbab545c50..aa7981641eb42dd6f0348e27d70dbf5a0b38e244 100755 (executable)
@@ -1540,148 +1540,212 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 update.getVpnInstanceNames());
         final String vpnInterfaceName = update.getName();
         final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
-        final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
-        final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
-            != null ? origAdjs.getAdjacency() : new ArrayList<>();
-        final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
-        final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
-            != null ? updateAdjs.getAdjacency() : new ArrayList<>();
-
         LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
         //handles switching between <internal VPN - external VPN>
         jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
-            if (handleVpnSwapForVpnInterface(identifier, original, update)) {
-                LOG.info("update: handled VPNInterface {} on dpn {} update"
-                                + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            if (handleVpnInstanceUpdateForVpnInterface(identifier, original, update, futures)) {
+                LOG.info("update: handled Instance update for VPNInterface {} on dpn {} from oldVpn(s) {} "
+                                + "to newVpn(s) {}",
                         original.getName(), dpnId,
                         VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
                         VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
                 return Collections.emptyList();
             }
-            List<ListenableFuture<Void>> futures = new ArrayList<>();
-            for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
-                String newVpnName = vpnInterfaceVpnInstance.getVpnName();
-                List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
-                List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
-                String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
-                if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
-                    // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
-                    futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
-                        futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
-                            InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
-                                    VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
-                            LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
-                                    update.getName(), newVpnName);
-                            //handle both addition and removal of adjacencies
-                            //currently, new adjacency may be an extra route
-                            boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
-                            if (!oldAdjs.equals(newAdjs)) {
-                                for (Adjacency adj : copyNewAdjs) {
-                                    if (copyOldAdjs.contains(adj)) {
-                                        copyOldAdjs.remove(adj);
-                                    } else {
-                                        // add new adjacency - right now only extra route will hit this path
-                                        if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
-                                            addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
-                                                    dpnId, operTx, confTx);
-                                        }
-                                        LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
-                                                + " vpn interface {} on vpn {} dpnId {}",
-                                                adj.getIpAddress(), adj.getNextHopIpList(),
-                                                adj.getLabel(), adj.getSubnetId(), update.getName(),
-                                                newVpnName, dpnId);
-                                    }
-                                }
-                                for (Adjacency adj : copyOldAdjs) {
-                                    if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
-                                        if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
-                                                && !adj.isPhysNetworkFunc()) {
-                                            delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
-                                                    operTx, confTx);
-                                            //remove FIB entry
-                                            String vpnRd = vpnUtil.getVpnRd(newVpnName);
-                                            LOG.debug("update: remove prefix {} from the FIB and BGP entry "
-                                                    + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
-                                            //remove BGP entry
-                                            fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
-                                            if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
-                                                bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
-                                            }
-                                        } else {
-                                            delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
-                                                operTx, confTx);
-                                        }
-                                    }
-                                    LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
-                                                    + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
-                                                    .getNextHopIpList(),
-                                            adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
-                                }
-                            }
-                        }));
-                    }));
-                    for (ListenableFuture<Void> future : futures) {
-                        ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
-                                update.getName(), update.getVpnInstanceNames());
-                    }
-                } else {
-                    LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
-                            + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
-                }
-            }
+            updateVpnInstanceAdjChange(original, update, vpnInterfaceName, futures);
             return futures;
         });
     }
 
-    private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
-                                                 VpnInterface original, VpnInterface update) {
-        boolean isSwap = Boolean.FALSE;
+    private boolean handleVpnInstanceUpdateForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
+                                                           VpnInterface original, VpnInterface update,
+                                                           List<ListenableFuture<Void>> futures) {
+        boolean isVpnInstanceUpdate = Boolean.FALSE;
         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
         final String interfaceName = key.getName();
-        List<String> oldVpnList = original.getVpnInstanceNames().stream()
-            .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
+        List<String> oldVpnList = vpnUtil.getVpnListForVpnInterface(original);
         List<String> oldVpnListCopy = new ArrayList<>();
         oldVpnListCopy.addAll(oldVpnList);
-        List<String> newVpnList = update.getVpnInstanceNames().stream()
-            .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
+        List<String> newVpnList = vpnUtil.getVpnListForVpnInterface(update);
+
         oldVpnList.removeAll(newVpnList);
         newVpnList.removeAll(oldVpnListCopy);
+        //This block will execute only on if there is a change in the VPN Instance.
         if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
-            for (String oldVpnName: oldVpnList) {
-                isSwap = Boolean.TRUE;
-                LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
-                        + " running config-driven swap removal", interfaceName, oldVpnName);
-                removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
-                LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
-                        + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
-            }
-            //Wait for previous interface bindings to be removed
+            /*
+             * Internet BGP-VPN Instance update with single router:
+             * ====================================================
+             * In this case single VPN Interface will be part of maximum 2 VPN Instance only.
+             *     1st VPN Instance : router VPN or external BGP-VPN.
+             *     2nd VPN Instance : Internet BGP-VPN(router-gw update/delete) for public network access.
+             *
+             * VPN Instance UPDATE:
+             * oldVpnList = 0 and newVpnList = 1 (Internet BGP-VPN)
+             * oldVpnList = 1 and newVpnList = 0 (Internet BGP-VPN)
+             *
+             * External BGP-VPN Instance update with single router:
+             * ====================================================
+             * In this case single VPN interface will be part of maximum 1 VPN Instance only.
+             *
+             * Updated VPN Instance will be always either internal router VPN to
+             * external BGP-VPN or external BGP-VPN to internal router VPN swap.
+             *
+             * VPN Instance UPDATE:
+             * oldVpnList = 1 and newVpnList = 1 (router VPN to Ext-BGPVPN)
+             * oldVpnList = 1 and newVpnList = 1 (Ext-BGPVPN to router VPN)
+             *
+             * TODO Two router VPN instance update use case will be addressed in separate patch
+             */
+            isVpnInstanceUpdate = Boolean.TRUE;
+            updateVpnInstanceChange(identifier, interfaceName, original, update, oldVpnList, newVpnList,
+                    oldVpnListCopy, futures);
+        }
+        return isVpnInstanceUpdate;
+    }
+
+    private void updateVpnInstanceChange(InstanceIdentifier<VpnInterface> identifier, String interfaceName,
+                                         VpnInterface original, VpnInterface update, List<String> oldVpnList,
+                                         List<String> newVpnList, List<String> oldVpnListCopy,
+                                         List<ListenableFuture<Void>> futures) {
+        final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
+        final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
+                ? origAdjs.getAdjacency() : new ArrayList<>();
+        final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
+        final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
+                ? updateAdjs.getAdjacency() : new ArrayList<>();
+
+        boolean isOldVpnRemoveCallExecuted = false;
+        for (String oldVpnName : oldVpnList) {
+            LOG.info("updateVpnInstanceChange: VPN Interface update event - intfName {} "
+                    + "remove from vpnName {} ", interfaceName, oldVpnName);
+            removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
+            LOG.info("updateVpnInstanceChange: Processed Remove for update on VPNInterface"
+                            + " {} upon VPN update from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName,
+                    newVpnList);
+            isOldVpnRemoveCallExecuted = true;
+        }
+        //Wait for previous interface bindings to be removed
+        if (isOldVpnRemoveCallExecuted && !newVpnList.isEmpty()) {
             try {
                 Thread.sleep(2000);
             } catch (InterruptedException e) {
                 //Ignore
             }
+        }
+        for (String newVpnName : newVpnList) {
+            String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
+            if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
+                LOG.info("updateVpnInstanceChange: VPN Interface update event - intfName {} "
+                        + "onto vpnName {} ", interfaceName, newVpnName);
+                addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
+                LOG.info("updateVpnInstanceChange: Processed Add for update on VPNInterface {}"
+                                + "from oldVpn(s) {} to newVpn {} ",
+                        interfaceName, oldVpnListCopy, newVpnName);
+                /* This block will execute only if V6 subnet is associated with internet BGP-VPN.
+                 * Use Case:
+                 *     In Dual stack network, first V4 subnet only attached to router and router is associated
+                 *     with internet BGP-VPN(router-gw). At this point VPN interface is having only router vpn instance.
+                 *     Later V6 subnet is added to router, at this point existing VPN interface will get updated
+                 *     with Internet BGP-VPN instance(Note: Internet BGP-VPN Instance update in vpn interface
+                 *     is applicable for only on V6 subnet is added to router). newVpnList = Contains only Internet
+                 *     BGP-VPN Instance. So we required V6 primary adjacency info needs to be populated onto
+                 *     router VPN as well as Internet BGP-VPN.
+                 *
+                 *     addVpnInterfaceCall() --> It will create V6 Adj onto Internet BGP-VPN only.
+                 *     updateVpnInstanceAdjChange() --> This method call is needed for second primary V6 Adj
+                 *                                       update in existing router VPN instance.
+                 */
+                if (vpnUtil.isBgpVpnInternet(newVpnName)) {
+                    LOG.info("updateVpnInstanceChange: VPN Interface {} with new Adjacency {} in existing "
+                            + "VPN instance {}", interfaceName, newAdjs, original.getVpnInstanceNames());
+                    updateVpnInstanceAdjChange(original, update, interfaceName, futures);
+                }
+            }
+        }
+    }
 
-            final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
-            final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
-                    ? origAdjs.getAdjacency() : new ArrayList<>();
-            final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
-            final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
-                    ? updateAdjs.getAdjacency() : new ArrayList<>();
-            for (String newVpnName: newVpnList) {
-                String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
-                isSwap = Boolean.TRUE;
-                if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
-                    LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
-                            + "running config-driven swap addition", interfaceName, newVpnName);
-                    addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
-                    LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
-                                    + "from oldVpn(s) {} to newVpn {} upon VPN swap",
-                            interfaceName, oldVpnListCopy, newVpnName);
+    private List<ListenableFuture<Void>> updateVpnInstanceAdjChange(VpnInterface original, VpnInterface update,
+                                                                    String vpnInterfaceName,
+                                                                    List<ListenableFuture<Void>> futures) {
+        final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
+        final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
+                != null ? origAdjs.getAdjacency() : new ArrayList<>();
+        final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
+        final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
+                != null ? updateAdjs.getAdjacency() : new ArrayList<>();
+
+        final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
+        for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
+            String newVpnName = vpnInterfaceVpnInstance.getVpnName();
+            List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
+            List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
+            String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
+            if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
+                // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
+                    futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> {
+                        InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
+                                VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
+                        LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
+                                update.getName(), newVpnName);
+                        //handle both addition and removal of adjacencies
+                        //currently, new adjacency may be an extra route
+                        boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
+                        if (!oldAdjs.equals(newAdjs)) {
+                            for (Adjacency adj : copyNewAdjs) {
+                                if (copyOldAdjs.contains(adj)) {
+                                    copyOldAdjs.remove(adj);
+                                } else {
+                                    // add new adjacency
+                                    if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+                                        addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
+                                                dpnId, operTx, confTx);
+                                    }
+                                    LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
+                                                    + " vpn interface {} on vpn {} dpnId {}",
+                                            adj.getIpAddress(), adj.getNextHopIpList(),
+                                            adj.getLabel(), adj.getSubnetId(), update.getName(),
+                                            newVpnName, dpnId);
+                                }
+                            }
+                            for (Adjacency adj : copyOldAdjs) {
+                                if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+                                    if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
+                                            && !adj.isPhysNetworkFunc()) {
+                                        delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
+                                                operTx, confTx);
+                                        //remove FIB entry
+                                        String vpnRd = vpnUtil.getVpnRd(newVpnName);
+                                        LOG.debug("update: remove prefix {} from the FIB and BGP entry "
+                                                + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
+                                        //remove BGP entry
+                                        fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
+                                        if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
+                                            bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
+                                        }
+                                    } else {
+                                        delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
+                                                operTx, confTx);
+                                    }
+                                }
+                                LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
+                                                + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
+                                                .getNextHopIpList(),
+                                        adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
+                            }
+                        }
+                    }));
+                }));
+                for (ListenableFuture<Void> future : futures) {
+                    ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
+                            update.getName(), update.getVpnInstanceNames());
                 }
+            } else {
+                LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
+                        + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
             }
         }
-        return isSwap;
+        return futures;
     }
 
     private void updateLabelMapper(Long label, List<String> nextHopIpList) {
index 5922561373441c6719d66373a119da13b9f9376c..c9efcb18d5a4e7af3059e817c5406591656e784f 100644 (file)
@@ -75,7 +75,6 @@ import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
-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.enums.IpVersionChoice;
@@ -169,7 +168,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInterfaceOpData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroutes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortBuilder;
@@ -1705,18 +1703,13 @@ public final class VpnUtil {
 
     boolean isAdjacencyEligibleToVpnInternet(Adjacency adjacency) {
         // returns true if BGPVPN Internet and adjacency is IPv6, false otherwise
-        boolean adjacencyEligible = true;
-        if (adjacency.getAdjacencyType() == AdjacencyType.ExtraRoute) {
-            if (FibHelper.isIpv6Prefix(adjacency.getIpAddress())) {
-                return adjacencyEligible;
+        boolean adjacencyEligible = false;
+        IpVersionChoice ipVerChoice = getIpVersionFromString(adjacency.getIpAddress());
+        if (ipVerChoice.isIpVersionChosen(IpVersionChoice.IPV6)) {
+            Subnetmap sn = getSubnetmapFromItsUuid(adjacency.getSubnetId());
+            if (sn != null && sn.getInternetVpnId() != null) {
+                adjacencyEligible = true;
             }
-            return false;
-        } else if (adjacency.getSubnetId() == null) {
-            return adjacencyEligible;
-        }
-        Subnetmap sn = getSubnetmapFromItsUuid(adjacency.getSubnetId());
-        if (sn != null && sn.getInternetVpnId() != null) {
-            adjacencyEligible = false;
         }
         return adjacencyEligible;
     }
@@ -2230,4 +2223,9 @@ public final class VpnUtil {
     public static String buildIpMonitorJobKey(String ip, String vpnName) {
         return VpnConstants.IP_MONITOR_JOB_PREFIX_KEY + "-" + vpnName + "-" + ip;
     }
+
+    public List<String> getVpnListForVpnInterface(VpnInterface vpnInter) {
+        return vpnInter.getVpnInstanceNames().stream()
+                .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
+    }
 }