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;
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;
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.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;
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,
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;
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
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 {
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
}
}
// 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
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);
}
//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
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();
- }
}