Gracefully Handle IDManager failure in NAT
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / RouterDpnChangeListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.natservice.internal;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11
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;
17 import java.util.Map;
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.NwConstants;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
37 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
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;
54
55 @Singleton
56 public class RouterDpnChangeListener
57         extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener> {
58
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 JobCoordinator coordinator;
69     private final SnatServiceManager natServiceManager;
70     private final NatMode natMode;
71     private final UpgradeState upgradeState;
72
73     @Inject
74     public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
75                                    final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
76                                    final NaptSwitchHA naptSwitchHA,
77                                    final IdManagerService idManager,
78                                    final ExternalNetworkGroupInstaller extNetGroupInstaller,
79                                    final INeutronVpnManager nvpnManager,
80                                    final SnatServiceManager natServiceManager,
81                                    final NatserviceConfig config,
82                                    final JobCoordinator coordinator,
83                                    final UpgradeState upgradeState) {
84         super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
85         this.dataBroker = dataBroker;
86         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
87         this.mdsalManager = mdsalManager;
88         this.snatDefaultRouteProgrammer = snatDefaultRouteProgrammer;
89         this.naptSwitchHA = naptSwitchHA;
90         this.idManager = idManager;
91         this.extNetGroupInstaller = extNetGroupInstaller;
92         this.nvpnManager = nvpnManager;
93         this.natServiceManager = natServiceManager;
94         this.coordinator = coordinator;
95         this.natMode = config != null ? config.getNatMode() : NatMode.Controller;
96         this.upgradeState = upgradeState;
97     }
98
99     @Override
100     @PostConstruct
101     public void init() {
102         LOG.info("{} init", getClass().getSimpleName());
103         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
104     }
105
106     @Override
107     protected RouterDpnChangeListener getDataTreeChangeListener() {
108         return RouterDpnChangeListener.this;
109     }
110
111     @Override
112     protected InstanceIdentifier<DpnVpninterfacesList> getWildCardPath() {
113         return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class)
114             .child(DpnVpninterfacesList.class);
115     }
116
117     @Override
118     protected void add(final InstanceIdentifier<DpnVpninterfacesList> identifier, final DpnVpninterfacesList dpnInfo) {
119         LOG.trace("add : key: {}, value: {}", dpnInfo.key(), dpnInfo);
120         final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
121         BigInteger dpnId = dpnInfo.getDpnId();
122         //check router is associated to external network
123         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
124         Optional<Routers> routerData =
125                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
126                         LogicalDatastoreType.CONFIGURATION, id);
127         if (routerData.isPresent()) {
128             Routers router = routerData.get();
129             Uuid networkId = router.getNetworkId();
130             if (networkId != null) {
131                 if (natMode == NatMode.Conntrack) {
132                     BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
133                     if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
134                         LOG.warn("add : NAPT switch is not selected.");
135                         return;
136                     }
137                     //If it is for NAPT switch skip as the flows would be already programmed.
138                     if (naptSwitch.equals(dpnId)) {
139                         LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
140                         return;
141                     }
142                     ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
143                         confTx -> {
144                             natServiceManager.notify(confTx, router, null, naptSwitch, dpnId,
145                                     SnatServiceManager.Action.CNT_ROUTER_ENBL);
146                             if (router.isEnableSnat()) {
147                                 natServiceManager.notify(confTx, router, null, naptSwitch, naptSwitch,
148                                         SnatServiceManager.Action.SNAT_ROUTER_ENBL);
149                             }
150                         }), LOG, "Error notifying NAT service manager");
151                 } else {
152                     Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
153                     if (routerId == NatConstants.INVALID_ID) {
154                         LOG.error("add : Invalid routerId returned for routerName {}", routerUuid);
155                         return;
156                     }
157                     ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
158                             routerUuid, networkId);
159                     if (extNwProvType == ProviderTypes.FLAT || extNwProvType == ProviderTypes.VLAN) {
160                         coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + networkId, () -> {
161                             extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId);
162                             installDefaultNatRouteForRouterExternalSubnets(dpnId,
163                                     NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
164                             return Collections.emptyList();
165                         });
166                     }
167                     coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + router.getRouterName(), () -> {
168                         LOG.debug("add : Router {} is associated with ext nw {}", routerUuid, networkId);
169                         Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
170                         return Collections.singletonList(
171                             txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
172                                 Long vpnId;
173                                 if (vpnName == null) {
174                                     LOG.debug("add : Internal vpn associated to router {}", routerUuid);
175                                     vpnId = routerId;
176                                     if (vpnId == NatConstants.INVALID_ID) {
177                                         LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
178                                         return;
179                                     }
180                                     LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
181                                     //Install default entry in FIB to SNAT table
182                                     LOG.info(
183                                         "add : Installing default route in FIB on dpn {} for router {} with vpn {}",
184                                         dpnId, routerUuid, vpnId);
185                                     snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, confTx);
186                                 } else {
187                                     LOG.debug("add : External BGP vpn associated to router {}", routerUuid);
188                                     vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
189                                     if (vpnId == NatConstants.INVALID_ID) {
190                                         LOG.error("add : Invalid vpnId returned for routerName {}", routerUuid);
191                                         return;
192                                     }
193                                     LOG.debug("add : Retrieved vpnId {} for router {}", vpnId, routerUuid);
194                                     //Install default entry in FIB to SNAT table
195                                     LOG.debug("add : Installing default route in FIB on dpn {} for routerId {} with "
196                                         + "vpnId {}...", dpnId, routerUuid, vpnId);
197                                     snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
198                                 }
199                                 /* install V6 internet default fallback rule in FIB_TABLE if router
200                                  * is having V6 subnet
201                                  */
202                                 nvpnManager.programV6InternetFallbackFlow(new Uuid(routerUuid),
203                                         NatUtil.getVpnIdfromNetworkId(dataBroker, networkId), NwConstants.ADD_FLOW);
204                                 if (router.isEnableSnat()) {
205                                     LOG.info("add : SNAT enabled for router {}", routerUuid);
206                                     if (extNwProvType == null) {
207                                         LOG.error("add : External Network Provider Type missing");
208                                         return;
209                                     }
210                                     handleSNATForDPN(dpnId, routerUuid, routerId, vpnId, confTx);
211                                 } else {
212                                     LOG.info("add : SNAT is not enabled for router {} to handle addDPN event {}",
213                                         routerUuid, dpnId);
214                                 }
215                             }));
216                     }, NatConstants.NAT_DJC_MAX_RETRIES);
217                 } // end of controller based SNAT
218             }
219         } else {
220             LOG.debug("add : Router {} is not associated with External network", routerUuid);
221         }
222     }
223
224     @Override
225     protected void remove(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList dpnInfo) {
226         LOG.trace("remove : key: {}, value: {}", dpnInfo.key(), dpnInfo);
227         final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
228         Long routerId = NatUtil.getVpnId(dataBroker, routerUuid);
229         if (routerId == NatConstants.INVALID_ID) {
230             LOG.error("REMOVE: Invalid routId returned for routerName {}",routerUuid);
231             return;
232         }
233         BigInteger dpnId = dpnInfo.getDpnId();
234         //check router is associated to external network
235         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
236         Optional<Routers> routerData =
237                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
238                         LogicalDatastoreType.CONFIGURATION, id);
239         if (routerData.isPresent()) {
240             Routers router = routerData.get();
241             Uuid networkId = router.getNetworkId();
242             if (networkId != null) {
243                 if (natMode == NatMode.Conntrack) {
244                     BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
245                     if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
246                         LOG.warn("remove : NAPT switch is not selected.");
247                         return;
248                     }
249                     //If it is for NAPT switch skip as the flows would be already programmed.
250                     if (naptSwitch.equals(dpnId)) {
251                         LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
252                         return;
253                     }
254                     ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
255                         confTx -> {
256                             natServiceManager.notify(confTx, router, null, naptSwitch, dpnId,
257                                     SnatServiceManager.Action.CNT_ROUTER_DISBL);
258                             if (router.isEnableSnat()) {
259                                 natServiceManager.notify(confTx, router, null, naptSwitch, naptSwitch,
260                                         SnatServiceManager.Action.SNAT_ROUTER_DISBL);
261                             }
262                         }), LOG, "Error notifying NAT service manager");
263                 } else {
264                     coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid, () -> {
265                         LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId);
266                         Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
267                         return Collections.singletonList(
268                             txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
269                                 Long vpnId;
270                                 if (vpnName == null) {
271                                     LOG.debug("remove : Internal vpn associated to router {}", routerUuid);
272                                     vpnId = routerId;
273                                     if (vpnId == NatConstants.INVALID_ID) {
274                                         LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
275                                         return;
276                                     }
277                                     LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
278                                     //Remove default entry in FIB
279                                     LOG.debug("remove : Removing default route in FIB on dpn {} ...", dpnId);
280                                     snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, confTx);
281                                 } else {
282                                     LOG.debug("remove : External vpn associated to router {}", routerUuid);
283                                     vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
284                                     if (vpnId == NatConstants.INVALID_ID) {
285                                         LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
286                                         return;
287                                     }
288                                     LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
289                                     //Remove default entry in FIB
290                                     LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
291                                         vpnName);
292                                     snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
293                                 }
294                                 /* remove V6 internet default fallback rule in FIB_TABLE if router
295                                  * is having V6 subnet
296                                  */
297                                 nvpnManager.programV6InternetFallbackFlow(new Uuid(routerUuid),
298                                         NatUtil.getVpnIdfromNetworkId(dataBroker, networkId), NwConstants.DEL_FLOW);
299                                 if (router.isEnableSnat()) {
300                                     LOG.info("remove : SNAT enabled for router {}", routerUuid);
301                                     removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, confTx);
302                                 } else {
303                                     LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}",
304                                         routerUuid, dpnId);
305                                 }
306                             }));
307                     }, NatConstants.NAT_DJC_MAX_RETRIES);
308                 } // end of controller based SNAT
309             }
310         }
311     }
312
313     @Override
314     protected void update(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList original,
315                           DpnVpninterfacesList update) {
316         LOG.trace("Update key: {}, original: {}, update: {}", update.key(), original, update);
317     }
318
319     void handleSNATForDPN(BigInteger dpnId, String routerName, long routerId, Long routerVpnId,
320         TypedReadWriteTransaction<Configuration> confTx) {
321        //Check if primary and secondary switch are selected, If not select the role
322         //Install select group to NAPT switch
323         //Install default miss entry to NAPT switch
324         BigInteger naptSwitch;
325         try {
326             BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
327             if (naptId == null || naptId.equals(BigInteger.ZERO)
328                     || !NatUtil.getSwitchStatus(dataBroker, naptId) && !upgradeState.isUpgradeInProgress()) {
329                 LOG.debug("handleSNATForDPN : NaptSwitch is down or not selected for router {},naptId {}",
330                         routerName, naptId);
331                 naptSwitch = dpnId;
332                 boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
333                 if (!naptstatus) {
334                     LOG.error("handleSNATForDPN : Failed to update newNaptSwitch {} for routername {}",
335                             naptSwitch, routerName);
336                     return;
337                 }
338                 LOG.debug("handleSNATForDPN : Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
339                 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
340                 if (extRouters != null) {
341                     NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
342                     naptSwitchHA.subnetRegisterMapping(extRouters, routerId);
343                 }
344
345                 naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, confTx);
346
347                 // Install miss entry (table 26) pointing to table 46
348                 FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName,
349                         routerVpnId, NatConstants.ADD_FLOW);
350                 if (flowEntity == null) {
351                     LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}",
352                             routerName, dpnId);
353                     return;
354                 }
355                 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {}", dpnId, routerName);
356                 mdsalManager.addFlow(confTx, flowEntity);
357                 //Removing primary flows from old napt switch
358                 if (naptId != null && !naptId.equals(BigInteger.ZERO)) {
359                     LOG.debug("handleSNATForDPN : Removing primary flows from old napt switch {} for router {}",
360                             naptId, routerName);
361                     naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptId, null, confTx);
362                 }
363             } else if (naptId.equals(dpnId)) {
364                 LOG.debug("handleSNATForDPN : NaptSwitch {} gone down during cluster reboot came alive", naptId);
365             } else {
366                 naptSwitch = naptId;
367                 LOG.debug("handleSNATForDPN : Napt switch with Id {} is already elected for router {}",
368                         naptId, routerName);
369
370                 //installing group
371                 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
372                         routerName, routerId, naptSwitch);
373                 naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
374
375                 // Install miss entry (table 26) pointing to group
376                 long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
377                     NatUtil.getGroupIdKey(routerName));
378                 if (groupId != NatConstants.INVALID_ID) {
379                     FlowEntity flowEntity =
380                         naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
381                             routerVpnId, NatConstants.ADD_FLOW);
382                     if (flowEntity == null) {
383                         LOG.error(
384                             "handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {} groupId {}",
385                             routerName, dpnId, groupId);
386                         return;
387                     }
388                     LOG.debug(
389                         "handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}",
390                         dpnId, routerName, groupId);
391                     mdsalManager.addFlow(confTx, flowEntity);
392                 } else {
393                     LOG.error("handleSNATForDPN : Failed to Obtain groupId  for router {}", routerName);
394                 }
395             }
396         } catch (InterruptedException | ExecutionException e) {
397             LOG.error("handleSNATForDPN : Exception in handleSNATForDPN", e);
398         }
399     }
400
401     // TODO Clean up the exception handling
402     @SuppressWarnings("checkstyle:IllegalCatch")
403     void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId,
404             Uuid extNetworkId, TypedReadWriteTransaction<Configuration> confTx) {
405         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
406         //remove miss entry to NAPT switch
407         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
408
409         Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
410         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
411         if (extNwProvType == null) {
412             return;
413         }
414         //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
415         Map<String, Long> externalIpLabel;
416         if (extNwProvType == ProviderTypes.VXLAN) {
417             externalIpLabel = null;
418         } else {
419             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
420         }
421         BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
422         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
423             LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
424             return;
425         }
426         try {
427             boolean naptStatus =
428                 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
429                         externalIpCache, confTx);
430             if (!naptStatus) {
431                 LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
432                     dpnId, routerName);
433                 FlowEntity flowEntity = null;
434                 long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
435                     NatUtil.getGroupIdKey(routerName));
436                 try {
437
438                     if (groupId != NatConstants.INVALID_ID) {
439                         flowEntity = naptSwitchHA
440                             .buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
441                                 NatConstants.DEL_FLOW);
442                         if (flowEntity == null) {
443                             LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
444                                 + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
445                             return;
446                         }
447                         LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}",
448                             flowEntity);
449                         mdsalManager.removeFlow(confTx, flowEntity);
450                     } else {
451                         LOG.error("removeSNATFromDPN : Failed to Obtained Groupid for Router {}", routerName);
452                     }
453                 } catch (Exception ex) {
454                     LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
455                         flowEntity, ex);
456                     return;
457                 }
458                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
459                     dpnId, routerName);
460
461                 //remove group
462                 GroupEntity groupEntity = null;
463                 try {
464                     groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
465                         GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
466                     LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
467                     mdsalManager.removeGroup(groupEntity);
468                 } catch (Exception ex) {
469                     LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
470                     return;
471                 }
472                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
473                     dpnId, routerName);
474             } else {
475                 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
476                         externalIpLabel, confTx);
477                 //remove table 26 flow ppointing to table46
478                 FlowEntity flowEntity = null;
479                 try {
480                     flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
481                         NatConstants.DEL_FLOW);
482                     if (flowEntity == null) {
483                         LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
484                                 routerName, dpnId);
485                         return;
486                     }
487                     LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
488                         + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
489                     mdsalManager.removeFlow(confTx, flowEntity);
490
491                 } catch (Exception ex) {
492                     LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
493                         flowEntity, ex);
494                     return;
495                 }
496                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
497                     dpnId, routerName);
498
499                 //best effort to check IntExt model
500                 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
501             }
502         } catch (InterruptedException | ExecutionException e) {
503             LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, e);
504         }
505     }
506
507     private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, Collection<Uuid> externalSubnetIds) {
508         if (externalSubnetIds == null) {
509             LOG.error("installDefaultNatRouteForRouterExternalSubnets : No external subnets for router");
510             return;
511         }
512
513         for (Uuid subnetId : externalSubnetIds) {
514             long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
515             if (vpnIdForSubnet != NatConstants.INVALID_ID) {
516                 LOG.info("installDefaultNatRouteForRouterExternalSubnets : Installing default routes in FIB on dpn {} "
517                         + "for subnetId {} with vpnId {}", dpnId, subnetId, vpnIdForSubnet);
518                 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue());
519             } else {
520                 LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId);
521             }
522         }
523     }
524 }