2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.natservice.internal;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Strings;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.JdkFutureAdapters;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.concurrent.Future;
23 import javax.annotation.PostConstruct;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
30 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.mdsalutil.BucketInfo;
33 import org.opendaylight.genius.mdsalutil.FlowEntity;
34 import org.opendaylight.genius.mdsalutil.GroupEntity;
35 import org.opendaylight.genius.mdsalutil.MDSALUtil;
36 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
37 import org.opendaylight.genius.mdsalutil.NwConstants;
38 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
39 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
42 import org.opendaylight.netvirt.elanmanager.api.IElanService;
43 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
44 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
45 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.common.RpcResult;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
80 public class NatTunnelInterfaceStateListener
81 extends AsyncDataTreeChangeListenerBase<StateTunnelList, NatTunnelInterfaceStateListener>
82 implements AutoCloseable {
84 private static final Logger LOG = LoggerFactory.getLogger(NatTunnelInterfaceStateListener.class);
85 private final DataBroker dataBroker;
86 private final IFibManager fibManager;
87 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
88 private final NaptSwitchHA naptSwitchHA;
89 private final IMdsalApiManager mdsalManager;
90 private final IdManagerService idManager;
91 private final IBgpManager bgpManager;
92 private final ExternalRoutersListener externalRouterListner;
93 private final SnatServiceManager natServiceManager;
94 private final OdlInterfaceRpcService interfaceService;
95 private final FloatingIPListener floatingIPListener;
96 private final FibRpcService fibRpcService;
97 private final IElanService elanManager;
98 private final IInterfaceManager interfaceManager;
99 private NatMode natMode = NatMode.Controller;
101 protected enum TunnelAction {
108 * Responsible for listening to tunnel interface state change.
110 * @param dataBroker - dataBroker service reference
111 * @param bgpManager Used to advertise routes to the BGP Router
112 * @param fibManager - FIB Manager
113 * @param defaultRouteProgrammer - Default Route Programmer
114 * @param naptSwitchHA - NAPT Switch HA
115 * @param mdsalManager - MDSAL Manager
116 * @param idManager - ID manager
117 * @param externalRouterListner - External Router Listner
118 * @param interfaceService - Interface Service
119 * @param floatingIPListener - Floating IP Listner
120 * @param fibRpcService - FIB RPC Service
121 * @param elanManager - Elan Manager
124 public NatTunnelInterfaceStateListener(final DataBroker dataBroker,
125 final IBgpManager bgpManager,
126 final IFibManager fibManager,
127 final SNATDefaultRouteProgrammer defaultRouteProgrammer,
128 final NaptSwitchHA naptSwitchHA,
129 final IMdsalApiManager mdsalManager,
130 final IdManagerService idManager,
131 final ExternalRoutersListener externalRouterListner,
132 final SnatServiceManager natServiceManager,
133 final OdlInterfaceRpcService interfaceService,
134 final FloatingIPListener floatingIPListener,
135 final FibRpcService fibRpcService,
136 final NatserviceConfig config,
137 final IElanService elanManager,
138 final IInterfaceManager interfaceManager) {
139 super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
140 this.dataBroker = dataBroker;
141 this.bgpManager = bgpManager;
142 this.fibManager = fibManager;
143 this.defaultRouteProgrammer = defaultRouteProgrammer;
144 this.naptSwitchHA = naptSwitchHA;
145 this.mdsalManager = mdsalManager;
146 this.idManager = idManager;
147 this.externalRouterListner = externalRouterListner;
148 this.natServiceManager = natServiceManager;
149 this.interfaceService = interfaceService;
150 this.floatingIPListener = floatingIPListener;
151 this.fibRpcService = fibRpcService;
152 this.elanManager = elanManager;
153 this.interfaceManager = interfaceManager;
154 if (config != null) {
155 this.natMode = config.getNatMode();
162 LOG.info("{} init", getClass().getSimpleName());
163 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
167 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
168 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
172 protected NatTunnelInterfaceStateListener getDataTreeChangeListener() {
173 return NatTunnelInterfaceStateListener.this;
177 protected void add(InstanceIdentifier<StateTunnelList> instanceIdentifier, StateTunnelList add) {
178 LOG.trace("NAT Service : TEP addtion---- {}", add);
179 hndlTepEvntsForDpn(add, TunnelAction.TUNNEL_EP_ADD);
183 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
184 LOG.trace("NAT Service : TEP deletion---- {}", del);
185 hndlTepEvntsForDpn(del, TunnelAction.TUNNEL_EP_DELETE);
189 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
190 StateTunnelList update) {
191 LOG.trace("NAT Service : Tunnel updation---- {}", update);
192 //UPDATE IS A SEQUENCE OF DELETE AND ADD EVENTS . DELETE MIGHT HAVE CHANGED THE PRIMARY AND ADVERTISED. SO
196 private int getTunnelType(StateTunnelList stateTunnelList) {
198 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
199 tunTypeVal = NatConstants.ITMTunnelLocType.Internal.getValue();
200 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
201 tunTypeVal = NatConstants.ITMTunnelLocType.External.getValue();
202 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
203 tunTypeVal = NatConstants.ITMTunnelLocType.Hwvtep.getValue();
205 tunTypeVal = NatConstants.ITMTunnelLocType.Invalid.getValue();
210 // TODO Clean up the exception handling
211 @SuppressWarnings("checkstyle:IllegalCatch")
212 void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerVpnId, Uuid networkId) {
213 //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
214 //remove miss entry to NAPT switch
215 //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
217 //get ExternalIpIn prior
218 List<String> externalIpCache;
220 HashMap<String, Long> externalIpLabel;
221 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
222 if (routerId == NatConstants.INVALID_ID) {
223 LOG.error("NAT Service : SNAT -> Invalid routerId returned for routerName {}", routerName);
226 externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
227 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
228 if (extNwProvType == null) {
231 if (extNwProvType == ProviderTypes.VXLAN) {
232 externalIpLabel = null;
234 externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
237 final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
238 if (externalVpnName == null) {
239 LOG.error("NAT Service : SNAT -> No VPN associated with ext nw {} in router {}",
240 networkId, routerId);
244 BigInteger naptSwitch = dpnId;
246 naptSwitchHA.isNaptSwitchDown(routerName, dpnId, naptSwitch, routerVpnId, externalIpCache, false);
248 LOG.debug("NAT Service : SNAT -> NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
250 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
251 FlowEntity flowEntity = null;
253 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
254 routerVpnId, NatConstants.DEL_FLOW);
255 if (flowEntity == null) {
256 LOG.debug("NAT Service : SNAT -> Failed to populate flowentity for "
257 + "router {} with dpnId {} groupIs {}", routerName, dpnId, groupId);
260 LOG.debug("NAT Service : SNAT -> Removing default SNAT miss entry flow entity {}", flowEntity);
261 mdsalManager.removeFlow(flowEntity);
263 } catch (Exception ex) {
264 LOG.debug("NAT Service : SNAT -> Failed to remove default SNAT miss entry flow entity {} : {}",
268 LOG.debug("NAT Service : SNAT -> Removed default SNAT miss entry flow for dpnID {} with routername {}",
272 GroupEntity groupEntity = null;
274 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
275 GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
276 LOG.info("NAT Service : SNAT -> Removing NAPT GroupEntity:{} on Dpn {}", groupEntity, dpnId);
277 mdsalManager.removeGroup(groupEntity);
278 } catch (Exception ex) {
279 LOG.debug("NAT Service : SNAT -> Failed to remove group entity {} : {}", groupEntity, ex);
282 LOG.debug("NAT Service : SNAT -> Removed default SNAT miss entry flow for dpnID {} with routerName {}",
285 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, dpnId, externalIpLabel);
286 //remove table 26 flow ppointing to table46
287 FlowEntity flowEntity = null;
289 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
290 NatConstants.DEL_FLOW);
291 if (flowEntity == null) {
292 LOG.debug("NAT Service : SNAT -> Failed to populate flowentity for router {} with dpnId {}",
296 LOG.debug("NAT Service : SNAT -> Removing default SNAT miss entry flow entity for "
297 + "router {} with dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
298 mdsalManager.removeFlow(flowEntity);
300 } catch (Exception ex) {
301 LOG.debug("NAT Service : SNAT -> Failed to remove default SNAT miss entry flow entity {} : {}",
305 LOG.debug("NAT Service : SNAT -> Removed default SNAT miss entry flow for dpnID {} with routername {}",
308 //best effort to check IntExt model
309 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel);
311 } catch (Exception ex) {
312 LOG.debug("NAT Service : SNAT -> Exception while handling naptSwitch down for router {} : {}",
317 // TODO Clean up the exception handling
318 @SuppressWarnings("checkstyle:IllegalCatch")
319 private void hndlTepEvntsForDpn(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
320 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
321 final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
322 final String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
323 LOG.trace("NAT Service : Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ", srcDpnId, srcTepIp,
325 int tunTypeVal = getTunnelType(stateTunnelList);
326 LOG.trace("NAT Service : tunTypeVal is {}", tunTypeVal);
328 String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId();
329 String tunnelType = stateTunnelList.getTransportType().toString();
330 String tunnelName = stateTunnelList.getTunnelInterfaceName();
332 if (tunTypeVal == NatConstants.ITMTunnelLocType.Invalid.getValue()) {
333 LOG.warn("NAT Service : Ignoring TEP event {} for the DPN {} "
334 + "since its a INVALID TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and " + "TUNNEL NAME {} ",
335 tunnelAction, srcTepId, tunnelType, srcTepIp, destTepIp, tunnelName);
339 switch (tunnelAction) {
341 if (isTunnelInLogicalGroup(stateTunnelList)
342 || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp)) {
343 LOG.debug("NAT Service : Unable to process TEP ADD");
346 case TUNNEL_EP_DELETE:
347 if (!handleTepDelForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp)) {
348 LOG.debug("NAT Service : Unable to process TEP DEL");
352 LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
355 } catch (Exception e) {
356 LOG.error("NAT Service : Unable to handle the TEP event.", e);
361 private boolean hndlTepAddForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
362 String destTepIp) throws Exception {
363 LOG.trace("NAT Service: TEP ADD ----- for EXTERNAL/HWVTEP ITM Tunnel, TYPE {} ,State is UP b/w SRC IP"
364 + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
366 InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
367 Optional<DpnRoutersList> optionalRouterDpnList =
368 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
369 LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
370 if (!optionalRouterDpnList.isPresent()) {
371 LOG.warn("NAT Service : RouterDpnList model is empty for DPN {}. Hence ignoring TEP add event for the ITM "
372 + "TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
373 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
377 List<RoutersList> routersList = optionalRouterDpnList.get().getRoutersList();
378 if (routersList == null) {
379 LOG.debug("NAT Service : Ignoring TEP add for the DPN {} since no routers are associated"
380 + " for the DPN having the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
381 + "TUNNEL NAME {} ", srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
385 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
386 for (RoutersList router : routersList) {
388 LOG.debug("NAT Service : TEP ADD : DNAT -> Advertising routes for router {} ", router.getRouter());
389 hndlTepAddForDnatInEachRtr(router, nextHopIp, srcDpnId);
391 LOG.debug("NAT Service : TEP ADD : SNAT -> Advertising routes for router {} ", router.getRouter());
392 hndlTepAddForSnatInEachRtr(router, srcDpnId, tunnelType, srcTepIp, destTepIp,
393 tunnelName, nextHopIp);
398 // TODO Clean up the exception handling
399 @SuppressWarnings("checkstyle:IllegalCatch")
400 private boolean handleTepDelForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
401 String destTepIp) throws Exception {
403 LOG.trace("NAT Service: TEP DEL ----- for EXTERNAL/HWVTEP ITM Tunnel, TYPE {} ,State is UP b/w SRC IP"
404 + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
406 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
407 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
408 // Handle only the DPN on which it was deleted , ignore other event.
409 // DPN on which TEP is deleted , endpoint IP will be null.
410 String endpointIpForDPN = null;
412 endpointIpForDPN = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
413 } catch (Exception e) {
414 /* this dpn does not have the VTEP */
415 LOG.debug("NAT Service : DPN {} does not have the VTEP", srcDpnId);
416 endpointIpForDPN = null;
419 if (endpointIpForDPN != null) {
420 LOG.trace("NAT Service : Ignore TEP DELETE event received for DPN {} VTEP IP {} since its "
421 + "the other end DPN w.r.t the delted TEP", srcDpnId, srcTepIp);
425 List<RoutersList> routersList = null;
426 InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
427 Optional<DpnRoutersList> optionalRouterDpnList =
428 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
429 LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
430 if (optionalRouterDpnList.isPresent()) {
431 routersList = optionalRouterDpnList.get().getRoutersList();
433 LOG.warn("NAT Service : RouterDpnList is empty for DPN {}. Hence ignoring TEP DEL event for the ITM "
434 + "TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
435 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
439 if (routersList == null) {
440 LOG.debug("NAT Service : DPN {} does not have the Routers presence", srcDpnId);
444 for (RoutersList router : routersList) {
445 LOG.debug("NAT Service : TEP DEL : DNAT -> Withdrawing routes for router {} ", router.getRouter());
446 hndlTepDelForDnatInEachRtr(router, srcDpnId);
447 LOG.debug("NAT Service : TEP DEL : SNAT -> Withdrawing and Advertising routes for router {} ",
449 hndlTepDelForSnatInEachRtr(router, srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
454 private void hndlTepAddForSnatInEachRtr(RoutersList router, final BigInteger srcDpnId, String tunnelType,
455 String srcTepIp, String destTepIp, String tunnelName, String nextHopIp) {
457 /*SNAT : Remove the old routes to the external IP having the old TEP IP as the next hop IP
458 Advertise to the BGP about the new route to the external IP having the new TEP IP
459 added as the next hop IP
461 String routerName = router.getRouter();
463 // Check if this is externalRouter else ignore
464 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
465 Optional<Routers> routerData =
466 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
467 LogicalDatastoreType.CONFIGURATION, extRoutersId);
468 if (!routerData.isPresent()) {
469 LOG.debug("NAT Service : SNAT -> Ignoring TEP add for router {} since its not External Router",
474 long routerId = NatUtil.getVpnId(dataBroker, routerName);
475 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
476 if (naptId == null || naptId.equals(BigInteger.ZERO)) {
477 LOG.warn("NAT Service : SNAT -> Ignoring TEP add for the DPN {} having the router {} since"
478 + " the router is not part of the NAT service - the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
479 + "TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
482 if (natMode == NatMode.Conntrack) {
483 natServiceManager.notify(routerData.get(), naptId, srcDpnId,
484 SnatServiceManager.Action.SNAT_ROUTER_ENBL);
486 //Check if the DPN having the router is the NAPT switch
487 if (!naptId.equals(srcDpnId)) {
489 1) Install default NAT rule from table 21 to 26
490 2) Install the group which forward packet to the tunnel port for the NAPT switch.
491 3) Install the flow 26 which forwards the packet to the group.
493 if (!hndlTepAddOnNonNaptSwitch(srcDpnId, naptId, tunnelType, srcTepIp, destTepIp, tunnelName,
494 routerName, routerId)) {
495 LOG.debug("NAT Service : Unable to process the TEP add event on NON-NAPT switch {}", srcDpnId);
500 if (!hndlTepAddOnNaptSwitch(srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName, routerId,
501 routerData, nextHopIp)) {
502 LOG.debug("NAT Service : Unable to process the TEP add event on NAPT switch {}", srcDpnId);
509 private boolean hndlTepAddOnNonNaptSwitch(BigInteger srcDpnId, BigInteger primaryDpnId, String tunnelType,
510 String srcTepIp, String destTepIp, String tunnelName, String routerName,
514 1) Install default NAT rule from table 21 to 26
515 2) Install the group which forward packet to the tunnel port for the NAPT switch.
516 3) Install the flow 26 which forwards the packet to the group.
518 LOG.debug("NAT Service : SNAT -> Processing TEP add for the DPN {} having the router {} since "
519 + "its THE NON NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
520 + "and TUNNEL NAME {} ",
521 srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
522 LOG.debug("NAT Service : SNAT -> Install default NAT rule from table 21 to 26");
523 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
525 if (vpnName == null) {
526 LOG.debug("NAT Service : SNAT -> Internal VPN associated to router {}", routerId);
528 if (vpnId == NatConstants.INVALID_ID) {
529 LOG.error("NAT Service : SNAT -> Invalid Internal VPN ID returned for routerName {}", routerId);
532 LOG.debug("NAT Service : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerName);
533 //Install default entry in FIB to SNAT table
534 LOG.debug("NAT Service : Installing default route in FIB on DPN {} for router {} with"
535 + " vpn {}...", srcDpnId, routerName, vpnId);
536 defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId);
538 LOG.debug("NAT Service : SNAT -> Install the group which forward packet to the tunnel port "
539 + "for the NAPT switch {} and the flow 26 which forwards to group", primaryDpnId);
540 externalRouterListner.handleSwitches(srcDpnId, routerName, primaryDpnId);
542 LOG.debug("NAT Service : SNAT -> External BGP VPN (Private BGP) associated to router {}", routerId);
543 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
544 if (vpnId == NatConstants.INVALID_ID) {
545 LOG.error("NAT Service : SNAT -> Invalid Private BGP VPN ID returned for routerName {}", routerId);
548 if (routerId == NatConstants.INVALID_ID) {
549 LOG.error("NAT Service : SNAT -> Invalid routId returned for routerName {}", routerId);
552 LOG.debug("NAT Service : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
553 //Install default entry in FIB to SNAT table
554 LOG.debug("NAT Service : Installing default route in FIB on dpn {} for routerId {} "
555 + "with vpnId {}...", srcDpnId, routerId, vpnId);
556 defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, routerId);
558 LOG.debug("NAT Service : Install group in non NAPT switch {} for router {}", srcDpnId, routerName);
559 List<BucketInfo> bucketInfoForNonNaptSwitches =
560 externalRouterListner.getBucketInfoForNonNaptSwitches(srcDpnId, primaryDpnId, routerName);
561 long groupId = externalRouterListner.installGroup(srcDpnId, routerName, bucketInfoForNonNaptSwitches);
563 LOG.debug("NAT Service : SNAT -> in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
564 vpnId, groupId, srcDpnId);
565 FlowEntity flowEntity =
566 externalRouterListner.buildSnatFlowEntityWithUpdatedVpnId(srcDpnId, routerName, groupId, vpnId);
567 mdsalManager.installFlow(flowEntity);
572 private boolean hndlTepAddOnNaptSwitch(BigInteger srcDpnId, String tunnelType, String srcTepIp,
573 String destTepIp, String tunnelName, long routerId,
574 Optional<Routers> routerData, String nextHopIp) {
575 if (!routerData.isPresent()) {
576 LOG.warn("hndlTepAddOnNaptSwitch: routerData is not present");
579 Routers router = routerData.get();
580 String routerName = router.getRouterName();
581 LOG.debug("NAT Service : SNAT -> Processing TEP add for the DPN {} having the router {} since "
582 + "its THE NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
583 + "and TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
585 Uuid networkId = router.getNetworkId();
586 if (networkId == null) {
587 LOG.warn("NAT Service : SNAT -> Ignoring TEP add since the router {} is not associated to the "
588 + "external network", routerName);
592 LOG.debug("NAT Service : SNAT -> Router {} is associated with Ext nw {}", routerId, networkId);
593 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
595 if (vpnName == null) {
596 LOG.debug("NAT Service : SNAT -> Internal VPN associated to router {}", routerId);
597 vpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
598 if (vpnId == NatConstants.INVALID_ID) {
599 LOG.error("Invalid External VPN-ID returned for routerName {}", routerName);
602 LOG.debug("NAT Service : SNAT -> Retrieved External VPN-ID {} for router {}", vpnId, routerId);
604 LOG.debug("NAT Service : SNAT -> Private BGP VPN associated to router {}", routerId);
605 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
606 if (vpnId == null || vpnId == NatConstants.INVALID_ID) {
607 LOG.error("NAT Service : Invalid vpnId returned for routerName {}", routerName);
610 LOG.debug("NAT Service : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
613 /*1) Withdraw the old route to the external IP from the BGP which was having the
614 next hop as the old TEP IP.
615 2) Advertise to the BGP about the new route to the external IP having the
616 new TEP IP as the next hop.
617 3) Populate a new FIB entry with the next hop IP as the new TEP IP using the
621 //Withdraw the old route to the external IP from the BGP which was having the
622 //next hop as the old TEP IP.
623 final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
624 if (externalVpnName == null) {
625 LOG.error("NAT Service : SNAT -> No VPN associated with ext nw {} in router {}",
626 networkId, routerId);
629 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
630 if (externalIps != null) {
631 LOG.debug("NAT Service : Clearing the FIB entries but not the BGP routes");
632 for (String externalIp : externalIps) {
633 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
634 LOG.debug("NAT Service : Removing Fib entry rd {} prefix {}", rd, externalIp);
635 fibManager.removeFibEntry(dataBroker, rd, externalIp, null);
640 Advertise to the BGP about the new route to the external IP having the
641 new TEP IP as the next hop.
642 Populate a new FIB entry with the next hop IP as the new TEP IP using the
645 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
646 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
647 if (extNwProvType == null) {
650 String gwMacAddress = null;
652 WriteTransaction writeTx = null;
653 if (extNwProvType == ProviderTypes.VXLAN) {
654 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
655 gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
656 //get l3Vni value for external VPN
657 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
658 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
659 LOG.debug("NAT Service : L3VNI value is not configured in Internet VPN {} and RD {} "
660 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
661 + "NAT flows", vpnName, rd);
662 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, routerId).longValue();
664 //Create writeTx Object
665 writeTx = dataBroker.newWriteOnlyTransaction();
667 if (externalIps != null) {
668 for (final String externalIp : externalIps) {
670 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
671 if (extNwProvType == ProviderTypes.VXLAN) {
672 LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
673 externalIp, nextHopIp);
674 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, externalVpnName, rd,
675 externalIp, nextHopIp, l3Vni, tunnelName, gwMacAddress, writeTx, RouteOrigin.STATIC,
680 Long label = externalRouterListner.checkExternalIpLabel(routerId,
682 if (label == null || label == NatConstants.INVALID_ID) {
683 LOG.debug("NAT Service : SNAT -> Unable to advertise to the DC GW since label is invalid");
686 LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
687 externalIp, nextHopIp);
689 if (elanManager.isOpenStackVniSemanticsEnforced()) {
690 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, l3vni).longValue();
692 Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIp,
694 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalSubnetId,
695 fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni, LOG,
696 RouteOrigin.STATIC, srcDpnId);
700 LOG.debug("NAT Service : SNAT -> Install custom FIB routes "
701 + "(Table 21 -> Push MPLS label to Tunnel port");
702 List<Instruction> customInstructions = new ArrayList<>();
703 int customInstructionIndex = 0;
704 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIp,
706 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
707 LOG.debug("NAT Service : Will install custom FIB router with external subnet VPN ID {}",
708 externalSubnetVpnId);
709 BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
710 customInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
711 MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(customInstructionIndex));
712 customInstructionIndex++;
714 customInstructions.add(new InstructionGotoTable(NwConstants.INBOUND_NAPT_TABLE)
715 .buildInstruction(customInstructionIndex));
716 CreateFibEntryInput input =
717 new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
718 .setInstruction(customInstructions).setIpAddress(fibExternalIp)
719 .setServiceId(serviceId).setInstruction(customInstructions).build();
720 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
721 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
723 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
726 public void onFailure(Throwable error) {
727 LOG.error("NAT Service : SNAT -> Error in generate label or fib install process", error);
731 public void onSuccess(RpcResult<Void> result) {
732 if (result.isSuccessful()) {
733 LOG.info("NAT Service : SNAT -> Successfully installed custom FIB routes for prefix {}",
736 LOG.error("NAT Service : SNAT -> Error in rpc call to create custom Fib entries "
737 + "for prefix {} in DPN {}, {}",
738 externalIp, srcDpnId, result.getErrors());
743 if (writeTx != null) {
750 private void hndlTepAddForDnatInEachRtr(RoutersList router, String nextHopIp, BigInteger tepAddedDpnId) {
751 //DNAT : Advertise the new route to the floating IP having the new TEP IP as the next hop IP
752 final String routerName = router.getRouter();
754 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
755 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
756 .CONFIGURATION, routerPortsId);
757 if (!optRouterPorts.isPresent()) {
758 LOG.debug("NAT Service : DNAT -> Could not read Router Ports data object with id: {} from DNAT "
759 + "FloatinIpInfo", routerName);
762 RouterPorts routerPorts = optRouterPorts.get();
763 Uuid extNwId = routerPorts.getExternalNetworkId();
764 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
765 if (vpnName == null) {
766 LOG.info("NAT Service : DNAT -> No External VPN associated with ext nw {} for router {}",
767 extNwId, routerName);
771 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
772 long routerId = NatUtil.getVpnId(dataBroker, routerName);
773 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
774 if (extNwProvType == null) {
777 String gwMacAddress = null;
779 WriteTransaction writeTx = null;
780 if (extNwProvType == ProviderTypes.VXLAN) {
781 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
782 gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
783 //get l3Vni value for external VPN
784 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
785 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
786 LOG.debug("NAT Service : L3VNI value is not configured in Internet VPN {} and RD {} "
787 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
788 + "NAT flows", vpnName, rd);
789 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
791 //Create writeTx Object
792 writeTx = dataBroker.newWriteOnlyTransaction();
794 List<Ports> interfaces = routerPorts.getPorts();
795 for (Ports port : interfaces) {
796 //Get the DPN on which this interface resides
797 final String interfaceName = port.getPortName();
798 final BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
799 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
800 LOG.info("NAT Service : DNAT -> Skip processing Floating ip configuration for the port {}, "
801 + "since no DPN present for it", interfaceName);
804 if (!fipCfgdDpnId.equals(tepAddedDpnId)) {
805 LOG.debug("NAT Service : DNAT -> TEP added DPN {} is not the DPN {} which has the "
806 + "floating IP configured for the port: {}",
807 tepAddedDpnId, fipCfgdDpnId, interfaceName);
810 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
811 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
812 final String internalIp = intExtPortMap.getInternalIp();
813 final String externalIp = intExtPortMap.getExternalIp();
814 LOG.debug("NAT Service : DNAT -> Advertising the FIB route to the floating IP {} configured "
815 + "for the port: {}",
816 externalIp, interfaceName);
818 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
820 if (extNwProvType == ProviderTypes.VXLAN) {
821 LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
822 externalIp, nextHopIp);
823 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
824 externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, writeTx, RouteOrigin.STATIC,
828 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
829 if (label == NatConstants.INVALID_ID) {
830 LOG.debug("NAT Service : DNAT -> Unable to advertise to the DC GW since label is invalid");
833 LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
834 externalIp, nextHopIp);
836 if (elanManager.isOpenStackVniSemanticsEnforced()) {
837 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
839 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
840 fibExternalIp, nextHopIp, null, null, label, l3vni, LOG, RouteOrigin.STATIC,
845 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
846 List<Instruction> customInstructions = new ArrayList<>();
847 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
848 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
849 .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
850 .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
852 Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
853 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
855 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
858 public void onFailure(Throwable error) {
859 LOG.error("NAT Service : DNAT -> Error in generate label or fib install process", error);
863 public void onSuccess(RpcResult<Void> result) {
864 if (result.isSuccessful()) {
865 LOG.info("NAT Service : DNAT -> Successfully installed custom FIB routes for prefix {}",
868 LOG.error("NAT Service : DNAT -> Error in rpc call to create custom Fib "
869 + "entries for prefix {} in DPN {}, {}", externalIp, fipCfgdDpnId, result.getErrors());
874 if (writeTx != null) {
880 private void hndlTepDelForSnatInEachRtr(RoutersList router, BigInteger dpnId, String tunnelType,
881 String srcTepIp, String destTepIp, String tunnelName) {
883 1) Elect a new switch as the primary NAPT
884 2) Advertise the new routes to BGP for the newly elected TEP IP as the DPN IP
885 3) This will make sure old routes are withdrawn and new routes are advertised.
888 String routerName = router.getRouter();
889 LOG.debug("NAT Service : SNAT -> Trying to clear routes to the External fixed IP associated to the router"
890 + " {}", routerName);
892 // Check if this is externalRouter else ignore
893 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
894 Optional<Routers> routerData =
895 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
896 LogicalDatastoreType.CONFIGURATION, extRoutersId);
897 if (!routerData.isPresent()) {
898 LOG.debug("NAT Service : SNAT -> Ignoring TEP del for router {} since its not External Router",
903 //Check if the router ID is valid
904 long routerId = NatUtil.getVpnId(dataBroker, routerName);
905 if (routerId == NatConstants.INVALID_ID) {
906 LOG.error("NAT Service : SNAT -> Invalid ROUTER-ID {} returned for routerName {}", routerId, routerName);
910 //Check if the DPN having the router is the NAPT switch
911 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
912 if (naptId == null || naptId.equals(BigInteger.ZERO) || (!naptId.equals(dpnId))) {
913 LOG.warn("NAT Service : SNAT -> Ignoring TEP delete for the DPN {} since"
914 + " its NOT a NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
915 + "TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
918 if (natMode == NatMode.Conntrack) {
919 natServiceManager.notify(routerData.get(), naptId, dpnId, SnatServiceManager.Action.SNAT_ROUTER_DISBL);
923 Uuid networkId = routerData.get().getNetworkId();
924 if (networkId == null) {
925 LOG.debug("NAT Service : SNAT -> Ignoring TEP delete for the DPN {} having the router {} "
926 + "since the Router instance {} not found in ExtRouters model b/w SRC IP {} and DST IP {} "
927 + "and TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
931 LOG.debug("NAT Service : SNAT -> Router {} is associated with ext nw {}", routerId, networkId);
932 Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerName);
934 if (vpnName == null) {
935 LOG.debug("NAT Service : SNAT -> Internal VPN-ID {} associated to router {}", routerId, routerName);
938 //Install default entry in FIB to SNAT table
939 LOG.debug("NAT Service : Installing default route in FIB on DPN {} for router {} with"
940 + " vpn {}...", dpnId, routerName, vpnId);
941 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
943 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
944 if (vpnId == NatConstants.INVALID_ID) {
945 LOG.error("NAT Service : SNAT -> Invalid Private BGP VPN ID returned for routerName {}",
949 LOG.debug("NAT Service : SNAT -> External BGP VPN (Private BGP) {} associated to router {}",
951 //Install default entry in FIB to SNAT table
952 LOG.debug("NAT Service : Installing default route in FIB on dpn {} for routerId {} "
953 + "with vpnId {}...", dpnId, routerId, vpnId);
954 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routerId);
957 if (routerData.get().isEnableSnat()) {
958 LOG.info("NAT Service : SNAT enabled for router {}", routerId);
960 long routerVpnId = routerId;
961 long bgpVpnId = NatConstants.INVALID_ID;
962 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
963 if (bgpVpnUuid != null) {
964 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
966 if (bgpVpnId != NatConstants.INVALID_ID) {
967 LOG.debug("NAT Service : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} associated "
968 + "to the router {}", bgpVpnId, routerName);
969 routerVpnId = bgpVpnId;
971 LOG.debug("NAT Service : SNAT -> Internal L3 VPN ID (Router ID) {} associated to the router {}",
972 routerVpnId, routerName);
974 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
975 removeSNATFromDPN(dpnId, routerName, routerVpnId, networkId);
977 LOG.info("NAT Service : SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
982 private void hndlTepDelForDnatInEachRtr(RoutersList router, BigInteger tepDeletedDpnId) {
983 //DNAT : Withdraw the routes from the BGP
984 String routerName = router.getRouter();
985 long routerId = NatUtil.getVpnId(dataBroker, routerName);
986 if (routerId == NatConstants.INVALID_ID) {
987 LOG.warn("Unable to get RouterId from RouterName {}", routerName);
990 LOG.debug("NAT Service : DNAT -> Trying to clear routes to the Floating IP associated to the router {}",
993 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
994 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
995 .CONFIGURATION, routerPortsId);
996 if (!optRouterPorts.isPresent()) {
997 LOG.debug("NAT Service : DNAT -> Could not read Router Ports data object with id: {} from DNAT "
1002 RouterPorts routerPorts = optRouterPorts.get();
1003 Uuid extNwId = routerPorts.getExternalNetworkId();
1004 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId, LOG);
1005 if (vpnName == null) {
1006 LOG.info("NAT Service : DNAT -> No External VPN associated with Ext N/W {} for Router {}",
1007 extNwId, routerName);
1010 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1011 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
1012 if (extNwProvType == null) {
1016 if (extNwProvType == ProviderTypes.VXLAN) {
1017 //get l3Vni value for external VPN
1018 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
1019 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
1020 LOG.debug("NAT Service : L3VNI value is not configured in Internet VPN {} and RD {} "
1021 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
1022 + "NAT flows", vpnName, rd);
1023 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
1026 List<Ports> interfaces = routerPorts.getPorts();
1027 for (Ports port : interfaces) {
1028 //Get the DPN on which this interface resides
1029 String interfaceName = port.getPortName();
1030 BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
1031 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
1032 LOG.info("NAT Service : DNAT -> Abort processing Floating ip configuration. No DPN for port : {}",
1036 if (!fipCfgdDpnId.equals(tepDeletedDpnId)) {
1037 LOG.info("NAT Service : DNAT -> TEP deleted DPN {} is not the DPN {} which has the "
1038 + "floating IP configured for the port: {}",
1039 tepDeletedDpnId, fipCfgdDpnId, interfaceName);
1042 List<InternalToExternalPortMap> intExtPortMapList = port.getInternalToExternalPortMap();
1043 for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
1044 String internalIp = intExtPortMap.getInternalIp();
1045 String externalIp = intExtPortMap.getExternalIp();
1046 externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1047 LOG.debug("NAT Service : DNAT -> Withdrawing the FIB route to the floating IP {} "
1048 + "configured for the port: {}",
1049 externalIp, interfaceName);
1050 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, vpnName, LOG);
1052 if (extNwProvType == ProviderTypes.VXLAN) {
1055 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
1056 if (label == NatConstants.INVALID_ID) {
1057 LOG.debug("NAT Service : DNAT -> Unable to remove the table 21 entry pushing the "
1058 + "MPLS label to the tunnel since label is invalid");
1064 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
1065 .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
1066 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
1067 Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
1068 ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
1070 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
1073 public void onFailure(Throwable error) {
1074 LOG.error("NAT Service : DNAT -> Error in removing the table 21 entry pushing "
1075 + "the MPLS label to the tunnel since label is invalid ", error);
1079 public void onSuccess(RpcResult<Void> result) {
1080 if (result.isSuccessful()) {
1081 LOG.info("NAT Service : DNAT -> Successfully removed the entry pushing the "
1082 + "MPLS label to the tunnel");
1084 LOG.error("NAT Service : DNAT -> Error in fib rpc call to remove the table 21 "
1085 + "entry pushing the MPLS label to the tunnnel due to {}", result.getErrors());
1093 protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
1094 String ifaceName = stateTunnelList.getTunnelInterfaceName();
1095 if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
1096 Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
1097 IfTunnel ifTunnel = (configIface != null) ? configIface.getAugmentation(IfTunnel.class) : null;
1098 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
1099 ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
1100 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
1101 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
1105 LOG.trace("MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);