OPNFLWPLUG-972 : Point to openflowplugin liblldp
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / RouterDpnChangeListener.java
index ea7009abe9446b4611127c2ca4c0e39c5dfbf10d..eeeef374138886dfdfee761bf287913707c69f71 100644 (file)
@@ -9,7 +9,6 @@ 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.ArrayList;
 import java.util.Collection;
@@ -19,11 +18,9 @@ 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.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.mdsalutil.BucketInfo;
@@ -31,6 +28,7 @@ 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;
@@ -40,22 +38,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group
 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.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
 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.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;
 
 @Singleton
 public class RouterDpnChangeListener
-        extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener>
-        implements AutoCloseable {
+        extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener> {
 
     private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
     private final DataBroker dataBroker;
@@ -66,8 +59,9 @@ public class RouterDpnChangeListener
     private final INeutronVpnManager nvpnManager;
     private final ExternalNetworkGroupInstaller extNetGroupInstaller;
     private final IElanService elanManager;
-    private SnatServiceManager natServiceManager;
-    private NatMode natMode = NatMode.Controller;
+    private final JobCoordinator coordinator;
+    private final SnatServiceManager natServiceManager;
+    private final NatMode natMode;
 
     @Inject
     public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
@@ -78,7 +72,8 @@ public class RouterDpnChangeListener
                                    final INeutronVpnManager nvpnManager,
                                    final SnatServiceManager natServiceManager,
                                    final NatserviceConfig config,
-                                   final IElanService elanManager) {
+                                   final IElanService elanManager,
+                                   final JobCoordinator coordinator) {
         super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
         this.dataBroker = dataBroker;
         this.mdsalManager = mdsalManager;
@@ -89,9 +84,8 @@ public class RouterDpnChangeListener
         this.nvpnManager = nvpnManager;
         this.elanManager = elanManager;
         this.natServiceManager = natServiceManager;
-        if (config != null) {
-            this.natMode = config.getNatMode();
-        }
+        this.coordinator = coordinator;
+        this.natMode = config != null ? config.getNatMode() : NatMode.Controller;
     }
 
     @Override
@@ -132,82 +126,85 @@ public class RouterDpnChangeListener
                         LOG.warn("add : NAPT switch is not selected.");
                         return;
                     }
-                    //If it is a router port skip the notify.
-                    for (Uuid subnetUuid :router.getSubnetIds()) {
-                        try {
-                            Optional<Subnetmap> subnetMapEntry =
-                                    SingleTransactionDataBroker.syncReadOptional(dataBroker,
-                                            LogicalDatastoreType.CONFIGURATION, getSubnetMapIdentifier(subnetUuid));
-                            if (subnetMapEntry.isPresent()) {
-                                String routerPortUuid = subnetMapEntry.get().getRouterInterfacePortId().getValue();
-                                List<RouterInterfaces> routerInterfaces = dpnInfo.getRouterInterfaces();
-                                for (RouterInterfaces routerInterface : routerInterfaces) {
-                                    if (routerPortUuid.equals(routerInterface.getInterface())) {
-                                        return;
-                                    }
-                                }
-                            }
-                        } catch (ReadFailedException e) {
-                            LOG.warn("add : The subnet map entry is not present.");
-                            return;
-                        }
-
+                    //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;
                     }
                     natServiceManager.notify(router, naptSwitch, dpnId,
                             SnatServiceManager.Action.SNAT_ROUTER_ENBL);
                 } else {
-                    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);
-                    if (routerId == NatConstants.INVALID_ID) {
-                        LOG.error("add : Invalid routerId returned for routerName {}", routerUuid);
-                        return;
-                    }
-                    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);
-                            return;
+                    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<ListenableFuture<Void>> futures = new ArrayList<>();
+                        if (routerId == NatConstants.INVALID_ID) {
+                            LOG.error("add : Invalid routerId 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);
-                            return;
+                        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);
                         }
 
-                        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);
-                    }
-                    extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId);
 
-                    if (router.isEnableSnat()) {
-                        LOG.info("add : SNAT enabled for router {}", routerUuid);
-                        handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, writeFlowInvTx, removeFlowInvTx);
-                    } else {
-                        LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}",
-                                routerUuid, dpnId);
-                    }
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
-                    futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
+                        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 {
@@ -240,46 +237,58 @@ public class RouterDpnChangeListener
                         LOG.warn("remove : NAPT switch is not selected.");
                         return;
                     }
+                    //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;
+                    }
                     natServiceManager.notify(router, naptSwitch, dpnId,
                             SnatServiceManager.Action.SNAT_ROUTER_DISBL);
                 } else {
-                    WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
-                    LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId);
-                    Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
-                    Long vpnId;
-                    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);
-                            return;
-                        }
-                        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);
-                            return;
+                    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<ListenableFuture<Void>> 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);
                         }
-                        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);
-                    }
-                    List<ListenableFuture<Void>> futures = new ArrayList<>();
-                    futures.add(NatUtil.waitForTransactionToComplete(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
             }
         }
@@ -294,7 +303,7 @@ public class RouterDpnChangeListener
     // TODO Clean up the exception handling
     @SuppressWarnings("checkstyle:IllegalCatch")
     void handleSNATForDPN(BigInteger dpnId, String routerName, long routerId, Long routerVpnId,
-            WriteTransaction writeFlowInvTx, WriteTransaction removeFlowInvTx) {
+            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
@@ -313,7 +322,7 @@ public class RouterDpnChangeListener
                 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 (elanManager.isOpenStackVniSemanticsEnforced()) {
+                if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
                     NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
                             idManager, NatConstants.ODL_VNI_POOL_NAME);
                 }
@@ -352,11 +361,6 @@ public class RouterDpnChangeListener
                 //installing group
                 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
                         routerName, routerId, naptSwitch);
-                if (bucketInfo == null) {
-                    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
@@ -489,16 +493,10 @@ public class RouterDpnChangeListener
             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);
+                snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue());
             } else {
                 LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId);
             }
         }
     }
-
-    private InstanceIdentifier<Subnetmap> getSubnetMapIdentifier(Uuid subnetId) {
-        return InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
-                new SubnetmapKey(subnetId)).build();
-    }
 }