IPv6 FIB enteries not appearing if ExtNwt enabled
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
index 1619d5f9bf3331a6afcab412cfd47f5a8a24d3a6..89abac66d910ee748b0c2a1e98cf8774f01eb1f9 100644 (file)
@@ -640,7 +640,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
     }
 
-    private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
+    protected void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
         VpnMapBuilder builder;
         boolean isLockAcquired = false;
         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
@@ -798,7 +798,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         String infName = port.getUuid().getValue();
         LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
         for (FixedIps ip : port.getFixedIps()) {
-            String ipValue = String.valueOf(ip.getIpAddress().getValue());
+            String ipValue = ip.getIpAddress().stringValue();
             String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
             if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
                 continue;
@@ -918,9 +918,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         if (vpnId != null) {
             updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
         }
-        if (internetVpnId != null) {
-            updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
-        }
         if (!isIpFromAnotherSubnet) {
             // no more subnetworks for neutron port
             if (sn != null && sn.getRouterId() != null) {
@@ -1028,7 +1025,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
                 List<FixedIps> ips = port.getFixedIps();
                 for (FixedIps ip : ips) {
-                    String ipValue = String.valueOf(ip.getIpAddress().getValue());
+                    String ipValue = ip.getIpAddress().stringValue();
+                    //skip IPv4 address
+                    if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
+                        continue;
+                    }
                     neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
                             ipValue, writeConfigTxn);
                 }
@@ -1106,7 +1107,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
                 List<FixedIps> ips = port.getFixedIps();
                 for (FixedIps ip : ips) {
-                    String ipValue = String.valueOf(ip.getIpAddress().getValue());
+                    String ipValue = ip.getIpAddress().stringValue();
                     if (oldVpnId != null) {
                         neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
                                 ipValue, writeConfigTxn);
@@ -1406,8 +1407,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)
-                        || (optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
+                if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
+                        || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
                     vpns.add(optionalVpn.get());
                 } else {
                     result.set(
@@ -1735,8 +1736,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                     updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
                             sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
                 } else {
-                    removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
-                                        wrtConfigTxn, sm);
+                    removeVpnFromVpnInterface(vpn,
+                            neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
                 }
                 }
             )));
@@ -1888,8 +1889,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
         for (Routes route : interVpnLinkRoutes) {
-            String nexthop = String.valueOf(route.getNexthop().getValue());
-            String destination = String.valueOf(route.getDestination().getValue());
+            String nexthop = route.getNexthop().stringValue();
+            String destination = route.getDestination().stringValue();
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 AddStaticRouteInput rpcInput =
@@ -1914,7 +1915,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
-                        String.valueOf(route.getDestination().getValue()), nexthop);
+                        route.getDestination().stringValue(), nexthop);
                 continue;
             }
         }
@@ -1931,8 +1932,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
         for (Routes route : interVpnLinkRoutes) {
-            String nexthop = String.valueOf(route.getNexthop().getValue());
-            String destination = String.valueOf(route.getDestination().getValue());
+            String nexthop = route.getNexthop().stringValue();
+            String destination = route.getDestination().stringValue();
             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
                 RemoveStaticRouteInput rpcInput =
@@ -1945,7 +1946,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             } else {
                 // Any other case is a fault.
                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
-                        String.valueOf(route.getDestination().getValue()), nexthop);
+                        route.getDestination().stringValue(), nexthop);
                 continue;
             }
         }
