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