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