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 javax.annotation.PostConstruct;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
24 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
25 import org.opendaylight.genius.infra.Datastore.Configuration;
26 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
28 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
29 import org.opendaylight.genius.mdsalutil.BucketInfo;
30 import org.opendaylight.genius.mdsalutil.FlowEntity;
31 import org.opendaylight.genius.mdsalutil.GroupEntity;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
34 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
35 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
36 import org.opendaylight.netvirt.elanmanager.api.IElanService;
37 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
38 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 public class RouterDpnChangeListener
55 extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener> {
57 private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
58 private final DataBroker dataBroker;
59 private final ManagedNewTransactionRunner txRunner;
60 private final IMdsalApiManager mdsalManager;
61 private final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer;
62 private final NaptSwitchHA naptSwitchHA;
63 private final IdManagerService idManager;
64 private final INeutronVpnManager nvpnManager;
65 private final ExternalNetworkGroupInstaller extNetGroupInstaller;
66 private final IElanService elanManager;
67 private final JobCoordinator coordinator;
68 private final SnatServiceManager natServiceManager;
69 private final NatMode natMode;
72 public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
73 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
74 final NaptSwitchHA naptSwitchHA,
75 final IdManagerService idManager,
76 final ExternalNetworkGroupInstaller extNetGroupInstaller,
77 final INeutronVpnManager nvpnManager,
78 final SnatServiceManager natServiceManager,
79 final NatserviceConfig config,
80 final IElanService elanManager,
81 final JobCoordinator coordinator) {
82 super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
83 this.dataBroker = dataBroker;
84 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
85 this.mdsalManager = mdsalManager;
86 this.snatDefaultRouteProgrammer = snatDefaultRouteProgrammer;
87 this.naptSwitchHA = naptSwitchHA;
88 this.idManager = idManager;
89 this.extNetGroupInstaller = extNetGroupInstaller;
90 this.nvpnManager = nvpnManager;
91 this.elanManager = elanManager;
92 this.natServiceManager = natServiceManager;
93 this.coordinator = coordinator;
94 this.natMode = config != null ? config.getNatMode() : NatMode.Controller;
100 LOG.info("{} init", getClass().getSimpleName());
101 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
105 protected RouterDpnChangeListener getDataTreeChangeListener() {
106 return RouterDpnChangeListener.this;
110 protected InstanceIdentifier<DpnVpninterfacesList> getWildCardPath() {
111 return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class)
112 .child(DpnVpninterfacesList.class);
116 protected void add(final InstanceIdentifier<DpnVpninterfacesList> identifier, final DpnVpninterfacesList dpnInfo) {
117 LOG.trace("add : key: {}, value: {}", dpnInfo.key(), dpnInfo);
118 final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
119 BigInteger dpnId = dpnInfo.getDpnId();
120 //check router is associated to external network
121 InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
122 Optional<Routers> routerData =
123 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
124 LogicalDatastoreType.CONFIGURATION, id);
125 if (routerData.isPresent()) {
126 Routers router = routerData.get();
127 Uuid networkId = router.getNetworkId();
128 if (networkId != null) {
129 if (natMode == NatMode.Conntrack) {
130 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
131 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
132 LOG.warn("add : NAPT switch is not selected.");
135 //If it is for NAPT switch skip as the flows would be already programmed.
136 if (naptSwitch.equals(dpnId)) {
137 LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
140 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
141 confTx -> natServiceManager.notify(confTx, router, naptSwitch, dpnId,
142 SnatServiceManager.Action.SNAT_ROUTER_ENBL)), LOG, "Error notifying NAT service manager");
144 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
145 if (routerId == NatConstants.INVALID_ID) {
146 LOG.error("add : Invalid routerId returned for routerName {}", routerUuid);
149 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
150 routerUuid, networkId);
151 if (extNwProvType == ProviderTypes.FLAT || extNwProvType == ProviderTypes.VLAN) {
152 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + networkId, () -> {
153 extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId);
154 installDefaultNatRouteForRouterExternalSubnets(dpnId,
155 NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
156 return Collections.emptyList();
159 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + router.getRouterName(), () -> {
160 LOG.debug("add : Router {} is associated with ext nw {}", routerUuid, networkId);
161 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
162 return Collections.singletonList(
163 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
165 if (vpnName == null) {
166 LOG.debug("add : Internal vpn associated to router {}", routerUuid);
168 if (vpnId == NatConstants.INVALID_ID) {
169 LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
172 LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
173 //Install default entry in FIB to SNAT table
175 "add : Installing default route in FIB on dpn {} for router {} with vpn {}",
176 dpnId, routerUuid, vpnId);
177 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, confTx);
179 LOG.debug("add : External BGP vpn associated to router {}", routerUuid);
180 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
181 if (vpnId == NatConstants.INVALID_ID) {
182 LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
185 LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
186 //Install default entry in FIB to SNAT table
187 LOG.debug("add : Installing default route in FIB on dpn {} for routerId {} with "
188 + "vpnId {}...", dpnId, routerUuid, vpnId);
189 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
191 if (router.isEnableSnat()) {
192 LOG.info("add : SNAT enabled for router {}", routerUuid);
193 if (extNwProvType == null) {
194 LOG.error("add : External Network Provider Type missing");
197 handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, confTx, extNwProvType);
199 LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}",
203 }, NatConstants.NAT_DJC_MAX_RETRIES);
204 } // end of controller based SNAT
207 LOG.debug("add : Router {} is not associated with External network", routerUuid);
212 protected void remove(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList dpnInfo) {
213 LOG.trace("remove : key: {}, value: {}", dpnInfo.key(), dpnInfo);
214 final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
215 Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
216 if (routerId == NatConstants.INVALID_ID) {
217 LOG.error("REMOVE: Invalid routId returned for routerName {}",routerUuid);
220 BigInteger dpnId = dpnInfo.getDpnId();
221 //check router is associated to external network
222 InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
223 Optional<Routers> routerData =
224 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
225 LogicalDatastoreType.CONFIGURATION, id);
226 if (routerData.isPresent()) {
227 Routers router = routerData.get();
228 Uuid networkId = router.getNetworkId();
229 if (networkId != null) {
230 if (natMode == NatMode.Conntrack) {
231 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
232 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
233 LOG.warn("remove : NAPT switch is not selected.");
236 //If it is for NAPT switch skip as the flows would be already programmed.
237 if (naptSwitch.equals(dpnId)) {
238 LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
241 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
242 confTx -> natServiceManager.notify(confTx, router, naptSwitch, dpnId,
243 SnatServiceManager.Action.SNAT_ROUTER_DISBL)), LOG, "Error notifying NAT service manager");
245 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid, () -> {
246 LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId);
247 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
248 return Collections.singletonList(
249 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
251 if (vpnName == null) {
252 LOG.debug("remove : Internal vpn associated to router {}", routerUuid);
254 if (vpnId == NatConstants.INVALID_ID) {
255 LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
258 LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
259 //Remove default entry in FIB
260 LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
262 snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, confTx);
264 LOG.debug("remove : External vpn associated to router {}", routerUuid);
265 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
266 if (vpnId == NatConstants.INVALID_ID) {
267 LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
270 LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
271 //Remove default entry in FIB
272 LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
274 snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
277 if (router.isEnableSnat()) {
278 LOG.info("remove : SNAT enabled for router {}", routerUuid);
279 removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, confTx);
281 LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}",
285 }, NatConstants.NAT_DJC_MAX_RETRIES);
286 } // end of controller based SNAT
292 protected void update(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList original,
293 DpnVpninterfacesList update) {
294 LOG.trace("Update key: {}, original: {}, update: {}", update.key(), original, update);
297 // TODO Clean up the exception handling
298 @SuppressWarnings("checkstyle:IllegalCatch")
299 void handleSNATForDPN(BigInteger dpnId, String routerName, long routerId, Long routerVpnId,
300 TypedReadWriteTransaction<Configuration> confTx, ProviderTypes extNwProvType) {
301 //Check if primary and secondary switch are selected, If not select the role
302 //Install select group to NAPT switch
303 //Install default miss entry to NAPT switch
304 BigInteger naptSwitch;
306 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
307 if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptSwitchHA.getSwitchStatus(naptId)) {
308 LOG.debug("handleSNATForDPN : No NaptSwitch is selected for router {}", routerName);
310 boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
312 LOG.error("handleSNATForDPN : Failed to update newNaptSwitch {} for routername {}",
313 naptSwitch, routerName);
316 LOG.debug("handleSNATForDPN : Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
318 // When NAPT switch is elected during first VM comes up for the given Router
319 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
320 NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
321 idManager, NatConstants.ODL_VNI_POOL_NAME);
324 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
325 if (extRouters != null) {
326 NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
327 naptSwitchHA.subnetRegisterMapping(extRouters, routerId);
330 naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, confTx);
332 // Install miss entry (table 26) pointing to table 46
333 FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName,
334 routerVpnId, NatConstants.ADD_FLOW);
335 if (flowEntity == null) {
336 LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}",
340 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {}", dpnId, routerName);
341 mdsalManager.addFlow(confTx, flowEntity);
342 //Removing primary flows from old napt switch
343 if (naptId != null && !naptId.equals(BigInteger.ZERO)) {
344 LOG.debug("handleSNATForDPN : Removing primary flows from old napt switch {} for router {}",
346 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptId, null, confTx);
348 } else if (naptId.equals(dpnId)) {
349 LOG.debug("handleSNATForDPN : NaptSwitch {} gone down during cluster reboot came alive", naptId);
352 LOG.debug("handleSNATForDPN : Napt switch with Id {} is already elected for router {}",
356 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
357 routerName, routerId, naptSwitch);
358 naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
360 // Install miss entry (table 26) pointing to group
361 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
362 FlowEntity flowEntity =
363 naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
364 routerVpnId, NatConstants.ADD_FLOW);
365 if (flowEntity == null) {
366 LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {} groupId {}",
367 routerName, dpnId, groupId);
370 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}",
371 dpnId, routerName, groupId);
372 mdsalManager.addFlow(confTx, flowEntity);
375 } catch (Exception ex) {
376 LOG.error("handleSNATForDPN : Exception in handleSNATForDPN", ex);
380 // TODO Clean up the exception handling
381 @SuppressWarnings("checkstyle:IllegalCatch")
382 void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId,
383 Uuid extNetworkId, TypedReadWriteTransaction<Configuration> confTx) {
384 //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
385 //remove miss entry to NAPT switch
386 //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
388 Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
389 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
390 if (extNwProvType == null) {
393 //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
394 Map<String, Long> externalIpLabel;
395 if (extNwProvType == ProviderTypes.VXLAN) {
396 externalIpLabel = null;
398 externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
400 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
401 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
402 LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
407 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
408 externalIpCache, confTx);
410 LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
412 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
413 FlowEntity flowEntity = null;
415 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
416 NatConstants.DEL_FLOW);
417 if (flowEntity == null) {
418 LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
419 + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
422 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity);
423 mdsalManager.removeFlow(confTx, flowEntity);
425 } catch (Exception ex) {
426 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
430 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
434 GroupEntity groupEntity = null;
436 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
437 GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
438 LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
439 mdsalManager.removeGroup(groupEntity);
440 } catch (Exception ex) {
441 LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
444 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
447 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
448 externalIpLabel, confTx);
449 //remove table 26 flow ppointing to table46
450 FlowEntity flowEntity = null;
452 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
453 NatConstants.DEL_FLOW);
454 if (flowEntity == null) {
455 LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
459 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
460 + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
461 mdsalManager.removeFlow(confTx, flowEntity);
463 } catch (Exception ex) {
464 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
468 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
471 //best effort to check IntExt model
472 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
474 } catch (Exception ex) {
475 LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, ex);
479 private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, Collection<Uuid> externalSubnetIds) {
480 if (externalSubnetIds == null) {
481 LOG.error("installDefaultNatRouteForRouterExternalSubnets : No external subnets for router");
485 for (Uuid subnetId : externalSubnetIds) {
486 long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
487 if (vpnIdForSubnet != NatConstants.INVALID_ID) {
488 LOG.info("installDefaultNatRouteForRouterExternalSubnets : Installing default routes in FIB on dpn {} "
489 + "for subnetId {} with vpnId {}", dpnId, subnetId, vpnIdForSubnet);
490 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue());
492 LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId);