Remove NatUtil::read()
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatTunnelInterfaceStateListener.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
9 package org.opendaylight.netvirt.natservice.internal;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Strings;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.JdkFutureAdapters;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.concurrent.Future;
23 import javax.annotation.PostConstruct;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
30 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.mdsalutil.BucketInfo;
33 import org.opendaylight.genius.mdsalutil.FlowEntity;
34 import org.opendaylight.genius.mdsalutil.GroupEntity;
35 import org.opendaylight.genius.mdsalutil.MDSALUtil;
36 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
37 import org.opendaylight.genius.mdsalutil.NwConstants;
38 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
39 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
42 import org.opendaylight.netvirt.elanmanager.api.IElanService;
43 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
44 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
45 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.common.RpcResult;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
78
79 @Singleton
80 public class NatTunnelInterfaceStateListener
81     extends AsyncDataTreeChangeListenerBase<StateTunnelList, NatTunnelInterfaceStateListener>
82     implements AutoCloseable {
83
84     private static final Logger LOG = LoggerFactory.getLogger(NatTunnelInterfaceStateListener.class);
85     private final DataBroker dataBroker;
86     private final IFibManager fibManager;
87     private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
88     private final NaptSwitchHA naptSwitchHA;
89     private final IMdsalApiManager mdsalManager;
90     private final IdManagerService idManager;
91     private final IBgpManager bgpManager;
92     private final ExternalRoutersListener externalRouterListner;
93     private final SnatServiceManager natServiceManager;
94     private final OdlInterfaceRpcService interfaceService;
95     private final FloatingIPListener floatingIPListener;
96     private final FibRpcService fibRpcService;
97     private final IElanService elanManager;
98     private final IInterfaceManager interfaceManager;
99     private NatMode natMode = NatMode.Controller;
100
101     protected enum TunnelAction {
102         TUNNEL_EP_ADD,
103         TUNNEL_EP_DELETE,
104         TUNNEL_EP_UPDATE
105     }
106
107     /**
108      * Responsible for listening to tunnel interface state change.
109      *
110      * @param dataBroker             - dataBroker service reference
111      * @param bgpManager             Used to advertise routes to the BGP Router
112      * @param fibManager             - FIB Manager
113      * @param defaultRouteProgrammer - Default Route Programmer
114      * @param naptSwitchHA           - NAPT Switch HA
115      * @param mdsalManager           - MDSAL Manager
116      * @param idManager              - ID manager
117      * @param externalRouterListner  - External Router Listner
118      * @param interfaceService       - Interface Service
119      * @param floatingIPListener     -  Floating IP Listner
120      * @param fibRpcService          - FIB RPC Service
121      * @param elanManager            - Elan Manager
122      */
123     @Inject
124     public NatTunnelInterfaceStateListener(final DataBroker dataBroker,
125                                            final IBgpManager bgpManager,
126                                            final IFibManager fibManager,
127                                            final SNATDefaultRouteProgrammer defaultRouteProgrammer,
128                                            final NaptSwitchHA naptSwitchHA,
129                                            final IMdsalApiManager mdsalManager,
130                                            final IdManagerService idManager,
131                                            final ExternalRoutersListener externalRouterListner,
132                                            final SnatServiceManager natServiceManager,
133                                            final OdlInterfaceRpcService interfaceService,
134                                            final FloatingIPListener floatingIPListener,
135                                            final FibRpcService fibRpcService,
136                                            final NatserviceConfig config,
137                                            final IElanService elanManager,
138                                            final IInterfaceManager interfaceManager) {
139         super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
140         this.dataBroker = dataBroker;
141         this.bgpManager = bgpManager;
142         this.fibManager = fibManager;
143         this.defaultRouteProgrammer = defaultRouteProgrammer;
144         this.naptSwitchHA = naptSwitchHA;
145         this.mdsalManager = mdsalManager;
146         this.idManager = idManager;
147         this.externalRouterListner = externalRouterListner;
148         this.natServiceManager = natServiceManager;
149         this.interfaceService = interfaceService;
150         this.floatingIPListener = floatingIPListener;
151         this.fibRpcService = fibRpcService;
152         this.elanManager = elanManager;
153         this.interfaceManager = interfaceManager;
154         if (config != null) {
155             this.natMode = config.getNatMode();
156         }
157     }
158
159     @Override
160     @PostConstruct
161     public void init() {
162         LOG.info("{} init", getClass().getSimpleName());
163         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
164     }
165
166     @Override
167     protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
168         return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
169     }
170
171     @Override
172     protected NatTunnelInterfaceStateListener getDataTreeChangeListener() {
173         return NatTunnelInterfaceStateListener.this;
174     }
175
176     @Override
177     protected void add(InstanceIdentifier<StateTunnelList> instanceIdentifier, StateTunnelList add) {
178         LOG.trace("NAT Service : TEP addtion---- {}", add);
179         hndlTepEvntsForDpn(add, TunnelAction.TUNNEL_EP_ADD);
180     }
181
182     @Override
183     protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
184         LOG.trace("NAT Service : TEP deletion---- {}", del);
185         hndlTepEvntsForDpn(del, TunnelAction.TUNNEL_EP_DELETE);
186     }
187
188     @Override
189     protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
190                           StateTunnelList update) {
191         LOG.trace("NAT Service : Tunnel updation---- {}", update);
192         //UPDATE IS A SEQUENCE OF DELETE AND ADD EVENTS . DELETE MIGHT HAVE CHANGED THE PRIMARY AND ADVERTISED. SO
193         // NOTHING TO HANDLE
194     }
195
196     private int getTunnelType(StateTunnelList stateTunnelList) {
197         int tunTypeVal = 0;
198         if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
199             tunTypeVal = NatConstants.ITMTunnelLocType.Internal.getValue();
200         } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
201             tunTypeVal = NatConstants.ITMTunnelLocType.External.getValue();
202         } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
203             tunTypeVal = NatConstants.ITMTunnelLocType.Hwvtep.getValue();
204         } else {
205             tunTypeVal = NatConstants.ITMTunnelLocType.Invalid.getValue();
206         }
207         return tunTypeVal;
208     }
209
210     // TODO Clean up the exception handling
211     @SuppressWarnings("checkstyle:IllegalCatch")
212     void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerVpnId, Uuid networkId) {
213         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
214         //remove miss entry to NAPT switch
215         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
216
217         //get ExternalIpIn prior
218         List<String> externalIpCache;
219         //HashMap Label
220         HashMap<String, Long> externalIpLabel;
221         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
222         if (routerId == NatConstants.INVALID_ID) {
223             LOG.error("NAT Service : SNAT -> Invalid routerId returned for routerName {}", routerName);
224             return;
225         }
226         externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
227         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
228         if (extNwProvType == null) {
229             return;
230         }
231         if (extNwProvType == ProviderTypes.VXLAN) {
232             externalIpLabel = null;
233         } else {
234             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
235         }
236         try {
237             final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
238             if (externalVpnName == null) {
239                 LOG.error("NAT Service : SNAT -> No VPN associated with ext nw {} in router {}",
240                     networkId, routerId);
241                 return;
242             }
243
244             BigInteger naptSwitch = dpnId;
245             boolean naptStatus =
246                 naptSwitchHA.isNaptSwitchDown(routerName, dpnId, naptSwitch, routerVpnId, externalIpCache, false);
247             if (!naptStatus) {
248                 LOG.debug("NAT Service : SNAT -> NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
249                     dpnId, routerName);
250                 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
251                 FlowEntity flowEntity = null;
252                 try {
253                     flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
254                         routerVpnId, NatConstants.DEL_FLOW);
255                     if (flowEntity == null) {
256                         LOG.debug("NAT Service : SNAT -> Failed to populate flowentity for "
257                             + "router {} with dpnId {} groupIs {}", routerName, dpnId, groupId);
258                         return;
259                     }
260                     LOG.debug("NAT Service : SNAT -> Removing default SNAT miss entry flow entity {}", flowEntity);
261                     mdsalManager.removeFlow(flowEntity);
262
263                 } catch (Exception ex) {
264                     LOG.debug("NAT Service : SNAT -> Failed to remove default SNAT miss entry flow entity {} : {}",
265                         flowEntity, ex);
266                     return;
267                 }
268                 LOG.debug("NAT Service : SNAT -> Removed default SNAT miss entry flow for dpnID {} with routername {}",
269                     dpnId, routerName);
270
271                 //remove group
272                 GroupEntity groupEntity = null;
273                 try {
274                     groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
275                         GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
276                     LOG.info("NAT Service : SNAT -> Removing NAPT GroupEntity:{} on Dpn {}", groupEntity, dpnId);
277                     mdsalManager.removeGroup(groupEntity);
278                 } catch (Exception ex) {
279                     LOG.debug("NAT Service : SNAT -> Failed to remove group entity {} : {}", groupEntity, ex);
280                     return;
281                 }
282                 LOG.debug("NAT Service : SNAT -> Removed default SNAT miss entry flow for dpnID {} with routerName {}",
283                     dpnId, routerName);
284             } else {
285                 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, dpnId, externalIpLabel);
286                 //remove table 26 flow ppointing to table46
287                 FlowEntity flowEntity = null;
288                 try {
289                     flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
290                         NatConstants.DEL_FLOW);
291                     if (flowEntity == null) {
292                         LOG.debug("NAT Service : SNAT -> Failed to populate flowentity for router {} with dpnId {}",
293                             routerName, dpnId);
294                         return;
295                     }
296                     LOG.debug("NAT Service : SNAT -> Removing default SNAT miss entry flow entity for "
297                         + "router {} with dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
298                     mdsalManager.removeFlow(flowEntity);
299
300                 } catch (Exception ex) {
301                     LOG.debug("NAT Service : SNAT -> Failed to remove default SNAT miss entry flow entity {} : {}",
302                         flowEntity, ex);
303                     return;
304                 }
305                 LOG.debug("NAT Service : SNAT -> Removed default SNAT miss entry flow for dpnID {} with routername {}",
306                     dpnId, routerName);
307
308                 //best effort to check IntExt model
309                 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel);
310             }
311         } catch (Exception ex) {
312             LOG.debug("NAT Service : SNAT -> Exception while handling naptSwitch down for router {} : {}",
313                 routerName, ex);
314         }
315     }
316
317     // TODO Clean up the exception handling
318     @SuppressWarnings("checkstyle:IllegalCatch")
319     private void hndlTepEvntsForDpn(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
320         final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
321         final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
322         final String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
323         LOG.trace("NAT Service : Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ", srcDpnId, srcTepIp,
324             destTepIp);
325         int tunTypeVal = getTunnelType(stateTunnelList);
326         LOG.trace("NAT Service : tunTypeVal is {}", tunTypeVal);
327         try {
328             String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId();
329             String tunnelType = stateTunnelList.getTransportType().toString();
330             String tunnelName = stateTunnelList.getTunnelInterfaceName();
331
332             if (tunTypeVal == NatConstants.ITMTunnelLocType.Invalid.getValue()) {
333                 LOG.warn("NAT Service : Ignoring TEP event {} for the DPN {} "
334                         + "since its a INVALID TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and " + "TUNNEL NAME {} ",
335                     tunnelAction, srcTepId, tunnelType, srcTepIp, destTepIp, tunnelName);
336                 return;
337             }
338
339             switch (tunnelAction) {
340                 case TUNNEL_EP_ADD:
341                     if (isTunnelInLogicalGroup(stateTunnelList)
342                             || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp)) {
343                         LOG.debug("NAT Service : Unable to process TEP ADD");
344                     }
345                     break;
346                 case TUNNEL_EP_DELETE:
347                     if (!handleTepDelForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp)) {
348                         LOG.debug("NAT Service : Unable to process TEP DEL");
349                     }
350                     break;
351                 default:
352                     LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
353                     break;
354             }
355         } catch (Exception e) {
356             LOG.error("NAT Service : Unable to handle the TEP event.", e);
357             return;
358         }
359     }
360
361     private boolean hndlTepAddForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
362                                          String destTepIp) throws Exception {
363         LOG.trace("NAT Service: TEP ADD ----- for EXTERNAL/HWVTEP ITM Tunnel, TYPE {} ,State is UP b/w SRC IP"
364             + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
365
366         InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
367         Optional<DpnRoutersList> optionalRouterDpnList =
368                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
369                         LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
370         if (!optionalRouterDpnList.isPresent()) {
371             LOG.warn("NAT Service : RouterDpnList model is empty for DPN {}. Hence ignoring TEP add event for the ITM "
372                     + "TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
373                 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
374             return false;
375         }
376
377         List<RoutersList> routersList = optionalRouterDpnList.get().getRoutersList();
378         if (routersList == null) {
379             LOG.debug("NAT Service : Ignoring TEP add for the DPN {} since no routers are associated"
380                 + " for the DPN having the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
381                 + "TUNNEL NAME {} ", srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
382             return false;
383         }
384
385         String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
386         for (RoutersList router : routersList) {
387
388             LOG.debug("NAT Service : TEP ADD : DNAT -> Advertising routes for router {} ", router.getRouter());
389             hndlTepAddForDnatInEachRtr(router, nextHopIp, srcDpnId);
390
391             LOG.debug("NAT Service : TEP ADD : SNAT -> Advertising routes for router {} ", router.getRouter());
392             hndlTepAddForSnatInEachRtr(router, srcDpnId, tunnelType, srcTepIp, destTepIp,
393                 tunnelName, nextHopIp);
394         }
395         return true;
396     }
397
398     // TODO Clean up the exception handling
399     @SuppressWarnings("checkstyle:IllegalCatch")
400     private boolean handleTepDelForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
401                                            String destTepIp) throws Exception {
402
403         LOG.trace("NAT Service: TEP DEL ----- for EXTERNAL/HWVTEP ITM Tunnel, TYPE {} ,State is UP b/w SRC IP"
404             + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
405
406         // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
407         // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
408         // Handle only the DPN on which it was deleted , ignore other event.
409         // DPN on which TEP is deleted , endpoint IP will be null.
410         String endpointIpForDPN = null;
411         try {
412             endpointIpForDPN = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
413         } catch (Exception e) {
414                 /* this dpn does not have the VTEP */
415             LOG.debug("NAT Service : DPN {} does not have the VTEP", srcDpnId);
416             endpointIpForDPN = null;
417         }
418
419         if (endpointIpForDPN != null) {
420             LOG.trace("NAT Service : Ignore TEP DELETE event received for DPN {} VTEP IP {} since its "
421                  + "the other end DPN w.r.t the delted TEP", srcDpnId, srcTepIp);
422             return false;
423         }
424
425         List<RoutersList> routersList = null;
426         InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
427         Optional<DpnRoutersList> optionalRouterDpnList =
428                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
429                         LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
430         if (optionalRouterDpnList.isPresent()) {
431             routersList = optionalRouterDpnList.get().getRoutersList();
432         } else {
433             LOG.warn("NAT Service : RouterDpnList is empty for DPN {}. Hence ignoring TEP DEL event for the ITM "
434                     + "TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
435                 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
436             return false;
437         }
438
439         if (routersList == null) {
440             LOG.debug("NAT Service : DPN {} does not have the Routers presence", srcDpnId);
441             return false;
442         }
443
444         for (RoutersList router : routersList) {
445             LOG.debug("NAT Service :  TEP DEL : DNAT -> Withdrawing routes for router {} ", router.getRouter());
446             hndlTepDelForDnatInEachRtr(router, srcDpnId);
447             LOG.debug("NAT Service :  TEP DEL : SNAT -> Withdrawing and Advertising routes for router {} ",
448                 router.getRouter());
449             hndlTepDelForSnatInEachRtr(router, srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
450         }
451         return true;
452     }
453
454     private void hndlTepAddForSnatInEachRtr(RoutersList router, final BigInteger srcDpnId, String tunnelType,
455             String srcTepIp, String destTepIp, String tunnelName, String nextHopIp) {
456
457         /*SNAT : Remove the old routes to the external IP having the old TEP IP as the next hop IP
458                  Advertise to the BGP about the new route to the external IP having the new TEP IP
459                   added as the next hop IP
460          */
461         String routerName = router.getRouter();
462
463         // Check if this is externalRouter else ignore
464         InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
465         Optional<Routers> routerData =
466                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
467                         LogicalDatastoreType.CONFIGURATION, extRoutersId);
468         if (!routerData.isPresent()) {
469             LOG.debug("NAT Service : SNAT -> Ignoring TEP add for router {} since its not External Router",
470                     routerName);
471             return;
472         }
473
474         long routerId = NatUtil.getVpnId(dataBroker, routerName);
475         BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
476         if (naptId == null || naptId.equals(BigInteger.ZERO)) {
477             LOG.warn("NAT Service : SNAT -> Ignoring TEP add for the DPN {} having the router {} since"
478                     + " the router is not part of the NAT service  - the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
479                     + "TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
480             return;
481         }
482         if (natMode == NatMode.Conntrack) {
483             natServiceManager.notify(routerData.get(), naptId, srcDpnId,
484                     SnatServiceManager.Action.SNAT_ROUTER_ENBL);
485         } else {
486             //Check if the DPN having the router is the NAPT switch
487             if (!naptId.equals(srcDpnId)) {
488                 /*
489             1) Install default NAT rule from table 21 to 26
490             2) Install the group which forward packet to the tunnel port for the NAPT switch.
491             3) Install the flow 26 which forwards the packet to the group.
492                  */
493                 if (!hndlTepAddOnNonNaptSwitch(srcDpnId, naptId, tunnelType, srcTepIp, destTepIp, tunnelName,
494                         routerName, routerId)) {
495                     LOG.debug("NAT Service : Unable to process the TEP add event on NON-NAPT switch {}", srcDpnId);
496                     return;
497                 }
498                 return;
499             }
500             if (!hndlTepAddOnNaptSwitch(srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName, routerId,
501                     routerData, nextHopIp)) {
502                 LOG.debug("NAT Service : Unable to process the TEP add event on NAPT switch {}", srcDpnId);
503                 return;
504             }
505         }
506         return;
507     }
508
509     private boolean hndlTepAddOnNonNaptSwitch(BigInteger srcDpnId, BigInteger primaryDpnId, String tunnelType,
510                                               String srcTepIp, String destTepIp, String tunnelName, String routerName,
511                                               long routerId) {
512
513         /*
514         1) Install default NAT rule from table 21 to 26
515         2) Install the group which forward packet to the tunnel port for the NAPT switch.
516         3) Install the flow 26 which forwards the packet to the group.
517         */
518         LOG.debug("NAT Service : SNAT -> Processing TEP add for the DPN {} having the router {} since "
519                 + "its THE NON NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
520                 + "and TUNNEL NAME {} ",
521             srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
522         LOG.debug("NAT Service : SNAT -> Install default NAT rule from table 21 to 26");
523         Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
524         Long vpnId;
525         if (vpnName == null) {
526             LOG.debug("NAT Service : SNAT -> Internal VPN associated to router {}", routerId);
527             vpnId = routerId;
528             if (vpnId == NatConstants.INVALID_ID) {
529                 LOG.error("NAT Service : SNAT -> Invalid Internal VPN ID returned for routerName {}", routerId);
530                 return false;
531             }
532             LOG.debug("NAT Service : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerName);
533             //Install default entry in FIB to SNAT table
534             LOG.debug("NAT Service : Installing default route in FIB on DPN {} for router {} with"
535                 + " vpn {}...", srcDpnId, routerName, vpnId);
536             defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId);
537
538             LOG.debug("NAT Service : SNAT -> Install the group which forward packet to the tunnel port "
539                 + "for the NAPT switch {} and the flow 26 which forwards to group", primaryDpnId);
540             externalRouterListner.handleSwitches(srcDpnId, routerName, primaryDpnId);
541         } else {
542             LOG.debug("NAT Service : SNAT -> External BGP VPN (Private BGP) associated to router {}", routerId);
543             vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
544             if (vpnId == NatConstants.INVALID_ID) {
545                 LOG.error("NAT Service : SNAT -> Invalid Private BGP VPN ID returned for routerName {}", routerId);
546                 return false;
547             }
548             if (routerId == NatConstants.INVALID_ID) {
549                 LOG.error("NAT Service : SNAT -> Invalid routId returned for routerName {}", routerId);
550                 return false;
551             }
552             LOG.debug("NAT Service : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
553             //Install default entry in FIB to SNAT table
554             LOG.debug("NAT Service : Installing default route in FIB on dpn {} for routerId {} "
555                 + "with vpnId {}...", srcDpnId, routerId, vpnId);
556             defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, routerId);
557
558             LOG.debug("NAT Service : Install group in non NAPT switch {} for router {}", srcDpnId, routerName);
559             List<BucketInfo> bucketInfoForNonNaptSwitches =
560                 externalRouterListner.getBucketInfoForNonNaptSwitches(srcDpnId, primaryDpnId, routerName);
561             long groupId = externalRouterListner.installGroup(srcDpnId, routerName, bucketInfoForNonNaptSwitches);
562
563             LOG.debug("NAT Service : SNAT -> in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
564                 vpnId, groupId, srcDpnId);
565             FlowEntity flowEntity =
566                 externalRouterListner.buildSnatFlowEntityWithUpdatedVpnId(srcDpnId, routerName, groupId, vpnId);
567             mdsalManager.installFlow(flowEntity);
568         }
569         return true;
570     }
571
572     private boolean hndlTepAddOnNaptSwitch(BigInteger srcDpnId, String tunnelType, String srcTepIp,
573                                            String destTepIp, String tunnelName, long routerId,
574                                            Optional<Routers> routerData, String nextHopIp) {
575         if (!routerData.isPresent()) {
576             LOG.warn("hndlTepAddOnNaptSwitch: routerData is not present");
577             return false;
578         }
579         Routers router = routerData.get();
580         String routerName = router.getRouterName();
581         LOG.debug("NAT Service : SNAT -> Processing TEP add for the DPN {} having the router {} since "
582             + "its THE NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
583             + "and TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
584
585         Uuid networkId = router.getNetworkId();
586         if (networkId == null) {
587             LOG.warn("NAT Service : SNAT -> Ignoring TEP add since the router {} is not associated to the "
588                 + "external network", routerName);
589             return false;
590         }
591
592         LOG.debug("NAT Service : SNAT -> Router {} is associated with Ext nw {}", routerId, networkId);
593         Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
594         Long vpnId;
595         if (vpnName == null) {
596             LOG.debug("NAT Service : SNAT -> Internal VPN associated to router {}", routerId);
597             vpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
598             if (vpnId == NatConstants.INVALID_ID) {
599                 LOG.error("Invalid External VPN-ID returned for routerName {}", routerName);
600                 return false;
601             }
602             LOG.debug("NAT Service : SNAT -> Retrieved External VPN-ID {} for router {}", vpnId, routerId);
603         } else {
604             LOG.debug("NAT Service : SNAT -> Private BGP VPN associated to router {}", routerId);
605             vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
606             if (vpnId == null || vpnId == NatConstants.INVALID_ID) {
607                 LOG.error("NAT Service : Invalid vpnId returned for routerName {}", routerName);
608                 return false;
609             }
610             LOG.debug("NAT Service : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
611         }
612
613         /*1) Withdraw the old route to the external IP from the BGP which was having the
614              next hop as the old TEP IP.
615           2) Advertise to the BGP about the new route to the external IP having the
616           new TEP IP as the next hop.
617           3) Populate a new FIB entry with the next hop IP as the new TEP IP using the
618           FIB manager.
619         */
620
621         //Withdraw the old route to the external IP from the BGP which was having the
622         //next hop as the old TEP IP.
623         final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
624         if (externalVpnName == null) {
625             LOG.error("NAT Service :  SNAT -> No VPN associated with ext nw {} in router {}",
626                 networkId, routerId);
627             return false;
628         }
629         List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
630         if (externalIps != null) {
631             LOG.debug("NAT Service : Clearing the FIB entries but not the BGP routes");
632             for (String externalIp : externalIps) {
633                 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
634                 LOG.debug("NAT Service : Removing Fib entry rd {} prefix {}", rd, externalIp);
635                 fibManager.removeFibEntry(dataBroker, rd, externalIp, null);
636             }
637         }
638
639         /*
640         Advertise to the BGP about the new route to the external IP having the
641         new TEP IP as the next hop.
642         Populate a new FIB entry with the next hop IP as the new TEP IP using the
643         FIB manager.
644         */
645         String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
646         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
647         if (extNwProvType == null) {
648             return false;
649         }
650         String gwMacAddress = null;
651         long l3Vni = 0;
652         WriteTransaction writeTx = null;
653         if (extNwProvType == ProviderTypes.VXLAN) {
654             // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
655             gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
656             //get l3Vni value for external VPN
657             l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
658             if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
659                 LOG.debug("NAT Service : L3VNI value is not configured in Internet VPN {} and RD {} "
660                         + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
661                         + "NAT flows", vpnName, rd);
662                 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, routerId).longValue();
663             }
664             //Create writeTx Object
665             writeTx = dataBroker.newWriteOnlyTransaction();
666         }
667         if (externalIps != null) {
668             for (final String externalIp : externalIps) {
669                 long serviceId = 0;
670                 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
671                 if (extNwProvType == ProviderTypes.VXLAN) {
672                     LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
673                             externalIp, nextHopIp);
674                     NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, externalVpnName, rd,
675                             externalIp, nextHopIp, l3Vni, tunnelName, gwMacAddress, writeTx, RouteOrigin.STATIC,
676                             srcDpnId);
677                     serviceId = l3Vni;
678                 } else {
679
680                     Long label = externalRouterListner.checkExternalIpLabel(routerId,
681                             externalIp);
682                     if (label == null || label == NatConstants.INVALID_ID) {
683                         LOG.debug("NAT Service : SNAT -> Unable to advertise to the DC GW since label is invalid");
684                         return false;
685                     }
686                     LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
687                             externalIp, nextHopIp);
688                     long l3vni = 0;
689                     if (elanManager.isOpenStackVniSemanticsEnforced()) {
690                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, l3vni).longValue();
691                     }
692                     Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIp,
693                             router);
694                     NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalSubnetId,
695                             fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni, LOG,
696                             RouteOrigin.STATIC, srcDpnId);
697                     serviceId = label;
698                 }
699
700                 LOG.debug("NAT Service : SNAT -> Install custom FIB routes "
701                     + "(Table 21 -> Push MPLS label to Tunnel port");
702                 List<Instruction> customInstructions = new ArrayList<>();
703                 int customInstructionIndex = 0;
704                 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIp,
705                         router);
706                 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
707                     LOG.debug("NAT Service : Will install custom FIB router with external subnet VPN ID {}",
708                             externalSubnetVpnId);
709                     BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
710                     customInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
711                             MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(customInstructionIndex));
712                     customInstructionIndex++;
713                 }
714                 customInstructions.add(new InstructionGotoTable(NwConstants.INBOUND_NAPT_TABLE)
715                         .buildInstruction(customInstructionIndex));
716                 CreateFibEntryInput input =
717                     new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
718                         .setInstruction(customInstructions).setIpAddress(fibExternalIp)
719                         .setServiceId(serviceId).setInstruction(customInstructions).build();
720                 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
721                 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
722
723                 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
724
725                     @Override
726                     public void onFailure(Throwable error) {
727                         LOG.error("NAT Service : SNAT -> Error in generate label or fib install process", error);
728                     }
729
730                     @Override
731                     public void onSuccess(RpcResult<Void> result) {
732                         if (result.isSuccessful()) {
733                             LOG.info("NAT Service : SNAT -> Successfully installed custom FIB routes for prefix {}",
734                                 externalIp);
735                         } else {
736                             LOG.error("NAT Service : SNAT -> Error in rpc call to create custom Fib entries "
737                                     + "for prefix {} in DPN {}, {}",
738                                 externalIp, srcDpnId, result.getErrors());
739                         }
740                     }
741                 });
742             }
743             if (writeTx != null) {
744                 writeTx.submit();
745             }
746         }
747         return true;
748     }
749
750     private void hndlTepAddForDnatInEachRtr(RoutersList router, String nextHopIp, BigInteger tepAddedDpnId) {
751         //DNAT : Advertise the new route to the floating IP having the new TEP IP as the next hop IP
752         final String routerName = router.getRouter();
753
754         InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
755         Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
756             .CONFIGURATION, routerPortsId);
757         if (!optRouterPorts.isPresent()) {
758             LOG.debug("NAT Service : DNAT -> Could not read Router Ports data object with id: {} from DNAT "
759                 + "FloatinIpInfo", routerName);
760             return;
761         }
762         RouterPorts routerPorts = optRouterPorts.get();
763         Uuid extNwId = routerPorts.getExternalNetworkId();
764         final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
765         if (vpnName == null) {
766             LOG.info("NAT Service : DNAT -> No External VPN associated with ext nw {} for router {}",
767                 extNwId, routerName);
768             return;
769         }
770
771         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
772         long routerId = NatUtil.getVpnId(dataBroker, routerName);
773         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
774         if (extNwProvType == null) {
775             return;
776         }
777         String gwMacAddress = null;
778         long l3Vni = 0;
779         WriteTransaction writeTx = null;
780         if (extNwProvType == ProviderTypes.VXLAN) {
781             // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
782             gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
783             //get l3Vni value for external VPN
784             l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
785             if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
786                 LOG.debug("NAT Service : L3VNI value is not configured in Internet VPN {} and RD {} "
787                         + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
788                         + "NAT flows", vpnName, rd);
789                 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
790             }
791             //Create writeTx Object
792             writeTx = dataBroker.newWriteOnlyTransaction();
793         }
794         List<Ports> interfaces = routerPorts.getPorts();
795         for (Ports port : interfaces) {
796             //Get the DPN on which this interface resides
797             final String interfaceName = port.getPortName();
798             final BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
799             if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
800                 LOG.info("NAT Service : DNAT -> Skip processing Floating ip configuration for the port {}, "
801                     + "since no DPN present for it", interfaceName);
802                 continue;
803             }
804             if (!fipCfgdDpnId.equals(tepAddedDpnId)) {
805                 LOG.debug("NAT Service : DNAT -> TEP added DPN {} is not the DPN {} which has the "
806                     + "floating IP configured for the port: {}",
807                     tepAddedDpnId, fipCfgdDpnId, interfaceName);
808                 continue;
809             }
810             List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
811             for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
812                 final String internalIp = intExtPortMap.getInternalIp();
813                 final String externalIp = intExtPortMap.getExternalIp();
814                 LOG.debug("NAT Service : DNAT -> Advertising the FIB route to the floating IP {} configured "
815                     + "for the port: {}",
816                     externalIp, interfaceName);
817                 long serviceId = 0;
818                 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
819
820                 if (extNwProvType == ProviderTypes.VXLAN) {
821                     LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
822                             externalIp, nextHopIp);
823                     NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
824                             externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, writeTx, RouteOrigin.STATIC,
825                             fipCfgdDpnId);
826                     serviceId = l3Vni;
827                 } else {
828                     long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
829                     if (label == NatConstants.INVALID_ID) {
830                         LOG.debug("NAT Service : DNAT -> Unable to advertise to the DC GW since label is invalid");
831                         return;
832                     }
833                     LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
834                             externalIp, nextHopIp);
835                     long l3vni = 0;
836                     if (elanManager.isOpenStackVniSemanticsEnforced()) {
837                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
838                     }
839                     NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
840                             fibExternalIp, nextHopIp, null, null, label, l3vni, LOG, RouteOrigin.STATIC,
841                             fipCfgdDpnId);
842                     serviceId = label;
843                 }
844
845                 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
846                 List<Instruction> customInstructions = new ArrayList<>();
847                 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
848                 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
849                     .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
850                     .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
851                         .build();
852                 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
853                 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
854
855                 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
856
857                     @Override
858                     public void onFailure(Throwable error) {
859                         LOG.error("NAT Service : DNAT -> Error in generate label or fib install process", error);
860                     }
861
862                     @Override
863                     public void onSuccess(RpcResult<Void> result) {
864                         if (result.isSuccessful()) {
865                             LOG.info("NAT Service : DNAT -> Successfully installed custom FIB routes for prefix {}",
866                                 externalIp);
867                         } else {
868                             LOG.error("NAT Service : DNAT -> Error in rpc call to create custom Fib "
869                                 + "entries for prefix {} in DPN {}, {}", externalIp, fipCfgdDpnId, result.getErrors());
870                         }
871                     }
872                 });
873             }
874             if (writeTx != null) {
875                 writeTx.submit();
876             }
877         }
878     }
879
880     private void hndlTepDelForSnatInEachRtr(RoutersList router, BigInteger dpnId, String tunnelType,
881                                             String srcTepIp, String destTepIp, String tunnelName) {
882        /*SNAT :
883             1) Elect a new switch as the primary NAPT
884             2) Advertise the new routes to BGP for the newly elected TEP IP as the DPN IP
885             3) This will make sure old routes are withdrawn and new routes are advertised.
886          */
887
888         String routerName = router.getRouter();
889         LOG.debug("NAT Service : SNAT -> Trying to clear routes to the External fixed IP associated to the router"
890                 + " {}", routerName);
891
892         // Check if this is externalRouter else ignore
893         InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
894         Optional<Routers> routerData =
895                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
896                         LogicalDatastoreType.CONFIGURATION, extRoutersId);
897         if (!routerData.isPresent()) {
898             LOG.debug("NAT Service : SNAT -> Ignoring TEP del for router {} since its not External Router",
899                     routerName);
900             return;
901         }
902
903         //Check if the router ID is valid
904         long routerId = NatUtil.getVpnId(dataBroker, routerName);
905         if (routerId == NatConstants.INVALID_ID) {
906             LOG.error("NAT Service : SNAT -> Invalid ROUTER-ID {} returned for routerName {}", routerId, routerName);
907             return;
908         }
909
910         //Check if the DPN having the router is the NAPT switch
911         BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
912         if (naptId == null || naptId.equals(BigInteger.ZERO) || (!naptId.equals(dpnId))) {
913             LOG.warn("NAT Service : SNAT -> Ignoring TEP delete for the DPN {} since"
914                     + " its NOT a NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
915                     + "TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
916             return;
917         }
918         if (natMode == NatMode.Conntrack) {
919             natServiceManager.notify(routerData.get(), naptId, dpnId, SnatServiceManager.Action.SNAT_ROUTER_DISBL);
920         } else {
921
922
923             Uuid networkId = routerData.get().getNetworkId();
924             if (networkId == null) {
925                 LOG.debug("NAT Service : SNAT -> Ignoring TEP delete for the DPN {} having the router {} "
926                         + "since the Router instance {} not found in ExtRouters model b/w SRC IP {} and DST IP {} "
927                         + "and TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
928                 return;
929             }
930
931             LOG.debug("NAT Service : SNAT -> Router {} is associated with ext nw {}", routerId, networkId);
932             Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
933             Long vpnId;
934             if (vpnName == null) {
935                 LOG.debug("NAT Service : SNAT -> Internal VPN-ID {} associated to router {}", routerId, routerName);
936                 vpnId = routerId;
937
938                 //Install default entry in FIB to SNAT table
939                 LOG.debug("NAT Service : Installing default route in FIB on DPN {} for router {} with"
940                         + " vpn {}...", dpnId, routerName, vpnId);
941                 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
942             } else {
943                 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
944                 if (vpnId == NatConstants.INVALID_ID) {
945                     LOG.error("NAT Service : SNAT -> Invalid Private BGP VPN ID returned for routerName {}",
946                             routerName);
947                     return;
948                 }
949                 LOG.debug("NAT Service : SNAT -> External BGP VPN (Private BGP) {} associated to router {}",
950                         vpnId, routerName);
951                 //Install default entry in FIB to SNAT table
952                 LOG.debug("NAT Service : Installing default route in FIB on dpn {} for routerId {} "
953                         + "with vpnId {}...", dpnId, routerId, vpnId);
954                 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId);
955             }
956
957             if (routerData.get().isEnableSnat()) {
958                 LOG.info("NAT Service : SNAT enabled for router {}", routerId);
959
960                 long routerVpnId = routerId;
961                 long bgpVpnId = NatConstants.INVALID_ID;
962                 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
963                 if (bgpVpnUuid != null) {
964                     bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
965                 }
966                 if (bgpVpnId != NatConstants.INVALID_ID) {
967                     LOG.debug("NAT Service : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} associated "
968                             + "to the router {}", bgpVpnId, routerName);
969                     routerVpnId = bgpVpnId;
970                 } else {
971                     LOG.debug("NAT Service : SNAT -> Internal L3 VPN ID (Router ID) {} associated to the router {}",
972                             routerVpnId, routerName);
973                 }
974                 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
975                 removeSNATFromDPN(dpnId, routerName, routerVpnId, networkId);
976             } else {
977                 LOG.info("NAT Service : SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
978             }
979         }
980     }
981
982     private void hndlTepDelForDnatInEachRtr(RoutersList router, BigInteger tepDeletedDpnId) {
983         //DNAT : Withdraw the routes from the BGP
984         String routerName = router.getRouter();
985         long routerId = NatUtil.getVpnId(dataBroker, routerName);
986         if (routerId == NatConstants.INVALID_ID) {
987             LOG.warn("Unable to get RouterId from RouterName {}", routerName);
988             return;
989         }
990         LOG.debug("NAT Service : DNAT -> Trying to clear routes to the Floating IP associated to the router {}",
991             routerName);
992
993         InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
994         Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
995             .CONFIGURATION, routerPortsId);
996         if (!optRouterPorts.isPresent()) {
997             LOG.debug("NAT Service : DNAT -> Could not read Router Ports data object with id: {} from DNAT "
998                     + "FloatingIpInfo",
999                 routerName);
1000             return;
1001         }
1002         RouterPorts routerPorts = optRouterPorts.get();
1003         Uuid extNwId = routerPorts.getExternalNetworkId();
1004         final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
1005         if (vpnName == null) {
1006             LOG.info("NAT Service : DNAT -> No External VPN associated with Ext N/W {} for Router {}",
1007                 extNwId, routerName);
1008             return;
1009         }
1010         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1011         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
1012         if (extNwProvType == null) {
1013             return;
1014         }
1015         long l3Vni = 0;
1016         if (extNwProvType == ProviderTypes.VXLAN) {
1017             //get l3Vni value for external VPN
1018             l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
1019             if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
1020                 LOG.debug("NAT Service : L3VNI value is not configured in Internet VPN {} and RD {} "
1021                         + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
1022                         + "NAT flows", vpnName, rd);
1023                 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
1024             }
1025         }
1026         List<Ports> interfaces = routerPorts.getPorts();
1027         for (Ports port : interfaces) {
1028             //Get the DPN on which this interface resides
1029             String interfaceName = port.getPortName();
1030             BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
1031             if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
1032                 LOG.info("NAT Service : DNAT -> Abort processing Floating ip configuration. No DPN for port : {}",
1033                     interfaceName);
1034                 continue;
1035             }
1036             if (!fipCfgdDpnId.equals(tepDeletedDpnId)) {
1037                 LOG.info("NAT Service : DNAT -> TEP deleted DPN {} is not the DPN {} which has the "
1038                     + "floating IP configured for the port: {}",
1039                     tepDeletedDpnId, fipCfgdDpnId, interfaceName);
1040                 continue;
1041             }
1042             List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
1043             for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
1044                 String internalIp = intExtPortMap.getInternalIp();
1045                 String externalIp = intExtPortMap.getExternalIp();
1046                 externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1047                 LOG.debug("NAT Service : DNAT -> Withdrawing the FIB route to the floating IP {} "
1048                     + "configured for the port: {}",
1049                     externalIp, interfaceName);
1050                 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, vpnName, LOG);
1051                 long serviceId = 0;
1052                 if (extNwProvType == ProviderTypes.VXLAN) {
1053                     serviceId = l3Vni;
1054                 } else {
1055                     long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
1056                     if (label == NatConstants.INVALID_ID) {
1057                         LOG.debug("NAT Service : DNAT -> Unable to remove the table 21 entry pushing the "
1058                                 + "MPLS label to the tunnel since label is invalid");
1059                         return;
1060                     }
1061                     serviceId = label;
1062                 }
1063
1064                 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
1065                     .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
1066                     .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
1067                 Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
1068                 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
1069
1070                 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
1071
1072                     @Override
1073                     public void onFailure(Throwable error) {
1074                         LOG.error("NAT Service : DNAT -> Error in removing the table 21 entry pushing "
1075                             + "the MPLS label to the tunnel since label is invalid ", error);
1076                     }
1077
1078                     @Override
1079                     public void onSuccess(RpcResult<Void> result) {
1080                         if (result.isSuccessful()) {
1081                             LOG.info("NAT Service : DNAT -> Successfully removed the entry pushing the "
1082                                 + "MPLS label to the tunnel");
1083                         } else {
1084                             LOG.error("NAT Service : DNAT -> Error in fib rpc call to remove the table 21 "
1085                                 + "entry pushing the MPLS label to the tunnnel due to {}", result.getErrors());
1086                         }
1087                     }
1088                 });
1089             }
1090         }
1091     }
1092
1093     protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
1094         String ifaceName = stateTunnelList.getTunnelInterfaceName();
1095         if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
1096             Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
1097             IfTunnel ifTunnel = (configIface != null) ? configIface.getAugmentation(IfTunnel.class) : null;
1098             if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
1099                 ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
1100                 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
1101                     return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
1102                 }
1103             }
1104         }
1105         LOG.trace("MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);
1106         return false;
1107     }
1108 }