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 static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Strings;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import java.math.BigInteger;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.List;
24 import java.util.concurrent.ExecutionException;
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.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
32 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
33 import org.opendaylight.genius.infra.Datastore.Configuration;
34 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
35 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
36 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
37 import org.opendaylight.genius.infra.TypedWriteTransaction;
38 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
39 import org.opendaylight.genius.mdsalutil.BucketInfo;
40 import org.opendaylight.genius.mdsalutil.FlowEntity;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
45 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
46 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
47 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
48 import org.opendaylight.netvirt.elanmanager.api.IElanService;
49 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
50 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
51 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibEntryInputs;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryOutput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
82 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
83 import org.opendaylight.yangtools.yang.common.RpcResult;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
88 public class NatTunnelInterfaceStateListener
89 extends AsyncDataTreeChangeListenerBase<StateTunnelList, NatTunnelInterfaceStateListener> {
91 private static final Logger LOG = LoggerFactory.getLogger(NatTunnelInterfaceStateListener.class);
92 private final DataBroker dataBroker;
93 private final ManagedNewTransactionRunner txRunner;
94 private final IFibManager fibManager;
95 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
96 private final NaptSwitchHA naptSwitchHA;
97 private final IMdsalApiManager mdsalManager;
98 private final IdManagerService idManager;
99 private final IBgpManager bgpManager;
100 private final ExternalRoutersListener externalRouterListner;
101 private final SnatServiceManager natServiceManager;
102 private final OdlInterfaceRpcService interfaceService;
103 private final FloatingIPListener floatingIPListener;
104 private final FibRpcService fibRpcService;
105 private final IElanService elanManager;
106 private final IInterfaceManager interfaceManager;
107 private final NatOverVxlanUtil natOverVxlanUtil;
108 private final NatMode natMode;
110 protected enum TunnelAction {
117 * Responsible for listening to tunnel interface state change.
119 * @param dataBroker - dataBroker service reference
120 * @param bgpManager Used to advertise routes to the BGP Router
121 * @param fibManager - FIB Manager
122 * @param defaultRouteProgrammer - Default Route Programmer
123 * @param naptSwitchHA - NAPT Switch HA
124 * @param mdsalManager - MDSAL Manager
125 * @param idManager - ID manager
126 * @param externalRouterListner - External Router Listener
127 * @param natServiceManager - Nat Service Manager
128 * @param interfaceService - Interface Service
129 * @param floatingIPListener - Floating IP Listener
130 * @param fibRpcService - FIB RPC Service
131 * @param config - Nat Service Config
132 * @param elanManager - Elan Manager
133 * @param interfaceManager - Interface Manager
134 * @param natOverVxlanUtils - Nat Over Vxlan Utility
137 public NatTunnelInterfaceStateListener(final DataBroker dataBroker,
138 final IBgpManager bgpManager,
139 final IFibManager fibManager,
140 final SNATDefaultRouteProgrammer defaultRouteProgrammer,
141 final NaptSwitchHA naptSwitchHA,
142 final IMdsalApiManager mdsalManager,
143 final IdManagerService idManager,
144 final ExternalRoutersListener externalRouterListner,
145 final SnatServiceManager natServiceManager,
146 final OdlInterfaceRpcService interfaceService,
147 final FloatingIPListener floatingIPListener,
148 final FibRpcService fibRpcService,
149 final NatserviceConfig config,
150 final IElanService elanManager,
151 final IInterfaceManager interfaceManager,
152 final NatOverVxlanUtil natOverVxlanUtils) {
153 super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
154 this.dataBroker = dataBroker;
155 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
156 this.bgpManager = bgpManager;
157 this.fibManager = fibManager;
158 this.defaultRouteProgrammer = defaultRouteProgrammer;
159 this.naptSwitchHA = naptSwitchHA;
160 this.mdsalManager = mdsalManager;
161 this.idManager = idManager;
162 this.externalRouterListner = externalRouterListner;
163 this.natServiceManager = natServiceManager;
164 this.interfaceService = interfaceService;
165 this.floatingIPListener = floatingIPListener;
166 this.fibRpcService = fibRpcService;
167 this.elanManager = elanManager;
168 this.interfaceManager = interfaceManager;
169 this.natOverVxlanUtil = natOverVxlanUtils;
170 if (config != null) {
171 this.natMode = config.getNatMode();
173 this.natMode = NatMode.Controller;
180 LOG.info("{} init", getClass().getSimpleName());
181 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
185 protected InstanceIdentifier<StateTunnelList> getWildCardPath() {
186 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
190 protected NatTunnelInterfaceStateListener getDataTreeChangeListener() {
191 return NatTunnelInterfaceStateListener.this;
195 protected void add(InstanceIdentifier<StateTunnelList> instanceIdentifier, StateTunnelList add) {
196 LOG.trace("add : TEP addtion---- {}", add);
197 hndlTepEvntsForDpn(add, TunnelAction.TUNNEL_EP_ADD);
201 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
202 LOG.trace("remove : TEP deletion---- {}", del);
203 hndlTepEvntsForDpn(del, TunnelAction.TUNNEL_EP_DELETE);
207 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original,
208 StateTunnelList update) {
209 LOG.trace("update : Tunnel updation---- {}", update);
210 //UPDATE IS A SEQUENCE OF DELETE AND ADD EVENTS . DELETE MIGHT HAVE CHANGED THE PRIMARY AND ADVERTISED. SO
214 private int getTunnelType(StateTunnelList stateTunnelList) {
216 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
217 tunTypeVal = NatConstants.ITMTunnelLocType.Internal.getValue();
218 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
219 tunTypeVal = NatConstants.ITMTunnelLocType.External.getValue();
220 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class) {
221 tunTypeVal = NatConstants.ITMTunnelLocType.Hwvtep.getValue();
223 tunTypeVal = NatConstants.ITMTunnelLocType.Invalid.getValue();
228 // TODO Clean up the exception handling
229 @SuppressWarnings("checkstyle:IllegalCatch")
230 void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerId, long routerVpnId,
231 Uuid networkId, ProviderTypes extNwProvType, TypedReadWriteTransaction<Configuration> confTx) {
232 //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
233 //remove miss entry to NAPT switch
234 //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
236 if (routerId == NatConstants.INVALID_ID) {
237 LOG.error("removeSNATFromDPN : SNAT -> Invalid routerId returned for routerName {}", routerName);
240 Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
241 if (extNwProvType == null) {
244 Map<String, Long> externalIpLabel;
245 if (extNwProvType == ProviderTypes.VXLAN) {
246 externalIpLabel = null;
248 externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
251 final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
252 if (externalVpnName == null) {
253 LOG.error("removeSNATFromDPN : SNAT -> No VPN associated with ext nw {} in router {}",
254 networkId, routerId);
258 BigInteger naptSwitch = dpnId;
260 naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch,
261 routerVpnId, externalIpCache, false, confTx);
263 LOG.debug("removeSNATFromDPN:SNAT->NaptSwitchDown:Switch with DpnId {} is not naptSwitch for router {}",
265 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
266 FlowEntity flowEntity = null;
268 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
269 routerVpnId, NatConstants.DEL_FLOW);
270 if (flowEntity == null) {
271 LOG.error("removeSNATFromDPN : SNAT -> Failed to populate flowentity for "
272 + "router {} with dpnId {} groupIs {}", routerName, dpnId, groupId);
275 LOG.debug("removeSNATFromDPN : SNAT->Removing default SNAT miss entry flow entity {}", flowEntity);
276 mdsalManager.removeFlow(confTx, flowEntity);
278 } catch (Exception ex) {
279 LOG.error("removeSNATFromDPN : SNAT->Failed to remove default SNAT miss entry flow entity {}",
283 LOG.debug("removeSNATFromDPN:SNAT->Removed default SNAT miss entry flow for dpnID {}, routername {}",
288 LOG.info("removeSNATFromDPN : SNAT->Removing NAPT Group :{} on Dpn {}", groupId, dpnId);
289 mdsalManager.removeGroup(confTx, dpnId, groupId);
290 } catch (Exception ex) {
291 LOG.error("removeSNATFromDPN : SNAT->Failed to remove group {}", groupId, ex);
294 LOG.debug("removeSNATFromDPN : SNAT->Removed default SNAT miss entry flow for dpnID {}, routerName {}",
297 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, dpnId, externalIpLabel, confTx);
298 //remove table 26 flow ppointing to table46
299 FlowEntity flowEntity = null;
301 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
302 NatConstants.DEL_FLOW);
303 if (flowEntity == null) {
304 LOG.error("removeSNATFromDPN : SNAT->Failed to populate flowentity for router {} with dpnId {}",
308 LOG.debug("removeSNATFromDPN : SNAT->Removing default SNAT miss entry flow entity for "
309 + "router {} with dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
310 mdsalManager.removeFlow(confTx, flowEntity);
312 } catch (Exception ex) {
313 LOG.error("removeSNATFromDPN : SNAT->Failed to remove default SNAT miss entry flow entity {}",
317 LOG.debug("removeSNATFromDPN : SNAT->Removed default SNAT miss entry flow for dpnID {} "
318 + "with routername {}", dpnId, routerName);
320 //best effort to check IntExt model
321 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
323 } catch (InterruptedException | ExecutionException e) {
324 LOG.error("removeSNATFromDPN : SNAT->Exception while handling naptSwitch down for router {}",
329 private void hndlTepEvntsForDpn(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
330 final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
331 final String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
332 final String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
333 LOG.trace("hndlTepEvntsForDpn : Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ",
334 srcDpnId, srcTepIp, destTepIp);
335 int tunTypeVal = getTunnelType(stateTunnelList);
336 LOG.trace("hndlTepEvntsForDpn : tunTypeVal is {}", tunTypeVal);
337 String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId();
338 String tunnelType = stateTunnelList.getTransportType().toString();
339 String tunnelName = stateTunnelList.getTunnelInterfaceName();
341 if (tunTypeVal == NatConstants.ITMTunnelLocType.Invalid.getValue()) {
342 LOG.warn("hndlTepEvntsForDpn : Ignoring TEP event {} for the DPN {} "
343 + "since its a INVALID TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and " + "TUNNEL NAME {} ",
344 tunnelAction, srcTepId, tunnelType, srcTepIp, destTepIp, tunnelName);
348 switch (tunnelAction) {
351 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
352 if (isTunnelInLogicalGroup(stateTunnelList)
353 || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp,
355 LOG.debug("hndlTepEvntsForDpn : Unable to process TEP ADD");
358 } catch (InterruptedException | ExecutionException e) {
359 LOG.error("Error processing tunnel endpoint addition", e);
362 case TUNNEL_EP_DELETE:
364 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
365 if (!handleTepDelForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp, tx)) {
366 LOG.debug("hndlTepEvntsForDpn : Unable to process TEP DEL");
369 } catch (InterruptedException | ExecutionException e) {
370 LOG.error("Error processing tunnel endpoint removal", e);
373 case TUNNEL_EP_UPDATE:
376 LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
381 private boolean hndlTepAddForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
382 String destTepIp, TypedReadWriteTransaction<Configuration> writeFlowInvTx)
383 throws ExecutionException, InterruptedException {
384 LOG.trace("hndlTepAddForAllRtrs: TEP ADD ----- for EXTERNAL/HWVTEP ITM Tunnel, TYPE {} ,State is UP b/w SRC IP"
385 + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
387 InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
388 Optional<DpnRoutersList> optionalRouterDpnList =
389 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
390 LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
391 if (!optionalRouterDpnList.isPresent()) {
392 LOG.info("hndlTepAddForAllRtrs : RouterDpnList model is empty for DPN {}. Hence ignoring TEP add event "
393 + "for the ITM TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
394 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
398 List<RoutersList> routersList = optionalRouterDpnList.get().getRoutersList();
399 if (routersList == null) {
400 LOG.debug("hndlTepAddForAllRtrs : Ignoring TEP add for the DPN {} since no routers are associated"
401 + " for the DPN having the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
402 + "TUNNEL NAME {} ", srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
406 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
407 for (RoutersList router : routersList) {
408 String routerName = router.getRouter();
409 long routerId = NatUtil.getVpnId(dataBroker, routerName);
410 if (routerId == NatConstants.INVALID_ID) {
411 LOG.error("hndlTepAddForAllRtrs :Invalid ROUTER-ID {} returned for routerName {}",
412 routerId, routerName);
415 LOG.debug("hndlTepAddForAllRtrs : TEP ADD : DNAT -> Advertising routes for router {} ", routerName);
416 Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker,routerName);
417 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
418 routerName, externalNetworkId);
419 if (extNwProvType == null) {
422 hndlTepAddForDnatInEachRtr(router, routerId, nextHopIp, srcDpnId, extNwProvType, writeFlowInvTx);
424 LOG.debug("hndlTepAddForAllRtrs : TEP ADD : SNAT -> Advertising routes for router {} ", routerName);
425 hndlTepAddForSnatInEachRtr(router, routerId, srcDpnId, tunnelType, srcTepIp, destTepIp,
426 tunnelName, nextHopIp, extNwProvType, writeFlowInvTx);
431 // TODO Clean up the exception handling
432 @SuppressWarnings("checkstyle:IllegalCatch")
433 private boolean handleTepDelForAllRtrs(BigInteger srcDpnId, String tunnelType, String tunnelName, String srcTepIp,
434 String destTepIp, TypedReadWriteTransaction<Configuration> writeFlowInvTx)
435 throws ExecutionException, InterruptedException {
437 LOG.trace("handleTepDelForAllRtrs : TEP DEL ----- for EXTERNAL/HWVTEP ITM Tunnel,TYPE {},State is UP b/w SRC IP"
438 + " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
440 // When tunnel EP is deleted on a DPN , VPN gets two deletion event.
441 // One for a DPN on which tunnel EP was deleted and another for other-end DPN.
442 // Handle only the DPN on which it was deleted , ignore other event.
443 // DPN on which TEP is deleted , endpoint IP will be null.
444 String endpointIpForDPN = null;
446 endpointIpForDPN = NatUtil.getEndpointIpAddressForDPN(dataBroker, srcDpnId);
447 } catch (Exception e) {
448 /* this dpn does not have the VTEP */
449 LOG.error("handleTepDelForAllRtrs : DPN {} does not have the VTEP", srcDpnId);
452 if (endpointIpForDPN != null) {
453 LOG.trace("handleTepDelForAllRtrs : Ignore TEP DELETE event received for DPN {} VTEP IP {} since its "
454 + "the other end DPN w.r.t the delted TEP", srcDpnId, srcTepIp);
458 List<RoutersList> routersList = null;
459 InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
460 Optional<DpnRoutersList> optionalRouterDpnList =
461 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
462 LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
463 if (optionalRouterDpnList.isPresent()) {
464 routersList = optionalRouterDpnList.get().getRoutersList();
466 LOG.warn("handleTepDelForAllRtrs : RouterDpnList is empty for DPN {}.Hence ignoring TEP DEL event "
467 + "for the ITM TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
468 srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
472 if (routersList == null) {
473 LOG.error("handleTepDelForAllRtrs : DPN {} does not have the Routers presence", srcDpnId);
477 for (RoutersList router : routersList) {
478 String routerName = router.getRouter();
479 LOG.debug("handleTepDelForAllRtrs : TEP DEL : DNAT -> Withdrawing routes for router {} ", routerName);
480 long routerId = NatUtil.getVpnId(dataBroker, routerName);
481 if (routerId == NatConstants.INVALID_ID) {
482 LOG.error("handleTepDelForAllRtrs :Invalid ROUTER-ID {} returned for routerName {}",
483 routerId, routerName);
486 Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker,routerName);
487 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,
488 routerName, externalNetworkId);
489 if (extNwProvType == null) {
492 hndlTepDelForDnatInEachRtr(router, routerId, srcDpnId, extNwProvType);
493 LOG.debug("handleTepDelForAllRtrs : TEP DEL : SNAT -> Withdrawing and Advertising routes for router {} ",
495 hndlTepDelForSnatInEachRtr(router, routerId, srcDpnId, tunnelType, srcTepIp, destTepIp,
496 tunnelName, extNwProvType, writeFlowInvTx);
501 private void hndlTepAddForSnatInEachRtr(RoutersList router, long routerId, final BigInteger srcDpnId,
502 String tunnelType, String srcTepIp, String destTepIp, String tunnelName, String nextHopIp,
503 ProviderTypes extNwProvType, TypedReadWriteTransaction<Configuration> writeFlowInvTx)
504 throws ExecutionException, InterruptedException {
506 /*SNAT : Remove the old routes to the external IP having the old TEP IP as the next hop IP
507 Advertise to the BGP about the new route to the external IP having the new TEP IP
508 added as the next hop IP
510 String routerName = router.getRouter();
512 // Check if this is externalRouter else ignore
513 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
514 Optional<Routers> routerData;
516 routerData = writeFlowInvTx.read(extRoutersId).get();
517 } catch (InterruptedException | ExecutionException e) {
518 LOG.error("Error reading router data for {}", extRoutersId, e);
519 routerData = Optional.absent();
521 if (!routerData.isPresent()) {
522 LOG.warn("hndlTepAddForSnatInEachRtr : SNAT->Ignoring TEP add for router {} since its not External Router",
527 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
528 if (naptId == null || naptId.equals(BigInteger.ZERO)) {
529 LOG.warn("hndlTepAddForSnatInEachRtr : SNAT -> Ignoring TEP add for the DPN {} having the router {} since"
530 + " the router is not part of the NAT service - the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
531 + "TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
534 if (natMode == NatMode.Conntrack) {
535 Routers extRouter = routerData.get();
536 natServiceManager.notify(writeFlowInvTx, extRouter, null, naptId, srcDpnId,
537 SnatServiceManager.Action.CNT_ROUTER_ALL_SWITCH_ENBL);
538 if (extRouter.isEnableSnat()) {
539 natServiceManager.notify(writeFlowInvTx, extRouter, null, naptId, srcDpnId,
540 SnatServiceManager.Action.SNAT_ROUTER_ENBL);
543 Uuid bgpVpnUuId = NatUtil.getVpnForRouter(dataBroker, routerName);
544 //Check if the DPN having the router is the NAPT switch
545 if (!naptId.equals(srcDpnId)) {
547 1) Install default NAT rule from table 21 to 26
548 2) Install the group which forward packet to the tunnel port for the NAPT switch.
549 3) Install the flow 26 which forwards the packet to the group.
551 if (!hndlTepAddOnNonNaptSwitch(srcDpnId, naptId, tunnelType, srcTepIp, destTepIp, tunnelName,
552 routerName, routerId, bgpVpnUuId, writeFlowInvTx)) {
553 LOG.error("hndlTepAddForSnatInEachRtr : Unable to process the TEP add event on NON-NAPT switch {}",
559 if (!hndlTepAddOnNaptSwitch(srcDpnId, tunnelType, srcTepIp, destTepIp, tunnelName, routerId,
560 routerData, nextHopIp, bgpVpnUuId, extNwProvType, writeFlowInvTx)) {
561 LOG.debug("hndlTepAddForSnatInEachRtr : Unable to process the TEP add event on NAPT switch {}",
569 private boolean hndlTepAddOnNonNaptSwitch(BigInteger srcDpnId, BigInteger primaryDpnId, String tunnelType,
570 String srcTepIp, String destTepIp, String tunnelName, String routerName, long routerId, Uuid vpnName,
571 TypedWriteTransaction<Configuration> confTx) {
574 1) Install default NAT rule from table 21 to 26
575 2) Install the group which forward packet to the tunnel port for the NAPT switch.
576 3) Install the flow 26 which forwards the packet to the group.
578 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Processing TEP add for the DPN {} having the router {} since "
579 + "its THE NON NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
580 + "and TUNNEL NAME {} ",
581 srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
582 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Install default NAT rule from table 21 to 26");
584 if (vpnName == null) {
585 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Internal VPN associated to router {}", routerId);
587 if (vpnId == NatConstants.INVALID_ID) {
588 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid Internal VPN ID returned for routerName {}",
592 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerName);
593 //Install default entry in FIB to SNAT table
594 LOG.debug("hndlTepAddOnNonNaptSwitch : Installing default route in FIB on DPN {} for router {} with"
595 + " vpn {}...", srcDpnId, routerName, vpnId);
596 defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, confTx);
598 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Install the group which forward packet to the tunnel port "
599 + "for the NAPT switch {} and the flow 26 which forwards to group", primaryDpnId);
600 externalRouterListner.handleSwitches(srcDpnId, routerName, routerId, primaryDpnId);
602 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> External BGP VPN (Private BGP) associated to router {}",
604 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
605 if (vpnId == NatConstants.INVALID_ID) {
606 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid Private BGP VPN ID returned for routerName {}",
610 if (routerId == NatConstants.INVALID_ID) {
611 LOG.error("hndlTepAddOnNonNaptSwitch : SNAT -> Invalid routId returned for routerName {}", routerId);
614 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
615 //Install default entry in FIB to SNAT table
616 LOG.debug("hndlTepAddOnNonNaptSwitch : Installing default route in FIB on dpn {} for routerId {} "
617 + "with vpnId {}...", srcDpnId, routerId, vpnId);
618 defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, routerId, confTx);
620 LOG.debug("hndlTepAddOnNonNaptSwitch : Install group in non NAPT switch {} for router {}",
621 srcDpnId, routerName);
622 List<BucketInfo> bucketInfoForNonNaptSwitches =
623 externalRouterListner.getBucketInfoForNonNaptSwitches(srcDpnId, primaryDpnId, routerName, routerId);
624 long groupId = externalRouterListner.installGroup(srcDpnId, routerName, bucketInfoForNonNaptSwitches);
626 LOG.debug("hndlTepAddOnNonNaptSwitch : SNAT -> in the SNAT miss entry pointing to group {} "
627 + "in the non NAPT switch {}", groupId, srcDpnId);
628 FlowEntity flowEntity =
629 externalRouterListner.buildSnatFlowEntityWithUpdatedVpnId(srcDpnId, routerName, groupId, vpnId);
630 mdsalManager.addFlow(confTx, flowEntity);
635 private boolean hndlTepAddOnNaptSwitch(BigInteger srcDpnId, String tunnelType, String srcTepIp,
636 String destTepIp, String tunnelName, long routerId,
637 Optional<Routers> routerData, String nextHopIp, Uuid vpnName,
638 ProviderTypes extNwProvType, TypedWriteTransaction<Configuration> confTx) {
639 if (!routerData.isPresent()) {
640 LOG.warn("hndlTepAddOnNaptSwitch: routerData is not present");
643 Routers router = routerData.get();
644 String routerName = router.getRouterName();
645 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Processing TEP add for the DPN {} having the router {} since "
646 + "its THE NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} "
647 + "and TUNNEL NAME {} ", srcDpnId, routerName, tunnelType, srcTepIp, destTepIp, tunnelName);
649 Uuid networkId = router.getNetworkId();
650 if (networkId == null) {
651 LOG.warn("hndlTepAddOnNaptSwitch : SNAT -> Ignoring TEP add since the router {} is not associated to the "
652 + "external network", routerName);
656 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Router {} is associated with Ext nw {}", routerId, networkId);
658 if (vpnName == null) {
659 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Internal VPN associated to router {}", routerId);
660 vpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
661 if (vpnId == NatConstants.INVALID_ID) {
662 LOG.error("hndlTepAddOnNaptSwitch : Invalid External VPN-ID returned for routerName {}", routerName);
665 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Retrieved External VPN-ID {} for router {}", vpnId, routerId);
667 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Private BGP VPN associated to router {}", routerId);
668 vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
669 if (vpnId == NatConstants.INVALID_ID) {
670 LOG.error("hndlTepAddOnNaptSwitch : Invalid vpnId returned for routerName {}", routerName);
673 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Retrieved vpnId {} for router {}", vpnId, routerId);
676 /*1) Withdraw the old route to the external IP from the BGP which was having the
677 next hop as the old TEP IP.
678 2) Advertise to the BGP about the new route to the external IP having the
679 new TEP IP as the next hop.
680 3) Populate a new FIB entry with the next hop IP as the new TEP IP using the
684 //Withdraw the old route to the external IP from the BGP which was having the
685 //next hop as the old TEP IP.
686 final String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
687 if (externalVpnName == null) {
688 LOG.error("hndlTepAddOnNaptSwitch : SNAT -> No VPN associated with ext nw {} in router {}",
689 networkId, routerId);
692 Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
693 LOG.debug("hndlTepAddOnNaptSwitch : Clearing the FIB entries but not the BGP routes");
694 for (String externalIp : externalIps) {
695 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
696 LOG.debug("hndlTepAddOnNaptSwitch : Removing Fib entry rd {} prefix {}", rd, externalIp);
697 fibManager.removeFibEntry(rd, externalIp, null);
701 Advertise to the BGP about the new route to the external IP having the
702 new TEP IP as the next hop.
703 Populate a new FIB entry with the next hop IP as the new TEP IP using the
706 String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
707 if (extNwProvType == null) {
710 String gwMacAddress = null;
712 if (extNwProvType == ProviderTypes.VXLAN) {
713 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
714 gwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
715 if (gwMacAddress != null) {
716 LOG.debug("hndlTepAddOnNaptSwitch : External Gateway MAC address {} found for External Router ID {}",
717 gwMacAddress, routerId);
719 LOG.error("hndlTepAddOnNaptSwitch : No External Gateway MAC address found for External Router ID {}",
723 //get l3Vni value for external VPN
724 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
725 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
726 LOG.debug("hndlTepAddOnNaptSwitch : L3VNI value is not configured in Internet VPN {} and RD {} "
727 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
728 + "NAT flows", vpnName, rd);
729 l3Vni = natOverVxlanUtil.getInternetVpnVni(externalVpnName, routerId).longValue();
733 for (final String externalIp : externalIps) {
735 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
736 if (extNwProvType == ProviderTypes.VXLAN) {
737 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Advertise the route to the externalIp {} "
738 + "having nextHopIp {}", externalIp, nextHopIp);
739 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, externalVpnName, rd,
740 externalIp, nextHopIp, l3Vni, tunnelName, gwMacAddress, confTx, RouteOrigin.STATIC,
741 srcDpnId, networkId);
745 Long label = externalRouterListner.checkExternalIpLabel(routerId,
747 if (label == null || label == NatConstants.INVALID_ID) {
748 LOG.error("hndlTepAddOnNaptSwitch : SNAT->Unable to advertise to the DC GW "
749 + "since label is invalid");
752 LOG.debug("hndlTepAddOnNaptSwitch : SNAT -> Advertise the route to the externalIp {} "
753 + "having nextHopIp {}", externalIp, nextHopIp);
755 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
756 l3vni = natOverVxlanUtil.getInternetVpnVni(externalVpnName, l3vni).longValue();
758 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd,
759 fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni,
760 RouteOrigin.STATIC, srcDpnId);
764 LOG.debug("hndlTepAddOnNaptSwitch: SNAT -> Install custom FIB routes "
765 + "(Table 21 -> Push MPLS label to Tunnel port");
766 List<Instruction> customInstructions = new ArrayList<>();
767 int customInstructionIndex = 0;
768 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIp,
770 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
771 LOG.debug("hndlTepAddOnNaptSwitch : Will install custom FIB router with external subnet VPN ID {}",
772 externalSubnetVpnId);
773 BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId);
774 customInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
775 MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(customInstructionIndex));
776 customInstructionIndex++;
778 customInstructions.add(new InstructionGotoTable(NwConstants.INBOUND_NAPT_TABLE)
779 .buildInstruction(customInstructionIndex));
780 CreateFibEntryInput input =
781 new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
782 .setInstruction(customInstructions).setIpAddress(fibExternalIp)
783 .setIpAddressSource(FibEntryInputs.IpAddressSource.ExternalFixedIP)
784 .setServiceId(serviceId).setInstruction(customInstructions).build();
785 ListenableFuture<RpcResult<CreateFibEntryOutput>> listenableFuture = fibRpcService.createFibEntry(input);
787 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
790 public void onFailure(@Nonnull Throwable error) {
791 LOG.error("hndlTepAddOnNaptSwitch : SNAT->Error in generate label or fib install process",
796 public void onSuccess(@Nonnull RpcResult<CreateFibEntryOutput> result) {
797 if (result.isSuccessful()) {
798 LOG.info("hndlTepAddOnNaptSwitch : SNAT -> Successfully installed custom FIB routes "
799 + "for prefix {}", externalIp);
801 LOG.error("hndlTepAddOnNaptSwitch : SNAT -> Error in rpc call to create custom Fib entries "
802 + "for prefix {} in DPN {}, {}", externalIp, srcDpnId, result.getErrors());
805 }, MoreExecutors.directExecutor());
811 private void hndlTepAddForDnatInEachRtr(RoutersList router, long routerId, String nextHopIp,
812 BigInteger tepAddedDpnId, ProviderTypes extNwProvType, TypedWriteTransaction<Configuration> confTx) {
813 //DNAT : Advertise the new route to the floating IP having the new TEP IP as the next hop IP
814 final String routerName = router.getRouter();
816 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
817 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
818 .CONFIGURATION, routerPortsId);
819 if (!optRouterPorts.isPresent()) {
820 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
821 + "from DNAT FloatinIpInfo", routerName);
824 RouterPorts routerPorts = optRouterPorts.get();
825 Uuid extNwId = routerPorts.getExternalNetworkId();
826 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId);
827 if (vpnName == null) {
828 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> No External VPN associated with ext nw {} for router {}",
829 extNwId, routerName);
833 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
834 if (extNwProvType == null) {
837 String gwMacAddress = null;
839 if (extNwProvType == ProviderTypes.VXLAN) {
840 // Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
841 gwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
842 if (gwMacAddress != null) {
843 LOG.debug("hndlTepAddForDnatInEachRtr : External GwMAC address {} found for External Router ID {}",
844 gwMacAddress, routerId);
846 LOG.error("hndlTepAddForDnatInEachRtr : No External GwMAC address found for External Router ID {}",
850 //get l3Vni value for external VPN
851 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
852 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
853 LOG.debug("hndlTepAddForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
854 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
855 + "NAT flows", vpnName, rd);
856 l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId).longValue();
859 for (Ports port : routerPorts.nonnullPorts()) {
860 //Get the DPN on which this interface resides
861 final String interfaceName = port.getPortName();
862 final BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
863 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
864 LOG.info("hndlTepAddForDnatInEachRtr : DNAT->Skip processing Floating ip configuration for the port {},"
865 + "since no DPN present for it", interfaceName);
868 if (!fipCfgdDpnId.equals(tepAddedDpnId)) {
869 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> TEP added DPN {} is not the DPN {} which has the "
870 + "floating IP configured for the port: {}",
871 tepAddedDpnId, fipCfgdDpnId, interfaceName);
874 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
875 final String internalIp = intExtPortMap.getInternalIp();
876 final String externalIp = intExtPortMap.getExternalIp();
877 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertising the FIB route to the floating IP {} "
878 + "configured for the port: {}", externalIp, interfaceName);
880 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
882 if (extNwProvType == ProviderTypes.VXLAN) {
883 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
884 + "having nextHopIp {}", externalIp, nextHopIp);
885 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd,
886 externalIp, nextHopIp, l3Vni, interfaceName, gwMacAddress, confTx, RouteOrigin.STATIC,
887 fipCfgdDpnId, extNwId);
890 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
891 if (label == NatConstants.INVALID_ID) {
892 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Unable to advertise to the DC GW since label "
896 LOG.debug("hndlTepAddForDnatInEachRtr : DNAT -> Advertise the route to the externalIp {} "
897 + "having nextHopIp {}", externalIp, nextHopIp);
899 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
900 l3vni = natOverVxlanUtil.getInternetVpnVni(vpnName, l3vni).longValue();
902 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd,
903 fibExternalIp, nextHopIp, null, null, label, l3vni, RouteOrigin.STATIC,
908 //Install custom FIB routes (Table 21 -> Push MPLS label to Tunnel port
909 List<Instruction> customInstructions = new ArrayList<>();
910 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
911 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
912 .setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
913 .setIpAddressSource(FibEntryInputs.IpAddressSource.FloatingIP)
914 .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
916 ListenableFuture<RpcResult<CreateFibEntryOutput>> listenableFuture =
917 fibRpcService.createFibEntry(input);
919 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
922 public void onFailure(@Nonnull Throwable error) {
923 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in generate label or fib install process",
928 public void onSuccess(@Nonnull RpcResult<CreateFibEntryOutput> result) {
929 if (result.isSuccessful()) {
930 LOG.info("hndlTepAddForDnatInEachRtr : DNAT -> Successfully installed custom FIB routes "
931 + "for prefix {}", externalIp);
933 LOG.error("hndlTepAddForDnatInEachRtr : DNAT -> Error in rpc call to create custom Fib "
934 + "entries for prefix {} in DPN {}, {}", externalIp, fipCfgdDpnId, result.getErrors());
937 }, MoreExecutors.directExecutor());
942 private void hndlTepDelForSnatInEachRtr(RoutersList router, long routerId, BigInteger dpnId, String tunnelType,
943 String srcTepIp, String destTepIp, String tunnelName, ProviderTypes extNwProvType,
944 TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
946 1) Elect a new switch as the primary NAPT
947 2) Advertise the new routes to BGP for the newly elected TEP IP as the DPN IP
948 3) This will make sure old routes are withdrawn and new routes are advertised.
951 String routerName = router.getRouter();
952 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Trying to clear routes to the External fixed IP associated "
953 + "to the router {}", routerName);
955 // Check if this is externalRouter else ignore
956 InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
957 Optional<Routers> routerData;
959 routerData = confTx.read(extRoutersId).get();
960 } catch (InterruptedException | ExecutionException e) {
961 LOG.error("Error retrieving routers {}", extRoutersId, e);
962 routerData = Optional.absent();
964 if (!routerData.isPresent()) {
965 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP del for router {} since its not External Router",
970 //Check if the DPN having the router is the NAPT switch
971 BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
972 if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptId.equals(dpnId)) {
973 LOG.warn("hndlTepDelForSnatInEachRtr : SNAT -> Ignoring TEP delete for the DPN {} since"
974 + " its NOT a NAPT switch for the TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and"
975 + "TUNNEL NAME {} ", dpnId, tunnelType, srcTepIp, destTepIp, tunnelName);
978 if (natMode == NatMode.Conntrack) {
979 Routers extRouter = routerData.get();
980 natServiceManager.notify(confTx, extRouter, null, naptId, dpnId,
981 SnatServiceManager.Action.CNT_ROUTER_DISBL);
982 if (extRouter.isEnableSnat()) {
983 natServiceManager.notify(confTx,extRouter, null, naptId, dpnId,
984 SnatServiceManager.Action.SNAT_ROUTER_DISBL);
989 Uuid networkId = routerData.get().getNetworkId();
990 if (networkId == null) {
991 LOG.error("hndlTepDelForSnatInEachRtr : SNAT->Ignoring TEP delete for the DPN {} having the router {} "
992 + "since the Router instance {} not found in ExtRouters model b/w SRC IP {} and DST "
993 + "IP {} and TUNNEL NAME {} ", dpnId, routerData.get().getRouterName(), tunnelType,
994 srcTepIp, destTepIp, tunnelName);
998 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Router {} is associated with ext nw {}", routerId, networkId);
999 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
1001 if (bgpVpnUuid == null) {
1002 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT->Internal VPN-ID {} associated to router {}",
1003 routerId, routerName);
1004 bgpVpnId = routerId;
1006 //Install default entry in FIB to SNAT table
1007 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on DPN {} for router {} with"
1008 + " vpn {}...", dpnId, routerName, bgpVpnId);
1009 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, confTx);
1011 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
1012 if (bgpVpnId == NatConstants.INVALID_ID) {
1013 LOG.error("hndlTepDelForSnatInEachRtr :SNAT->Invalid Private BGP VPN ID returned for routerName {}",
1017 LOG.debug("hndlTepDelForSnatInEachRtr :SNAT->External BGP VPN (Private BGP) {} associated to router {}",
1018 bgpVpnId, routerName);
1019 //Install default entry in FIB to SNAT table
1020 LOG.debug("hndlTepDelForSnatInEachRtr : Installing default route in FIB on dpn {} for routerId {} "
1021 + "with vpnId {}...", dpnId, routerId, bgpVpnId);
1022 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId, confTx);
1025 if (routerData.get().isEnableSnat()) {
1026 LOG.info("hndlTepDelForSnatInEachRtr : SNAT enabled for router {}", routerId);
1028 long routerVpnId = routerId;
1029 if (bgpVpnId != NatConstants.INVALID_ID) {
1030 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Private BGP VPN ID (Internal BGP VPN ID) {} "
1031 + "associated to the router {}", bgpVpnId, routerName);
1032 routerVpnId = bgpVpnId;
1034 LOG.debug("hndlTepDelForSnatInEachRtr : SNAT -> Internal L3 VPN ID (Router ID) {} "
1035 + "associated to the router {}", routerVpnId, routerName);
1037 //Re-elect the other available switch as the NAPT switch and program the NAT flows.
1038 removeSNATFromDPN(dpnId, routerName, routerId, routerVpnId, networkId, extNwProvType, confTx);
1040 LOG.info("hndlTepDelForSnatInEachRtr : SNAT is not enabled for router {} to handle addDPN event {}",
1046 private void hndlTepDelForDnatInEachRtr(RoutersList router, long routerId, BigInteger tepDeletedDpnId,
1047 ProviderTypes extNwProvType) {
1048 //DNAT : Withdraw the routes from the BGP
1049 String routerName = router.getRouter();
1051 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Trying to clear routes to the Floating IP "
1052 + "associated to the router {}", routerName);
1054 InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
1055 Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType
1056 .CONFIGURATION, routerPortsId);
1057 if (!optRouterPorts.isPresent()) {
1058 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Could not read Router Ports data object with id: {} "
1059 + "from DNAT FloatingIpInfo", routerName);
1062 RouterPorts routerPorts = optRouterPorts.get();
1063 Uuid extNwId = routerPorts.getExternalNetworkId();
1064 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, extNwId);
1065 if (vpnName == null) {
1066 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> No External VPN associated with Ext N/W {} for Router {}",
1067 extNwId, routerName);
1070 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1071 if (extNwProvType == null) {
1075 if (extNwProvType == ProviderTypes.VXLAN) {
1076 //get l3Vni value for external VPN
1077 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
1078 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
1079 LOG.debug("hndlTepDelForDnatInEachRtr : L3VNI value is not configured in Internet VPN {} and RD {} "
1080 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue to installing "
1081 + "NAT flows", vpnName, rd);
1082 l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId).longValue();
1085 for (Ports port : routerPorts.nonnullPorts()) {
1086 //Get the DPN on which this interface resides
1087 String interfaceName = port.getPortName();
1088 BigInteger fipCfgdDpnId = NatUtil.getDpnForInterface(interfaceService, interfaceName);
1089 if (fipCfgdDpnId.equals(BigInteger.ZERO)) {
1090 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Abort processing Floating ip configuration. "
1091 + "No DPN for port : {}", interfaceName);
1094 if (!fipCfgdDpnId.equals(tepDeletedDpnId)) {
1095 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> TEP deleted DPN {} is not the DPN {} which has the "
1096 + "floating IP configured for the port: {}",
1097 tepDeletedDpnId, fipCfgdDpnId, interfaceName);
1100 for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap()) {
1101 String internalIp = intExtPortMap.getInternalIp();
1102 String externalIp = intExtPortMap.getExternalIp();
1103 externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1104 LOG.debug("hndlTepDelForDnatInEachRtr : DNAT -> Withdrawing the FIB route to the floating IP {} "
1105 + "configured for the port: {}",
1106 externalIp, interfaceName);
1107 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, externalIp, vpnName, LOG);
1109 if (extNwProvType == ProviderTypes.VXLAN) {
1112 long label = floatingIPListener.getOperationalIpMapping(routerName, interfaceName, internalIp);
1113 if (label == NatConstants.INVALID_ID) {
1114 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Unable to remove the table 21 entry pushing the"
1115 + " MPLS label to the tunnel since label is invalid");
1121 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
1122 .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
1123 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
1124 ListenableFuture<RpcResult<RemoveFibEntryOutput>> listenableFuture =
1125 fibRpcService.removeFibEntry(input);
1127 Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<RemoveFibEntryOutput>>() {
1130 public void onFailure(@Nonnull Throwable error) {
1131 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in removing the table 21 entry pushing "
1132 + "the MPLS label to the tunnel since label is invalid ", error);
1136 public void onSuccess(@Nonnull RpcResult<RemoveFibEntryOutput> result) {
1137 if (result.isSuccessful()) {
1138 LOG.info("hndlTepDelForDnatInEachRtr : DNAT -> Successfully removed the entry pushing the "
1139 + "MPLS label to the tunnel");
1141 LOG.error("hndlTepDelForDnatInEachRtr : DNAT -> Error in fib rpc call to remove the table "
1142 + "21 entry pushing the MPLS label to the tunnnel due to {}", result.getErrors());
1145 }, MoreExecutors.directExecutor());
1150 protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
1151 String ifaceName = stateTunnelList.getTunnelInterfaceName();
1152 if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
1153 Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
1154 IfTunnel ifTunnel = configIface != null ? configIface.augmentation(IfTunnel.class) : null;
1155 if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
1156 ParentRefs refs = configIface.augmentation(ParentRefs.class);
1157 if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
1158 return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
1162 LOG.trace("isTunnelInLogicalGroup: ignoring the tunnel event for {}", ifaceName);