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