Switch to using spotbugs
[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.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
377                 FlowEntity flowEntity =
378                         naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
379                                 routerVpnId, NatConstants.ADD_FLOW);
380                 if (flowEntity == null) {
381                     LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {} groupId {}",
382                             routerName, dpnId, groupId);
383                     return;
384                 }
385                 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}",
386                         dpnId, routerName, groupId);
387                 mdsalManager.addFlow(confTx, flowEntity);
388             }
389
390         } catch (InterruptedException | ExecutionException e) {
391             LOG.error("handleSNATForDPN : Exception in handleSNATForDPN", e);
392         }
393     }
394
395     // TODO Clean up the exception handling
396     @SuppressWarnings("checkstyle:IllegalCatch")
397     void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId,
398             Uuid extNetworkId, TypedReadWriteTransaction<Configuration> confTx) {
399         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
400         //remove miss entry to NAPT switch
401         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
402
403         Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
404         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
405         if (extNwProvType == null) {
406             return;
407         }
408         //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
409         Map<String, Long> externalIpLabel;
410         if (extNwProvType == ProviderTypes.VXLAN) {
411             externalIpLabel = null;
412         } else {
413             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
414         }
415         BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
416         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
417             LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
418             return;
419         }
420         try {
421             boolean naptStatus =
422                 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
423                         externalIpCache, confTx);
424             if (!naptStatus) {
425                 LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
426                     dpnId, routerName);
427                 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
428                 FlowEntity flowEntity = null;
429                 try {
430                     flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
431                         NatConstants.DEL_FLOW);
432                     if (flowEntity == null) {
433                         LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
434                                 + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
435                         return;
436                     }
437                     LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity);
438                     mdsalManager.removeFlow(confTx, flowEntity);
439
440                 } catch (Exception ex) {
441                     LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
442                         flowEntity, ex);
443                     return;
444                 }
445                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
446                     dpnId, routerName);
447
448                 //remove group
449                 GroupEntity groupEntity = null;
450                 try {
451                     groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
452                         GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
453                     LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
454                     mdsalManager.removeGroup(groupEntity);
455                 } catch (Exception ex) {
456                     LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
457                     return;
458                 }
459                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
460                     dpnId, routerName);
461             } else {
462                 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
463                         externalIpLabel, confTx);
464                 //remove table 26 flow ppointing to table46
465                 FlowEntity flowEntity = null;
466                 try {
467                     flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
468                         NatConstants.DEL_FLOW);
469                     if (flowEntity == null) {
470                         LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
471                                 routerName, dpnId);
472                         return;
473                     }
474                     LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
475                         + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
476                     mdsalManager.removeFlow(confTx, flowEntity);
477
478                 } catch (Exception ex) {
479                     LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
480                         flowEntity, ex);
481                     return;
482                 }
483                 LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
484                     dpnId, routerName);
485
486                 //best effort to check IntExt model
487                 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
488             }
489         } catch (InterruptedException | ExecutionException e) {
490             LOG.error("removeSNATFromDPN : Exception while handling naptSwitch down for router {}", routerName, e);
491         }
492     }
493
494     private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, Collection<Uuid> externalSubnetIds) {
495         if (externalSubnetIds == null) {
496             LOG.error("installDefaultNatRouteForRouterExternalSubnets : No external subnets for router");
497             return;
498         }
499
500         for (Uuid subnetId : externalSubnetIds) {
501             long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
502             if (vpnIdForSubnet != NatConstants.INVALID_ID) {
503                 LOG.info("installDefaultNatRouteForRouterExternalSubnets : Installing default routes in FIB on dpn {} "
504                         + "for subnetId {} with vpnId {}", dpnId, subnetId, vpnIdForSubnet);
505                 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue());
506             } else {
507                 LOG.debug("installDefaultNatRouteForRouterExternalSubnets : No vpnID for subnet {} found", subnetId);
508             }
509         }
510     }
511 }