2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.natservice.internal;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import com.google.common.base.Optional;
13 import java.math.BigInteger;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
18 import java.util.concurrent.ExecutionException;
19 import javax.annotation.PostConstruct;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
25 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
26 import org.opendaylight.genius.infra.Datastore.Configuration;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
30 import org.opendaylight.genius.mdsalutil.BucketInfo;
31 import org.opendaylight.genius.mdsalutil.FlowEntity;
32 import org.opendaylight.genius.mdsalutil.GroupEntity;
33 import org.opendaylight.genius.mdsalutil.MDSALUtil;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
37 import org.opendaylight.netvirt.elanmanager.api.IElanService;
38 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
39 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
40 import org.opendaylight.serviceutils.upgrade.UpgradeState;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 public class RouterDpnChangeListener
57 extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener> {
59 private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
60 private final DataBroker dataBroker;
61 private final ManagedNewTransactionRunner txRunner;
62 private final IMdsalApiManager mdsalManager;
63 private final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer;
64 private final NaptSwitchHA naptSwitchHA;
65 private final IdManagerService idManager;
66 private final INeutronVpnManager nvpnManager;
67 private final ExternalNetworkGroupInstaller extNetGroupInstaller;
68 private final IElanService elanManager;
69 private final JobCoordinator coordinator;
70 private final SnatServiceManager natServiceManager;
71 private final NatMode natMode;
72 private final UpgradeState upgradeState;
75 public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
76 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
77 final NaptSwitchHA naptSwitchHA,
78 final IdManagerService idManager,
79 final ExternalNetworkGroupInstaller extNetGroupInstaller,
80 final INeutronVpnManager nvpnManager,
81 final SnatServiceManager natServiceManager,
82 final NatserviceConfig config,
83 final IElanService elanManager,
84 final JobCoordinator coordinator,
85 final UpgradeState upgradeState) {
86 super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
87 this.dataBroker = dataBroker;
88 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
89 this.mdsalManager = mdsalManager;
90 this.snatDefaultRouteProgrammer = snatDefaultRouteProgrammer;
91 this.naptSwitchHA = naptSwitchHA;
92 this.idManager = idManager;
93 this.extNetGroupInstaller = extNetGroupInstaller;
94 this.nvpnManager = nvpnManager;
95 this.elanManager = elanManager;
96 this.natServiceManager = natServiceManager;
97 this.coordinator = coordinator;
98 this.natMode = config != null ? config.getNatMode() : NatMode.Controller;
99 this.upgradeState = upgradeState;
105 LOG.info("{} init", getClass().getSimpleName());
106 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
110 protected RouterDpnChangeListener getDataTreeChangeListener() {
111 return RouterDpnChangeListener.this;
115 protected InstanceIdentifier<DpnVpninterfacesList> getWildCardPath() {
116 return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class)
117 .child(DpnVpninterfacesList.class);
121 protected void add(final InstanceIdentifier<DpnVpninterfacesList> identifier, final DpnVpninterfacesList dpnInfo) {
122 LOG.trace("add : key: {}, value: {}", dpnInfo.key(), dpnInfo);
123 final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
124 BigInteger dpnId = dpnInfo.getDpnId();
125 //check router is associated to external network
126 InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
127 Optional<Routers> routerData =
128 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
129 LogicalDatastoreType.CONFIGURATION, id);
130 if (routerData.isPresent()) {
131 Routers router = routerData.get();
132 Uuid networkId = router.getNetworkId();
133 if (networkId != null) {
134 if (natMode == NatMode.Conntrack) {
135 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
136 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
137 LOG.warn("add : NAPT switch is not selected.");
140 //If it is for NAPT switch skip as the flows would be already programmed.
141 if (naptSwitch.equals(dpnId)) {
142 LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
145 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
147 natServiceManager.notify(confTx, router, null, naptSwitch, dpnId,
148 SnatServiceManager.Action.CNT_ROUTER_ENBL);
149 if (router.isEnableSnat()) {
150 natServiceManager.notify(confTx, router, null, naptSwitch, naptSwitch,
151 SnatServiceManager.Action.SNAT_ROUTER_ENBL);
153 }), LOG, "Error notifying NAT service manager");
155 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
156 if (routerId == NatConstants.INVALID_ID) {
157 LOG.error("add : Invalid routerId returned for routerName {}", routerUuid);
160 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
161 routerUuid, networkId);
162 if (extNwProvType == ProviderTypes.FLAT || extNwProvType == ProviderTypes.VLAN) {
163 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + networkId, () -> {
164 extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId);
165 installDefaultNatRouteForRouterExternalSubnets(dpnId,
166 NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
167 return Collections.emptyList();
170 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + router.getRouterName(), () -> {
171 LOG.debug("add : Router {} is associated with ext nw {}", routerUuid, networkId);
172 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
173 return Collections.singletonList(
174 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
176 if (vpnName == null) {
177 LOG.debug("add : Internal vpn associated to router {}", routerUuid);
179 if (vpnId == NatConstants.INVALID_ID) {
180 LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
183 LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
184 //Install default entry in FIB to SNAT table
186 "add : Installing default route in FIB on dpn {} for router {} with vpn {}",
187 dpnId, routerUuid, vpnId);
188 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, confTx);
190 LOG.debug("add : External BGP vpn associated to router {}", routerUuid);
191 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
192 if (vpnId == NatConstants.INVALID_ID) {
193 LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
196 LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
197 //Install default entry in FIB to SNAT table
198 LOG.debug("add : Installing default route in FIB on dpn {} for routerId {} with "
199 + "vpnId {}...", dpnId, routerUuid, vpnId);
200 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
202 if (router.isEnableSnat()) {
203 LOG.info("add : SNAT enabled for router {}", routerUuid);
204 if (extNwProvType == null) {
205 LOG.error("add : External Network Provider Type missing");
208 handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, confTx, extNwProvType);
210 LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}",
214 }, NatConstants.NAT_DJC_MAX_RETRIES);
215 } // end of controller based SNAT
218 LOG.debug("add : Router {} is not associated with External network", routerUuid);
223 protected void remove(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList dpnInfo) {
224 LOG.trace("remove : key: {}, value: {}", dpnInfo.key(), dpnInfo);
225 final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
226 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
227 if (routerId == NatConstants.INVALID_ID) {
228 LOG.error("REMOVE: Invalid routId returned for routerName {}",routerUuid);
231 BigInteger dpnId = dpnInfo.getDpnId();
232 //check router is associated to external network
233 InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
234 Optional<Routers> routerData =
235 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
236 LogicalDatastoreType.CONFIGURATION, id);
237 if (routerData.isPresent()) {
238 Routers router = routerData.get();
239 Uuid networkId = router.getNetworkId();
240 if (networkId != null) {
241 if (natMode == NatMode.Conntrack) {
242 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
243 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
244 LOG.warn("remove : NAPT switch is not selected.");
247 //If it is for NAPT switch skip as the flows would be already programmed.
248 if (naptSwitch.equals(dpnId)) {
249 LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
252 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
254 natServiceManager.notify(confTx, router, null, naptSwitch, dpnId,
255 SnatServiceManager.Action.CNT_ROUTER_DISBL);
256 if (router.isEnableSnat()) {
257 natServiceManager.notify(confTx, router, null, naptSwitch, naptSwitch,
258 SnatServiceManager.Action.SNAT_ROUTER_DISBL);
260 }), LOG, "Error notifying NAT service manager");
262 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid, () -> {
263 LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId);
264 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
265 return Collections.singletonList(
266 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
268 if (vpnName == null) {
269 LOG.debug("remove : Internal vpn associated to router {}", routerUuid);
271 if (vpnId == NatConstants.INVALID_ID) {
272 LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
275 LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
276 //Remove default entry in FIB
277 LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
279 snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, confTx);
281 LOG.debug("remove : External vpn associated to router {}", routerUuid);
282 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
283 if (vpnId == NatConstants.INVALID_ID) {
284 LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
287 LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
288 //Remove default entry in FIB
289 LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
291 snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
294 if (router.isEnableSnat()) {
295 LOG.info("remove : SNAT enabled for router {}", routerUuid);
296 removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, confTx);
298 LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}",
302 }, NatConstants.NAT_DJC_MAX_RETRIES);
303 } // end of controller based SNAT
309 protected void update(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList original,
310 DpnVpninterfacesList update) {
311 LOG.trace("Update key: {}, original: {}, update: {}", update.key(), original, update);
314 void handleSNATForDPN(BigInteger dpnId, String routerName, long routerId, Long routerVpnId,
315 TypedReadWriteTransaction<Configuration> confTx, ProviderTypes extNwProvType) {
316 //Check if primary and secondary switch are selected, If not select the role
317 //Install select group to NAPT switch
318 //Install default miss entry to NAPT switch
319 BigInteger naptSwitch;
321 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
322 if (naptId == null || naptId.equals(BigInteger.ZERO)
323 || !NatUtil.getSwitchStatus(dataBroker, naptId) && !upgradeState.isUpgradeInProgress()) {
324 LOG.debug("handleSNATForDPN : NaptSwitch is down or not selected for router {},naptId {}",
327 boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
329 LOG.error("handleSNATForDPN : Failed to update newNaptSwitch {} for routername {}",
330 naptSwitch, routerName);
333 LOG.debug("handleSNATForDPN : Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
335 // When NAPT switch is elected during first VM comes up for the given Router
336 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
337 NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
338 idManager, NatConstants.ODL_VNI_POOL_NAME);
341 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
342 if (extRouters != null) {
343 NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
344 naptSwitchHA.subnetRegisterMapping(extRouters, routerId);
347 naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, confTx);
349 // Install miss entry (table 26) pointing to table 46
350 FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName,
351 routerVpnId, NatConstants.ADD_FLOW);
352 if (flowEntity == null) {
353 LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}",
357 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {}", dpnId, routerName);
358 mdsalManager.addFlow(confTx, flowEntity);
359 //Removing primary flows from old napt switch
360 if (naptId != null && !naptId.equals(BigInteger.ZERO)) {
361 LOG.debug("handleSNATForDPN : Removing primary flows from old napt switch {} for router {}",
363 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptId, null, confTx);
365 } else if (naptId.equals(dpnId)) {
366 LOG.debug("handleSNATForDPN : NaptSwitch {} gone down during cluster reboot came alive", naptId);
369 LOG.debug("handleSNATForDPN : Napt switch with Id {} is already elected for router {}",
373 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
374 routerName, routerId, naptSwitch);
375 naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
377 // Install miss entry (table 26) pointing to group
378 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
379 FlowEntity flowEntity =
380 naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
381 routerVpnId, NatConstants.ADD_FLOW);
382 if (flowEntity == null) {
383 LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {} groupId {}",
384 routerName, dpnId, groupId);
387 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}",
388 dpnId, routerName, groupId);
389 mdsalManager.addFlow(confTx, flowEntity);
392 } catch (InterruptedException | ExecutionException e) {
393 LOG.error("handleSNATForDPN : Exception in handleSNATForDPN", e);
397 // TODO Clean up the exception handling
398 @SuppressWarnings("checkstyle:IllegalCatch")
399 void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId,
400 Uuid extNetworkId, TypedReadWriteTransaction<Configuration> confTx) {
401 //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
402 //remove miss entry to NAPT switch
403 //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
405 Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
406 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
407 if (extNwProvType == null) {
410 //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
411 Map<String, Long> externalIpLabel;
412 if (extNwProvType == ProviderTypes.VXLAN) {
413 externalIpLabel = null;
415 externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
417 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
418 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
419 LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
424 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
425 externalIpCache, confTx);
427 LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
429 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
430 FlowEntity flowEntity = null;
432 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
433 NatConstants.DEL_FLOW);
434 if (flowEntity == null) {
435 LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
436 + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
439 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity);
440 mdsalManager.removeFlow(confTx, flowEntity);
442 } catch (Exception ex) {
443 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
447 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
451 GroupEntity groupEntity = null;
453 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
454 GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
455 LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
456 mdsalManager.removeGroup(groupEntity);
457 } catch (Exception ex) {
458 LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
461 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
464 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
465 externalIpLabel, confTx);
466 //remove table 26 flow ppointing to table46
467 FlowEntity flowEntity = null;
469 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
470 NatConstants.DEL_FLOW);
471 if (flowEntity == null) {
472 LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
476 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
477 + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
478 mdsalManager.removeFlow(confTx, flowEntity);
480 } catch (Exception ex) {
481 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
485 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
488 //best effort to check IntExt model
489 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
491 } catch (InterruptedException | ExecutionException e) {
492 LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, e);
496 private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, Collection<Uuid> externalSubnetIds) {
497 if (externalSubnetIds == null) {
498 LOG.error("installDefaultNatRouteForRouterExternalSubnets : No external subnets for router");
502 for (Uuid subnetId : externalSubnetIds) {
503 long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
504 if (vpnIdForSubnet != NatConstants.INVALID_ID) {
505 LOG.info("installDefaultNatRouteForRouterExternalSubnets : Installing default routes in FIB on dpn {} "
506 + "for subnetId {} with vpnId {}", dpnId, subnetId, vpnIdForSubnet);
507 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue());
509 LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId);