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 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;
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;
83 public class NatTunnelInterfaceStateListener
84 extends AsyncDataTreeChangeListenerBase<StateTunnelList, NatTunnelInterfaceStateListener> {
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;
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 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
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();
162 this.natMode = NatMode.Controller;
169 LOG.info("{} init", getClass().getSimpleName());
170 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
174 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
175 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
179 protected NatTunnelInterfaceStateListener getDataTreeChangeListener() {
180 return NatTunnelInterfaceStateListener.this;
184 protected void add(InstanceIdentifier<StateTunnelList> instanceIdentifier, StateTunnelList add) {
185 LOG.trace("add : TEP addtion---- {}", add);
186 hndlTepEvntsForDpn(add, TunnelAction.TUNNEL_EP_ADD);
190 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
191 LOG.trace("remove : TEP deletion---- {}", del);
192 hndlTepEvntsForDpn(del, TunnelAction.TUNNEL_EP_DELETE);
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
203 private int getTunnelType(StateTunnelList stateTunnelList) {
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();
212 tunTypeVal = NatConstants.ITMTunnelLocType.Invalid.getValue();
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
225 if (routerId == NatConstants.INVALID_ID) {
226 LOG.error("removeSNATFromDPN : SNAT -> Invalid routerId returned for routerName {}", routerName);
229 Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
230 if (extNwProvType == null) {
233 Map<String, Long> externalIpLabel;
234 if (extNwProvType == ProviderTypes.VXLAN) {
235 externalIpLabel = null;
237 externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
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);
247 BigInteger naptSwitch = dpnId;
249 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch,
250 routerVpnId, externalIpCache, false, writeFlowInvTx);
252 LOG.debug("removeSNATFromDPN:SNAT->NaptSwitchDown:Switch with DpnId {} is not naptSwitch for router {}",
254 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
255 FlowEntity flowEntity = null;
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);
264 LOG.debug("removeSNATFromDPN : SNAT->Removing default SNAT miss entry flow entity {}", flowEntity);
265 mdsalManager.removeFlowToTx(flowEntity, writeFlowInvTx);
267 } catch (Exception ex) {
268 LOG.error("removeSNATFromDPN : SNAT->Failed to remove default SNAT miss entry flow entity {} : {}",
272 LOG.debug("removeSNATFromDPN:SNAT->Removed default SNAT miss entry flow for dpnID {}, routername {}",
276 GroupEntity groupEntity = null;
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);
286 LOG.debug("removeSNATFromDPN : SNAT->Removed default SNAT miss entry flow for dpnID {}, routerName {}",
289 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, dpnId,
290 externalIpLabel, writeFlowInvTx);
291 //remove table 26 flow ppointing to table46
292 FlowEntity flowEntity = null;
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 {}",
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);
305 } catch (Exception ex) {
306 LOG.error("removeSNATFromDPN : SNAT->Failed to remove default SNAT miss entry flow entity {}",
310 LOG.debug("removeSNATFromDPN : SNAT->Removed default SNAT miss entry flow for dpnID {} "
311 + "with routername {}", dpnId, routerName);
313 //best effort to check IntExt model
314 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, writeFlowInvTx);
316 } catch (Exception ex) {
317 LOG.error("removeSNATFromDPN : SNAT->Exception while handling naptSwitch down for router {}",
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);
333 String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId();
334 String tunnelType = stateTunnelList.getTransportType().toString();
335 String tunnelName = stateTunnelList.getTunnelInterfaceName();
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);
344 switch (tunnelAction) {
346 WriteTransaction writeFlowInvTx = dataBroker.newWriteOnlyTransaction();
347 if (isTunnelInLogicalGroup(stateTunnelList)
348 || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
350 LOG.debug("hndlTepEvntsForDpn : Unable to process TEP ADD");
352 NatUtil.waitForTransactionToComplete(writeFlowInvTx);
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");
360 NatUtil.waitForTransactionToComplete(writeFlowRemovetx);
363 LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
366 } catch (Exception e) {
367 LOG.error("hndlTepEvntsForDpn : Unable to handle the TEP event.", e);
372 private boolean hndlTepAddForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
373 String destTepIp, WriteTransaction writeFlowInvTx) throws Exception {
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);
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);
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);
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);
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) {
412 hndlTepAddForDnatInEachRtr(router, routerId, nextHopIp, srcDpnId, extNwProvType, writeFlowInvTx);
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);
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) throws Exception {
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);
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;
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;
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);
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();
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);
462 if (routersList == null) {
463 LOG.error("handleTepDelForAllRtrs : DPN {} does not have the Routers presence", srcDpnId);
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);
476 Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker,routerName);
477 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
478 routerName, externalNetworkId);
479 if (extNwProvType == null) {
482 hndlTepDelForDnatInEachRtr(router, routerId, srcDpnId, extNwProvType, writeFlowInvTx);
483 LOG.debug("handleTepDelForAllRtrs : TEP DEL : SNAT -> Withdrawing and Advertising routes for router {} ",
485 hndlTepDelForSnatInEachRtr(router, routerId, srcDpnId, tunnelType, srcTepIp, destTepIp,
486 tunnelName, extNwProvType, writeFlowInvTx);
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) {
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
499 String routerName = router.getRouter();
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",
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);
519 if (natMode == NatMode.Conntrack) {
520 natServiceManager.notify(routerData.get(), naptId, srcDpnId,
521 SnatServiceManager.Action.SNAT_ROUTER_ENBL);
523 Uuid bgpVpnUuId = NatUtil.getVpnForRouter(dataBroker, routerName);
524 //Check if the DPN having the router is the NAPT switch
525 if (!naptId.equals(srcDpnId)) {
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.
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 {}",
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 {}",
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) {
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.
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");
564 if (vpnName == null) {
565 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Internal VPN associated to router {}", routerId);
567 if (vpnId == NatConstants.INVALID_ID) {
568 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid Internal VPN ID returned for routerName {}",
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);
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, writeFlowInvTx);
582 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> External BGP VPN (Private BGP) associated to router {}",
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 {}",
590 if (routerId == NatConstants.INVALID_ID) {
591 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid routId returned for routerName {}", routerId);
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);
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);
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);
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");
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);
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);
636 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Router {} is associated with Ext nw {}", routerId, networkId);
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);
645 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Retrieved External VPN-ID {} for router {}", vpnId, routerId);
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);
653 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
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
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);
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(dataBroker, rd, externalIp, null);
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
686 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
687 if (extNwProvType == null) {
690 String gwMacAddress = null;
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);
699 LOG.error("hndlTepAddOnNaptSwitch : No External Gateway MAC address found for External Router ID {}",
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();
713 for (final String externalIp : externalIps) {
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,
725 Long label = externalRouterListner.checkExternalIpLabel(routerId,
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");
732 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Advertise the route to the externalIp {} "
733 + "having nextHopIp {}", externalIp, nextHopIp);
735 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
736 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, l3vni).longValue();
738 Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIp,
740 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalSubnetId,
741 fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni,
742 RouteOrigin.STATIC, srcDpnId);
746 LOG.debug("hndlTepAddOnNaptSwitch: SNAT -> Install custom FIB routes "
747 + "(Table 21 -> Push MPLS label to Tunnel port");
748 List<Instruction> customInstructions = new ArrayList<>();
749 int customInstructionIndex = 0;
750 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIp,
752 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
753 LOG.debug("hndlTepAddOnNaptSwitch : Will install custom FIB router with external subnet VPN ID {}",
754 externalSubnetVpnId);
755 BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
756 customInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
757 MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(customInstructionIndex));
758 customInstructionIndex++;
760 customInstructions.add(new InstructionGotoTable(NwConstants.INBOUND_NAPT_TABLE)
761 .buildInstruction(customInstructionIndex));
762 CreateFibEntryInput input =
763 new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
764 .setInstruction(customInstructions).setIpAddress(fibExternalIp)
765 .setServiceId(serviceId).setInstruction(customInstructions).build();
766 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
767 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
769 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
772 public void onFailure(@Nonnull Throwable error) {
773 LOG.error("hndlTepAddOnNaptSwitch : SNAT->Error in generate label or fib install process",
778 public void onSuccess(@Nonnull RpcResult<Void> result) {
779 if (result.isSuccessful()) {
780 LOG.info("hndlTepAddOnNaptSwitch : SNAT -> Successfully installed custom FIB routes "
781 + "for prefix {}", externalIp);
783 LOG.error("hndlTepAddOnNaptSwitch : SNAT -> Error in rpc call to create custom Fib entries "
784 + "for prefix {} in DPN {}, {}", externalIp, srcDpnId, result.getErrors());
787 }, MoreExecutors.directExecutor());
793 private void hndlTepAddForDnatInEachRtr(RoutersList router, long routerId, String nextHopIp,
794 BigInteger tepAddedDpnId, ProviderTypes extNwProvType, WriteTransaction writeFlowInvTx) {
795 //DNAT : Advertise the new route to the floating IP having the new TEP IP as the next hop IP
796 final String routerName = router.getRouter();
798 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
799 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
800 .CONFIGURATION, routerPortsId);
801 if (!optRouterPorts.isPresent()) {
802 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
803 + "from DNAT FloatinIpInfo", routerName);
806 RouterPorts routerPorts = optRouterPorts.get();
807 Uuid extNwId = routerPorts.getExternalNetworkId();
808 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId);
809 if (vpnName == null) {
810 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> No External VPN associated with ext nw {} for router {}",
811 extNwId, routerName);
815 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
816 if (extNwProvType == null) {
819 String gwMacAddress = null;
821 if (extNwProvType == ProviderTypes.VXLAN) {
822 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
823 gwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
824 if (gwMacAddress != null) {
825 LOG.debug("hndlTepAddForDnatInEachRtr : External GwMAC address {} found for External Router ID {}",
826 gwMacAddress, routerId);
828 LOG.error("hndlTepAddForDnatInEachRtr : No External GwMAC address found for External Router ID {}",
832 //get l3Vni value for external VPN
833 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
834 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
835 LOG.debug("hndlTepAddForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
836 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
837 + "NAT flows", vpnName, rd);
838 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
841 List<Ports> interfaces = routerPorts.getPorts();
842 for (Ports port : interfaces) {
843 //Get the DPN on which this interface resides
844 final String interfaceName = port.getPortName();
845 final BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
846 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
847 LOG.info("hndlTepAddForDnatInEachRtr : DNAT->Skip processing Floating ip configuration for the port {},"
848 + "since no DPN present for it", interfaceName);
851 if (!fipCfgdDpnId.equals(tepAddedDpnId)) {
852 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> TEP added DPN {} is not the DPN {} which has the "
853 + "floating IP configured for the port: {}",
854 tepAddedDpnId, fipCfgdDpnId, interfaceName);
857 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
858 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
859 final String internalIp = intExtPortMap.getInternalIp();
860 final String externalIp = intExtPortMap.getExternalIp();
861 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertising the FIB route to the floating IP {} "
862 + "configured for the port: {}", externalIp, interfaceName);
864 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
866 if (extNwProvType == ProviderTypes.VXLAN) {
867 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
868 + "having nextHopIp {}", externalIp, nextHopIp);
869 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
870 externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, writeFlowInvTx,
871 RouteOrigin.STATIC, fipCfgdDpnId);
874 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
875 if (label == NatConstants.INVALID_ID) {
876 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Unable to advertise to the DC GW since label "
880 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
881 + "having nextHopIp {}", externalIp, nextHopIp);
883 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
884 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
886 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
887 fibExternalIp, nextHopIp, null, null, label, l3vni, RouteOrigin.STATIC,
892 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
893 List<Instruction> customInstructions = new ArrayList<>();
894 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
895 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
896 .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
897 .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
899 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
900 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
902 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
905 public void onFailure(@Nonnull Throwable error) {
906 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in generate label or fib install process",
911 public void onSuccess(@Nonnull RpcResult<Void> result) {
912 if (result.isSuccessful()) {
913 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> Successfully installed custom FIB routes "
914 + "for prefix {}", externalIp);
916 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in rpc call to create custom Fib "
917 + "entries for prefix {} in DPN {}, {}", externalIp, fipCfgdDpnId, result.getErrors());
920 }, MoreExecutors.directExecutor());
925 private void hndlTepDelForSnatInEachRtr(RoutersList router, long routerId, BigInteger dpnId, String tunnelType,
926 String srcTepIp, String destTepIp, String tunnelName,
927 ProviderTypes extNwProvType, WriteTransaction writeFlowInvTx) {
929 1) Elect a new switch as the primary NAPT
930 2) Advertise the new routes to BGP for the newly elected TEP IP as the DPN IP
931 3) This will make sure old routes are withdrawn and new routes are advertised.
934 String routerName = router.getRouter();
935 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Trying to clear routes to the External fixed IP associated "
936 + "to the router {}", routerName);
938 // Check if this is externalRouter else ignore
939 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
940 Optional<Routers> routerData =
941 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
942 LogicalDatastoreType.CONFIGURATION, extRoutersId);
943 if (!routerData.isPresent()) {
944 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP del for router {} since its not External Router",
949 //Check if the DPN having the router is the NAPT switch
950 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
951 if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptId.equals(dpnId)) {
952 LOG.warn("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring TEP delete for the DPN {} since"
953 + " its NOT a NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
954 + "TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
957 if (natMode == NatMode.Conntrack) {
958 natServiceManager.notify(routerData.get(), naptId, dpnId, SnatServiceManager.Action.SNAT_ROUTER_DISBL);
962 Uuid networkId = routerData.get().getNetworkId();
963 if (networkId == null) {
964 LOG.error("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP delete for the DPN {} having the router {} "
965 + "since the Router instance {} not found in ExtRouters model b/w SRC IP {} and DST IP {} "
966 + "and TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
970 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
971 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
973 if (bgpVpnUuid == null) {
974 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
975 routerId, routerName);
978 //Install default entry in FIB to SNAT table
979 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on DPN {} for router {} with"
980 + " vpn {}...", dpnId, routerName, bgpVpnId);
981 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, writeFlowInvTx);
983 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
984 if (bgpVpnId == NatConstants.INVALID_ID) {
985 LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
989 LOG.debug("hndlTepDelForSnatInEachRtr :SNAT->External BGP VPN (Private BGP) {} associated to router {}",
990 bgpVpnId, routerName);
991 //Install default entry in FIB to SNAT table
992 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on dpn {} for routerId {} "
993 + "with vpnId {}...", dpnId, routerId, bgpVpnId);
994 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId, writeFlowInvTx);
997 if (routerData.get().isEnableSnat()) {
998 LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
1000 long routerVpnId = routerId;
1001 if (bgpVpnId != NatConstants.INVALID_ID) {
1002 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
1003 + "associated to the router {}", bgpVpnId, routerName);
1004 routerVpnId = bgpVpnId;
1006 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
1007 + "associated to the router {}", routerVpnId, routerName);
1009 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
1010 removeSNATFromDPN(dpnId, routerName, routerId, routerVpnId, networkId, extNwProvType, writeFlowInvTx);
1012 LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
1018 private void hndlTepDelForDnatInEachRtr(RoutersList router, long routerId, BigInteger tepDeletedDpnId,
1019 ProviderTypes extNwProvType, WriteTransaction writeFlowInvTx) {
1020 //DNAT : Withdraw the routes from the BGP
1021 String routerName = router.getRouter();
1023 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Trying to clear routes to the Floating IP "
1024 + "associated to the router {}", routerName);
1026 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
1027 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
1028 .CONFIGURATION, routerPortsId);
1029 if (!optRouterPorts.isPresent()) {
1030 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
1031 + "from DNAT FloatingIpInfo", routerName);
1034 RouterPorts routerPorts = optRouterPorts.get();
1035 Uuid extNwId = routerPorts.getExternalNetworkId();
1036 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId);
1037 if (vpnName == null) {
1038 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> No External VPN associated with Ext N/W {} for Router {}",
1039 extNwId, routerName);
1042 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1043 if (extNwProvType == null) {
1047 if (extNwProvType == ProviderTypes.VXLAN) {
1048 //get l3Vni value for external VPN
1049 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
1050 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
1051 LOG.debug("hndlTepDelForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
1052 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
1053 + "NAT flows", vpnName, rd);
1054 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
1057 List<Ports> interfaces = routerPorts.getPorts();
1058 for (Ports port : interfaces) {
1059 //Get the DPN on which this interface resides
1060 String interfaceName = port.getPortName();
1061 BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
1062 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
1063 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Abort processing Floating ip configuration. "
1064 + "No DPN for port : {}", interfaceName);
1067 if (!fipCfgdDpnId.equals(tepDeletedDpnId)) {
1068 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> TEP deleted DPN {} is not the DPN {} which has the "
1069 + "floating IP configured for the port: {}",
1070 tepDeletedDpnId, fipCfgdDpnId, interfaceName);
1073 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
1074 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
1075 String internalIp = intExtPortMap.getInternalIp();
1076 String externalIp = intExtPortMap.getExternalIp();
1077 externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1078 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Withdrawing the FIB route to the floating IP {} "
1079 + "configured for the port: {}",
1080 externalIp, interfaceName);
1081 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, vpnName, LOG);
1083 if (extNwProvType == ProviderTypes.VXLAN) {
1086 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
1087 if (label == NatConstants.INVALID_ID) {
1088 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Unable to remove the table 21 entry pushing the"
1089 + " MPLS label to the tunnel since label is invalid");
1095 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
1096 .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
1097 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
1098 Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
1099 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
1101 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
1104 public void onFailure(@Nonnull Throwable error) {
1105 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in removing the table 21 entry pushing "
1106 + "the MPLS label to the tunnel since label is invalid ", error);
1110 public void onSuccess(@Nonnull RpcResult<Void> result) {
1111 if (result.isSuccessful()) {
1112 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Successfully removed the entry pushing the "
1113 + "MPLS label to the tunnel");
1115 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in fib rpc call to remove the table "
1116 + "21 entry pushing the MPLS label to the tunnnel due to {}", result.getErrors());
1119 }, MoreExecutors.directExecutor());
1124 protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
1125 String ifaceName = stateTunnelList.getTunnelInterfaceName();
1126 if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
1127 Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
1128 IfTunnel ifTunnel = configIface != null ? configIface.getAugmentation(IfTunnel.class) : null;
1129 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
1130 ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
1131 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
1132 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
1136 LOG.trace("isTunnelInLogicalGroup: ignoring the tunnel event for {}", ifaceName);