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