natservice dead code removal
[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 {} for vpn {} ...", dpnId,
280                                         vpnName);
281                                     snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, confTx);
282                                 } else {
283                                     LOG.debug("remove : External vpn associated to router {}", routerUuid);
284                                     vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
285                                     if (vpnId == NatConstants.INVALID_ID) {
286                                         LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
287                                         return;
288                                     }
289                                     LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
290                                     //Remove default entry in FIB
291                                     LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId,
292                                         vpnName);
293                                     snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
294                                 }
295                                 /* remove V6 internet default fallback rule in FIB_TABLE if router
296                                  * is having V6 subnet
297                                  */
298                                 nvpnManager.programV6InternetFallbackFlow(new Uuid(routerUuid),
299                                         NatUtil.getVpnIdfromNetworkId(dataBroker, networkId), NwConstants.DEL_FLOW);
300                                 if (router.isEnableSnat()) {
301                                     LOG.info("remove : SNAT enabled for router {}", routerUuid);
302                                     removeSNATFromDPN(dpnId, routerUuid, routerId, vpnId, networkId, confTx);
303                                 } else {
304                                     LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}",
305                                         routerUuid, dpnId);
306                                 }
307                             }));
308                     }, NatConstants.NAT_DJC_MAX_RETRIES);
309                 } // end of controller based SNAT
310             }
311         }
312     }
313
314     @Override
315     protected void update(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList original,
316                           DpnVpninterfacesList update) {
317         LOG.trace("Update key: {}, original: {}, update: {}", update.key(), original, update);
318     }
319
320     void handleSNATForDPN(BigInteger dpnId, String routerName, long routerId, Long routerVpnId,
321         TypedReadWriteTransaction<Configuration> confTx) {
322        //Check if primary and secondary switch are selected, If not select the role
323         //Install select group to NAPT switch
324         //Install default miss entry to NAPT switch
325         BigInteger naptSwitch;
326         try {
327             BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
328             if (naptId == null || naptId.equals(BigInteger.ZERO)
329                     || !NatUtil.getSwitchStatus(dataBroker, naptId) && !upgradeState.isUpgradeInProgress()) {
330                 LOG.debug("handleSNATForDPN : NaptSwitch is down or not selected for router {},naptId {}",
331                         routerName, naptId);
332                 naptSwitch = dpnId;
333                 boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
334                 if (!naptstatus) {
335                     LOG.error("handleSNATForDPN : Failed to update newNaptSwitch {} for routername {}",
336                             naptSwitch, routerName);
337                     return;
338                 }
339                 LOG.debug("handleSNATForDPN : Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
340                 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
341                 if (extRouters != null) {
342                     NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
343                     naptSwitchHA.subnetRegisterMapping(extRouters, routerId);
344                 }
345
346                 naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, confTx);
347
348                 // Install miss entry (table 26) pointing to table 46
349                 FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName,
350                         routerVpnId, NatConstants.ADD_FLOW);
351                 if (flowEntity == null) {
352                     LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}",
353                             routerName, dpnId);
354                     return;
355                 }
356                 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {}", dpnId, routerName);
357                 mdsalManager.addFlow(confTx, flowEntity);
358                 //Removing primary flows from old napt switch
359                 if (naptId != null && !naptId.equals(BigInteger.ZERO)) {
360                     LOG.debug("handleSNATForDPN : Removing primary flows from old napt switch {} for router {}",
361                             naptId, routerName);
362                     naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptId, null, confTx);
363                 }
364             } else if (naptId.equals(dpnId)) {
365                 LOG.debug("handleSNATForDPN : NaptSwitch {} gone down during cluster reboot came alive", naptId);
366             } else {
367                 naptSwitch = naptId;
368                 LOG.debug("handleSNATForDPN : Napt switch with Id {} is already elected for router {}",
369                         naptId, routerName);
370
371                 //installing group
372                 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
373                         routerName, routerId, naptSwitch);
374                 naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
375
376                 // Install miss entry (table 26) pointing to group
377                 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
378                 FlowEntity flowEntity =
379                         naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
380                                 routerVpnId, NatConstants.ADD_FLOW);
381                 if (flowEntity == null) {
382                     LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {} groupId {}",
383                             routerName, dpnId, groupId);
384                     return;
385                 }
386                 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}",
387                         dpnId, routerName, groupId);
388                 mdsalManager.addFlow(confTx, flowEntity);
389             }
390
391         } catch (InterruptedException | ExecutionException e) {
392             LOG.error("handleSNATForDPN : Exception in handleSNATForDPN", e);
393         }
394     }
395
396     // TODO Clean up the exception handling
397     @SuppressWarnings("checkstyle:IllegalCatch")
398     void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId,
399             Uuid extNetworkId, TypedReadWriteTransaction<Configuration> confTx) {
400         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
401         //remove miss entry to NAPT switch
402         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
403
404         Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
405         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
406         if (extNwProvType == null) {
407             return;
408         }
409         //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
410         Map<String, Long> externalIpLabel;
411         if (extNwProvType == ProviderTypes.VXLAN) {
412             externalIpLabel = null;
413         } else {
414             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
415         }
416         BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
417         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
418             LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
419             return;
420         }
421         try {
422             boolean naptStatus =
423                 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
424                         externalIpCache, confTx);
425             if (!naptStatus) {
426                 LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
427                     dpnId, routerName);
428                 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
429                 FlowEntity flowEntity = null;
430                 try {
431                     flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
432                         NatConstants.DEL_FLOW);
433                     if (flowEntity == null) {
434                         LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
435                                 + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
436                         return;
437                     }
438                     LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity);
439                     mdsalManager.removeFlow(confTx, flowEntity);
440
441                 } catch (Exception ex) {
442                     LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
443                         flowEntity, ex);
444                     return;
445                 }
446                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
447                     dpnId, routerName);
448
449                 //remove group
450                 GroupEntity groupEntity = null;
451                 try {
452                     groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
453                         GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
454                     LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
455                     mdsalManager.removeGroup(groupEntity);
456                 } catch (Exception ex) {
457                     LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
458                     return;
459                 }
460                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
461                     dpnId, routerName);
462             } else {
463                 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
464                         externalIpLabel, confTx);
465                 //remove table 26 flow ppointing to table46
466                 FlowEntity flowEntity = null;
467                 try {
468                     flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
469                         NatConstants.DEL_FLOW);
470                     if (flowEntity == null) {
471                         LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
472                                 routerName, dpnId);
473                         return;
474                     }
475                     LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
476                         + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
477                     mdsalManager.removeFlow(confTx, flowEntity);
478
479                 } catch (Exception ex) {
480                     LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
481                         flowEntity, ex);
482                     return;
483                 }
484                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
485                     dpnId, routerName);
486
487                 //best effort to check IntExt model
488                 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
489             }
490         } catch (InterruptedException | ExecutionException e) {
491             LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, e);
492         }
493     }
494
495     private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, Collection<Uuid> externalSubnetIds) {
496         if (externalSubnetIds == null) {
497             LOG.error("installDefaultNatRouteForRouterExternalSubnets : No external subnets for router");
498             return;
499         }
500
501         for (Uuid subnetId : externalSubnetIds) {
502             long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
503             if (vpnIdForSubnet != NatConstants.INVALID_ID) {
504                 LOG.info("installDefaultNatRouteForRouterExternalSubnets : Installing default routes in FIB on dpn {} "
505                         + "for subnetId {} with vpnId {}", dpnId, subnetId, vpnIdForSubnet);
506                 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue());
507             } else {
508                 LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId);
509             }
510         }
511     }
512 }