2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.natservice.internal;
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.Collection;
20 import java.util.Collections;
21 import java.util.List;
23 import java.util.concurrent.Future;
24 import javax.annotation.Nonnull;
25 import javax.annotation.PostConstruct;
26 import javax.inject.Inject;
27 import javax.inject.Singleton;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
32 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
33 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
34 import org.opendaylight.genius.mdsalutil.BucketInfo;
35 import org.opendaylight.genius.mdsalutil.FlowEntity;
36 import org.opendaylight.genius.mdsalutil.GroupEntity;
37 import org.opendaylight.genius.mdsalutil.MDSALUtil;
38 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
39 import org.opendaylight.genius.mdsalutil.NwConstants;
40 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
41 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
42 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
43 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
44 import org.opendaylight.netvirt.elanmanager.api.IElanService;
45 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
46 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
47 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.opendaylight.yangtools.yang.common.RpcResult;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
82 public class NatTunnelInterfaceStateListener
83 extends AsyncDataTreeChangeListenerBase<StateTunnelList, NatTunnelInterfaceStateListener>
84 implements AutoCloseable {
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 NatMode natMode = NatMode.Controller;
103 protected enum TunnelAction {
110 * Responsible for listening to tunnel interface state change.
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 Listner
120 * @param interfaceService - Interface Service
121 * @param floatingIPListener - Floating IP Listner
122 * @param fibRpcService - FIB RPC Service
123 * @param elanManager - Elan Manager
126 public NatTunnelInterfaceStateListener(final DataBroker dataBroker,
127 final IBgpManager bgpManager,
128 final IFibManager fibManager,
129 final SNATDefaultRouteProgrammer defaultRouteProgrammer,
130 final NaptSwitchHA naptSwitchHA,
131 final IMdsalApiManager mdsalManager,
132 final IdManagerService idManager,
133 final ExternalRoutersListener externalRouterListner,
134 final SnatServiceManager natServiceManager,
135 final OdlInterfaceRpcService interfaceService,
136 final FloatingIPListener floatingIPListener,
137 final FibRpcService fibRpcService,
138 final NatserviceConfig config,
139 final IElanService elanManager,
140 final IInterfaceManager interfaceManager) {
141 super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
142 this.dataBroker = dataBroker;
143 this.bgpManager = bgpManager;
144 this.fibManager = fibManager;
145 this.defaultRouteProgrammer = defaultRouteProgrammer;
146 this.naptSwitchHA = naptSwitchHA;
147 this.mdsalManager = mdsalManager;
148 this.idManager = idManager;
149 this.externalRouterListner = externalRouterListner;
150 this.natServiceManager = natServiceManager;
151 this.interfaceService = interfaceService;
152 this.floatingIPListener = floatingIPListener;
153 this.fibRpcService = fibRpcService;
154 this.elanManager = elanManager;
155 this.interfaceManager = interfaceManager;
156 if (config != null) {
157 this.natMode = config.getNatMode();
164 LOG.info("{} init", getClass().getSimpleName());
165 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
169 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
170 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
174 protected NatTunnelInterfaceStateListener getDataTreeChangeListener() {
175 return NatTunnelInterfaceStateListener.this;
179 protected void add(InstanceIdentifier<StateTunnelList> instanceIdentifier, StateTunnelList add) {
180 LOG.trace("add : TEP addtion---- {}", add);
181 hndlTepEvntsForDpn(add, TunnelAction.TUNNEL_EP_ADD);
185 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
186 LOG.trace("remove : TEP deletion---- {}", del);
187 hndlTepEvntsForDpn(del, TunnelAction.TUNNEL_EP_DELETE);
191 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
192 StateTunnelList update) {
193 LOG.trace("update : Tunnel updation---- {}", update);
194 //UPDATE IS A SEQUENCE OF DELETE AND ADD EVENTS . DELETE MIGHT HAVE CHANGED THE PRIMARY AND ADVERTISED. SO
198 private int getTunnelType(StateTunnelList stateTunnelList) {
200 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
201 tunTypeVal = NatConstants.ITMTunnelLocType.Internal.getValue();
202 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
203 tunTypeVal = NatConstants.ITMTunnelLocType.External.getValue();
204 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
205 tunTypeVal = NatConstants.ITMTunnelLocType.Hwvtep.getValue();
207 tunTypeVal = NatConstants.ITMTunnelLocType.Invalid.getValue();
212 // TODO Clean up the exception handling
213 @SuppressWarnings("checkstyle:IllegalCatch")
214 void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerVpnId, Uuid networkId,
215 WriteTransaction writeFlowInvTx) {
216 //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
217 //remove miss entry to NAPT switch
218 //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
220 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
221 if (routerId == NatConstants.INVALID_ID) {
222 LOG.error("removeSNATFromDPN : SNAT -> Invalid routerId returned for routerName {}", routerName);
225 Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
226 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
227 if (extNwProvType == null) {
230 Map<String, Long> externalIpLabel;
231 if (extNwProvType == ProviderTypes.VXLAN) {
232 externalIpLabel = null;
234 externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
237 final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
238 if (externalVpnName == null) {
239 LOG.error("removeSNATFromDPN : SNAT -> No VPN associated with ext nw {} in router {}",
240 networkId, routerId);
244 BigInteger naptSwitch = dpnId;
246 naptSwitchHA.isNaptSwitchDown(routerName, dpnId, naptSwitch, routerVpnId, externalIpCache, false,
249 LOG.debug("removeSNATFromDPN:SNAT->NaptSwitchDown:Switch with DpnId {} is not naptSwitch for router {}",
251 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
252 FlowEntity flowEntity = null;
254 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
255 routerVpnId, NatConstants.DEL_FLOW);
256 if (flowEntity == null) {
257 LOG.error("removeSNATFromDPN : SNAT -> Failed to populate flowentity for "
258 + "router {} with dpnId {} groupIs {}", routerName, dpnId, groupId);
261 LOG.debug("removeSNATFromDPN : SNAT->Removing default SNAT miss entry flow entity {}", flowEntity);
262 mdsalManager.removeFlowToTx(flowEntity, writeFlowInvTx);
264 } catch (Exception ex) {
265 LOG.error("removeSNATFromDPN : SNAT->Failed to remove default SNAT miss entry flow entity {} : {}",
269 LOG.debug("removeSNATFromDPN:SNAT->Removed default SNAT miss entry flow for dpnID {}, routername {}",
273 GroupEntity groupEntity = null;
275 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
276 GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
277 LOG.info("removeSNATFromDPN : SNAT->Removing NAPT GroupEntity:{} on Dpn {}", groupEntity, dpnId);
278 mdsalManager.removeGroup(groupEntity);
279 } catch (Exception ex) {
280 LOG.error("removeSNATFromDPN : SNAT->Failed to remove group entity {}", groupEntity, ex);
283 LOG.debug("removeSNATFromDPN : SNAT->Removed default SNAT miss entry flow for dpnID {}, routerName {}",
286 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, dpnId, externalIpLabel, writeFlowInvTx);
287 //remove table 26 flow ppointing to table46
288 FlowEntity flowEntity = null;
290 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
291 NatConstants.DEL_FLOW);
292 if (flowEntity == null) {
293 LOG.error("removeSNATFromDPN : SNAT->Failed to populate flowentity for router {} with dpnId {}",
297 LOG.debug("removeSNATFromDPN : SNAT->Removing default SNAT miss entry flow entity for "
298 + "router {} with dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
299 mdsalManager.removeFlowToTx(flowEntity, writeFlowInvTx);
301 } catch (Exception ex) {
302 LOG.error("removeSNATFromDPN : SNAT->Failed to remove default SNAT miss entry flow entity {}",
306 LOG.debug("removeSNATFromDPN : SNAT->Removed default SNAT miss entry flow for dpnID {} "
307 + "with routername {}", dpnId, routerName);
309 //best effort to check IntExt model
310 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, writeFlowInvTx);
312 } catch (Exception ex) {
313 LOG.error("removeSNATFromDPN : SNAT->Exception while handling naptSwitch down for router {}",
318 // TODO Clean up the exception handling
319 @SuppressWarnings("checkstyle:IllegalCatch")
320 private void hndlTepEvntsForDpn(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
321 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
322 final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
323 final String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
324 LOG.trace("hndlTepEvntsForDpn : Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
325 srcDpnId, srcTepIp, destTepIp);
326 int tunTypeVal = getTunnelType(stateTunnelList);
327 LOG.trace("hndlTepEvntsForDpn : tunTypeVal is {}", tunTypeVal);
329 String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId();
330 String tunnelType = stateTunnelList.getTransportType().toString();
331 String tunnelName = stateTunnelList.getTunnelInterfaceName();
333 if (tunTypeVal == NatConstants.ITMTunnelLocType.Invalid.getValue()) {
334 LOG.warn("hndlTepEvntsForDpn : Ignoring TEP event {} for the DPN {} "
335 + "since its a INVALID TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and " + "TUNNEL NAME {} ",
336 tunnelAction, srcTepId, tunnelType, srcTepIp, destTepIp, tunnelName);
340 switch (tunnelAction) {
342 WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
343 List<ListenableFuture<Void>> futures = new ArrayList<>();
344 if (isTunnelInLogicalGroup(stateTunnelList)
345 || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
347 LOG.debug("hndlTepEvntsForDpn : Unable to process TEP ADD");
349 futures.add(NatUtil.waitForTransactionToComplete(writeFlowInvTx));
351 case TUNNEL_EP_DELETE:
352 WriteTransaction writeFlowRemovetx = dataBroker.newWriteOnlyTransaction();
353 List<ListenableFuture<Void>> futuresRemove = new ArrayList<>();
354 if (!handleTepDelForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
355 writeFlowRemovetx)) {
356 LOG.debug("hndlTepEvntsForDpn : Unable to process TEP DEL");
358 futuresRemove.add(NatUtil.waitForTransactionToComplete(writeFlowRemovetx));
361 LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
364 } catch (Exception e) {
365 LOG.error("hndlTepEvntsForDpn : Unable to handle the TEP event.", e);
370 private boolean hndlTepAddForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
371 String destTepIp, WriteTransaction writeFlowInvTx) throws Exception {
372 LOG.trace("hndlTepAddForAllRtrs: TEP ADD ----- for EXTERNAL/HWVTEP ITM Tunnel, TYPE {} ,State is UP b/w SRC IP"
373 + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
375 InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
376 Optional<DpnRoutersList> optionalRouterDpnList =
377 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
378 LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
379 if (!optionalRouterDpnList.isPresent()) {
380 LOG.warn("hndlTepAddForAllRtrs : RouterDpnList model is empty for DPN {}. Hence ignoring TEP add event "
381 + "for the ITM TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
382 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
386 List<RoutersList> routersList = optionalRouterDpnList.get().getRoutersList();
387 if (routersList == null) {
388 LOG.debug("hndlTepAddForAllRtrs : Ignoring TEP add for the DPN {} since no routers are associated"
389 + " for the DPN having the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
390 + "TUNNEL NAME {} ", srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
394 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
395 for (RoutersList router : routersList) {
397 LOG.debug("hndlTepAddForAllRtrs : TEP ADD : DNAT -> Advertising routes for router {} ", router.getRouter());
398 hndlTepAddForDnatInEachRtr(router, nextHopIp, srcDpnId, writeFlowInvTx);
400 LOG.debug("hndlTepAddForAllRtrs : TEP ADD : SNAT -> Advertising routes for router {} ", router.getRouter());
401 hndlTepAddForSnatInEachRtr(router, srcDpnId, tunnelType, srcTepIp, destTepIp,
402 tunnelName, nextHopIp, writeFlowInvTx);
407 // TODO Clean up the exception handling
408 @SuppressWarnings("checkstyle:IllegalCatch")
409 private boolean handleTepDelForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
410 String destTepIp, WriteTransaction writeFlowInvTx) throws Exception {
412 LOG.trace("handleTepDelForAllRtrs : TEP DEL ----- for EXTERNAL/HWVTEP ITM Tunnel,TYPE {},State is UP b/w SRC IP"
413 + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
415 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
416 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
417 // Handle only the DPN on which it was deleted , ignore other event.
418 // DPN on which TEP is deleted , endpoint IP will be null.
419 String endpointIpForDPN = null;
421 endpointIpForDPN = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
422 } catch (Exception e) {
423 /* this dpn does not have the VTEP */
424 LOG.error("handleTepDelForAllRtrs : DPN {} does not have the VTEP", srcDpnId);
425 endpointIpForDPN = null;
428 if (endpointIpForDPN != null) {
429 LOG.trace("handleTepDelForAllRtrs : Ignore TEP DELETE event received for DPN {} VTEP IP {} since its "
430 + "the other end DPN w.r.t the delted TEP", srcDpnId, srcTepIp);
434 List<RoutersList> routersList = null;
435 InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
436 Optional<DpnRoutersList> optionalRouterDpnList =
437 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
438 LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
439 if (optionalRouterDpnList.isPresent()) {
440 routersList = optionalRouterDpnList.get().getRoutersList();
442 LOG.warn("handleTepDelForAllRtrs : RouterDpnList is empty for DPN {}.Hence ignoring TEP DEL event "
443 + "for the ITM TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
444 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
448 if (routersList == null) {
449 LOG.error("handleTepDelForAllRtrs : DPN {} does not have the Routers presence", srcDpnId);
453 for (RoutersList router : routersList) {
454 LOG.debug("handleTepDelForAllRtrs : TEP DEL : DNAT -> Withdrawing routes for router {} ",
456 hndlTepDelForDnatInEachRtr(router, srcDpnId, writeFlowInvTx);
457 LOG.debug("handleTepDelForAllRtrs : TEP DEL : SNAT -> Withdrawing and Advertising routes for router {} ",
459 hndlTepDelForSnatInEachRtr(router, srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName, writeFlowInvTx);
464 private void hndlTepAddForSnatInEachRtr(RoutersList router, final BigInteger srcDpnId, String tunnelType,
465 String srcTepIp, String destTepIp, String tunnelName, String nextHopIp, WriteTransaction writeFlowInvTx) {
467 /*SNAT : Remove the old routes to the external IP having the old TEP IP as the next hop IP
468 Advertise to the BGP about the new route to the external IP having the new TEP IP
469 added as the next hop IP
471 String routerName = router.getRouter();
473 // Check if this is externalRouter else ignore
474 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
475 Optional<Routers> routerData =
476 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
477 LogicalDatastoreType.CONFIGURATION, extRoutersId);
478 if (!routerData.isPresent()) {
479 LOG.warn("hndlTepAddForSnatInEachRtr : SNAT->Ignoring TEP add for router {} since its not External Router",
484 long routerId = NatUtil.getVpnId(dataBroker, routerName);
485 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
486 if (naptId == null || naptId.equals(BigInteger.ZERO)) {
487 LOG.warn("hndlTepAddForSnatInEachRtr : SNAT -> Ignoring TEP add for the DPN {} having the router {} since"
488 + " the router is not part of the NAT service - the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
489 + "TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
492 if (natMode == NatMode.Conntrack) {
493 natServiceManager.notify(routerData.get(), naptId, srcDpnId,
494 SnatServiceManager.Action.SNAT_ROUTER_ENBL);
496 //Check if the DPN having the router is the NAPT switch
497 if (!naptId.equals(srcDpnId)) {
499 1) Install default NAT rule from table 21 to 26
500 2) Install the group which forward packet to the tunnel port for the NAPT switch.
501 3) Install the flow 26 which forwards the packet to the group.
503 if (!hndlTepAddOnNonNaptSwitch(srcDpnId, naptId, tunnelType, srcTepIp, destTepIp, tunnelName,
504 routerName, routerId, writeFlowInvTx)) {
505 LOG.error("hndlTepAddForSnatInEachRtr : Unable to process the TEP add event on NON-NAPT switch {}",
511 if (!hndlTepAddOnNaptSwitch(srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName, routerId,
512 routerData, nextHopIp,writeFlowInvTx)) {
513 LOG.debug("hndlTepAddForSnatInEachRtr : Unable to process the TEP add event on NAPT switch {}",
521 private boolean hndlTepAddOnNonNaptSwitch(BigInteger srcDpnId, BigInteger primaryDpnId, String tunnelType,
522 String srcTepIp, String destTepIp, String tunnelName, String routerName,
523 long routerId, WriteTransaction writeFlowInvTx) {
526 1) Install default NAT rule from table 21 to 26
527 2) Install the group which forward packet to the tunnel port for the NAPT switch.
528 3) Install the flow 26 which forwards the packet to the group.
530 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Processing TEP add for the DPN {} having the router {} since "
531 + "its THE NON NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
532 + "and TUNNEL NAME {} ",
533 srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
534 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Install default NAT rule from table 21 to 26");
535 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
537 if (vpnName == null) {
538 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Internal VPN associated to router {}", routerId);
540 if (vpnId == NatConstants.INVALID_ID) {
541 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid Internal VPN ID returned for routerName {}",
545 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerName);
546 //Install default entry in FIB to SNAT table
547 LOG.debug("hndlTepAddOnNonNaptSwitch : Installing default route in FIB on DPN {} for router {} with"
548 + " vpn {}...", srcDpnId, routerName, vpnId);
549 defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, writeFlowInvTx);
551 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Install the group which forward packet to the tunnel port "
552 + "for the NAPT switch {} and the flow 26 which forwards to group", primaryDpnId);
553 externalRouterListner.handleSwitches(srcDpnId, routerName, primaryDpnId, writeFlowInvTx);
555 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> External BGP VPN (Private BGP) associated to router {}",
557 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
558 if (vpnId == NatConstants.INVALID_ID) {
559 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid Private BGP VPN ID returned for routerName {}",
563 if (routerId == NatConstants.INVALID_ID) {
564 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid routId returned for routerName {}", routerId);
567 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
568 //Install default entry in FIB to SNAT table
569 LOG.debug("hndlTepAddOnNonNaptSwitch : Installing default route in FIB on dpn {} for routerId {} "
570 + "with vpnId {}...", srcDpnId, routerId, vpnId);
571 defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, routerId, writeFlowInvTx);
573 LOG.debug("hndlTepAddOnNonNaptSwitch : Install group in non NAPT switch {} for router {}",
574 srcDpnId, routerName);
575 List<BucketInfo> bucketInfoForNonNaptSwitches =
576 externalRouterListner.getBucketInfoForNonNaptSwitches(srcDpnId, primaryDpnId, routerName);
577 long groupId = externalRouterListner.installGroup(srcDpnId, routerName, bucketInfoForNonNaptSwitches);
579 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> in the SNAT miss entry pointing to group {} "
580 + "in the non NAPT switch {}", vpnId, groupId, srcDpnId);
581 FlowEntity flowEntity =
582 externalRouterListner.buildSnatFlowEntityWithUpdatedVpnId(srcDpnId, routerName, groupId, vpnId);
583 mdsalManager.addFlowToTx(flowEntity, writeFlowInvTx);
588 private boolean hndlTepAddOnNaptSwitch(BigInteger srcDpnId, String tunnelType, String srcTepIp,
589 String destTepIp, String tunnelName, long routerId,
590 Optional<Routers> routerData, String nextHopIp,
591 WriteTransaction writeFlowInvTx) {
592 if (!routerData.isPresent()) {
593 LOG.warn("hndlTepAddOnNaptSwitch: routerData is not present");
596 Routers router = routerData.get();
597 String routerName = router.getRouterName();
598 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Processing TEP add for the DPN {} having the router {} since "
599 + "its THE NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
600 + "and TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
602 Uuid networkId = router.getNetworkId();
603 if (networkId == null) {
604 LOG.warn("hndlTepAddOnNaptSwitch : SNAT -> Ignoring TEP add since the router {} is not associated to the "
605 + "external network", routerName);
609 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Router {} is associated with Ext nw {}", routerId, networkId);
610 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
612 if (vpnName == null) {
613 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Internal VPN associated to router {}", routerId);
614 vpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
615 if (vpnId == NatConstants.INVALID_ID) {
616 LOG.error("hndlTepAddOnNaptSwitch : Invalid External VPN-ID returned for routerName {}", routerName);
619 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Retrieved External VPN-ID {} for router {}", vpnId, routerId);
621 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Private BGP VPN associated to router {}", routerId);
622 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
623 if (vpnId == null || vpnId == NatConstants.INVALID_ID) {
624 LOG.error("hndlTepAddOnNaptSwitch : Invalid vpnId returned for routerName {}", routerName);
627 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
630 /*1) Withdraw the old route to the external IP from the BGP which was having the
631 next hop as the old TEP IP.
632 2) Advertise to the BGP about the new route to the external IP having the
633 new TEP IP as the next hop.
634 3) Populate a new FIB entry with the next hop IP as the new TEP IP using the
638 //Withdraw the old route to the external IP from the BGP which was having the
639 //next hop as the old TEP IP.
640 final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
641 if (externalVpnName == null) {
642 LOG.error("hndlTepAddOnNaptSwitch : SNAT -> No VPN associated with ext nw {} in router {}",
643 networkId, routerId);
646 Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
647 LOG.debug("hndlTepAddOnNaptSwitch : Clearing the FIB entries but not the BGP routes");
648 for (String externalIp : externalIps) {
649 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
650 LOG.debug("hndlTepAddOnNaptSwitch : Removing Fib entry rd {} prefix {}", rd, externalIp);
651 fibManager.removeFibEntry(dataBroker, rd, externalIp, null);
655 Advertise to the BGP about the new route to the external IP having the
656 new TEP IP as the next hop.
657 Populate a new FIB entry with the next hop IP as the new TEP IP using the
660 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
661 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
662 if (extNwProvType == null) {
665 String gwMacAddress = null;
667 if (extNwProvType == ProviderTypes.VXLAN) {
668 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
669 gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
670 if (gwMacAddress != null) {
671 LOG.debug("hndlTepAddOnNaptSwitch : External Gateway MAC address {} found for External Router ID {}",
672 gwMacAddress, routerId);
674 LOG.error("hndlTepAddOnNaptSwitch : No External Gateway MAC address found for External Router ID {}",
678 //get l3Vni value for external VPN
679 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
680 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
681 LOG.debug("hndlTepAddOnNaptSwitch : L3VNI value is not configured in Internet VPN {} and RD {} "
682 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
683 + "NAT flows", vpnName, rd);
684 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, routerId).longValue();
687 if (externalIps != null) {
688 for (final String externalIp : externalIps) {
690 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
691 if (extNwProvType == ProviderTypes.VXLAN) {
692 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Advertise the route to the externalIp {} "
693 + "having nextHopIp {}", externalIp, nextHopIp);
694 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, externalVpnName, rd,
695 externalIp, nextHopIp, l3Vni, tunnelName, gwMacAddress, writeFlowInvTx, RouteOrigin.STATIC,
700 Long label = externalRouterListner.checkExternalIpLabel(routerId,
702 if (label == null || label == NatConstants.INVALID_ID) {
703 LOG.error("hndlTepAddOnNaptSwitch : SNAT->Unable to advertise to the DC GW "
704 + "since label is invalid");
707 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Advertise the route to the externalIp {} "
708 + "having nextHopIp {}", externalIp, nextHopIp);
710 if (elanManager.isOpenStackVniSemanticsEnforced()) {
711 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, l3vni).longValue();
713 Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIp,
715 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalSubnetId,
716 fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni, LOG,
717 RouteOrigin.STATIC, srcDpnId);
721 LOG.debug("hndlTepAddOnNaptSwitch: SNAT -> Install custom FIB routes "
722 + "(Table 21 -> Push MPLS label to Tunnel port");
723 List<Instruction> customInstructions = new ArrayList<>();
724 int customInstructionIndex = 0;
725 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIp,
727 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
728 LOG.debug("hndlTepAddOnNaptSwitch : Will install custom FIB router with external subnet VPN ID {}",
729 externalSubnetVpnId);
730 BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
731 customInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
732 MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(customInstructionIndex));
733 customInstructionIndex++;
735 customInstructions.add(new InstructionGotoTable(NwConstants.INBOUND_NAPT_TABLE)
736 .buildInstruction(customInstructionIndex));
737 CreateFibEntryInput input =
738 new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
739 .setInstruction(customInstructions).setIpAddress(fibExternalIp)
740 .setServiceId(serviceId).setInstruction(customInstructions).build();
741 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
742 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
744 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
747 public void onFailure(@Nonnull Throwable error) {
748 LOG.error("hndlTepAddOnNaptSwitch : SNAT->Error in generate label or fib install process",
753 public void onSuccess(RpcResult<Void> result) {
754 if (result.isSuccessful()) {
755 LOG.info("hndlTepAddOnNaptSwitch : SNAT -> Successfully installed custom FIB routes "
756 + "for prefix {}", externalIp);
758 LOG.error("hndlTepAddOnNaptSwitch : SNAT -> Error in rpc call to create custom Fib entries "
759 + "for prefix {} in DPN {}, {}", externalIp, srcDpnId, result.getErrors());
768 private void hndlTepAddForDnatInEachRtr(RoutersList router, String nextHopIp, BigInteger tepAddedDpnId,
769 WriteTransaction writeFlowInvTx) {
770 //DNAT : Advertise the new route to the floating IP having the new TEP IP as the next hop IP
771 final String routerName = router.getRouter();
773 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
774 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
775 .CONFIGURATION, routerPortsId);
776 if (!optRouterPorts.isPresent()) {
777 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
778 + "from DNAT FloatinIpInfo", routerName);
781 RouterPorts routerPorts = optRouterPorts.get();
782 Uuid extNwId = routerPorts.getExternalNetworkId();
783 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
784 if (vpnName == null) {
785 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> No External VPN associated with ext nw {} for router {}",
786 extNwId, routerName);
790 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
791 long routerId = NatUtil.getVpnId(dataBroker, routerName);
792 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
793 if (extNwProvType == null) {
796 String gwMacAddress = null;
798 if (extNwProvType == ProviderTypes.VXLAN) {
799 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
800 gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
801 if (gwMacAddress != null) {
802 LOG.debug("hndlTepAddForDnatInEachRtr : External GwMAC address {} found for External Router ID {}",
803 gwMacAddress, routerId);
805 LOG.error("hndlTepAddForDnatInEachRtr : No External GwMAC address found for External Router ID {}",
809 //get l3Vni value for external VPN
810 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
811 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
812 LOG.debug("hndlTepAddForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
813 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
814 + "NAT flows", vpnName, rd);
815 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
818 List<Ports> interfaces = routerPorts.getPorts();
819 for (Ports port : interfaces) {
820 //Get the DPN on which this interface resides
821 final String interfaceName = port.getPortName();
822 final BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
823 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
824 LOG.info("hndlTepAddForDnatInEachRtr : DNAT->Skip processing Floating ip configuration for the port {},"
825 + "since no DPN present for it", interfaceName);
828 if (!fipCfgdDpnId.equals(tepAddedDpnId)) {
829 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> TEP added DPN {} is not the DPN {} which has the "
830 + "floating IP configured for the port: {}",
831 tepAddedDpnId, fipCfgdDpnId, interfaceName);
834 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
835 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
836 final String internalIp = intExtPortMap.getInternalIp();
837 final String externalIp = intExtPortMap.getExternalIp();
838 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertising the FIB route to the floating IP {} "
839 + "configured for the port: {}", externalIp, interfaceName);
841 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
843 if (extNwProvType == ProviderTypes.VXLAN) {
844 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
845 + "having nextHopIp {}", externalIp, nextHopIp);
846 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
847 externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, writeFlowInvTx,
848 RouteOrigin.STATIC, fipCfgdDpnId);
851 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
852 if (label == NatConstants.INVALID_ID) {
853 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Unable to advertise to the DC GW since label "
857 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
858 + "having nextHopIp {}", externalIp, nextHopIp);
860 if (elanManager.isOpenStackVniSemanticsEnforced()) {
861 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
863 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
864 fibExternalIp, nextHopIp, null, null, label, l3vni, LOG, RouteOrigin.STATIC,
869 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
870 List<Instruction> customInstructions = new ArrayList<>();
871 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
872 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
873 .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
874 .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
876 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
877 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
879 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
882 public void onFailure(@Nonnull Throwable error) {
883 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in generate label or fib install process",
888 public void onSuccess(RpcResult<Void> result) {
889 if (result.isSuccessful()) {
890 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> Successfully installed custom FIB routes "
891 + "for prefix {}", externalIp);
893 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in rpc call to create custom Fib "
894 + "entries for prefix {} in DPN {}, {}", externalIp, fipCfgdDpnId, result.getErrors());
902 private void hndlTepDelForSnatInEachRtr(RoutersList router, BigInteger dpnId, String tunnelType,
903 String srcTepIp, String destTepIp, String tunnelName,
904 WriteTransaction writeFlowInvTx) {
906 1) Elect a new switch as the primary NAPT
907 2) Advertise the new routes to BGP for the newly elected TEP IP as the DPN IP
908 3) This will make sure old routes are withdrawn and new routes are advertised.
911 String routerName = router.getRouter();
912 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Trying to clear routes to the External fixed IP associated "
913 + "to the router {}", routerName);
915 // Check if this is externalRouter else ignore
916 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
917 Optional<Routers> routerData =
918 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
919 LogicalDatastoreType.CONFIGURATION, extRoutersId);
920 if (!routerData.isPresent()) {
921 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP del for router {} since its not External Router",
926 //Check if the router ID is valid
927 long routerId = NatUtil.getVpnId(dataBroker, routerName);
928 if (routerId == NatConstants.INVALID_ID) {
929 LOG.error("hndlTepDelForSnatInEachRtr : SNAT -> Invalid ROUTER-ID {} returned for routerName {}",
930 routerId, routerName);
934 //Check if the DPN having the router is the NAPT switch
935 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
936 if (naptId == null || naptId.equals(BigInteger.ZERO) || (!naptId.equals(dpnId))) {
937 LOG.warn("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring TEP delete for the DPN {} since"
938 + " its NOT a NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
939 + "TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
942 if (natMode == NatMode.Conntrack) {
943 natServiceManager.notify(routerData.get(), naptId, dpnId, SnatServiceManager.Action.SNAT_ROUTER_DISBL);
947 Uuid networkId = routerData.get().getNetworkId();
948 if (networkId == null) {
949 LOG.error("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP delete for the DPN {} having the router {} "
950 + "since the Router instance {} not found in ExtRouters model b/w SRC IP {} and DST IP {} "
951 + "and TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
955 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
956 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
958 if (vpnName == null) {
959 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
960 routerId, routerName);
963 //Install default entry in FIB to SNAT table
964 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on DPN {} for router {} with"
965 + " vpn {}...", dpnId, routerName, vpnId);
966 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, writeFlowInvTx);
968 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
969 if (vpnId == NatConstants.INVALID_ID) {
970 LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
974 LOG.debug("hndlTepDelForSnatInEachRtr :SNAT->External BGP VPN (Private BGP) {} associated to router {}",
976 //Install default entry in FIB to SNAT table
977 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on dpn {} for routerId {} "
978 + "with vpnId {}...", dpnId, routerId, vpnId);
979 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId, writeFlowInvTx);
982 if (routerData.get().isEnableSnat()) {
983 LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
985 long routerVpnId = routerId;
986 long bgpVpnId = NatConstants.INVALID_ID;
987 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
988 if (bgpVpnUuid != null) {
989 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
991 if (bgpVpnId != NatConstants.INVALID_ID) {
992 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
993 + "associated to the router {}", bgpVpnId, routerName);
994 routerVpnId = bgpVpnId;
996 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
997 + "associated to the router {}", routerVpnId, routerName);
999 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
1000 removeSNATFromDPN(dpnId, routerName, routerVpnId, networkId, writeFlowInvTx);
1002 LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
1008 private void hndlTepDelForDnatInEachRtr(RoutersList router, BigInteger tepDeletedDpnId,
1009 WriteTransaction writeFlowInvTx) {
1010 //DNAT : Withdraw the routes from the BGP
1011 String routerName = router.getRouter();
1012 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1013 if (routerId == NatConstants.INVALID_ID) {
1014 LOG.error("hndlTepDelForDnatInEachRtr : Unable to get RouterId from RouterName {}", routerName);
1017 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Trying to clear routes to the Floating IP "
1018 + "associated to the router {}", routerName);
1020 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
1021 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
1022 .CONFIGURATION, routerPortsId);
1023 if (!optRouterPorts.isPresent()) {
1024 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
1025 + "from DNAT FloatingIpInfo", routerName);
1028 RouterPorts routerPorts = optRouterPorts.get();
1029 Uuid extNwId = routerPorts.getExternalNetworkId();
1030 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
1031 if (vpnName == null) {
1032 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> No External VPN associated with Ext N/W {} for Router {}",
1033 extNwId, routerName);
1036 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1037 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
1038 if (extNwProvType == null) {
1042 if (extNwProvType == ProviderTypes.VXLAN) {
1043 //get l3Vni value for external VPN
1044 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
1045 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
1046 LOG.debug("hndlTepDelForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
1047 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
1048 + "NAT flows", vpnName, rd);
1049 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
1052 List<Ports> interfaces = routerPorts.getPorts();
1053 for (Ports port : interfaces) {
1054 //Get the DPN on which this interface resides
1055 String interfaceName = port.getPortName();
1056 BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
1057 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
1058 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Abort processing Floating ip configuration. "
1059 + "No DPN for port : {}", interfaceName);
1062 if (!fipCfgdDpnId.equals(tepDeletedDpnId)) {
1063 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> TEP deleted DPN {} is not the DPN {} which has the "
1064 + "floating IP configured for the port: {}",
1065 tepDeletedDpnId, fipCfgdDpnId, interfaceName);
1068 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
1069 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
1070 String internalIp = intExtPortMap.getInternalIp();
1071 String externalIp = intExtPortMap.getExternalIp();
1072 externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1073 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Withdrawing the FIB route to the floating IP {} "
1074 + "configured for the port: {}",
1075 externalIp, interfaceName);
1076 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, vpnName, LOG);
1078 if (extNwProvType == ProviderTypes.VXLAN) {
1081 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
1082 if (label == NatConstants.INVALID_ID) {
1083 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Unable to remove the table 21 entry pushing the"
1084 + " MPLS label to the tunnel since label is invalid");
1090 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
1091 .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
1092 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
1093 Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
1094 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
1096 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
1099 public void onFailure(@Nonnull Throwable error) {
1100 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in removing the table 21 entry pushing "
1101 + "the MPLS label to the tunnel since label is invalid ", error);
1105 public void onSuccess(RpcResult<Void> result) {
1106 if (result.isSuccessful()) {
1107 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Successfully removed the entry pushing the "
1108 + "MPLS label to the tunnel");
1110 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in fib rpc call to remove the table "
1111 + "21 entry pushing the MPLS label to the tunnnel due to {}", result.getErrors());
1119 protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
1120 String ifaceName = stateTunnelList.getTunnelInterfaceName();
1121 if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
1122 Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
1123 IfTunnel ifTunnel = (configIface != null) ? configIface.getAugmentation(IfTunnel.class) : null;
1124 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
1125 ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
1126 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
1127 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
1131 LOG.trace("isTunnelInLogicalGroup: ignoring the tunnel event for {}", ifaceName);