@@ -1972,8 +1973,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
                 LOG.error("Incorrect input received for extra route. {}", route);
             } else {
-                String nextHop = String.valueOf(route.getNexthop().getValue());
-                String destination = String.valueOf(route.getDestination().getValue());
+                String nextHop = route.getNexthop().stringValue();
+                String destination = route.getDestination().stringValue();
                 if (!nextHop.equals(fixedIp)) {
                     LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
                     continue;
@@ -2005,8 +2006,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
                 LOG.error("Incorrect input received for extra route. {}", route);
             } else {
-                String nextHop = String.valueOf(route.getNexthop().getValue());
-                String destination = String.valueOf(route.getDestination().getValue());
+                String nextHop = route.getNexthop().stringValue();
+                String destination = route.getDestination().stringValue();
                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
                         nextHop);
                 if (infName != null) {
@@ -2079,22 +2080,22 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         }
         for (Routes route : routeList) {
             // count  the number of nexthops for each same route.getDestingation().getValue()
-            String destination = String.valueOf(route.getDestination().getValue());
-            String nextHop = String.valueOf(route.getNexthop().getValue());
-            List<String> nextHopList = new ArrayList();
+            String destination = route.getDestination().stringValue();
+            String nextHop = route.getNexthop().stringValue();
+            List<String> nextHopList = new ArrayList<>();
             nextHopList.add(nextHop);
             int nbNextHops = 0;
             for (Routes routeTmp : routeList) {
-                String routeDest = String.valueOf(routeTmp.getDestination().getValue());
+                String routeDest = routeTmp.getDestination().stringValue();
                 if (!destination.equals(routeDest)) {
                     continue;
                 }
-                String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
+                String routeNextH = routeTmp.getNexthop().stringValue();
                 if (nextHop.equals(routeNextH)) {
                     continue;
                 }
                 nbNextHops++;
-                nextHopList.add(new String(routeTmp.getNexthop().getValue()));
+                nextHopList.add(routeTmp.getNexthop().stringValue());
             }
             final List<String> rdList = new ArrayList<>();
             if (vpnInstance.getIpv4Family() != null
@@ -2130,7 +2131,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
 
             // 4. Prefix in question
             detailsAlarm.append(" for prefix: ");
-            detailsAlarm.append(route.getDestination().getValue());
+            detailsAlarm.append(route.getDestination().stringValue());
 
             // 5. List of NHs for the prefix
             detailsAlarm.append(" for nextHops: ");
@@ -2153,8 +2154,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         for (Routes route : routeList) {
             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
                 boolean isLockAcquired = false;
-                String nextHop = String.valueOf(route.getNexthop().getValue());
-                String destination = String.valueOf(route.getDestination().getValue());
+                String nextHop = route.getNexthop().stringValue();
+                String destination = route.getDestination().stringValue();
                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
                         nextHop);
                 if (infName == null) {
@@ -2260,14 +2261,20 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
         updateVpnMaps(vpnId, null, routerId, null, null);
         LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
-        List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
-        for (Uuid subnetId : routerSubnets) {
-            Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
-            if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
-                neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                          NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
+        for (Subnetmap sn : subMapList) {
+            updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
+            IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
+            if (!ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
             }
         }
+        if (ipVersion != IpVersionChoice.UNDEFINED) {
+            LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", ipVersion,
+                    vpnId);
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
+        }
 
         try {
             checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
@@ -2298,22 +2305,21 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     @SuppressWarnings("checkstyle:IllegalCatch")
     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
 
-        List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
-        boolean vpnInstanceIpVersionsRemoved = false;
-        IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
-        for (Uuid subnetId : routerSubnets) {
-            Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
-            if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
-                vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
-                        .getIpVersionFromString(sn.getSubnetIp()));
-                vpnInstanceIpVersionsRemoved = true;
+        List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        for (Subnetmap sn : subMapList) {
+            IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
+            if (ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
             }
             LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
-            updateVpnForSubnet(vpnId, routerId, subnetId, false);
+            updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
         }
-
-        if (vpnInstanceIpVersionsRemoved) {
-            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
+        if (ipVersion != IpVersionChoice.UNDEFINED) {
+            LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
+                    ipVersion, vpnId);
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
+                    false);
         }
         clearFromVpnMaps(vpnId, routerId, null);
         try {
@@ -2383,7 +2389,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                                    + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
                     continue;
                 }
-                if (neutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
+                if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
                     LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
                             nw.getValue(), vpnId.getValue());
                     failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
@@ -2398,6 +2404,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
                     continue;
                 }
+                IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
                 for (Subnetmap subnetmap : subnetmapList) {
                     Uuid subnetId = subnetmap.getId();
                     Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
@@ -2408,11 +2415,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                                 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
                         continue;
                     }
-                    if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(subnetmap, vpnId)) {
-                        neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                                NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()), true);
+                    IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
+                    if (!ipVersion.isIpVersionChosen(ipVers)) {
+                        ipVersion = ipVersion.addVersion(ipVers);
                     }
-                    if (!neutronvpnUtils.getIsExternal(network)) {
+                    if (!NeutronvpnUtils.getIsExternal(network)) {
                         LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
                                 vpnId.getValue());
                         addSubnetToVpn(vpnId, subnetId, null);
@@ -2421,6 +2428,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         passedNwList.add(nw);
                     }
                 }
+                if (ipVersion != IpVersionChoice.UNDEFINED) {
+                    LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
+                            ipVersion, vpnId);
+                    neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
+                }
                 passedNwList.add(nw);
             }
         } catch (ReadFailedException e) {
@@ -2435,31 +2447,38 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
     }
 
     private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
