From: Karthikeyan Krishnan Date: Wed, 3 Oct 2018 09:41:24 +0000 (+0530) Subject: VPNv6 external network support for multiple router X-Git-Tag: release/neon~107 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;ds=sidebyside;h=refs%2Fchanges%2F00%2F76600%2F21;hp=14cd5115173a053cf6d99b7dc9c9493f0f809b8b;p=netvirt.git VPNv6 external network support for multiple router Issue: ======= 1) Single external network/internet(public) is sharing to more than one router is not working as expected for IPv6 internet data traffic. 2) Before spawning the VM on the compute, internet access was set/enabled with router already. In this case if boot the VM on the new DPN, default V6 internet fallback rule is not getting programmed. Solution: ========= RCA for issue (1): ------------------ IPv6 internet default fall back rule(21->21) is not getting programmed for if external network is associated with more than one router due to flow-id is not proper for each router. RCA for issue (2): ------------------ When first/last VM is booted/removed from the DPN, there is no check for whether router is already been set with external/internet connectivity via router-gw set as a result V6 internet default fallback rule is missing for newly added DPN. As part of this fix, internet default fall back rule flow-id is constrcted based on the router-id always. Since we can not go with either external-vpn(router) or internet bgp-vpn. Also addressed the issue (2) problem as well. NAT Module Dependency: ======================= + RouterDpnChangeListener --> Program and un-program the V6 internet default fallback flows on when first VM is booted on the compute or last VM is removed from the compute for router VPN Issue: NETVIRT-1440 Change-Id: I2e20158368984172117597e32a5310477ad57d16 Signed-off-by: Karthikeyan Krishnan --- diff --git a/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java b/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java index 11401b3efd..1e21c71ee8 100644 --- a/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java +++ b/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java @@ -31,6 +31,7 @@ import org.opendaylight.genius.mdsalutil.BucketInfo; import org.opendaylight.genius.mdsalutil.FlowEntity; import org.opendaylight.genius.mdsalutil.GroupEntity; import org.opendaylight.genius.mdsalutil.MDSALUtil; +import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; @@ -199,6 +200,11 @@ public class RouterDpnChangeListener + "vpnId {}...", dpnId, routerUuid, vpnId); snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, confTx); } + /* install V6 internet default fallback rule in FIB_TABLE if router + * is having V6 subnet + */ + nvpnManager.programV6InternetFallbackFlow(new Uuid(routerUuid), + NatUtil.getVpnIdfromNetworkId(dataBroker, networkId), NwConstants.ADD_FLOW); if (router.isEnableSnat()) { LOG.info("add : SNAT enabled for router {}", routerUuid); if (extNwProvType == null) { @@ -290,7 +296,11 @@ public class RouterDpnChangeListener vpnName); snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, confTx); } - + /* remove V6 internet default fallback rule in FIB_TABLE if router + * is having V6 subnet + */ + nvpnManager.programV6InternetFallbackFlow(new Uuid(routerUuid), + NatUtil.getVpnIdfromNetworkId(dataBroker, networkId), NwConstants.DEL_FLOW); if (router.isEnableSnat()) { LOG.info("remove : SNAT enabled for router {}", routerUuid); removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, confTx); diff --git a/neutronvpn/api/src/main/java/org/opendaylight/netvirt/neutronvpn/interfaces/INeutronVpnManager.java b/neutronvpn/api/src/main/java/org/opendaylight/netvirt/neutronvpn/interfaces/INeutronVpnManager.java index 8fc1937670..c7a3af896c 100644 --- a/neutronvpn/api/src/main/java/org/opendaylight/netvirt/neutronvpn/interfaces/INeutronVpnManager.java +++ b/neutronvpn/api/src/main/java/org/opendaylight/netvirt/neutronvpn/interfaces/INeutronVpnManager.java @@ -46,5 +46,7 @@ public interface INeutronVpnManager { String getOpenDaylightVniRangesConfig(); + void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove); + } diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/IPV6InternetDefaultRouteProgrammer.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/IPV6InternetDefaultRouteProgrammer.java index 516fbbb221..6cf49d923c 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/IPV6InternetDefaultRouteProgrammer.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/IPV6InternetDefaultRouteProgrammer.java @@ -41,7 +41,8 @@ public class IPV6InternetDefaultRouteProgrammer { this.mdsalManager = mdsalManager; } - private FlowEntity buildIPv6FallbacktoExternalVpn(BigInteger dpId, long internetBgpVpnId, long vpnId, boolean add) { + private FlowEntity buildIPv6FallbacktoExternalVpn(BigInteger dpId, String routerId, long internetBgpVpnId, + long vpnId, boolean add) { List matches = new ArrayList<>(); matches.add(MatchEthernetType.IPV6); @@ -58,7 +59,10 @@ public class IPV6InternetDefaultRouteProgrammer { instructionInfo.add(new InstructionApplyActions(listActionInfo)); } String defaultIPv6 = "0:0:0:0:0:0:0:0"; - String flowRef = getIPv6FlowRefL3(dpId, NwConstants.L3_FIB_TABLE, defaultIPv6, internetBgpVpnId); + /* For each router it needs to have unique flow-id. Hence router-id is being used to generate the + * flow-id for each DPN instead of internet vpnId. + */ + String flowRef = getIPv6FlowRefL3(dpId, NwConstants.L3_FIB_TABLE, defaultIPv6, routerId); FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef, NwConstants.TABLE_MISS_PRIORITY, flowRef/* "L3 ipv6 internet default route",*/, 0, 0, @@ -74,20 +78,20 @@ public class IPV6InternetDefaultRouteProgrammer { * @param internetBgpVpnId internetVpn id as long * @param vpnId id of router associated to internet bgpvpn as long */ - public void installDefaultRoute(BigInteger dpnId, long internetBgpVpnId, long vpnId) { - FlowEntity flowEntity = buildIPv6FallbacktoExternalVpn(dpnId, internetBgpVpnId, vpnId, true); + public void installDefaultRoute(BigInteger dpnId, String routerId, long internetBgpVpnId, long vpnId) { + FlowEntity flowEntity = buildIPv6FallbacktoExternalVpn(dpnId, routerId, internetBgpVpnId, vpnId, true); LOG.trace("installDefaultRoute: flowEntity: {} ", flowEntity); mdsalManager.installFlow(flowEntity); } - public void removeDefaultRoute(BigInteger dpnId, long internetBgpVpnId, long vpnId) { - FlowEntity flowEntity = buildIPv6FallbacktoExternalVpn(dpnId, internetBgpVpnId, vpnId, false); + public void removeDefaultRoute(BigInteger dpnId, String routerId, long internetBgpVpnId, long vpnId) { + FlowEntity flowEntity = buildIPv6FallbacktoExternalVpn(dpnId, routerId, internetBgpVpnId, vpnId, false); LOG.trace("removeDefaultRoute: flowEntity: {} ", flowEntity); mdsalManager.removeFlow(flowEntity); } - public String getIPv6FlowRefL3(BigInteger dpnId, short tableId, String destPrefix, long vpnId) { + public String getIPv6FlowRefL3(BigInteger dpnId, short tableId, String destPrefix, String routerId) { return "L3." + dpnId.toString() + NwConstants.FLOWID_SEPARATOR + tableId - + NwConstants.FLOWID_SEPARATOR + destPrefix + NwConstants.FLOWID_SEPARATOR + vpnId; + + NwConstants.FLOWID_SEPARATOR + destPrefix + NwConstants.FLOWID_SEPARATOR + routerId; } } diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java index db11a13578..42f07a2cc4 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java @@ -61,7 +61,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries; -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.natservice.rev160111.ext.routers.Routers; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder; @@ -318,7 +317,7 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase

snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId); diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java index 00a145aeed..0c52cdf6be 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java @@ -52,6 +52,7 @@ import org.opendaylight.genius.infra.Datastore.Configuration; import org.opendaylight.genius.infra.ManagedNewTransactionRunner; import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; import org.opendaylight.genius.infra.TypedWriteTransaction; +import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; import org.opendaylight.infrautils.utils.concurrent.KeyedLocks; import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; @@ -312,8 +313,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (vpnId != null) { builder.setVpnId(vpnId); } - builder.setInternetVpnId(internetvpnId); - + if (neutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) { + builder.setInternetVpnId(internetvpnId); + } Subnetmap subnetmap = builder.build(); LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue()); SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap); @@ -1782,8 +1784,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even * associated with internet BGP-VPN. */ if (vpnExtUuid != null) { - //Update V6 Internet default route match with new VPN metadata - neutronvpnUtils.updateVpnInstanceWithFallback(vpnExtUuid, isBeingAssociated); + /* Update V6 Internet default route match with new VPN metadata. + * isBeingAssociated = true means oldVpnId is same as routerId + * isBeingAssociated = false means newVpnId is same as routerId + */ + if (isBeingAssociated) { + neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true); + } else { + neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true); + } } //Update Router Interface first synchronously. //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again ! @@ -2313,6 +2322,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even @SuppressWarnings("checkstyle:IllegalCatch") protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) { + clearFromVpnMaps(vpnId, routerId, null); List subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId); IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (Subnetmap sn : subMapList) { @@ -2329,7 +2339,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false); } - clearFromVpnMaps(vpnId, routerId, null); try { checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId); LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(), @@ -2351,6 +2360,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even protected List associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List networkList) { List failedNwList = new ArrayList<>(); HashSet passedNwList = new HashSet<>(); + boolean isExternalNetwork = false; if (networkList.isEmpty()) { LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue()); failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty", @@ -2404,6 +2414,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even nw.getValue(), vpnId.getValue())); continue; } + if (NeutronvpnUtils.getIsExternal(network)) { + isExternalNetwork = true; + } List subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw); if (subnetmapList == null || subnetmapList.isEmpty()) { passedNwList.add(nw); @@ -2449,7 +2462,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(), networkList, e)); } - updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList)); + //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method. + if (!isExternalNetwork) { + updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList)); + } LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue()); return failedNwList; } @@ -2467,6 +2483,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue()); neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId); } + //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows + List extNwList = Collections.singletonList(extNet.key().getUuid()); + updateVpnMaps(vpnId, null, null, null, extNwList); IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) { Subnetmap sm = neutronvpnUtils.getSubnetmap(snId); @@ -2475,6 +2494,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even continue; } IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) { + continue; + } if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { updateVpnInternetForSubnet(sm, vpnId, true); } @@ -2482,10 +2504,10 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even ipVersion = ipVersion.addVersion(ipVers); } } - if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) { + if (ipVersion != IpVersionChoice.UNDEFINED) { neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true); LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue()); - neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, true); + neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true); } return true; } @@ -2538,7 +2560,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (NeutronvpnUtils.getIsExternal(network)) { if (disassociateExtNetworkFromVpn(vpnId, network)) { passedNwList.add(nw); - continue; } else { LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}", nw.getValue(), vpnId.getValue()); @@ -2547,7 +2568,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even continue; } } - Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED; for (Uuid subnet : networkSubnets) { Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet); @@ -2555,12 +2575,15 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even if (!ipVersion.isIpVersionChosen(ipVers)) { ipVersion = ipVersion.addVersion(ipVers); } - 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); + if (!NeutronvpnUtils.getIsExternal(network)) { + LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(), + vpnId.getValue()); + removeSubnetFromVpn(vpnId, subnet, null); + Set routeTargets = vpnManager.getRtListForVpn(vpnId.getValue()); + vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(), + vpnId.getValue()); + passedNwList.add(nw); + } } if (ipVersion != IpVersionChoice.UNDEFINED) { LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}", @@ -2603,6 +2626,9 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even continue; } IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()); + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) { + continue; + } if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { updateVpnInternetForSubnet(sm, vpnId, false); } @@ -2610,11 +2636,11 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even ipVersion = ipVersion.addVersion(ipVers); } } - if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) { + if (ipVersion != IpVersionChoice.UNDEFINED) { neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false); LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue()); - neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, false); + neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false); } return true; } @@ -3332,24 +3358,27 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId, @Nonnull Subnetmap subnetMap) { updateVpnInternetForSubnet(subnetMap, internetVpnId, true); - if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange( - IpVersionChoice.IPV6, routerId, true)) { + neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true); + if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) { neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true); LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}", - subnetMap.getId(), internetVpnId.getValue()); + subnetMap.getId().getValue(), internetVpnId.getValue()); } - neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, true); } protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId, @Nonnull Subnetmap subnetMap) { updateVpnInternetForSubnet(subnetMap, internetVpnId, false); - if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange( - IpVersionChoice.IPV6, routerId, false)) { - neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, false); - LOG.info("removeV6PrivateSubnetToExtNetwork: withdraw IPv6 Private subnet {} from Internet VPN {}", - subnetMap.getId(), internetVpnId.getValue()); + neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false); + } + + protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) { + if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) { + LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule " + + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed", + internetVpnId.getValue(), routerId.getValue()); + neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW + ? true : false); } - neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, false); } } diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManagerImpl.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManagerImpl.java index 5663de7f58..3b8a27bfb3 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManagerImpl.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManagerImpl.java @@ -96,4 +96,9 @@ public class NeutronvpnManagerImpl implements INeutronVpnManager { public String getOpenDaylightVniRangesConfig() { return nvManager.getOpenDaylightVniRangesConfig(); } + + @Override + public void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) { + nvManager.programV6InternetFallbackFlow(routerId, internetVpnId, addOrRemove); + } } diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnNatManager.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnNatManager.java index 200d132887..eb64a970cf 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnNatManager.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnNatManager.java @@ -28,7 +28,6 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; import org.opendaylight.netvirt.elanmanager.api.IElanService; -import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice; import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface; @@ -56,7 +55,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.ExternalGatewayInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.external_gateway_info.ExternalFixedIps; @@ -347,27 +345,6 @@ public class NeutronvpnNatManager implements AutoCloseable { SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier, networkss); LOG.trace("Updated externalnetworks successfully to CONFIG Datastore"); - //get vpn external form this network external to setup vpnInternet for ipv6 - Uuid vpnExternal = neutronvpnUtils.getVpnForNetwork(extNetId); - if (vpnExternal == null) { - LOG.debug("addExternalNetworkToRouter : no vpnExternal for Network {}", extNetId); - } - LOG.debug("addExternalNetworkToRouter : the vpnExternal {}", vpnExternal); - //get subnetmap associate to the router, any subnetmap "external" could be existing - List snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId); - LOG.debug("addExternalNetworkToRouter : the vpnExternal {} subnetmap to be set with vpnInternet {}", - vpnExternal, snList); - for (Subnetmap sn : snList) { - if (sn.getInternetVpnId() == null) { - continue; - } - IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()); - if (ipVers == IpVersionChoice.IPV6) { - LOG.debug("addExternalNetworkToRouter : setup vpnInternet IPv6 for vpnExternal {} subnetmap {}", - vpnExternal, sn); - nvpnManager.updateVpnInternetForSubnet(sn, vpnExternal, true); - } - } } catch (TransactionCommitFailedException | ReadFailedException ex) { LOG.error("Creation of externalnetworks failed for {}", extNetId.getValue(), ex); @@ -421,26 +398,6 @@ public class NeutronvpnNatManager implements AutoCloseable { LOG.error("removeExternalNetworkFromRouter: Failed to remove provider network {} from router {}", origExtNetId.getValue(), routerId.getValue(), ex); } - - // Remove the vpnInternetId fromSubnetmap - Network net = neutronvpnUtils.getNeutronNetwork(nets.getId()); - List submapIds = neutronvpnUtils.getPrivateSubnetsToExport(net, /*internetVpnId*/ null); - for (Uuid snId : submapIds) { - Subnetmap subnetMap = neutronvpnUtils.getSubnetmap(snId); - if (subnetMap == null || subnetMap.getInternetVpnId() == null) { - LOG.error("removeExternalNetworkFromRouter: Can not find Subnetmap for SubnetId {} in ConfigDS", - snId.getValue()); - continue; - } - LOG.trace("removeExternalNetworkFromRouter: Remove Internet VPN Id {} from SubnetMap {}", - subnetMap.getInternetVpnId(), subnetMap.getId()); - IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetMap.getSubnetIp()); - if (ipVers == IpVersionChoice.IPV6) { - nvpnManager.updateVpnInternetForSubnet(subnetMap, subnetMap.getInternetVpnId(), false); - LOG.debug("removeExternalNetworkFromRouter: Withdraw IPv6 routes from VPN {}", - subnetMap.getInternetVpnId()); - } - } } public void addExternalRouter(Router update) { diff --git a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java index cacacf9844..c365c1ea54 100644 --- a/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java +++ b/neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java @@ -1550,21 +1550,21 @@ public class NeutronvpnUtils { } public void updateVpnInstanceWithIpFamily(String vpnName, IpVersionChoice ipVersion, boolean add) { - VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName); - if (vpnInstanceOpDataEntry == null) { - return; - } - if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) { - LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with ipFamily {}." - + "VpnInstanceOpDataEntry is L2 instance. Do nothing.", vpnName, ipVersion); - return; - } - if (ipVersion == IpVersionChoice.UNDEFINED) { - LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with Undefined address family" - + "is not allowed. Do nothing", vpnName); - return; - } jobCoordinator.enqueueJob("VPN-" + vpnName, () -> { + VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName); + if (vpnInstanceOpDataEntry == null) { + return Collections.emptyList(); + } + if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) { + LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with ipFamily {}." + + "VpnInstanceOpDataEntry is L2 instance. Do nothing.", vpnName, ipVersion); + return Collections.emptyList(); + } + if (ipVersion == IpVersionChoice.UNDEFINED) { + LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with Undefined address family" + + "is not allowed. Do nothing", vpnName); + return Collections.emptyList(); + } VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry); boolean ipConfigured = add; if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4AND6)) { @@ -1678,19 +1678,26 @@ public class NeutronvpnUtils { router.getUuid().getValue(), extNet.getUuid().getValue()); continue; } - subList.addAll(getSubnetsforVpn(rtrId)); + subList.addAll(getNeutronRouterSubnetIds(rtrId)); } return subList; } - public void updateVpnInstanceWithFallback(Uuid vpnName, boolean add) { + public void updateVpnInstanceWithFallback(Uuid routerId, Uuid vpnName, boolean add) { VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName.getValue()); if (vpnInstanceOpDataEntry == null) { LOG.error("updateVpnInstanceWithFallback: vpnInstanceOpDataEntry not found for vpn {}", vpnName); return; } Long internetBgpVpnId = vpnInstanceOpDataEntry.getVpnId(); - List routerIds = getRouterIdListforVpn(vpnName); + List routerIds = new ArrayList<>(); + //Handle router specific V6 internet fallback flow else handle all V6 external routers + if (routerId != null) { + routerIds.add(routerId); + } else { + //This block will execute for ext-nw to Internet VPN association/disassociation event. + routerIds = getRouterIdListforVpn(vpnName); + } if (routerIds == null || routerIds.isEmpty()) { LOG.error("updateVpnInstanceWithFallback: router not found for vpn {}", vpnName); return; @@ -1715,9 +1722,9 @@ public class NeutronvpnUtils { } for (BigInteger dpnId : dpnIds) { if (add) { - ipV6InternetDefRt.installDefaultRoute(dpnId, internetBgpVpnId, vpnId); + ipV6InternetDefRt.installDefaultRoute(dpnId, rtrId.getValue(), internetBgpVpnId, vpnId); } else { - ipV6InternetDefRt.removeDefaultRoute(dpnId, internetBgpVpnId, vpnId); + ipV6InternetDefRt.removeDefaultRoute(dpnId, rtrId.getValue(), internetBgpVpnId, vpnId); } } } @@ -1886,4 +1893,19 @@ public class NeutronvpnUtils { org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id .VpnInstance::getVpnId).orElse(null); } + + protected boolean isV6SubnetPartOfRouter(Uuid routerId) { + List subnetList = getNeutronRouterSubnetMapList(routerId); + for (Subnetmap sm: subnetList) { + if (sm == null) { + continue; + } + IpVersionChoice ipVers = getIpVersionFromString(sm.getSubnetIp()); + //skip further subnet processing once found first V6 subnet for the router + if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) { + return true; + } + } + return false; + } }