X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=vpnservice%2Fnatservice%2Fnatservice-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fnatservice%2Finternal%2FRouterDpnChangeListener.java;h=709492b04a3edc16ed29b8e7c3d15a02262e6a21;hb=42c3e7c865e2d0392a5b12e3ce6ebdf937b525b7;hp=fa7a26dbce0b8479c3579de5343e5d8367a3d6bb;hpb=a5d9b6a04e0e503e07442526cddc74e5c76c9a66;p=netvirt.git diff --git a/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java b/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java index fa7a26dbce..709492b04a 100644 --- a/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java +++ b/vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java @@ -8,46 +8,76 @@ package org.opendaylight.netvirt.natservice.internal; import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; import java.math.BigInteger; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; +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.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase; +import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; 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.interfaces.IMdsalApiManager; +import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; +import org.opendaylight.netvirt.elanmanager.api.IElanService; +import org.opendaylight.netvirt.natservice.api.SnatServiceManager; +import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers; -import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RouterDpnChangeListener extends AsyncDataTreeChangeListenerBase implements - AutoCloseable{ +@Singleton +public class RouterDpnChangeListener + extends AsyncDataTreeChangeListenerBase + implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class); - private ListenerRegistration listenerRegistration; private final DataBroker dataBroker; private final IMdsalApiManager mdsalManager; private final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer; private final NaptSwitchHA naptSwitchHA; private final IdManagerService idManager; + private final INeutronVpnManager nvpnManager; private final ExternalNetworkGroupInstaller extNetGroupInstaller; + private final IElanService elanManager; + private final JobCoordinator coordinator; + private final SnatServiceManager natServiceManager; + private NatMode natMode = NatMode.Controller; + @Inject public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager, final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer, final NaptSwitchHA naptSwitchHA, final IdManagerService idManager, - final ExternalNetworkGroupInstaller extNetGroupInstaller) { + final ExternalNetworkGroupInstaller extNetGroupInstaller, + final INeutronVpnManager nvpnManager, + final SnatServiceManager natServiceManager, + final NatserviceConfig config, + final IElanService elanManager, + final JobCoordinator coordinator) { super(DpnVpninterfacesList.class, RouterDpnChangeListener.class); this.dataBroker = dataBroker; this.mdsalManager = mdsalManager; @@ -55,9 +85,17 @@ public class RouterDpnChangeListener extends AsyncDataTreeChangeListenerBase getWildCardPath() { - return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class).child(DpnVpninterfacesList.class); + return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class) + .child(DpnVpninterfacesList.class); } @Override protected void add(final InstanceIdentifier identifier, final DpnVpninterfacesList dpnInfo) { - LOG.trace("Add event - key: {}, value: {}", identifier, dpnInfo); - final String routerId = identifier.firstKeyOf(RouterDpnList.class).getRouterId(); + LOG.trace("add : key: {}, value: {}", dpnInfo.getKey(), dpnInfo); + final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId(); BigInteger dpnId = dpnInfo.getDpnId(); //check router is associated to external network - InstanceIdentifier id = NatUtil.buildRouterIdentifier(routerId); - Optional routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id); + InstanceIdentifier id = NatUtil.buildRouterIdentifier(routerUuid); + Optional routerData = + SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker, + LogicalDatastoreType.CONFIGURATION, id); if (routerData.isPresent()) { - Uuid networkId = routerData.get().getNetworkId(); - if(networkId != null) { - LOG.debug("Router {} is associated with ext nw {}", routerId, networkId); - Uuid vpnName = NatUtil.getVpnForRouter(dataBroker,routerId); - Long vpnId; - if (vpnName == null) { - LOG.debug("Internal vpn associated to router {}",routerId); - vpnId = NatUtil.getVpnId(dataBroker,routerId); - if (vpnId == NatConstants.INVALID_ID) { - LOG.error("Invalid vpnId returned for routerName {}",routerId); - return; - } - LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId); - //Install default entry in FIB to SNAT table - LOG.debug("Installing default route in FIB on dpn {} for router {} with vpn {}...", dpnId,routerId,vpnId); - snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId); - } else { - LOG.debug("External BGP vpn associated to router {}",routerId); - vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue()); - if (vpnId == NatConstants.INVALID_ID) { - LOG.error("Invalid vpnId returned for routerName {}", routerId); + Routers router = routerData.get(); + Uuid networkId = router.getNetworkId(); + if (networkId != null) { + if (natMode == NatMode.Conntrack) { + BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName()); + if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) { + LOG.warn("add : NAPT switch is not selected."); return; } - Long routId = NatUtil.getVpnId(dataBroker, routerId); - if (routId == NatConstants.INVALID_ID) { - LOG.error("Invalid routId returned for routerName {}",routerId); + //If it is for NAPT switch skip as the flows would be already programmed. + if (naptSwitch.equals(dpnId)) { + LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid); return; } - LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId); - //Install default entry in FIB to SNAT table - LOG.debug("Installing default route in FIB on dpn {} for routerId {} with vpnId {}...", dpnId,routerId,vpnId); - snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routId); - } - extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId); - - if (routerData.get().isEnableSnat()) { - LOG.info("SNAT enabled for router {}", routerId); - handleSNATForDPN(dpnId, routerId ,vpnId); + natServiceManager.notify(router, naptSwitch, dpnId, + SnatServiceManager.Action.SNAT_ROUTER_ENBL); } else { - LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId); - } + coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + dpnInfo.getKey(), () -> { + WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction(); + WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction(); + LOG.debug("add : Router {} is associated with ext nw {}", routerUuid, networkId); + Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid); + Long routerId = NatUtil.getVpnId(dataBroker, routerUuid); + List> futures = new ArrayList<>(); + if (routerId == NatConstants.INVALID_ID) { + LOG.error("add : Invalid routerId returned for routerName {}", routerUuid); + writeFlowInvTx.cancel(); + removeFlowInvTx.cancel(); + return futures; + } + extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId); + Long vpnId; + if (vpnName == null) { + LOG.debug("add : Internal vpn associated to router {}", routerUuid); + vpnId = routerId; + if (vpnId == NatConstants.INVALID_ID) { + LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid); + writeFlowInvTx.cancel(); + removeFlowInvTx.cancel(); + return futures; + } + LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid); + //Install default entry in FIB to SNAT table + LOG.info("add : Installing default route in FIB on dpn {} for router {} with vpn {}", + dpnId, routerUuid, vpnId); + installDefaultNatRouteForRouterExternalSubnets(dpnId, + NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps())); + snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, writeFlowInvTx); + } else { + LOG.debug("add : External BGP vpn associated to router {}", routerUuid); + vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue()); + if (vpnId == NatConstants.INVALID_ID) { + LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid); + writeFlowInvTx.cancel(); + removeFlowInvTx.cancel(); + return futures; + } + + LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid); + //Install default entry in FIB to SNAT table + LOG.debug("add : Installing default route in FIB on dpn {} for routerId {} with " + + "vpnId {}...", dpnId, routerUuid, vpnId); + installDefaultNatRouteForRouterExternalSubnets(dpnId, + NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps())); + snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, writeFlowInvTx); + } + + + if (router.isEnableSnat()) { + LOG.info("add : SNAT enabled for router {}", routerUuid); + ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, + routerUuid, networkId); + if (extNwProvType == null) { + LOG.error("add : External Network Provider Type missing"); + writeFlowInvTx.cancel(); + removeFlowInvTx.cancel(); + return futures; + } + handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, writeFlowInvTx, removeFlowInvTx, + extNwProvType); + } else { + LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}", + routerUuid, dpnId); + } + futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx)); + futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx)); + return futures; + }, NatConstants.NAT_DJC_MAX_RETRIES); + } // end of controller based SNAT } } else { - LOG.debug("Router {} is not associated with External network", routerId); + LOG.debug("add : Router {} is not associated with External network", routerUuid); } } @Override protected void remove(InstanceIdentifier identifier, DpnVpninterfacesList dpnInfo) { - LOG.trace("Remove event - key: {}, value: {}", identifier, dpnInfo); - final String routerId = identifier.firstKeyOf(RouterDpnList.class).getRouterId(); + LOG.trace("remove : key: {}, value: {}", dpnInfo.getKey(), dpnInfo); + final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId(); + Long routerId = NatUtil.getVpnId(dataBroker, routerUuid); + if (routerId == NatConstants.INVALID_ID) { + LOG.error("REMOVE: Invalid routId returned for routerName {}",routerUuid); + return; + } BigInteger dpnId = dpnInfo.getDpnId(); //check router is associated to external network - InstanceIdentifier id = NatUtil.buildRouterIdentifier(routerId); - Optional routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id); + InstanceIdentifier id = NatUtil.buildRouterIdentifier(routerUuid); + Optional routerData = + SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker, + LogicalDatastoreType.CONFIGURATION, id); if (routerData.isPresent()) { - Uuid networkId = routerData.get().getNetworkId(); + Routers router = routerData.get(); + Uuid networkId = router.getNetworkId(); if (networkId != null) { - LOG.debug("Router {} is associated with ext nw {}", routerId, networkId); - Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerId); - Long vpnId; - if (vpnName == null) { - LOG.debug("Internal vpn associated to router {}", routerId); - vpnId = NatUtil.getVpnId(dataBroker, routerId); - if (vpnId == NatConstants.INVALID_ID) { - LOG.error("Invalid vpnId returned for routerName {}", routerId); + if (natMode == NatMode.Conntrack) { + BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName()); + if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) { + LOG.warn("remove : NAPT switch is not selected."); return; } - LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId); - //Remove default entry in FIB - LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName); - snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId); - } else { - LOG.debug("External vpn associated to router {}", routerId); - vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue()); - if (vpnId == NatConstants.INVALID_ID) { - LOG.error("Invalid vpnId returned for routerName {}", routerId); + //If it is for NAPT switch skip as the flows would be already programmed. + if (naptSwitch.equals(dpnId)) { + LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid); return; } - Long routId = NatUtil.getVpnId(dataBroker, routerId); - if (routId == NatConstants.INVALID_ID) { - LOG.error("Invalid routId returned for routerName {}",routerId); - return; - } - LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId); - //Remove default entry in FIB - LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName); - snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId,vpnId,routId); - } - - if (routerData.get().isEnableSnat()) { - LOG.info("SNAT enabled for router {}", routerId); - removeSNATFromDPN(dpnId, routerId, vpnId); + natServiceManager.notify(router, naptSwitch, dpnId, + SnatServiceManager.Action.SNAT_ROUTER_DISBL); } else { - LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId); - } + coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + dpnInfo.getKey(), () -> { + WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction(); + LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId); + Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid); + Long vpnId; + List> futures = new ArrayList<>(); + if (vpnName == null) { + LOG.debug("remove : Internal vpn associated to router {}", routerUuid); + vpnId = routerId; + if (vpnId == NatConstants.INVALID_ID) { + LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid); + removeFlowInvTx.cancel(); + return futures; + } + LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid); + //Remove default entry in FIB + LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId, + vpnName); + snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, removeFlowInvTx); + } else { + LOG.debug("remove : External vpn associated to router {}", routerUuid); + vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue()); + if (vpnId == NatConstants.INVALID_ID) { + LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid); + removeFlowInvTx.cancel(); + return futures; + } + LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid); + //Remove default entry in FIB + LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId, + vpnName); + snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, removeFlowInvTx); + } + + if (router.isEnableSnat()) { + LOG.info("remove : SNAT enabled for router {}", routerUuid); + removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, removeFlowInvTx); + } else { + LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}", + routerUuid, dpnId); + } + futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx)); + return futures; + }, NatConstants.NAT_DJC_MAX_RETRIES); + } // end of controller based SNAT } } } @Override - protected void update(InstanceIdentifier identifier, DpnVpninterfacesList original, DpnVpninterfacesList update) { - LOG.trace("Update event - key: {}, original: {}, update: {}", identifier, original, update); + protected void update(InstanceIdentifier identifier, DpnVpninterfacesList original, + DpnVpninterfacesList update) { + LOG.trace("Update key: {}, original: {}, update: {}", update.getKey(), original, update); } - void handleSNATForDPN(BigInteger dpnId, String routerName,Long routerVpnId) { - //Check if primary and secondary switch are selected, If not select the role + + // TODO Clean up the exception handling + @SuppressWarnings("checkstyle:IllegalCatch") + void handleSNATForDPN(BigInteger dpnId, String routerName, long routerId, Long routerVpnId, + WriteTransaction writeFlowInvTx, WriteTransaction removeFlowInvTx, ProviderTypes extNwProvType) { + //Check if primary and secondary switch are selected, If not select the role //Install select group to NAPT switch //Install default miss entry to NAPT switch BigInteger naptSwitch; try { - Long routerId = NatUtil.getVpnId(dataBroker, routerName); - if (routerId == NatConstants.INVALID_ID) { - LOG.error("Invalid routerId returned for routerName {}", routerName); - return; - } BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName); if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptSwitchHA.getSwitchStatus(naptId)) { - LOG.debug("No NaptSwitch is selected for router {}", routerName); - + LOG.debug("handleSNATForDPN : No NaptSwitch is selected for router {}", routerName); naptSwitch = dpnId; boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch); if (!naptstatus) { - LOG.error("Failed to update newNaptSwitch {} for routername {}", naptSwitch, routerName); + LOG.error("handleSNATForDPN : Failed to update newNaptSwitch {} for routername {}", + naptSwitch, routerName); return; } - LOG.debug("Switch {} is elected as NaptSwitch for router {}", dpnId, routerName); + LOG.debug("handleSNATForDPN : Switch {} is elected as NaptSwitch for router {}", dpnId, routerName); + + // When NAPT switch is elected during first VM comes up for the given Router + if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) { + NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager, + idManager, NatConstants.ODL_VNI_POOL_NAME); + } Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName); if (extRouters != null) { - NatUtil.createRouterIdsConfigDS(dataBroker, routerName); + NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName); naptSwitchHA.subnetRegisterMapping(extRouters, routerId); } - naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId); + + naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, writeFlowInvTx); // Install miss entry (table 26) pointing to table 46 - FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId, NatConstants.ADD_FLOW); + FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, + routerVpnId, NatConstants.ADD_FLOW); if (flowEntity == null) { - LOG.debug("Failed to populate flowentity for router {} with dpnId {}", routerName, dpnId); + LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}", + routerName, dpnId); return; } - LOG.debug("Successfully installed flow for dpnId {} router {}", dpnId, routerName); - mdsalManager.installFlow(flowEntity); + LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {}", dpnId, routerName); + mdsalManager.addFlowToTx(flowEntity, writeFlowInvTx); //Removing primary flows from old napt switch if (naptId != null && !naptId.equals(BigInteger.ZERO)) { - LOG.debug("Removing primary flows from old napt switch {} for router {}", naptId, routerName); - naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, naptId, null); + LOG.debug("handleSNATForDPN : Removing primary flows from old napt switch {} for router {}", + naptId, routerName); + naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptId, null, removeFlowInvTx); } } else if (naptId.equals(dpnId)) { - LOG.debug("NaptSwitch {} gone down during cluster reboot came alive", naptId); + LOG.debug("handleSNATForDPN : NaptSwitch {} gone down during cluster reboot came alive", naptId); } else { - - LOG.debug("Napt switch with Id {} is already elected for router {}", naptId, routerName); naptSwitch = naptId; + LOG.debug("handleSNATForDPN : Napt switch with Id {} is already elected for router {}", + naptId, routerName); //installing group - List bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, routerName, naptSwitch); + List bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, + routerName, routerId, naptSwitch); if (bucketInfo == null) { - LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}", dpnId, routerName, - naptSwitch); + LOG.error("handleSNATForDPN:Failed to populate bucketInfo for dpnId {},routername {},naptSwitch {}", + dpnId, routerName, naptSwitch); return; } naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName); // Install miss entry (table 26) pointing to group long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager); - FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId, NatConstants.ADD_FLOW); + FlowEntity flowEntity = + naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, + routerVpnId, NatConstants.ADD_FLOW); if (flowEntity == null) { - LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}", routerName, dpnId, groupId); + LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {} groupId {}", + routerName, dpnId, groupId); return; } - LOG.debug("Successfully installed flow for dpnId {} router {} group {}", dpnId, routerName, groupId); - mdsalManager.installFlow(flowEntity); + LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}", + dpnId, routerName, groupId); + mdsalManager.addFlowToTx(flowEntity, writeFlowInvTx); } + } catch (Exception ex) { - LOG.error("Exception in handleSNATForDPN method : {}", ex); + LOG.error("handleSNATForDPN : Exception in handleSNATForDPN", ex); } } - void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerVpnId) { + // TODO Clean up the exception handling + @SuppressWarnings("checkstyle:IllegalCatch") + void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId, + Uuid extNetworkId, WriteTransaction removeFlowInvTx) { //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed //remove miss entry to NAPT switch //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch - //get ExternalIpIn prior - List externalIpCache; - //HashMap Label - HashMap externalIpLabel; - Long routerId = NatUtil.getVpnId(dataBroker, routerName); - if (routerId == NatConstants.INVALID_ID) { - LOG.error("Invalid routerId returned for routerName {}",routerName); + Collection externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId); + ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId); + if (extNwProvType == null) { return; } - externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker,routerId); - externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker,routerId); + //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN + Map externalIpLabel; + if (extNwProvType == ProviderTypes.VXLAN) { + externalIpLabel = null; + } else { + externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId); + } BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName); if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) { - LOG.debug("No naptSwitch is selected for router {}", routerName); + LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName); return; } try { - boolean naptStatus = naptSwitchHA.isNaptSwitchDown(routerName,dpnId,naptSwitch,routerVpnId,externalIpCache); + boolean naptStatus = + naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId, + externalIpCache, removeFlowInvTx); if (!naptStatus) { - LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}", - dpnId, routerName); + LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}", + dpnId, routerName); long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager); FlowEntity flowEntity = null; try { - flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId, NatConstants.DEL_FLOW); + flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId, + NatConstants.DEL_FLOW); if (flowEntity == null) { - LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",routerName,dpnId,groupId); + LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} " + + "with dpnId:{} groupId:{}", routerName, dpnId, groupId); return; } - LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}",flowEntity); - mdsalManager.removeFlow(flowEntity); + LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity); + mdsalManager.removeFlowToTx(flowEntity, removeFlowInvTx); } catch (Exception ex) { - LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex); + LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}", + flowEntity, ex); return; } - LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName); + LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}", + dpnId, routerName); //remove group GroupEntity groupEntity = null; try { groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, - GroupTypes.GroupAll, null); - LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity); + GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/); + LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity); mdsalManager.removeGroup(groupEntity); } catch (Exception ex) { - LOG.debug("NAT Service : Failed to remove group entity {} : {}",groupEntity,ex); + LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex); return; } - LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}", dpnId, routerName); + LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}", + dpnId, routerName); } else { - naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, naptSwitch,externalIpLabel); + naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch, + externalIpLabel, removeFlowInvTx); //remove table 26 flow ppointing to table46 FlowEntity flowEntity = null; try { - flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId, NatConstants.DEL_FLOW); + flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId, + NatConstants.DEL_FLOW); if (flowEntity == null) { - LOG.debug("Failed to populate flowentity for router {} with dpnId {}",routerName,dpnId); + LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}", + routerName, dpnId); return; } - LOG.debug("NAT Service : Removing default SNAT miss entry flow entity for router {} with dpnId {} in napt switch {}" - ,routerName,dpnId,naptSwitch); - mdsalManager.removeFlow(flowEntity); + LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with " + + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch); + mdsalManager.removeFlowToTx(flowEntity, removeFlowInvTx); } catch (Exception ex) { - LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex); + LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}", + flowEntity, ex); return; } - LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName); + LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}", + dpnId, routerName); //best effort to check IntExt model - naptSwitchHA.bestEffortDeletion(routerId,routerName,externalIpLabel); + naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, removeFlowInvTx); } } catch (Exception ex) { - LOG.debug("Exception while handling naptSwitch down for router {} : {}",routerName,ex); + LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, ex); } } -} \ No newline at end of file + + private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, Collection externalSubnetIds) { + if (externalSubnetIds == null) { + LOG.error("installDefaultNatRouteForRouterExternalSubnets : No external subnets for router"); + return; + } + + for (Uuid subnetId : externalSubnetIds) { + long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId); + if (vpnIdForSubnet != NatConstants.INVALID_ID) { + LOG.info("installDefaultNatRouteForRouterExternalSubnets : Installing default routes in FIB on dpn {} " + + "for subnetId {} with vpnId {}", dpnId, subnetId, vpnIdForSubnet); + snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue(), + idManager); + } else { + LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId); + } + } + } + + private InstanceIdentifier getSubnetMapIdentifier(Uuid subnetId) { + return InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, + new SubnetmapKey(subnetId)).build(); + } +}