Test Scenario1: All OVS are connected back after upgrade.
1) Take the back-up of the Config DS and bring down the controller.
2) Disconnect OVS(by blocking port 6640 & 6653)
3) Upgrade ODL, set upgrade-flag=true and reload the config DS.
4) Start connecting back the OVS with first connecting non-napt
switches followed by Napt-Switches.
5) set upgrade-flag=false once all the OVS are connected by to ODL.
6) Verify earlier Napt Switches continues to work as Napt Switches
and all earlier on-going SNAT session and new sessions are not
impacted.
Test Scenario2: Few OVS(which are elected as Napt) are not
connected back after upgrade.
1) Take the back-up of the Config DS and bring down the controller.
2) Disconnect OVS(by blocking port 6640 & 6653)
3) Upgrade ODL, set upgrade-flag=true and reload the config DS.
4) Start connecting back the OVS with first connecting non-napt
switches and do not connect few OVS elected as Napt Switches earlier.
5) set upgrade-flag=false.
6) Verify a new Napt Switch is elected for those router whose Napt
Switches are not been connected back after upgrade.
7) Verify new SNAT sessions are established and earlier on-going SNAT
session gets migrated to newly elected Napt Switch.
JIRA: NETVIRT-1222
Change-Id: I194124596e987c43703be37707235a6c88c91013
Signed-off-by: xcheara <chetan.arakere@altencalsoftlabs.com>
Signed-off-by: shaik <shaik.b@altencalsoftlabs.com>
Signed-off-by: xcheara <chetan.arakere@altencalsoftlabs.com>
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.netvirt.natservice.internal.NatUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
@Override
protected Object doExecute() throws Exception {
PrintStream ps = session.getConsole();
- Optional<NaptSwitches> npatSwitches = SingleTransactionDataBroker.syncReadOptional(dataBroker,
- LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier());
+ Optional<NaptSwitches> npatSwitches = NatUtil.getAllPrimaryNaptSwitches(dataBroker);
ps.printf(String.format(" %-36s %-20s %-20s %n", "Router Id ", "Datapath Node Id", "Managment Ip Address"));
ps.printf("-------------------------------------------------------------------------------------------%n");
if (npatSwitches.isPresent()) {
return null;
}
- private InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
- return InstanceIdentifier.builder(NaptSwitches.class).build();
- }
-
@SuppressWarnings("unchecked")
private Optional<Node> getPortsNode(BigInteger dpnId) {
InstanceIdentifier<BridgeRefEntry> bridgeRefInfoPath = InstanceIdentifier.create(BridgeRefInfo.class)
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SnatNodeEventListener extends AbstractClusteredAsyncDataTreeChangeListener<Node> {
private static final Logger LOG = LoggerFactory.getLogger(SnatNodeEventListener.class);
private final CentralizedSwitchScheduler centralizedSwitchScheduler;
+ private final NatserviceConfig.NatMode natMode;
@Inject
public SnatNodeEventListener(final DataBroker dataBroker,
- final CentralizedSwitchScheduler centralizedSwitchScheduler) {
+ final CentralizedSwitchScheduler centralizedSwitchScheduler,
+ final NatserviceConfig config) {
super(dataBroker,new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier
.create(Nodes.class).child(Node.class)),
Executors.newSingleThreadExecutor());
this.centralizedSwitchScheduler = centralizedSwitchScheduler;
+ if (config != null) {
+ this.natMode = config.getNatMode();
+ } else {
+ this.natMode = NatserviceConfig.NatMode.Controller;
+ }
}
@Override
public void remove(Node dataObjectModification) {
- NodeKey nodeKey = dataObjectModification.key();
- BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
- LOG.info("Dpn removed {}", dpnId);
- centralizedSwitchScheduler.removeSwitch(dpnId);
+ if (natMode == NatserviceConfig.NatMode.Conntrack) {
+ NodeKey nodeKey = dataObjectModification.key();
+ BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
+ LOG.info("Dpn removed {}", dpnId);
+ centralizedSwitchScheduler.removeSwitch(dpnId);
+ }
}
@Override
@Override
public void add(Node dataObjectModification) {
- NodeKey nodeKey = dataObjectModification.key();
- BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
- LOG.info("Dpn added {}", dpnId);
- centralizedSwitchScheduler.addSwitch(dpnId);
-
+ if (natMode == NatserviceConfig.NatMode.Conntrack) {
+ NodeKey nodeKey = dataObjectModification.key();
+ BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
+ LOG.info("Dpn added {}", dpnId);
+ centralizedSwitchScheduler.addSwitch(dpnId);
+ }
}
}
NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
try {
- coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routers.key(),
- () -> Collections.singletonList(
- txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
- LOG.info("add : Installing NAT default route on all dpns part of router {}", routerName);
- long bgpVpnId = NatConstants.INVALID_ID;
- if (bgpVpnUuid != null) {
- bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
- }
- addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, confTx);
- // Allocate Primary Napt Switch for this router
- BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName);
- if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
- if (!routers.isEnableSnat()) {
- LOG.info("add : SNAT is disabled for external router {} ", routerName);
- /* If SNAT is disabled on ext-router though L3_FIB_TABLE(21) -> PSNAT_TABLE(26) flow
- * is required for DNAT. Hence writeFlowInvTx object submit is required.
- */
- return;
+ if (routers.isEnableSnat()) {
+ coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routers.key(),
+ () -> Collections.singletonList(
+ txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
+ LOG.info("add : Installing NAT default route on all dpns part of router {}", routerName);
+ long bgpVpnId = NatConstants.INVALID_ID;
+ if (bgpVpnUuid != null) {
+ bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
+ }
+ addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, confTx);
+ // Allocate Primary Napt Switch for this router
+ BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName);
+ if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
+ handleEnableSnat(routers, routerId, primarySwitchId, bgpVpnId, confTx);
}
- handleEnableSnat(routers, routerId, primarySwitchId, bgpVpnId, confTx);
}
- })), NatConstants.NAT_DJC_MAX_RETRIES);
+ )), NatConstants.NAT_DJC_MAX_RETRIES);
+ } else {
+ LOG.info("add : SNAT is disabled for external router {} ", routerName);
+ }
} catch (Exception ex) {
LOG.error("add : Exception while Installing NAT flows on all dpns as part of router {}",
routerName, ex);
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
return true;
}
//checking elected switch health status
- if (!getSwitchStatus(naptSwitch)) {
+ if (!NatUtil.getSwitchStatus(dataBroker, naptSwitch)) {
LOG.error("isNaptSwitchDown : Newly elected Napt switch {} for router {} is down",
naptSwitch, routerName);
return true;
SessionAddress externalAddress = new SessionAddress(externalIpAddress, extportNumber);
//checking naptSwitch status before installing flows
- if (getSwitchStatus(newNaptSwitch)) {
+ if (NatUtil.getSwitchStatus(dataBroker, newNaptSwitch)) {
//Install the flow in newNaptSwitch Inbound NAPT table.
try {
naptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NwConstants.INBOUND_NAPT_TABLE,
return NatConstants.INVALID_ID;
}
- public boolean getSwitchStatus(BigInteger switchId) {
- NodeId nodeId = new NodeId("openflow:" + switchId);
- LOG.debug("getSwitchStatus : Querying switch with dpnId {} is up/down", nodeId);
- InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
- .child(Node.class, new NodeKey(nodeId)).build();
- Optional<Node> nodeOptional =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
- LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
- if (nodeOptional.isPresent()) {
- LOG.debug("getSwitchStatus : Switch {} is up", nodeId);
- return true;
- }
- LOG.debug("getSwitchStatus : Switch {} is down", nodeId);
- return false;
- }
-
public List<BucketInfo> handleGroupInPrimarySwitch() {
List<BucketInfo> listBucketInfo = new ArrayList<>();
List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
import org.opendaylight.genius.mdsalutil.ActionInfo;
import org.opendaylight.genius.mdsalutil.FlowEntity;
import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
+import org.opendaylight.genius.mdsalutil.GroupEntity;
import org.opendaylight.genius.mdsalutil.InstructionInfo;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.MatchInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
return rtrNaptSw;
}
+ public static Optional<NaptSwitches> getAllPrimaryNaptSwitches(DataBroker broker) {
+ return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
+ LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier());
+ }
+
public static String getRouterName(DataBroker broker, Long routerId) {
InstanceIdentifier<RouterIds> id = buildRouterIdentifier(routerId);
- return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
- LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(RouterIds::getRouterName).orElse(null);
+ String routerName = SingleTransactionDataBroker
+ .syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker, LogicalDatastoreType.CONFIGURATION,
+ id)
+ .toJavaUtil().map(RouterIds::getRouterName).orElse(null);
+ if (routerName == null) {
+ routerName = getVpnInstanceFromVpnIdentifier(broker, routerId);
+ }
+ return routerName;
}
static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
}), LOG, "Error installing router gateway flows");
}
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public static void removeSNATFromDPN(DataBroker dataBroker, IMdsalApiManager mdsalManager,
+ IdManagerService idManager, NaptSwitchHA naptSwitchHA, BigInteger dpnId,
+ String routerName, long routerId, long routerVpnId,
+ ProviderTypes extNwProvType, TypedReadWriteTransaction<Configuration> confTx) {
+ //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
+
+ Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+ if (extNwProvType == null) {
+ return;
+ }
+ //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
+ Map<String, Long> 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.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
+ return;
+ }
+ try {
+ boolean naptStatus =
+ naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
+ externalIpCache, confTx);
+ if (!naptStatus) {
+ 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);
+ if (flowEntity == null) {
+ LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
+ + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
+ return;
+ }
+ LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity);
+ mdsalManager.removeFlow(confTx, flowEntity);
+
+ } catch (Exception ex) {
+ LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
+ flowEntity, ex);
+ return;
+ }
+ 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, Collections.emptyList() /*listBucketInfo*/);
+ LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
+ mdsalManager.removeGroup(groupEntity);
+ } catch (Exception ex) {
+ LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
+ return;
+ }
+ LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
+ dpnId, routerName);
+ } else {
+ naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
+ externalIpLabel, confTx);
+ //remove table 26 flow ppointing to table46
+ FlowEntity flowEntity = null;
+ try {
+ flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
+ NatConstants.DEL_FLOW);
+ if (flowEntity == null) {
+ LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
+ routerName, dpnId);
+ return;
+ }
+ LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
+ + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
+ mdsalManager.removeFlow(confTx, flowEntity);
+
+ } catch (Exception ex) {
+ LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
+ flowEntity, ex);
+ return;
+ }
+ 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, confTx);
+ }
+ } catch (Exception ex) {
+ LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, ex);
+ }
+ }
+
public static Boolean isOpenStackVniSemanticsEnforcedForGreAndVxlan(IElanService elanManager,
ProviderTypes extNwProvType) {
if (elanManager.isOpenStackVniSemanticsEnforced() && (extNwProvType == ProviderTypes.GRE
LOG.error("createGroupIdPool : Failed to create PortPool for NAPT Service", e);
}
}
+
+ public static boolean getSwitchStatus(DataBroker broker, BigInteger switchId) {
+ NodeId nodeId = new NodeId("openflow:" + switchId);
+ LOG.debug("getSwitchStatus : Querying switch with dpnId {} is up/down", nodeId);
+ InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId)).build();
+ Optional<Node> nodeOptional =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
+ LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
+ if (nodeOptional.isPresent()) {
+ LOG.debug("getSwitchStatus : Switch {} is up", nodeId);
+ return true;
+ }
+ LOG.debug("getSwitchStatus : Switch {} is down", nodeId);
+ return false;
+ }
}
import org.opendaylight.genius.mdsalutil.FlowEntity;
import org.opendaylight.genius.mdsalutil.GroupEntity;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.UpgradeState;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
private final JobCoordinator coordinator;
private final SnatServiceManager natServiceManager;
private final NatMode natMode;
+ private final UpgradeState upgradeState;
@Inject
public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
final SnatServiceManager natServiceManager,
final NatserviceConfig config,
final IElanService elanManager,
- final JobCoordinator coordinator) {
+ final JobCoordinator coordinator,
+ final UpgradeState upgradeState) {
super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
this.dataBroker = dataBroker;
this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.natServiceManager = natServiceManager;
this.coordinator = coordinator;
this.natMode = config != null ? config.getNatMode() : NatMode.Controller;
+ this.upgradeState = upgradeState;
}
@Override
BigInteger naptSwitch;
try {
BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
- if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptSwitchHA.getSwitchStatus(naptId)) {
- LOG.debug("handleSNATForDPN : No NaptSwitch is selected for router {}", routerName);
+ if (naptId == null || naptId.equals(BigInteger.ZERO)
+ || (!NatUtil.getSwitchStatus(dataBroker, naptId) && !upgradeState.isUpgradeInProgress())) {
+ LOG.debug("handleSNATForDPN : NaptSwitch is down or not selected for router {},naptId {}",
+ routerName, naptId);
naptSwitch = dpnId;
boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
if (!naptstatus) {
package org.opendaylight.netvirt.natservice.internal;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
+import com.google.common.base.Optional;
+
+import java.math.BigInteger;
+import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.inject.Inject;
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.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
import org.opendaylight.serviceutils.tools.mdsal.listener.AbstractClusteredSyncDataTreeChangeListener;
+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.netvirt.natservice.config.rev170206.NatserviceConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
+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.natservice.rev160111.ext.routers.routers.ExternalIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsalutil.rev170830.Config;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
private final DataBroker dataBroker;
private final CentralizedSwitchScheduler centralizedSwitchScheduler;
private final NatserviceConfig.NatMode natMode;
+ private SNATDefaultRouteProgrammer defaultRouteProgrammer;
+ private IMdsalApiManager mdsalManager;
+ private IdManagerService idManager;
+ private NaptSwitchHA naptSwitchHA;
+ private final JobCoordinator coordinator;
+ private final ManagedNewTransactionRunner txRunner;
@Inject
public UpgradeStateListener(final DataBroker dataBroker,
final CentralizedSwitchScheduler centralizedSwitchScheduler,
- final NatserviceConfig config) {
+ final SNATDefaultRouteProgrammer defaultRouteProgrammer,
+ final IMdsalApiManager mdsalManager,
+ final IdManagerService idManager,
+ final NaptSwitchHA naptSwitchHA,
+ final NatserviceConfig config, final JobCoordinator coordinator) {
super(dataBroker, new DataTreeIdentifier<>(
LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Config.class)));
this.dataBroker = dataBroker;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.centralizedSwitchScheduler = centralizedSwitchScheduler;
+ this.defaultRouteProgrammer = defaultRouteProgrammer;
+ this.coordinator = coordinator;
+ this.naptSwitchHA = naptSwitchHA;
if (config != null) {
this.natMode = config.getNatMode();
} else {
@Override
public void remove(@Nonnull Config removedDataObject) {
+ if (natMode == NatserviceConfig.NatMode.Conntrack) {
+ return;
+ }
+ LOG.debug("Verify is all Elected Napt Switch and connected back post upgrade");
}
@Override
public void update(@Nonnull Config original, Config updated) {
- if (natMode != NatserviceConfig.NatMode.Conntrack) {
+ if (natMode == NatserviceConfig.NatMode.Controller) {
+ if (original.isUpgradeInProgress() && !updated.isUpgradeInProgress()) {
+ Optional<NaptSwitches> npatSwitches = NatUtil.getAllPrimaryNaptSwitches(dataBroker);
+ if (npatSwitches.isPresent()) {
+ for (RouterToNaptSwitch routerToNaptSwitch : npatSwitches.get().getRouterToNaptSwitch()) {
+ BigInteger primaryNaptDpnId = routerToNaptSwitch.getPrimarySwitchId();
+ if (!NatUtil.getSwitchStatus(dataBroker, routerToNaptSwitch.getPrimarySwitchId())) {
+ String routerUuid = routerToNaptSwitch.getRouterName();
+ coordinator.enqueueJob((NatConstants.NAT_DJC_PREFIX + routerUuid),
+ () -> Collections.singletonList(
+ txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
+ reElectNewNaptSwitch(routerUuid, primaryNaptDpnId, confTx);
+ }
+ )), NatConstants.NAT_DJC_MAX_RETRIES);
+ }
+ }
+ }
+ }
return;
}
}
}
}
+
+ private void reElectNewNaptSwitch(String routerName, BigInteger primaryNaptDpnId,
+ TypedReadWriteTransaction<Configuration> confTx) {
+ // Check if this is externalRouter else ignore
+ InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
+ Optional<Routers> routerData =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, extRoutersId);
+ if (!routerData.isPresent()) {
+ LOG.debug("reElectNewNaptSwitch : SNAT->Ignoring Re-election for router {} since its not External Router",
+ routerName);
+ return;
+ }
+ Uuid networkId = routerData.get().getNetworkId();
+ if (networkId == null) {
+ LOG.error("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring Re-election with Napt {} for router {}"
+ + "as external network configuraton is missing", primaryNaptDpnId, routerName);
+ return;
+ }
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
+ Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
+ Long bgpVpnId;
+ if (bgpVpnUuid == null) {
+ LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
+ routerId, routerName);
+ bgpVpnId = routerId;
+ } else {
+ bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
+ if (bgpVpnId == NatConstants.INVALID_ID) {
+ LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
+ routerName);
+ return;
+ }
+ }
+ defaultRouteProgrammer.removeDefNATRouteInDPN(primaryNaptDpnId, bgpVpnId, confTx);
+ if (routerData.get().isEnableSnat()) {
+ LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
+
+ long routerVpnId = routerId;
+ if (bgpVpnId != NatConstants.INVALID_ID) {
+ LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
+ + "associated to the router {}", bgpVpnId, routerName);
+ routerVpnId = bgpVpnId;
+ } else {
+ LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
+ + "associated to the router {}", routerVpnId, routerName);
+ }
+ //Re-elect the other available switch as the NAPT switch and program the NAT flows.
+ ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
+ routerName, networkId);
+ if (extNwProvType == null) {
+ return;
+ }
+ NatUtil.removeSNATFromDPN(dataBroker, mdsalManager, idManager, naptSwitchHA, primaryNaptDpnId, routerName,
+ routerId, routerVpnId, extNwProvType, confTx);
+
+ } else {
+ LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
+ routerId, primaryNaptDpnId);
+ }
+ }
+
}