+        if (!addExternalNetworkToVpn(extNet, vpnId)) {
+            return false;
+        }
         VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
         if (vpnOpDataEntry == null) {
             LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
             return false;
         }
-        if (!addExternalNetworkToVpn(extNet, vpnId)) {
-            return false;
-        }
         if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
             LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
             neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
         }
-        for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
             if (sm == null) {
                 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
                 continue;
             }
-            updateVpnInternetForSubnet(sm, vpnId, true);
-            if (!vpnOpDataEntry.isIpv6Configured()
-                    && NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6) {
-                LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
-                neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
+            IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
+            if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
+                updateVpnInternetForSubnet(sm, vpnId, true);
+            }
+            if (!ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
             }
         }
+        if (ipVersion != IpVersionChoice.UNDEFINED && ipVersion != IpVersionChoice.IPV4) {
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
+            LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
+            neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, true);
+        }
         return true;
     }
 
@@ -2521,13 +2540,12 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
             Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
+            IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
             for (Uuid subnet : networkSubnets) {
                 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
-                if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(subnetmap, vpnId)) {
-                    IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
-                    IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
-                    neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
-                        ipVersionsToRemove.addVersion(ipVersion), false);
+                IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
+                if (!ipVersion.isIpVersionChosen(ipVers)) {
+                    ipVersion = ipVersion.addVersion(ipVers);
                 }
                 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
                           vpnId.getValue());
@@ -2536,6 +2554,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                         vpnId.getValue());
                 passedNwList.add(nw);
             }
+            if (ipVersion != IpVersionChoice.UNDEFINED) {
+                LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
+                        ipVersion, vpnId);
+                neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
+            }
         }
         clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
         LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
@@ -2550,6 +2573,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         // check, if there is another Provider Networks associated with given VPN
         List<Uuid> vpnNets = getNetworksForVpn(vpnId);
         if (vpnNets != null) {
+            //Remove currently disassociated network from the list
+            vpnNets.remove(extNet.getUuid());
             for (Uuid netId : vpnNets) {
                 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
                     LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
@@ -2558,20 +2583,31 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
                 }
             }
         }
+        //Set VPN Type is BGPVPNExternal from BGPVPNInternet
         LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
                 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
         neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
-        for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
+        IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
+        for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
             if (sm == null) {
                 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
                 continue;
             }
-            updateVpnInternetForSubnet(sm, vpnId, false);
+            IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
+            if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
+                updateVpnInternetForSubnet(sm, vpnId, false);
+            }
+            if (!ipVersion.isIpVersionChosen(ipVers)) {
+                ipVersion = ipVersion.addVersion(ipVers);
+            }
+        }
+        if (ipVersion != IpVersionChoice.UNDEFINED && ipVersion != IpVersionChoice.IPV4) {
+            neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
+            LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
+                    vpnId.getValue());
+            neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, false);
         }
-        neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
-        LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
-        neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
         return true;
     }
 
@@ -2688,7 +2724,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             if (port != null) {
                 List<FixedIps> fixedIPs = port.getFixedIps();
                 for (FixedIps ip : fixedIPs) {
-                    fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
+                    fixedIPList.add(ip.getIpAddress().stringValue());
                 }
             } else {
                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
@@ -3282,4 +3318,30 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         logger.accept(message);
         return message;
     }
+
+    protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid internetVpnId, @Nonnull Subnetmap subnetMap) {
+        //Set VPN type BGPVPNInternet from BGPVPNExternal
+        LOG.info("addV6PrivateSubnetToExtNetwork: set type {} for Internet VPN {}",
+                BgpvpnType.BGPVPNInternet, internetVpnId.getValue());
+        neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, internetVpnId);
+        updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
+
+        neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
+        LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
+                subnetMap.getId(), internetVpnId.getValue());
+        neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, true);
+    }
+
+    protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid internetVpnId, @Nonnull Subnetmap subnetMap) {
+        //Set VPN type BGPVPNExternal from BGPVPNInternet
+        LOG.info("removeV6PrivateSubnetToExtNetwork: set type {} for Internet VPN {}",
+                VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, internetVpnId.getValue());
+        neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, internetVpnId);
+        updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
+
+        neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, false);
+        LOG.info("removeV6PrivateSubnetToExtNetwork: withdraw IPv6 Private subnet {} from Internet VPN {}",
+                subnetMap.getId(), internetVpnId.getValue());
+        neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, false);
+    }
 }