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) {
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) {
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);
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);
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(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(externalIp, router);
739 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalSubnetId,
740 fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni,
741 RouteOrigin.STATIC, srcDpnId);
745 LOG.debug("hndlTepAddOnNaptSwitch: SNAT -> Install custom FIB routes "
746 + "(Table 21 -> Push MPLS label to Tunnel port");
747 List<Instruction> customInstructions = new ArrayList<>();
748 int customInstructionIndex = 0;
749 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIp,
751 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
752 LOG.debug("hndlTepAddOnNaptSwitch : Will install custom FIB router with external subnet VPN ID {}",
753 externalSubnetVpnId);
754 BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
755 customInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
756 MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(customInstructionIndex));
757 customInstructionIndex++;
759 customInstructions.add(new InstructionGotoTable(NwConstants.INBOUND_NAPT_TABLE)
760 .buildInstruction(customInstructionIndex));
761 CreateFibEntryInput input =
762 new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
763 .setInstruction(customInstructions).setIpAddress(fibExternalIp)
764 .setServiceId(serviceId).setInstruction(customInstructions).build();
765 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
766 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
768 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
771 public void onFailure(@Nonnull Throwable error) {
772 LOG.error("hndlTepAddOnNaptSwitch : SNAT->Error in generate label or fib install process",
777 public void onSuccess(@Nonnull RpcResult<Void> result) {
778 if (result.isSuccessful()) {
779 LOG.info("hndlTepAddOnNaptSwitch : SNAT -> Successfully installed custom FIB routes "
780 + "for prefix {}", externalIp);
782 LOG.error("hndlTepAddOnNaptSwitch : SNAT -> Error in rpc call to create custom Fib entries "
783 + "for prefix {} in DPN {}, {}", externalIp, srcDpnId, result.getErrors());
786 }, MoreExecutors.directExecutor());
792 private void hndlTepAddForDnatInEachRtr(RoutersList router, long routerId, String nextHopIp,
793 BigInteger tepAddedDpnId, ProviderTypes extNwProvType, WriteTransaction writeFlowInvTx) {
794 //DNAT : Advertise the new route to the floating IP having the new TEP IP as the next hop IP
795 final String routerName = router.getRouter();
797 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
798 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
799 .CONFIGURATION, routerPortsId);
800 if (!optRouterPorts.isPresent()) {
801 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
802 + "from DNAT FloatinIpInfo", routerName);
805 RouterPorts routerPorts = optRouterPorts.get();
806 Uuid extNwId = routerPorts.getExternalNetworkId();
807 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId);
808 if (vpnName == null) {
809 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> No External VPN associated with ext nw {} for router {}",
810 extNwId, routerName);
814 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
815 if (extNwProvType == null) {
818 String gwMacAddress = null;
820 if (extNwProvType == ProviderTypes.VXLAN) {
821 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
822 gwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
823 if (gwMacAddress != null) {
824 LOG.debug("hndlTepAddForDnatInEachRtr : External GwMAC address {} found for External Router ID {}",
825 gwMacAddress, routerId);
827 LOG.error("hndlTepAddForDnatInEachRtr : No External GwMAC address found for External Router ID {}",
831 //get l3Vni value for external VPN
832 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
833 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
834 LOG.debug("hndlTepAddForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
835 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
836 + "NAT flows", vpnName, rd);
837 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
840 List<Ports> interfaces = routerPorts.getPorts();
841 for (Ports port : interfaces) {
842 //Get the DPN on which this interface resides
843 final String interfaceName = port.getPortName();
844 final BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
845 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
846 LOG.info("hndlTepAddForDnatInEachRtr : DNAT->Skip processing Floating ip configuration for the port {},"
847 + "since no DPN present for it", interfaceName);
850 if (!fipCfgdDpnId.equals(tepAddedDpnId)) {
851 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> TEP added DPN {} is not the DPN {} which has the "
852 + "floating IP configured for the port: {}",
853 tepAddedDpnId, fipCfgdDpnId, interfaceName);
856 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
857 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
858 final String internalIp = intExtPortMap.getInternalIp();
859 final String externalIp = intExtPortMap.getExternalIp();
860 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertising the FIB route to the floating IP {} "
861 + "configured for the port: {}", externalIp, interfaceName);
863 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
865 if (extNwProvType == ProviderTypes.VXLAN) {
866 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
867 + "having nextHopIp {}", externalIp, nextHopIp);
868 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
869 externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, writeFlowInvTx,
870 RouteOrigin.STATIC, fipCfgdDpnId);
873 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
874 if (label == NatConstants.INVALID_ID) {
875 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Unable to advertise to the DC GW since label "
879 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
880 + "having nextHopIp {}", externalIp, nextHopIp);
882 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
883 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
885 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
886 fibExternalIp, nextHopIp, null, null, label, l3vni, RouteOrigin.STATIC,
891 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
892 List<Instruction> customInstructions = new ArrayList<>();
893 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
894 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
895 .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
896 .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
898 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
899 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
901 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
904 public void onFailure(@Nonnull Throwable error) {
905 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in generate label or fib install process",
910 public void onSuccess(@Nonnull RpcResult<Void> result) {
911 if (result.isSuccessful()) {
912 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> Successfully installed custom FIB routes "
913 + "for prefix {}", externalIp);
915 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in rpc call to create custom Fib "
916 + "entries for prefix {} in DPN {}, {}", externalIp, fipCfgdDpnId, result.getErrors());
919 }, MoreExecutors.directExecutor());
924 private void hndlTepDelForSnatInEachRtr(RoutersList router, long routerId, BigInteger dpnId, String tunnelType,
925 String srcTepIp, String destTepIp, String tunnelName,
926 ProviderTypes extNwProvType, WriteTransaction writeFlowInvTx) {
928 1) Elect a new switch as the primary NAPT
929 2) Advertise the new routes to BGP for the newly elected TEP IP as the DPN IP
930 3) This will make sure old routes are withdrawn and new routes are advertised.
933 String routerName = router.getRouter();
934 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Trying to clear routes to the External fixed IP associated "
935 + "to the router {}", routerName);
937 // Check if this is externalRouter else ignore
938 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
939 Optional<Routers> routerData =
940 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
941 LogicalDatastoreType.CONFIGURATION, extRoutersId);
942 if (!routerData.isPresent()) {
943 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP del for router {} since its not External Router",
948 //Check if the DPN having the router is the NAPT switch
949 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
950 if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptId.equals(dpnId)) {
951 LOG.warn("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring TEP delete for the DPN {} since"
952 + " its NOT a NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
953 + "TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
956 if (natMode == NatMode.Conntrack) {
957 natServiceManager.notify(routerData.get(), naptId, dpnId, SnatServiceManager.Action.SNAT_ROUTER_DISBL);
961 Uuid networkId = routerData.get().getNetworkId();
962 if (networkId == null) {
963 LOG.error("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP delete for the DPN {} having the router {} "
964 + "since the Router instance {} not found in ExtRouters model b/w SRC IP {} and DST IP {} "
965 + "and TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
969 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
970 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
972 if (bgpVpnUuid == null) {
973 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
974 routerId, routerName);
977 //Install default entry in FIB to SNAT table
978 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on DPN {} for router {} with"
979 + " vpn {}...", dpnId, routerName, bgpVpnId);
980 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, writeFlowInvTx);
982 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
983 if (bgpVpnId == NatConstants.INVALID_ID) {
984 LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
988 LOG.debug("hndlTepDelForSnatInEachRtr :SNAT->External BGP VPN (Private BGP) {} associated to router {}",
989 bgpVpnId, routerName);
990 //Install default entry in FIB to SNAT table
991 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on dpn {} for routerId {} "
992 + "with vpnId {}...", dpnId, routerId, bgpVpnId);
993 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId, writeFlowInvTx);
996 if (routerData.get().isEnableSnat()) {
997 LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
999 long routerVpnId = routerId;
1000 if (bgpVpnId != NatConstants.INVALID_ID) {
1001 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
1002 + "associated to the router {}", bgpVpnId, routerName);
1003 routerVpnId = bgpVpnId;
1005 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
1006 + "associated to the router {}", routerVpnId, routerName);
1008 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
1009 removeSNATFromDPN(dpnId, routerName, routerId, routerVpnId, networkId, extNwProvType, writeFlowInvTx);
1011 LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
1017 private void hndlTepDelForDnatInEachRtr(RoutersList router, long routerId, BigInteger tepDeletedDpnId,
1018 ProviderTypes extNwProvType) {
1019 //DNAT : Withdraw the routes from the BGP
1020 String routerName = router.getRouter();
1022 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Trying to clear routes to the Floating IP "
1023 + "associated to the router {}", routerName);
1025 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
1026 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
1027 .CONFIGURATION, routerPortsId);
1028 if (!optRouterPorts.isPresent()) {
1029 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
1030 + "from DNAT FloatingIpInfo", routerName);
1033 RouterPorts routerPorts = optRouterPorts.get();
1034 Uuid extNwId = routerPorts.getExternalNetworkId();
1035 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId);
1036 if (vpnName == null) {
1037 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> No External VPN associated with Ext N/W {} for Router {}",
1038 extNwId, routerName);
1041 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1042 if (extNwProvType == null) {
1046 if (extNwProvType == ProviderTypes.VXLAN) {
1047 //get l3Vni value for external VPN
1048 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
1049 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
1050 LOG.debug("hndlTepDelForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
1051 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
1052 + "NAT flows", vpnName, rd);
1053 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
1056 List<Ports> interfaces = routerPorts.getPorts();
1057 for (Ports port : interfaces) {
1058 //Get the DPN on which this interface resides
1059 String interfaceName = port.getPortName();
1060 BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
1061 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
1062 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Abort processing Floating ip configuration. "
1063 + "No DPN for port : {}", interfaceName);
1066 if (!fipCfgdDpnId.equals(tepDeletedDpnId)) {
1067 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> TEP deleted DPN {} is not the DPN {} which has the "
1068 + "floating IP configured for the port: {}",
1069 tepDeletedDpnId, fipCfgdDpnId, interfaceName);
1072 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
1073 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
1074 String internalIp = intExtPortMap.getInternalIp();
1075 String externalIp = intExtPortMap.getExternalIp();
1076 externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1077 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Withdrawing the FIB route to the floating IP {} "
1078 + "configured for the port: {}",
1079 externalIp, interfaceName);
1080 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, externalIp, vpnName, LOG);
1082 if (extNwProvType == ProviderTypes.VXLAN) {
1085 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
1086 if (label == NatConstants.INVALID_ID) {
1087 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Unable to remove the table 21 entry pushing the"
1088 + " MPLS label to the tunnel since label is invalid");
1094 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
1095 .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
1096 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
1097 Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
1098 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
1100 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
1103 public void onFailure(@Nonnull Throwable error) {
1104 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in removing the table 21 entry pushing "
1105 + "the MPLS label to the tunnel since label is invalid ", error);
1109 public void onSuccess(@Nonnull RpcResult<Void> result) {
1110 if (result.isSuccessful()) {
1111 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Successfully removed the entry pushing the "
1112 + "MPLS label to the tunnel");
1114 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in fib rpc call to remove the table "
1115 + "21 entry pushing the MPLS label to the tunnnel due to {}", result.getErrors());
1118 }, MoreExecutors.directExecutor());
1123 protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
1124 String ifaceName = stateTunnelList.getTunnelInterfaceName();
1125 if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
1126 Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
1127 IfTunnel ifTunnel = configIface != null ? configIface.getAugmentation(IfTunnel.class) : null;
1128 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
1129 ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
1130 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
1131 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
1135 LOG.trace("isTunnelInLogicalGroup: ignoring the tunnel event for {}", ifaceName);