2 * Copyright © 2016, 2017 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
8 package org.opendaylight.netvirt.natservice.internal;
10 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.JdkFutureAdapters;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
20 import java.math.BigInteger;
21 import java.net.Inet6Address;
22 import java.net.InetAddress;
23 import java.net.UnknownHostException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
32 import java.util.Objects;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.Future;
36 import javax.annotation.PostConstruct;
37 import javax.inject.Inject;
38 import javax.inject.Singleton;
39 import org.eclipse.jdt.annotation.NonNull;
40 import org.eclipse.jdt.annotation.Nullable;
41 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
42 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
43 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
44 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
45 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
46 import org.opendaylight.genius.infra.Datastore.Configuration;
47 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
48 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
49 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
50 import org.opendaylight.genius.infra.TypedWriteTransaction;
51 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
52 import org.opendaylight.genius.mdsalutil.ActionInfo;
53 import org.opendaylight.genius.mdsalutil.BucketInfo;
54 import org.opendaylight.genius.mdsalutil.FlowEntity;
55 import org.opendaylight.genius.mdsalutil.GroupEntity;
56 import org.opendaylight.genius.mdsalutil.InstructionInfo;
57 import org.opendaylight.genius.mdsalutil.MDSALUtil;
58 import org.opendaylight.genius.mdsalutil.MatchInfo;
59 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
60 import org.opendaylight.genius.mdsalutil.NwConstants;
61 import org.opendaylight.genius.mdsalutil.NwConstants.NxmOfFieldType;
62 import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
63 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
64 import org.opendaylight.genius.mdsalutil.actions.ActionLearn;
65 import org.opendaylight.genius.mdsalutil.actions.ActionLearn.MatchFromField;
66 import org.opendaylight.genius.mdsalutil.actions.ActionLearn.MatchFromValue;
67 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
68 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
69 import org.opendaylight.genius.mdsalutil.actions.ActionPopMpls;
70 import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
71 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
72 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
73 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
74 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
75 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
76 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
77 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
78 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
79 import org.opendaylight.genius.mdsalutil.matches.MatchMplsLabel;
80 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
81 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
82 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
83 import org.opendaylight.netvirt.elanmanager.api.IElanService;
84 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
85 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
86 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelOutput;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
147 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
148 import org.opendaylight.yangtools.yang.common.RpcResult;
149 import org.opendaylight.yangtools.yang.common.Uint32;
150 import org.opendaylight.yangtools.yang.common.Uint64;
151 import org.slf4j.Logger;
152 import org.slf4j.LoggerFactory;
156 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener> {
157 private static final Logger LOG = LoggerFactory.getLogger(ExternalRoutersListener.class);
159 private static final Uint64 COOKIE_TUNNEL = Uint64.valueOf("9000000", 16).intern();
160 private static final Uint64 COOKIE_VM_LFIB_TABLE = Uint64.valueOf("8000022", 16).intern();
162 private final DataBroker dataBroker;
163 private final ManagedNewTransactionRunner txRunner;
164 private final IMdsalApiManager mdsalManager;
165 private final ItmRpcService itmManager;
166 private final OdlInterfaceRpcService odlInterfaceRpcService;
167 private final IdManagerService idManager;
168 private final NaptManager naptManager;
169 private final NAPTSwitchSelector naptSwitchSelector;
170 private final IBgpManager bgpManager;
171 private final VpnRpcService vpnService;
172 private final FibRpcService fibService;
173 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
174 private final NaptEventHandler naptEventHandler;
175 private final NaptPacketInHandler naptPacketInHandler;
176 private final IFibManager fibManager;
177 private final IVpnManager vpnManager;
178 private final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer;
179 private final NatMode natMode;
180 private final IElanService elanManager;
181 private final JobCoordinator coordinator;
182 private final IInterfaceManager interfaceManager;
183 private final NatOverVxlanUtil natOverVxlanUtil;
184 private final int snatPuntTimeout;
187 public ExternalRoutersListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
188 final ItmRpcService itmManager,
189 final OdlInterfaceRpcService odlInterfaceRpcService,
190 final IdManagerService idManager,
191 final NaptManager naptManager,
192 final NAPTSwitchSelector naptSwitchSelector,
193 final IBgpManager bgpManager,
194 final VpnRpcService vpnService,
195 final FibRpcService fibService,
196 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
197 final NaptEventHandler naptEventHandler,
198 final NaptPacketInHandler naptPacketInHandler,
199 final IFibManager fibManager,
200 final IVpnManager vpnManager,
201 final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer,
202 final NatserviceConfig config,
203 final IElanService elanManager,
204 final JobCoordinator coordinator,
205 final NatOverVxlanUtil natOverVxlanUtil,
206 final IInterfaceManager interfaceManager) {
207 super(Routers.class, ExternalRoutersListener.class);
208 this.dataBroker = dataBroker;
209 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
210 this.mdsalManager = mdsalManager;
211 this.itmManager = itmManager;
212 this.odlInterfaceRpcService = odlInterfaceRpcService;
213 this.idManager = idManager;
214 this.naptManager = naptManager;
215 this.naptSwitchSelector = naptSwitchSelector;
216 this.bgpManager = bgpManager;
217 this.vpnService = vpnService;
218 this.fibService = fibService;
219 this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
220 this.naptEventHandler = naptEventHandler;
221 this.naptPacketInHandler = naptPacketInHandler;
222 this.fibManager = fibManager;
223 this.vpnManager = vpnManager;
224 this.evpnSnatFlowProgrammer = evpnSnatFlowProgrammer;
225 this.elanManager = elanManager;
226 this.coordinator = coordinator;
227 this.interfaceManager = interfaceManager;
228 this.natOverVxlanUtil = natOverVxlanUtil;
229 if (config != null) {
230 this.natMode = config.getNatMode();
231 this.snatPuntTimeout = config.getSnatPuntTimeout().intValue();
233 this.natMode = NatMode.Controller;
234 this.snatPuntTimeout = 0;
241 LOG.info("{} init", getClass().getSimpleName());
242 // This class handles ExternalRouters for Controller SNAT mode.
243 // For Conntrack SNAT mode, its handled in SnatExternalRoutersListener.java
244 if (natMode == NatMode.Controller) {
245 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
246 NatUtil.createGroupIdPool(idManager);
251 protected InstanceIdentifier<Routers> getWildCardPath() {
252 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
256 // TODO Clean up the exception handling
257 @SuppressWarnings("checkstyle:IllegalCatch")
258 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
259 // Populate the router-id-name container
260 String routerName = routers.getRouterName();
261 LOG.info("add : external router event for {}", routerName);
262 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
263 NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
264 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
266 if (routers.isEnableSnat()) {
267 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routers.key(),
268 () -> Collections.singletonList(
269 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
270 LOG.info("add : Installing NAT default route on all dpns part of router {}", routerName);
271 Uint32 bgpVpnId = NatConstants.INVALID_ID;
272 if (bgpVpnUuid != null) {
273 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
275 addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, true, confTx);
276 // Allocate Primary Napt Switch for this router
277 Uint64 primarySwitchId = getPrimaryNaptSwitch(routerName);
278 if (primarySwitchId != null && !primarySwitchId.equals(Uint64.ZERO)) {
279 handleEnableSnat(routers, routerId, primarySwitchId, bgpVpnId, confTx);
282 )), NatConstants.NAT_DJC_MAX_RETRIES);
284 LOG.info("add : SNAT is disabled for external router {} ", routerName);
286 } catch (Exception ex) {
287 LOG.error("add : Exception while Installing NAT flows on all dpns as part of router {}",
292 public void handleEnableSnat(Routers routers, Uint32 routerId, Uint64 primarySwitchId, Uint32 bgpVpnId,
293 TypedWriteTransaction<Configuration> confTx) {
294 String routerName = routers.getRouterName();
295 LOG.info("handleEnableSnat : Handling SNAT for router {}", routerName);
297 naptManager.initialiseExternalCounter(routers, routerId);
298 subnetRegisterMapping(routers, routerId);
300 LOG.debug("handleEnableSnat:About to create and install outbound miss entry in Primary Switch {} for router {}",
301 primarySwitchId, routerName);
303 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
304 routers.getNetworkId());
305 if (extNwProvType == null) {
306 LOG.error("handleEnableSnat : External Network Provider Type missing");
310 if (bgpVpnId != NatConstants.INVALID_ID) {
311 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId,
312 routers.getNetworkId(),false, confTx, extNwProvType);
314 // write metadata and punt
315 installOutboundMissEntry(routerName, routerId, primarySwitchId, confTx);
316 handlePrimaryNaptSwitch(primarySwitchId, routerName, routerId, routers.getNetworkId(), confTx);
317 // Now install entries in SNAT tables to point to Primary for each router
318 List<Uint64> switches = naptSwitchSelector.getDpnsForVpn(routerName);
319 for (Uint64 dpnId : switches) {
320 // Handle switches and NAPT switches separately
321 if (!dpnId.equals(primarySwitchId)) {
322 LOG.debug("handleEnableSnat : Handle Ordinary switch");
323 handleSwitches(dpnId, routerName, routerId, primarySwitchId);
328 Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
329 if (externalIps.isEmpty()) {
330 LOG.error("handleEnableSnat : Internal External mapping not found for router {}", routerName);
333 for (String externalIpAddrPrefix : externalIps) {
334 LOG.debug("handleEnableSnat : Calling handleSnatReverseTraffic for primarySwitchId {}, "
335 + "routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
336 externalIpAddrPrefix = NatUtil.validateAndAddNetworkMask(externalIpAddrPrefix);
337 handleSnatReverseTraffic(confTx, primarySwitchId, routers, routerId, routerName, externalIpAddrPrefix
341 LOG.debug("handleEnableSnat : Exit");
344 private Uint64 getPrimaryNaptSwitch(String routerName) {
345 // Allocate Primary Napt Switch for this router
346 Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
347 if (primarySwitchId != null && !primarySwitchId.equals(Uint64.ZERO)) {
348 LOG.debug("getPrimaryNaptSwitch : Primary NAPT switch with DPN ID {} is already elected for router {}",
349 primarySwitchId, routerName);
350 return primarySwitchId;
352 return selectNewNAPTSwitch(routerName);
355 private Uint64 selectNewNAPTSwitch(String routerName) {
356 // Allocated an id from VNI pool for the Router.
357 natOverVxlanUtil.getRouterVni(routerName, NatConstants.INVALID_ID);
358 Uint64 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName, null);
359 LOG.debug("getPrimaryNaptSwitch : Primary NAPT switch DPN ID {}", primarySwitchId);
361 return primarySwitchId;
364 protected void installNaptPfibExternalOutputFlow(String routerName, Uint32 routerId, Uint64 dpnId,
365 TypedWriteTransaction<Configuration> confTx) {
366 Uint32 extVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
367 if (extVpnId == NatConstants.INVALID_ID) {
368 LOG.error("installNaptPfibExternalOutputFlow - not found extVpnId for router {}", routerId);
371 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerName);
372 if (externalIps.isEmpty()) {
373 LOG.error("installNaptPfibExternalOutputFlow - empty external Ips list for dpnId {} extVpnId {}",
377 for (String ip : externalIps) {
378 Uuid subnetId = getSubnetIdForFixedIp(ip);
379 if (subnetId != null) {
380 Uint32 subnetVpnId = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
381 if (subnetVpnId != NatConstants.INVALID_ID) {
382 extVpnId = subnetVpnId;
384 LOG.debug("installNaptPfibExternalOutputFlow - dpnId {} extVpnId {} subnetId {}",
385 dpnId, extVpnId, subnetId);
386 FlowEntity postNaptFlowEntity = buildNaptPfibFlowEntity(dpnId, extVpnId);
387 if (postNaptFlowEntity != null) {
388 mdsalManager.addFlow(confTx, postNaptFlowEntity);
395 private Uuid getSubnetIdForFixedIp(String ip) {
397 IpAddress externalIpv4Address = new IpAddress(new Ipv4Address(ip));
398 Port port = NatUtil.getNeutronPortForRouterGetewayIp(dataBroker, externalIpv4Address);
399 return NatUtil.getSubnetIdForFloatingIp(port, externalIpv4Address);
401 LOG.error("getSubnetIdForFixedIp : ip is null");
405 protected void subnetRegisterMapping(Routers routerEntry, Uint32 segmentId) {
406 LOG.debug("subnetRegisterMapping : Fetching values from extRouters model");
407 List<String> externalIps = NatUtil.getIpsListFromExternalIps(routerEntry.getExternalIps());
409 int extIpCounter = externalIps.size();
410 LOG.debug("subnetRegisterMapping : counter values before looping counter {} and extIpCounter {}",
411 counter, extIpCounter);
412 @Nullable List<Uuid> subnetIds = routerEntry.getSubnetIds();
413 if (subnetIds == null) {
416 for (Uuid subnet : subnetIds) {
417 LOG.debug("subnetRegisterMapping : Looping internal subnets for subnet {}", subnet);
418 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
419 .builder(Subnetmaps.class)
420 .child(Subnetmap.class, new SubnetmapKey(subnet))
422 Optional<Subnetmap> sn;
424 sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
425 LogicalDatastoreType.CONFIGURATION, subnetmapId);
426 } catch (ReadFailedException e) {
427 LOG.error("Failed to read SubnetMap for subnetmap Id {}", subnetmapId, e);
428 sn = Optional.absent();
430 if (sn.isPresent()) {
432 Subnetmap subnetmapEntry = sn.get();
433 String subnetString = subnetmapEntry.getSubnetIp();
434 String[] subnetSplit = subnetString.split("/");
435 String subnetIp = subnetSplit[0];
437 InetAddress address = InetAddress.getByName(subnetIp);
438 if (address instanceof Inet6Address) {
439 LOG.debug("subnetRegisterMapping : Skipping ipv6 subnet {} for the router {} with ipv6 address "
440 + "{} ", subnet, routerEntry.getRouterName(), address);
443 } catch (UnknownHostException e) {
444 LOG.error("subnetRegisterMapping : Invalid ip address {}", subnetIp, e);
447 String subnetPrefix = "0";
448 if (subnetSplit.length == 2) {
449 subnetPrefix = subnetSplit[1];
451 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
452 LOG.debug("subnetRegisterMapping : subnetAddr is {} and subnetPrefix is {}",
453 subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
455 LOG.debug("subnetRegisterMapping : counter values counter {} and extIpCounter {}",
456 counter, extIpCounter);
457 if (extIpCounter != 0) {
458 if (counter < extIpCounter) {
459 String[] ipSplit = externalIps.get(counter).split("/");
460 String externalIp = ipSplit[0];
461 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
462 if (ipSplit.length == 2) {
463 extPrefix = ipSplit[1];
465 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
466 LOG.debug("subnetRegisterMapping : externalIp is {} and extPrefix is {}",
467 externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
468 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
469 LOG.debug("subnetRegisterMapping : Called registerMapping for subnetIp {}, prefix {}, "
470 + "externalIp {}. prefix {}", subnetIp, subnetPrefix, externalIp, extPrefix);
472 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
473 LOG.debug("subnetRegisterMapping : Counter on externalIps got reset");
474 String[] ipSplit = externalIps.get(counter).split("/");
475 String externalIp = ipSplit[0];
476 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
477 if (ipSplit.length == 2) {
478 extPrefix = ipSplit[1];
480 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
481 LOG.debug("subnetRegisterMapping : externalIp is {} and extPrefix is {}",
482 externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
483 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
484 LOG.debug("subnetRegisterMapping : Called registerMapping for subnetIp {}, prefix {}, "
485 + "externalIp {}. prefix {}", subnetIp, subnetPrefix,
486 externalIp, extPrefix);
490 LOG.debug("subnetRegisterMapping : Counter on externalIps incremented to {}", counter);
492 LOG.warn("subnetRegisterMapping : No internal subnets present in extRouters Model");
497 private void addOrDelDefFibRouteToSNAT(String routerName, Uint32 routerId, Uint32 bgpVpnId,
498 Uuid bgpVpnUuid, boolean create, TypedReadWriteTransaction<Configuration> confTx)
499 throws ExecutionException, InterruptedException {
500 //Check if BGP VPN exists. If exists then invoke the new method.
501 if (bgpVpnId != NatConstants.INVALID_ID) {
502 if (bgpVpnUuid != null) {
503 String bgpVpnName = bgpVpnUuid.getValue();
504 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}",
505 bgpVpnId, bgpVpnName);
506 RouterIds rtrs = new RouterIdsBuilder().withKey(new RouterIdsKey(bgpVpnId))
507 .setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
508 confTx.put(getRoutersIdentifier(bgpVpnId), rtrs, CREATE_MISSING_PARENTS);
511 addDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, bgpVpnId, confTx);
513 removeDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, bgpVpnId, confTx);
518 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
519 addOrDelDefaultFibRouteForSNAT(routerName, routerId, create, confTx);
522 private void addOrDelDefaultFibRouteForSNAT(String routerName, Uint32 routerId, boolean create,
523 TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
524 List<Uint64> switches = naptSwitchSelector.getDpnsForVpn(routerName);
525 if (switches.isEmpty()) {
526 LOG.info("addOrDelDefaultFibRouteForSNAT : No switches found for router {}", routerName);
529 if (routerId == NatConstants.INVALID_ID) {
530 LOG.error("addOrDelDefaultFibRouteForSNAT : Could not retrieve router Id for {} to program "
531 + "default NAT route in FIB", routerName);
534 for (Uint64 dpnId : switches) {
536 LOG.debug("addOrDelDefaultFibRouteForSNAT : installing default NAT route for router {} in dpn {} "
537 + "for the internal vpn-id {}", routerId, dpnId, routerId);
538 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId, confTx);
540 LOG.debug("addOrDelDefaultFibRouteForSNAT : removing default NAT route for router {} in dpn {} "
541 + "for the internal vpn-id {}", routerId, dpnId, routerId);
542 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId, confTx);
547 private void addDefaultFibRouteForSnatWithBgpVpn(String routerName, Uint32 routerId,
548 Uint32 bgpVpnId, TypedWriteTransaction<Configuration> confTx) {
549 List<Uint64> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
550 if (dpnIds.isEmpty()) {
551 LOG.error("addOrDelDefaultFibRouteForSNATWIthBgpVpn: No dpns are part of router {} to program "
552 + "default NAT flows for BGP-VPN {}", routerName, bgpVpnId);
555 for (Uint64 dpnId : dpnIds) {
556 if (bgpVpnId != NatConstants.INVALID_ID) {
557 LOG.debug("addOrDelDefaultFibRouteForSnatWithBgpVpn : installing default NAT route for router {} "
558 + "in dpn {} for the BGP vpnID {}", routerId, dpnId, bgpVpnId);
559 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId, confTx);
561 LOG.debug("addOrDelDefaultFibRouteForSnatWithBgpVpn : installing default NAT route for router {} "
562 + "in dpn {} for the internal vpn", routerId, dpnId);
563 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId, confTx);
568 private void removeDefaultFibRouteForSnatWithBgpVpn(String routerName, Uint32 routerId, Uint32 bgpVpnId,
569 TypedReadWriteTransaction<Configuration> confTx)
570 throws ExecutionException, InterruptedException {
571 List<Uint64> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
572 if (dpnIds.isEmpty()) {
573 LOG.error("addOrDelDefaultFibRouteForSNATWIthBgpVpn: No dpns are part of router {} to program "
574 + "default NAT flows for BGP-VPN {}", routerName, bgpVpnId);
577 for (Uint64 dpnId : dpnIds) {
578 if (bgpVpnId != NatConstants.INVALID_ID) {
579 LOG.debug("addOrDelDefaultFibRouteForSnatWithBgpVpn : removing default NAT route for router {} "
580 + "in dpn {} for the BGP vpnID {}", routerId, dpnId, bgpVpnId);
581 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId, confTx);
583 LOG.debug("addOrDelDefaultFibRouteForSnatWithBgpVpn : removing default NAT route for router {} "
584 + "in dpn {} for the internal vpn", routerId, dpnId);
585 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId, confTx);
590 protected void installOutboundMissEntry(String routerName, Uint32 routerId, Uint64 primarySwitchId,
591 TypedWriteTransaction<Configuration> confTx) {
592 LOG.debug("installOutboundMissEntry : Router ID from getVpnId {}", routerId);
593 if (routerId != NatConstants.INVALID_ID) {
594 LOG.debug("installOutboundMissEntry : Creating miss entry on primary {}, for router {}",
595 primarySwitchId, routerId);
596 createOutboundTblEntry(primarySwitchId, routerId, confTx);
598 LOG.error("installOutboundMissEntry : Unable to fetch Router Id for RouterName {}, failed to "
599 + "createAndInstallMissEntry", routerName);
603 public String getFlowRefOutbound(Uint64 dpnId, short tableId, Uint32 routerID, int protocol) {
604 return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
605 .FLOWID_SEPARATOR + routerID + NatConstants.FLOWID_SEPARATOR + protocol;
608 private String getFlowRefNaptPreFib(Uint64 dpnId, short tableId, Uint32 vpnId) {
609 return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
610 .FLOWID_SEPARATOR + vpnId;
613 public Uint64 getCookieOutboundFlow(Uint32 routerId) {
614 return Uint64.valueOf((NwConstants.COOKIE_OUTBOUND_NAPT_TABLE).toJava().add(
615 new BigInteger("0110001", 16)).add(BigInteger.valueOf(routerId.longValue())));
618 private ActionLearn getLearnActionForPunt(int protocol, int hardTimeout, Uint64 cookie) {
621 int l4portFieldLen = NxmOfFieldType.NXM_OF_TCP_SRC.getFlowModHeaderLenInt();
623 if (protocol == NwConstants.IP_PROT_TCP) {
624 l4SrcPortField = NxmOfFieldType.NXM_OF_TCP_SRC.getType();
625 l4DstPortField = NxmOfFieldType.NXM_OF_TCP_DST.getType();
627 l4SrcPortField = NxmOfFieldType.NXM_OF_UDP_SRC.getType();
628 l4DstPortField = NxmOfFieldType.NXM_OF_UDP_DST.getType();
630 List<ActionLearn.FlowMod> flowMods = Arrays.asList(
631 new MatchFromValue(NwConstants.ETHTYPE_IPV4, NxmOfFieldType.NXM_OF_ETH_TYPE.getType(),
632 NxmOfFieldType.NXM_OF_ETH_TYPE.getFlowModHeaderLenInt()),
633 new MatchFromValue(protocol, NxmOfFieldType.NXM_OF_IP_PROTO.getType(),
634 NxmOfFieldType.NXM_OF_IP_PROTO.getFlowModHeaderLenInt()),
635 new MatchFromField(NxmOfFieldType.NXM_OF_IP_SRC.getType(), NxmOfFieldType.NXM_OF_IP_SRC.getType(),
636 NxmOfFieldType.NXM_OF_IP_SRC.getFlowModHeaderLenInt()),
637 new MatchFromField(NxmOfFieldType.NXM_OF_IP_DST.getType(), NxmOfFieldType.NXM_OF_IP_DST.getType(),
638 NxmOfFieldType.NXM_OF_IP_DST.getFlowModHeaderLenInt()),
639 new MatchFromField(l4SrcPortField, l4SrcPortField, l4portFieldLen),
640 new MatchFromField(l4DstPortField, l4DstPortField, l4portFieldLen),
641 new MatchFromField(NxmOfFieldType.OXM_OF_METADATA.getType(),
642 MetaDataUtil.METADATA_VPN_ID_OFFSET,
643 NxmOfFieldType.OXM_OF_METADATA.getType(), MetaDataUtil.METADATA_VPN_ID_OFFSET,
644 MetaDataUtil.METADATA_VPN_ID_BITLEN));
646 return new ActionLearn(0, hardTimeout, 7, cookie, 0,
647 NwConstants.OUTBOUND_NAPT_TABLE, 0, 0, flowMods);
650 private FlowEntity buildIcmpDropFlow(Uint64 dpnId, Uint32 routerId, Uint32 vpnId) {
651 List<MatchInfo> matches = new ArrayList<>();
652 matches.add(MatchEthernetType.IPV4);
653 matches.add(MatchIpProtocol.ICMP);
654 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
655 MetaDataUtil.METADATA_MASK_VRFID));
657 List<ActionInfo> actionInfos = new ArrayList<>();
658 actionInfos.add(new ActionDrop());
660 List<InstructionInfo> instructions = new ArrayList<>();
661 instructions.add(new InstructionApplyActions(actionInfos));
663 String flowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId,
664 NwConstants.IP_PROT_ICMP);
665 FlowEntity flow = MDSALUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
666 NwConstants.TABLE_MISS_PRIORITY, "icmp drop flow", 0, 0,
667 NwConstants.COOKIE_OUTBOUND_NAPT_TABLE, matches, instructions);
671 protected FlowEntity buildOutboundFlowEntity(Uint64 dpId, Uint32 routerId, int protocol) {
672 LOG.debug("buildOutboundFlowEntity : called for dpId {} and routerId{}", dpId, routerId);
673 Uint64 cookie = getCookieOutboundFlow(routerId);
674 List<MatchInfo> matches = new ArrayList<>();
675 matches.add(MatchEthernetType.IPV4);
676 matches.add(new MatchIpProtocol((short)protocol));
677 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
678 MetaDataUtil.METADATA_MASK_VRFID));
680 List<InstructionInfo> instructions = new ArrayList<>();
681 List<ActionInfo> actionsInfos = new ArrayList<>();
682 actionsInfos.add(new ActionPuntToController());
683 if (snatPuntTimeout != 0) {
684 actionsInfos.add(getLearnActionForPunt(protocol, snatPuntTimeout, cookie));
686 instructions.add(new InstructionApplyActions(actionsInfos));
688 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, protocol);
689 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
691 cookie, matches, instructions);
692 LOG.debug("installOutboundMissEntry : returning flowEntity {}", flowEntity);
696 public void createOutboundTblEntry(Uint64 dpnId, Uint32 routerId, TypedWriteTransaction<Configuration> confTx) {
697 LOG.debug("createOutboundTblEntry : called for dpId {} and routerId {}", dpnId, routerId);
698 FlowEntity tcpflowEntity = buildOutboundFlowEntity(dpnId, routerId, NwConstants.IP_PROT_TCP);
699 LOG.debug("createOutboundTblEntry : Installing tcp flow {}", tcpflowEntity);
700 mdsalManager.addFlow(confTx, tcpflowEntity);
702 FlowEntity udpflowEntity = buildOutboundFlowEntity(dpnId, routerId, NwConstants.IP_PROT_UDP);
703 LOG.debug("createOutboundTblEntry : Installing udp flow {}", udpflowEntity);
704 mdsalManager.addFlow(confTx, udpflowEntity);
706 FlowEntity icmpDropFlow = buildIcmpDropFlow(dpnId, routerId, routerId);
707 LOG.debug("createOutboundTblEntry: Installing icmp drop flow {}", icmpDropFlow);
708 mdsalManager.addFlow(confTx, icmpDropFlow);
712 protected String getTunnelInterfaceName(Uint64 srcDpId, Uint64 dstDpId) {
713 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
714 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
716 Future<RpcResult<GetTunnelInterfaceNameOutput>> result =
717 itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
718 .setSourceDpid(srcDpId)
719 .setDestinationDpid(dstDpId)
720 .setTunnelType(tunType)
722 rpcResult = result.get();
723 if (!rpcResult.isSuccessful()) {
724 tunType = TunnelTypeGre.class;
725 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
726 .setSourceDpid(srcDpId)
727 .setDestinationDpid(dstDpId)
728 .setTunnelType(tunType)
730 rpcResult = result.get();
731 if (!rpcResult.isSuccessful()) {
732 LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
733 rpcResult.getErrors());
735 return rpcResult.getResult().getInterfaceName();
737 LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
738 rpcResult.getErrors());
740 return rpcResult.getResult().getInterfaceName();
742 } catch (InterruptedException | ExecutionException | NullPointerException e) {
743 LOG.error("getTunnelInterfaceName : Exception when getting tunnel interface Id for tunnel "
744 + "between {} and {}", srcDpId, dstDpId, e);
750 protected void installSnatMissEntryForPrimrySwch(Uint64 dpnId, String routerName, Uint32 routerId,
751 TypedWriteTransaction<Configuration> confTx) {
753 LOG.debug("installSnatMissEntry : called for for the primary NAPT switch dpnId {} ", dpnId);
754 // Install miss entry pointing to group
755 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName, routerId);
756 mdsalManager.addFlow(confTx, flowEntity);
759 protected void installSnatMissEntry(Uint64 dpnId, List<BucketInfo> bucketInfo,
760 String routerName, Uint32 routerId) {
761 LOG.debug("installSnatMissEntry : called for dpnId {} with primaryBucket {} ",
762 dpnId, bucketInfo.get(0));
763 // Install the select group
764 Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
765 NatUtil.getGroupIdKey(routerName));
766 if (groupId == NatConstants.INVALID_ID) {
767 LOG.error("installSnatMissEntry: Unable to obtain group ID for Key: {}", routerName);
770 GroupEntity groupEntity =
771 MDSALUtil.buildGroupEntity(dpnId, groupId.longValue(), routerName, GroupTypes.GroupAll, bucketInfo);
772 LOG.debug("installSnatMissEntry : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
773 mdsalManager.syncInstallGroup(groupEntity);
774 // Install miss entry pointing to group
775 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, routerId, groupId);
776 if (flowEntity == null) {
777 LOG.error("installSnatMissEntry : Flow entity received as NULL. "
778 + "Cannot proceed with installation of SNAT Flow in table {} which is pointing to Group "
779 + "on Non NAPT DPN {} for router {}", NwConstants.PSNAT_TABLE, dpnId, routerName);
782 mdsalManager.installFlow(flowEntity);
785 void installGroup(Uint64 dpnId, String routerName, Uint32 groupId, List<BucketInfo> bucketInfo) {
786 GroupEntity groupEntity =
787 MDSALUtil.buildGroupEntity(dpnId, groupId.longValue(), routerName, GroupTypes.GroupAll, bucketInfo);
788 LOG.debug("installGroup : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
789 mdsalManager.syncInstallGroup(groupEntity);
792 private FlowEntity buildSnatFlowEntity(Uint64 dpId, String routerName, Uint32 routerId, Uint32 groupId) {
793 LOG.debug("buildSnatFlowEntity : called for dpId {}, routerName {} and groupId {}",
794 dpId, routerName, groupId);
795 List<MatchInfo> matches = new ArrayList<>();
796 matches.add(MatchEthernetType.IPV4);
797 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
798 MetaDataUtil.METADATA_MASK_VRFID));
800 List<ActionInfo> actionsInfo = new ArrayList<>();
801 Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager, idManager,
802 routerId, routerName);
803 actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
804 LOG.debug("buildSnatFlowEntity : Setting the tunnel to the list of action infos {}", actionsInfo);
805 actionsInfo.add(new ActionGroup(groupId.longValue()));
806 List<InstructionInfo> instructions = new ArrayList<>();
807 instructions.add(new InstructionApplyActions(actionsInfo));
808 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
809 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
810 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
811 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
813 LOG.debug("buildSnatFlowEntity : Returning SNAT Flow Entity {}", flowEntity);
817 private FlowEntity buildSnatFlowEntityForPrmrySwtch(Uint64 dpId, String routerName, Uint32 routerId) {
819 LOG.debug("buildSnatFlowEntityForPrmrySwtch : called for primary NAPT switch dpId {}, routerName {}", dpId,
821 List<MatchInfo> matches = new ArrayList<>();
822 matches.add(MatchEthernetType.IPV4);
823 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
824 MetaDataUtil.METADATA_MASK_VRFID));
826 List<InstructionInfo> instructions = new ArrayList<>();
827 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
829 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
830 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
831 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
832 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
834 LOG.debug("buildSnatFlowEntityForPrmrySwtch : Returning SNAT Flow Entity {}", flowEntity);
838 // TODO : Replace this with ITM Rpc once its available with full functionality
839 protected void installTerminatingServiceTblEntry(Uint64 dpnId, String routerName, Uint32 routerId,
840 TypedWriteTransaction<Configuration> confTx) {
842 LOG.debug("installTerminatingServiceTblEntry : for switch {}, routerName {}",
844 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName, routerId);
845 if (flowEntity == null) {
846 LOG.error("installTerminatingServiceTblEntry : Flow entity received as NULL. "
847 + "Cannot proceed with installation of Terminating Service table {} which is pointing to table {} "
848 + "on DPN {} for router {}", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.OUTBOUND_NAPT_TABLE,
852 mdsalManager.addFlow(confTx, flowEntity);
856 private FlowEntity buildTsFlowEntity(Uint64 dpId, String routerName, Uint32 routerId) {
857 List<MatchInfo> matches = new ArrayList<>();
858 matches.add(MatchEthernetType.IPV4);
859 Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager,
860 idManager, routerId, routerName);
861 matches.add(new MatchTunnelId(tunnelId));
862 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, Uint32.valueOf(tunnelId.longValue()));
863 List<InstructionInfo> instructions = new ArrayList<>();
864 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
865 MetaDataUtil.METADATA_MASK_VRFID));
866 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
867 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
868 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
869 NwConstants.COOKIE_TS_TABLE, matches, instructions);
873 public String getFlowRefTs(Uint64 dpnId, short tableId, Uint32 routerID) {
874 return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
875 .FLOWID_SEPARATOR + routerID;
878 public static String getFlowRefSnat(Uint64 dpnId, short tableId, String routerID) {
879 return NatConstants.SNAT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
880 .FLOWID_SEPARATOR + routerID;
883 protected void handleSwitches(Uint64 dpnId, String routerName, Uint32 routerId, Uint64 primarySwitchId) {
884 LOG.debug("handleSwitches : Installing SNAT miss entry in switch {}", dpnId);
885 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
886 String ifNamePrimary = getTunnelInterfaceName(dpnId, primarySwitchId);
887 List<BucketInfo> listBucketInfo = new ArrayList<>();
889 if (ifNamePrimary != null) {
890 LOG.debug("handleSwitches : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
891 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
892 interfaceManager, ifNamePrimary, routerId, true);
893 if (listActionInfoPrimary.isEmpty()) {
894 LOG.error("handleSwitches : Unable to retrieve output actions on Non-NAPT switch {} for router {}"
895 + " towards Napt-switch {} via tunnel interface {}", dpnId, routerName, primarySwitchId,
899 LOG.error("handleSwitches : Unable to obtain primary tunnel interface to Napt-Switch {} from "
900 + "Non-Napt switch {} for router {}", primarySwitchId, dpnId, routerName);
902 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
904 listBucketInfo.add(0, bucketPrimary);
905 installSnatMissEntry(dpnId, listBucketInfo, routerName, routerId);
908 List<BucketInfo> getBucketInfoForNonNaptSwitches(Uint64 nonNaptSwitchId,
909 Uint64 primarySwitchId, String routerName, Uint32 routerId) {
910 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
911 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
912 List<BucketInfo> listBucketInfo = new ArrayList<>();
914 if (ifNamePrimary != null) {
915 LOG.debug("getBucketInfoForNonNaptSwitches : On Non- Napt switch , Primary Tunnel interface is {}",
917 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager,
918 interfaceManager, ifNamePrimary, routerId, true);
919 if (listActionInfoPrimary.isEmpty()) {
920 LOG.error("getBucketInfoForNonNaptSwitches : Unable to retrieve output actions on Non-NAPT switch {} "
921 + "for router {} towards Napt-switch {} via tunnel interface {}",
922 nonNaptSwitchId, routerName, primarySwitchId, ifNamePrimary);
925 LOG.error("getBucketInfoForNonNaptSwitches : Unable to obtain primary tunnel interface to Napt-Switch {} "
926 + "from Non-Napt switch {} for router {}", primarySwitchId, nonNaptSwitchId, routerName);
928 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
930 listBucketInfo.add(0, bucketPrimary);
931 return listBucketInfo;
934 protected void handlePrimaryNaptSwitch(Uint64 dpnId, String routerName, Uint32 routerId, Uuid externalNwUuid,
935 TypedWriteTransaction<Configuration> confTx) {
938 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
941 LOG.debug("handlePrimaryNaptSwitch : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
944 List<BucketInfo> listBucketInfo = new ArrayList<>();
945 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
946 listActionInfoPrimary.add(new ActionNxResubmit(NatConstants.TERMINATING_SERVICE_TABLE));
947 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
948 listBucketInfo.add(0, bucketPrimary);
951 installSnatMissEntryForPrimrySwch(dpnId, routerName, routerId, confTx);
952 installTerminatingServiceTblEntry(dpnId, routerName, routerId, confTx);
953 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
954 installNaptPfibEntry(dpnId, routerId, confTx);
955 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
956 if (networkId != null) {
957 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
958 if (vpnUuid != null) {
959 Uint32 extVpnId = NatUtil.getExternalVpnIdForExtNetwork(dataBroker, externalNwUuid);
960 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + networkId, () -> {
961 installNaptPfibEntriesForExternalSubnets(routerName, dpnId, null);
962 //Install the NAPT PFIB TABLE which forwards outgoing packet to FIB Table matching on the VPN ID.
963 if (extVpnId != null && extVpnId != NatConstants.INVALID_ID) {
964 installNaptPfibEntry(dpnId, extVpnId, null);
966 return Collections.emptyList();
969 LOG.warn("handlePrimaryNaptSwitch : External Vpn ID missing for Ext-Network : {}", networkId);
972 LOG.warn("handlePrimaryNaptSwitch : External Network not available for router : {}", routerName);
976 public void installNaptPfibEntry(Uint64 dpnId, Uint32 segmentId,
977 @Nullable TypedWriteTransaction<Configuration> confTx) {
978 LOG.debug("installNaptPfibEntry : called for dpnId {} and segmentId {} ", dpnId, segmentId);
979 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
980 if (confTx != null) {
981 mdsalManager.addFlow(confTx, naptPfibFlowEntity);
983 mdsalManager.installFlow(naptPfibFlowEntity);
987 public FlowEntity buildNaptPfibFlowEntity(Uint64 dpId, Uint32 segmentId) {
989 LOG.debug("buildNaptPfibFlowEntity : called for dpId {}, segmentId {}", dpId, segmentId);
990 List<MatchInfo> matches = new ArrayList<>();
991 matches.add(MatchEthernetType.IPV4);
992 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
993 MetaDataUtil.METADATA_MASK_VRFID));
995 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
996 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
997 listActionInfo.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
998 listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
999 instructionInfo.add(new InstructionApplyActions(listActionInfo));
1001 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
1002 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
1003 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
1004 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
1005 LOG.debug("buildNaptPfibFlowEntity : Returning NaptPFib Flow Entity {}", flowEntity);
1009 public void handleSnatReverseTraffic(TypedWriteTransaction<Configuration> confTx, Uint64 dpnId, Routers router,
1010 Uint32 routerId, String routerName, String externalIp) {
1011 LOG.debug("handleSnatReverseTraffic : entry for DPN ID {}, routerId {}, externalIp: {}",
1012 dpnId, routerId, externalIp);
1013 Uuid networkId = router.getNetworkId();
1014 if (networkId == null) {
1015 LOG.error("handleSnatReverseTraffic : networkId is null for the router ID {}", routerId);
1018 Collection<Uuid> externalSubnetList = NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps());
1019 // FLAT/VLAN case having external-subnet as VPN
1020 String externalSubnetVpn = null;
1021 if (externalSubnetList != null && !externalSubnetList.isEmpty()) {
1022 for (Uuid externalSubnetId : externalSubnetList) {
1023 Optional<Subnets> externalSubnet = NatUtil
1024 .getOptionalExternalSubnets(dataBroker, externalSubnetId);
1025 // externalSubnet data model will exist for FLAT/VLAN external netowrk UCs.
1026 if (externalSubnet.isPresent()) {
1027 externalSubnetVpn = externalSubnetId.getValue();
1028 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE,
1029 externalSubnetVpn, routerId, routerName,
1030 externalIp, networkId, router, confTx);
1035 // VXVLAN/GRE case having Internet-VPN
1036 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
1037 if (vpnName == null) {
1038 LOG.error("handleSnatReverseTraffic : No VPN associated with ext nw {} to handle add external ip "
1039 + "configuration {} in router {}", networkId, externalIp, routerId);
1042 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, routerName,
1043 externalIp, networkId, router, confTx);
1044 LOG.debug("handleSnatReverseTraffic : exit for DPN ID {}, routerId {}, externalIp : {}",
1045 dpnId, routerId, externalIp);
1048 public void advToBgpAndInstallFibAndTsFlows(final Uint64 dpnId, final short tableId, final String vpnName,
1049 final Uint32 routerId, final String routerName, final String externalIp,
1050 final Uuid extNetworkId, @Nullable final Routers router,
1051 final TypedWriteTransaction<Configuration> confTx) {
1052 LOG.debug("advToBgpAndInstallFibAndTsFlows : entry for DPN ID {}, tableId {}, vpnname {} "
1053 + "and externalIp {}", dpnId, tableId, vpnName, externalIp);
1054 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
1055 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1056 if (rd == null || rd.isEmpty()) {
1057 LOG.error("advToBgpAndInstallFibAndTsFlows : Unable to get RD for VPN Name {}", vpnName);
1060 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
1061 if (extNwProvType == null) {
1062 LOG.error("advToBgpAndInstallFibAndTsFlows : External Network Provider Type missing");
1065 if (extNwProvType == ProviderTypes.VXLAN) {
1066 evpnSnatFlowProgrammer.evpnAdvToBgpAndInstallFibAndTsFlows(dpnId, tableId, externalIp, vpnName, rd,
1067 nextHopIp, routerId, routerName, extNetworkId, confTx);
1070 //Generate VPN label for the external IP
1071 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName)
1072 .setIpPrefix(externalIp).build();
1073 ListenableFuture<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
1075 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
1076 ListenableFuture<RpcResult<CreateFibEntryOutput>> future = Futures.transformAsync(labelFuture, result -> {
1077 if (result.isSuccessful()) {
1078 LOG.debug("advToBgpAndInstallFibAndTsFlows : inside apply with result success");
1079 GenerateVpnLabelOutput output = result.getResult();
1080 final Uint32 label = output.getLabel();
1082 int externalIpInDsFlag = 0;
1083 //Get IPMaps from the DB for the router ID
1084 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1085 for (IpMap dbIpMap : dbIpMaps) {
1086 String dbExternalIp = dbIpMap.getExternalIp();
1087 //Select the IPMap, whose external IP is the IP for which FIB is installed
1088 if (dbExternalIp.contains(externalIp)) {
1089 String dbInternalIp = dbIpMap.getInternalIp();
1090 IpMapKey dbIpMapKey = dbIpMap.key();
1091 LOG.debug("advToBgpAndInstallFibAndTsFlows : Setting label {} for internalIp {} "
1092 + "and externalIp {}", label, dbInternalIp, externalIp);
1093 IpMap newIpm = new IpMapBuilder().withKey(dbIpMapKey).setInternalIp(dbInternalIp)
1094 .setExternalIp(dbExternalIp).setLabel(label).build();
1095 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
1096 naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
1097 externalIpInDsFlag++;
1100 if (externalIpInDsFlag <= 0) {
1101 LOG.debug("advToBgpAndInstallFibAndTsFlows : External Ip {} not found in DS, "
1102 + "Failed to update label {} for routerId {} in DS",
1103 externalIp, label, routerId);
1104 String errMsg = String.format("Failed to update label %s due to external Ip %s not"
1105 + " found in DS for router %s", label, externalIp, routerId);
1106 return Futures.immediateFailedFuture(new Exception(errMsg));
1109 Uint32 l3vni = Uint32.ZERO;
1110 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
1111 l3vni = natOverVxlanUtil.getInternetVpnVni(vpnName, l3vni);
1113 Routers extRouter = router != null ? router :
1114 NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
1115 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd,
1116 externalIp, nextHopIp, extRouter.getNetworkId().getValue(), null, label, l3vni,
1117 RouteOrigin.STATIC, dpnId);
1119 //Install custom FIB routes
1120 List<Instruction> tunnelTableCustomInstructions = new ArrayList<>();
1121 tunnelTableCustomInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
1122 makeTunnelTableEntry(dpnId, label, l3vni, tunnelTableCustomInstructions, confTx,
1124 makeLFibTableEntry(dpnId, label, tableId, confTx);
1126 //Install custom FIB routes - FIB table.
1127 List<Instruction> fibTableCustomInstructions = createFibTableCustomInstructions(tableId,
1128 routerName, externalIp);
1129 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
1130 //Install the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
1131 NatUtil.makePreDnatToSnatTableEntry(mdsalManager, dpnId, NwConstants.INBOUND_NAPT_TABLE, confTx);
1133 String externalVpn = vpnName;
1134 Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIp, extRouter);
1135 if (extNwProvType == ProviderTypes.VLAN || extNwProvType == ProviderTypes.FLAT) {
1136 Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker,
1138 if (externalSubnet.isPresent()) {
1139 externalVpn = externalSubnetId.getValue();
1142 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
1143 CreateFibEntryInput input = new CreateFibEntryInputBuilder()
1144 .setVpnName(externalVpn)
1145 .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(label)
1146 .setIpAddressSource(CreateFibEntryInput.IpAddressSource.ExternalFixedIP)
1147 .setInstruction(fibTableCustomInstructions).build();
1148 return fibService.createFibEntry(input);
1150 LOG.error("advToBgpAndInstallFibAndTsFlows : inside apply with result failed");
1151 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s",
1152 externalIp, vpnName, result.getErrors());
1153 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1155 }, MoreExecutors.directExecutor());
1157 Futures.addCallback(future, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
1160 public void onFailure(@NonNull Throwable error) {
1161 LOG.error("advToBgpAndInstallFibAndTsFlows : Error in generate label or fib install process", error);
1165 public void onSuccess(@NonNull RpcResult<CreateFibEntryOutput> result) {
1166 if (result.isSuccessful()) {
1167 LOG.info("advToBgpAndInstallFibAndTsFlows : Successfully installed custom FIB routes for prefix {}",
1170 LOG.error("advToBgpAndInstallFibAndTsFlows : Error in rpc call to create custom Fib entries "
1171 + "for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1174 }, MoreExecutors.directExecutor());
1177 private List<Instruction> createFibTableCustomInstructions(short tableId, String routerName,
1178 String externalIp) {
1179 List<Instruction> fibTableCustomInstructions = new ArrayList<>();
1180 Routers router = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
1181 Uint32 externalSubnetVpnId = NatUtil.getExternalSubnetVpnIdForRouterExternalIp(dataBroker,
1182 externalIp, router);
1183 int instructionIndex = 0;
1184 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
1185 Uint64 subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(externalSubnetVpnId.longValue());
1186 fibTableCustomInstructions.add(new InstructionWriteMetadata(subnetIdMetaData,
1187 MetaDataUtil.METADATA_MASK_VRFID).buildInstruction(instructionIndex));
1191 fibTableCustomInstructions.add(new InstructionGotoTable(tableId).buildInstruction(instructionIndex));
1192 return fibTableCustomInstructions;
1195 private void makeLFibTableEntry(Uint64 dpId, Uint32 serviceId, short tableId,
1196 TypedWriteTransaction<Configuration> confTx) {
1197 List<MatchInfo> matches = new ArrayList<>();
1198 matches.add(MatchEthernetType.MPLS_UNICAST);
1199 matches.add(new MatchMplsLabel(serviceId.longValue()));
1201 List<Instruction> instructions = new ArrayList<>();
1202 List<ActionInfo> actionsInfos = new ArrayList<>();
1203 //NAT is required for IPv4 only. Hence always etherType will be IPv4
1204 actionsInfos.add(new ActionPopMpls(NwConstants.ETHTYPE_IPV4));
1205 Instruction writeInstruction = new InstructionApplyActions(actionsInfos).buildInstruction(0);
1206 instructions.add(writeInstruction);
1207 instructions.add(new InstructionGotoTable(tableId).buildInstruction(1));
1209 // Install the flow entry in L3_LFIB_TABLE
1210 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1212 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1214 COOKIE_VM_LFIB_TABLE, matches, instructions);
1216 mdsalManager.addFlow(confTx, dpId, flowEntity);
1218 LOG.debug("makeLFibTableEntry : LFIB Entry for dpID {} : label : {} modified successfully", dpId, serviceId);
1221 private void makeTunnelTableEntry(Uint64 dpnId, Uint32 serviceId, Uint32 l3Vni,
1222 List<Instruction> customInstructions, TypedWriteTransaction<Configuration> confTx,
1223 ProviderTypes extNwProvType) {
1225 List<MatchInfo> mkMatches = new ArrayList<>();
1227 LOG.debug("makeTunnelTableEntry : DpnId = {} and serviceId = {} and actions = {}",
1228 dpnId, serviceId, customInstructions);
1230 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
1231 mkMatches.add(new MatchTunnelId(Uint64.valueOf(l3Vni)));
1233 mkMatches.add(new MatchTunnelId(Uint64.valueOf(serviceId)));
1236 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1237 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1238 NatConstants.DEFAULT_VPN_INTERNAL_TUNNEL_TABLE_PRIORITY,
1239 String.format("%s:%s", "TST Flow Entry ", serviceId), 0, 0,
1240 Uint64.valueOf(COOKIE_TUNNEL.toJava().add(BigInteger.valueOf(serviceId.longValue()))),
1241 mkMatches, customInstructions);
1243 mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
1246 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(Uint32 routerId) {
1247 return InstanceIdentifier.builder(RouterIdName.class).child(RouterIds.class,
1248 new RouterIdsKey(routerId)).build();
1251 private String getFlowRef(Uint64 dpnId, short tableId, Uint32 id, String ipAddress) {
1252 return NatConstants.SNAT_FLOWID_PREFIX + dpnId.toString() + NwConstants.FLOWID_SEPARATOR + tableId
1253 + NwConstants.FLOWID_SEPARATOR + id + NwConstants.FLOWID_SEPARATOR + ipAddress;
1257 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1258 LOG.trace("update : origRouter: {} updatedRouter: {}", original, update);
1259 String routerName = original.getRouterName();
1260 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
1261 if (routerId == NatConstants.INVALID_ID) {
1262 LOG.error("update : external router event - Invalid routerId for routerName {}", routerName);
1265 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.key(), () -> {
1266 List<ListenableFuture<Void>> futures = new ArrayList<>();
1267 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeFlowInvTx -> {
1268 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, removeFlowInvTx -> {
1269 Uint32 bgpVpnId = NatConstants.INVALID_ID;
1270 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
1271 if (bgpVpnUuid != null) {
1272 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
1274 //BigInteger dpnId = getPrimaryNaptSwitch(routerName);
1275 /* Get Primary Napt Switch for existing router from "router-to-napt-switch" DS.
1276 * if dpnId value is null or zero then go for electing new Napt switch for existing router.
1278 Uint64 dpnId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
1279 boolean isPrimaryNaptSwitchNotSelected = (dpnId == null || dpnId.equals(Uint64
1280 .valueOf(BigInteger.ZERO)));
1281 Uuid networkId = original.getNetworkId();
1282 // Check if its update on SNAT flag
1283 boolean originalSNATEnabled = original.isEnableSnat();
1284 boolean updatedSNATEnabled = update.isEnableSnat();
1285 LOG.debug("update :called with originalFlag and updatedFlag for SNAT enabled "
1286 + "as {} and {} with Elected Dpn {}(isPrimaryNaptSwitchNotSelected:{})",
1287 originalSNATEnabled, updatedSNATEnabled, dpnId, isPrimaryNaptSwitchNotSelected);
1288 // Cluster Reboot Case Handling
1289 // 1. DPN not elected during add event(due to none of the OVS connected)
1290 // 2. Update event called with changes of parameters(but enableSnat is not changed)
1291 // 3. First Elect dpnId and process other changes with valid dpnId
1292 if (originalSNATEnabled != updatedSNATEnabled || isPrimaryNaptSwitchNotSelected) {
1293 if (originalSNATEnabled && !updatedSNATEnabled) {
1294 if (isPrimaryNaptSwitchNotSelected) {
1295 LOG.info("No Action to be taken when SNAT is disabled "
1296 + "with no Napt Switch Election for Router {}", routerName);
1299 //SNAT disabled for the router
1300 Uuid networkUuid = original.getNetworkId();
1301 LOG.info("update : SNAT disabled for Router {}", routerName);
1302 Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1303 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
1304 handleDisableSnat(original, networkUuid, externalIps, false, vpnName,
1305 dpnId, routerId, removeFlowInvTx);
1306 } else if (updatedSNATEnabled) {
1307 LOG.info("update : SNAT enabled for Router {}", routerName);
1308 addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid,
1309 true, writeFlowInvTx);
1310 if (isPrimaryNaptSwitchNotSelected) {
1311 dpnId = selectNewNAPTSwitch(routerName);
1312 if (dpnId != null && !dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
1313 handleEnableSnat(update, routerId, dpnId, bgpVpnId, removeFlowInvTx);
1315 LOG.error("update : Failed to elect Napt Switch During update event"
1316 + " of router {}", routerName);
1320 LOG.info("update : no need to process external/subnet changes as it's will taken care"
1321 + "in handleDisableSnat/handleEnableSnat");
1324 if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
1325 NatUtil.installRouterGwFlows(txRunner, vpnManager, original, dpnId, NwConstants.DEL_FLOW);
1326 NatUtil.installRouterGwFlows(txRunner, vpnManager, update, dpnId, NwConstants.ADD_FLOW);
1329 if (updatedSNATEnabled != originalSNATEnabled) {
1330 LOG.info("update : no need to process external/subnet changes as it's will taken care in "
1331 + "handleDisableSnat/handleEnableSnat");
1334 //Check if the Update is on External IPs
1335 LOG.debug("update : Checking if this is update on External IPs for router {}", routerName);
1336 List<String> originalExternalIps = NatUtil.getIpsListFromExternalIps(original.getExternalIps());
1337 List<String> updatedExternalIps = NatUtil.getIpsListFromExternalIps(update.getExternalIps());
1339 //Check if the External IPs are removed during the update.
1340 Set<String> removedExternalIps = new HashSet<>(originalExternalIps);
1341 removedExternalIps.removeAll(updatedExternalIps);
1342 if (removedExternalIps.size() > 0) {
1343 LOG.debug("update : Start processing of the External IPs removal for router {}", routerName);
1344 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
1345 removedExternalIps, original.getExtGwMacAddress(),
1348 for (String removedExternalIp : removedExternalIps) {
1350 1) Remove the mappings in the IntExt IP model which has external IP.
1351 2) Remove the external IP in the ExternalCounter model.
1352 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the
1353 least loaded external IP.
1354 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1355 4) Increase the count of the allocated external IP by one.
1356 5) Advertise to the BGP if external IP is allocated for the first time for the router
1357 i.e. the route for the external IP is absent.
1358 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for
1359 the removed external IPs and also from the model.
1360 7) Advertise to the BGP for removing the route for the removed external IPs.
1363 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1364 String externalIp = externalIpParts[0];
1365 String externalIpPrefix = externalIpParts[1];
1366 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1368 LOG.debug("update : Clear the routes from the BGP and remove the FIB and TS "
1369 + "entries for removed external IP {}", externalIpAddrStr);
1370 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1371 String vpnName = "";
1372 if (vpnUuId != null) {
1373 vpnName = vpnUuId.getValue();
1375 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName, networkId,
1376 update.getExtGwMacAddress(), removeFlowInvTx);
1378 LOG.debug("update : Remove the mappings in the IntExtIP model which has external IP.");
1379 //Get the internal IPs which are associated to the removed external IPs
1380 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1381 List<String> removedInternalIps = new ArrayList<>();
1382 for (IpMap ipMap : ipMaps) {
1383 if (ipMap.getExternalIp().equals(externalIpAddrStr)) {
1384 removedInternalIps.add(ipMap.getInternalIp());
1388 LOG.debug("update : Remove the mappings of the internal IPs from the IntExtIP model.");
1389 for (String removedInternalIp : removedInternalIps) {
1390 LOG.debug("update : Remove the IP mapping of the internal IP {} for the "
1391 + "router ID {} from the IntExtIP model",
1392 removedInternalIp, routerId);
1393 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1396 LOG.debug("update : Remove the count mapping of the external IP {} for the "
1397 + "router ID {} from the ExternalIpsCounter model.",
1398 externalIpAddrStr, routerId);
1399 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1401 LOG.debug("update : Allocate the least loaded external IPs to the subnets "
1402 + "whose external IPs were removed.");
1403 for (String removedInternalIp : removedInternalIps) {
1404 allocateExternalIp(dpnId, update, routerId, routerName, networkId,
1405 removedInternalIp, writeFlowInvTx);
1407 LOG.debug("update : Remove the NAPT translation entries from "
1408 + "Inbound and Outbound NAPT tables for the removed external IPs.");
1409 //Get the internalIP and internal Port which were associated to the removed external IP.
1410 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1411 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier
1412 .builder(IntextIpPortMap.class)
1413 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1414 Optional<IpPortMapping> ipPortMapping;
1416 ipPortMapping = SingleTransactionDataBroker
1417 .syncReadOptional(dataBroker,
1418 LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1419 } catch (ReadFailedException e) {
1420 LOG.error("Failed to read ipPortMapping for router id {}", routerId, e);
1421 ipPortMapping = Optional.absent();
1424 if (ipPortMapping.isPresent()) {
1425 for (IntextIpProtocolType intextIpProtocolType :
1426 ipPortMapping.get().nonnullIntextIpProtocolType()) {
1427 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1428 for (IpPortMap ipPortMap : intextIpProtocolType.nonnullIpPortMap()) {
1429 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1430 if (ipPortExternal.getIpAddress().equals(externalIp)) {
1431 List<String> removedInternalIpPorts =
1432 protoTypesIntIpPortsMap.get(protoType);
1433 if (removedInternalIpPorts != null) {
1434 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1435 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1437 removedInternalIpPorts = new ArrayList<>();
1438 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1439 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1446 //Remove the IP port map from the intext-ip-port-map model, which were containing
1447 // the removed external IP.
1448 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts =
1449 protoTypesIntIpPortsMap.entrySet();
1450 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1451 for (Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts) {
1452 ProtocolTypes protocolType = (ProtocolTypes) protoTypesIntIpPort.getKey();
1453 List<String> removedInternalIpPorts = (List<String>) protoTypesIntIpPort.getValue();
1454 for (String removedInternalIpPort : removedInternalIpPorts) {
1455 // Remove the IP port map from the intext-ip-port-map model,
1456 // which were containing the removed external IP
1457 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort,
1459 //Remove the IP port incomint packer map.
1460 naptPacketInHandler.removeIncomingPacketMap(
1461 routerId + NatConstants.COLON_SEPARATOR + removedInternalIpPort);
1462 String[] removedInternalIpPortParts = removedInternalIpPort
1463 .split(NatConstants.COLON_SEPARATOR);
1464 if (removedInternalIpPortParts.length == 2) {
1465 String removedInternalIp = removedInternalIpPortParts[0];
1466 String removedInternalPort = removedInternalIpPortParts[1];
1467 List<String> removedInternalPortsList =
1468 internalIpPortMap.get(removedInternalPort);
1469 if (removedInternalPortsList != null) {
1470 removedInternalPortsList.add(removedInternalPort);
1471 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1472 naptPacketInHandler.removeIncomingPacketMap(routerId
1473 + NatConstants.COLON_SEPARATOR + removedInternalIp
1474 + NatConstants.COLON_SEPARATOR + removedInternalPort);
1475 //Remove the NAPT translation entries from Outbound NAPT table
1476 naptEventHandler.removeNatFlows(dpnId,
1477 NwConstants.OUTBOUND_NAPT_TABLE,
1478 routerId, removedInternalIp,
1479 Integer.parseInt(removedInternalPort),
1480 protocolType.getName());
1481 naptEventHandler.removeNatFlows(dpnId,
1482 NwConstants.INBOUND_NAPT_TABLE,
1483 routerId, removedInternalIp,
1484 Integer.parseInt(removedInternalPort),
1485 protocolType.getName());
1487 removedInternalPortsList = new ArrayList<>();
1488 removedInternalPortsList.add(removedInternalPort);
1489 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1490 naptPacketInHandler.removeIncomingPacketMap(routerId
1491 + NatConstants.COLON_SEPARATOR + removedInternalIp
1492 + NatConstants.COLON_SEPARATOR + removedInternalPort);
1493 //Remove the NAPT translation entries from Outbound NAPT table
1494 naptEventHandler.removeNatFlows(dpnId,
1495 NwConstants.OUTBOUND_NAPT_TABLE,
1496 routerId, removedInternalIp,
1497 Integer.parseInt(removedInternalPort),
1498 protocolType.getName());
1499 naptEventHandler.removeNatFlows(dpnId,
1500 NwConstants.INBOUND_NAPT_TABLE, routerId, removedInternalIp,
1501 Integer.parseInt(removedInternalPort),
1502 protocolType.getName());
1508 // Delete the entry from SnatIntIpPortMap DS
1509 Set<String> internalIps = internalIpPortMap.keySet();
1510 for (String internalIp : internalIps) {
1511 LOG.debug("update : Removing IpPort having the internal IP {} from the "
1512 + "model SnatIntIpPortMap", internalIp);
1513 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1516 naptManager.removeNaptPortPool(externalIp);
1519 "update : End processing of the External IPs removal for router {}", routerName);
1522 //Check if the External IPs are added during the update.
1523 Set<String> addedExternalIps = new HashSet<>(updatedExternalIps);
1524 addedExternalIps.removeAll(originalExternalIps);
1525 if (addedExternalIps.size() != 0) {
1526 LOG.debug("update : Start processing of the External IPs addition for router {}",
1528 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps,
1529 update.getExtGwMacAddress(), dpnId,
1530 update.getNetworkId());
1532 for (String addedExternalIp : addedExternalIps) {
1534 1) Do nothing in the IntExtIp model.
1535 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1537 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1538 String externalIp = externalIpParts[0];
1539 String externalIpPrefix = externalIpParts[1];
1540 String externalpStr = externalIp + "/" + externalIpPrefix;
1541 LOG.debug("update : Initialise the count mapping of the external IP {} for the "
1542 + "router ID {} in the ExternalIpsCounter model.",
1543 externalpStr, routerId);
1544 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1545 subnetRegisterMapping(update, routerId);
1546 LOG.info("update : Installing fib flow fo newly added Ips");
1547 handleSnatReverseTraffic(writeFlowInvTx, dpnId, update, routerId, routerName, externalpStr);
1550 "update : End processing of the External IPs addition during the update operation");
1553 //Check if its Update on subnets
1554 LOG.debug("update : Checking if this is update on subnets for router {}", routerName);
1555 List<Uuid> originalSubnetIds = original.getSubnetIds();
1556 List<Uuid> updatedSubnetIds = update.getSubnetIds();
1557 Set<Uuid> addedSubnetIds =
1558 updatedSubnetIds != null ? new HashSet<>(updatedSubnetIds) : new HashSet<>();
1559 if (originalSubnetIds != null) {
1560 addedSubnetIds.removeAll(originalSubnetIds);
1563 //Check if the Subnet IDs are added during the update.
1564 if (addedSubnetIds.size() != 0) {
1566 "update : Start processing of the Subnet IDs addition for router {}", routerName);
1567 for (Uuid addedSubnetId : addedSubnetIds) {
1569 1) Select the least loaded external IP for the subnet and store the mapping of the
1570 subnet IP and the external IP in the IntExtIp model.
1571 2) Increase the count of the selected external IP by one.
1572 3) Advertise to the BGP if external IP is allocated for the first time for the
1573 router i.e. the route for the external IP is absent.
1575 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1576 if (subnetIp != null) {
1577 allocateExternalIp(dpnId, update, routerId, routerName, networkId, subnetIp,
1581 LOG.debug("update : End processing of the Subnet IDs addition for router {}", routerName);
1584 //Check if the Subnet IDs are removed during the update.
1585 Set<Uuid> removedSubnetIds = new HashSet<>(originalSubnetIds);
1586 removedSubnetIds.removeAll(updatedSubnetIds);
1587 if (removedSubnetIds.size() != 0) {
1589 "update : Start processing of the Subnet IDs removal for router {}", routerName);
1590 for (Uuid removedSubnetId : removedSubnetIds) {
1591 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1592 if (subnetAddr != null) {
1594 1) Remove the subnet IP and the external IP in the IntExtIp map
1595 2) Decrease the count of the coresponding external IP by one.
1596 3) Advertise to the BGP for removing the routes of the corresponding external
1597 IP if its not allocated to any other internal IP.
1600 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId,
1601 subnetAddr[0] + "/" + subnetAddr[1]);
1602 if (externalIp == null) {
1603 LOG.error("update : No mapping found for router ID {} and internal IP {}",
1604 routerId, subnetAddr[0]);
1608 naptManager.updateCounter(routerId, externalIp, false);
1609 // Traverse entire model of external-ip counter whether external ip is not
1610 // used by any other internal ip in any router
1611 if (!isExternalIpAllocated(externalIp)) {
1612 LOG.debug("update : external ip is not allocated to any other "
1613 + "internal IP so proceeding to remove routes");
1614 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId,
1615 Collections.singleton(externalIp), null, update.getExtGwMacAddress(),
1617 LOG.debug("update : Successfully removed fib entries in switch {} for "
1618 + "router {} with networkId {} and externalIp {}",
1619 dpnId, routerId, networkId, externalIp);
1622 LOG.debug("update : Remove the IP mapping for the router ID {} and "
1623 + "internal IP {} external IP {}", routerId, subnetAddr[0], externalIp);
1624 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1627 LOG.debug("update : End processing of the Subnet IDs removal for router {}", routerName);
1632 }, NatConstants.NAT_DJC_MAX_RETRIES);
1635 private boolean isExternalIpAllocated(String externalIp) {
1636 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1637 Optional<ExternalIpsCounter> externalCountersData;
1639 externalCountersData = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1640 LogicalDatastoreType.OPERATIONAL, id);
1641 } catch (ReadFailedException e) {
1642 LOG.error("Failed to read external counters data for ExternalIp {}", externalIp, e);
1643 externalCountersData = Optional.absent();
1645 if (externalCountersData.isPresent()) {
1646 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1647 for (ExternalCounters ext : externalIpsCounters.nonnullExternalCounters()) {
1648 for (ExternalIpCounter externalIpCount : ext.nonnullExternalIpCounter()) {
1649 if (externalIpCount.getExternalIp().equals(externalIp)) {
1650 if (externalIpCount.getCounter().toJava() != 0) {
1661 private void allocateExternalIp(Uint64 dpnId, Routers router, Uint32 routerId, String routerName,
1662 Uuid networkId, String subnetIp, TypedWriteTransaction<Configuration> writeFlowInvTx) {
1663 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1665 InetAddress address = InetAddress.getByName(subnetIpParts[0]);
1666 if (address instanceof Inet6Address) {
1667 LOG.debug("allocateExternalIp : Skipping ipv6 address {} for the router {}.", address, routerName);
1670 } catch (UnknownHostException e) {
1671 LOG.error("allocateExternalIp : Invalid ip address {}", subnetIpParts[0], e);
1674 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1675 if (leastLoadedExtIpAddr != null) {
1676 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1677 String leastLoadedExtIp = externalIpParts[0];
1678 String leastLoadedExtIpPrefix = externalIpParts[1];
1679 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1680 subnetIp = subnetIpParts[0];
1681 String subnetIpPrefix = subnetIpParts[1];
1682 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1683 LOG.debug("allocateExternalIp : Add the IP mapping for the router ID {} and internal "
1684 + "IP {} and prefix {} -> external IP {} and prefix {}",
1685 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1686 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1689 // Check if external IP is already assigned a route. (i.e. External IP is previously
1690 // allocated to any of the subnets)
1691 // If external IP is already assigned a route, (, do not re-advertise to the BGP
1692 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1693 Uint32 label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1694 if (label != null) {
1696 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1697 IpMapKey ipMapKey = new IpMapKey(internalIp);
1698 LOG.debug("allocateExternalIp : Setting label {} for internalIp {} and externalIp {}",
1699 label, internalIp, leastLoadedExtIpAddrStr);
1700 IpMap newIpm = new IpMapBuilder().withKey(ipMapKey).setInternalIp(internalIp)
1701 .setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1702 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
1703 naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1707 // Re-advertise to the BGP for the external IP, which is allocated to the subnet
1708 // for the first time and hence not having a route.
1709 //Get the VPN Name using the network ID
1710 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
1711 if (vpnName != null) {
1712 LOG.debug("allocateExternalIp : Retrieved vpnName {} for networkId {}", vpnName, networkId);
1713 if (dpnId == null || dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
1714 LOG.debug("allocateExternalIp : Best effort for getting primary napt switch when router i/f are"
1715 + "added after gateway-set");
1716 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1717 if (dpnId == null || dpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
1718 LOG.error("allocateExternalIp : dpnId is null or Zero for the router {}", routerName);
1722 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, routerName,
1723 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, networkId, router,
1730 protected Uint32 checkExternalIpLabel(Uint32 routerId, String externalIp) {
1731 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1732 for (IpMap ipMap : ipMaps) {
1733 if (ipMap.getExternalIp().equals(externalIp)) {
1734 if (ipMap.getLabel() != null) {
1735 return ipMap.getLabel();
1739 LOG.error("checkExternalIpLabel : no ipMaps found for routerID:{} and externalIP:{}", routerId, externalIp);
1744 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1745 LOG.trace("remove : Router delete method");
1747 ROUTER DELETE SCENARIO
1748 1) Get the router ID from the event.
1749 2) Build the cookie information from the router ID.
1750 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1751 4) Build the flow with the cookie value.
1752 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1753 6) Remove the flows from the other switches which points to the primary and secondary
1754 switches for the flows related the router ID.
1755 7) Get the list of external IP address maintained for the router ID.
1756 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1757 9) Withdraw the corresponding routes from the BGP.
1760 if (identifier == null || router == null) {
1761 LOG.error("remove : returning without processing since routers is null");
1765 String routerName = router.getRouterName();
1766 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + router.key(),
1767 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
1768 LOG.info("remove : Removing default NAT route from FIB on all dpns part of router {} ",
1770 Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
1771 if (routerId == NatConstants.INVALID_ID) {
1772 LOG.error("remove : Remove external router event - Invalid routerId for routerName {}",
1776 Uint32 bgpVpnId = NatConstants.INVALID_ID;
1777 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
1778 if (bgpVpnUuid != null) {
1779 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
1781 addOrDelDefFibRouteToSNAT(routerName, routerId, bgpVpnId, bgpVpnUuid, false,
1783 Uuid networkUuid = router.getNetworkId();
1785 Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
1786 if (primarySwitchId == null || primarySwitchId.equals(Uint64.ZERO)) {
1787 // No NAPT switch for external router, probably because the router is not attached to
1789 // internal networks
1791 "No NAPT switch for router {}, check if router is attached to any internal "
1796 Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1797 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid);
1798 handleDisableSnat(router, networkUuid, externalIps, true, vpnName, primarySwitchId,
1801 if (NatUtil.releaseId(idManager, NatConstants.ODL_VNI_POOL_NAME, routerName)
1802 == NatConstants.INVALID_ID) {
1803 LOG.error("remove: Unable to release VNI for router - {}", routerName);
1805 })), NatConstants.NAT_DJC_MAX_RETRIES);
1808 public void handleDisableSnat(Routers router, Uuid networkUuid, @NonNull Collection<String> externalIps,
1809 boolean routerFlag, @Nullable String vpnName, Uint64 naptSwitchDpnId,
1810 Uint32 routerId, TypedReadWriteTransaction<Configuration> removeFlowInvTx) {
1811 LOG.info("handleDisableSnat : Entry");
1812 String routerName = router.getRouterName();
1815 removeNaptSwitch(routerName);
1817 updateNaptSwitch(routerName, Uint64.valueOf(BigInteger.ZERO));
1820 LOG.debug("handleDisableSnat : Remove the ExternalCounter model for the router ID {}", routerId);
1821 naptManager.removeExternalCounter(routerId);
1823 LOG.debug("handleDisableSnat : got primarySwitch as dpnId {}", naptSwitchDpnId);
1824 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(Uint64.valueOf(BigInteger.ZERO))) {
1825 LOG.error("handleDisableSnat : Unable to retrieve the primary NAPT switch for the "
1826 + "router ID {} from RouterNaptSwitch model", routerId);
1829 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
1831 if (extNwProvType == null) {
1832 LOG.error("handleDisableSnat : External Network Provider Type missing");
1835 Collection<Uuid> externalSubnetList = NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps());
1836 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnName, externalIps,
1837 externalSubnetList, removeFlowInvTx, extNwProvType);
1838 removeFlowsFromNonActiveSwitches(routerId, routerName, naptSwitchDpnId, removeFlowInvTx);
1839 String externalSubnetVpn = null;
1840 for (Uuid externalSubnetId : externalSubnetList) {
1841 Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker, externalSubnetId);
1842 // externalSubnet data model will exist for FLAT/VLAN external netowrk UCs.
1843 if (externalSubnet.isPresent()) {
1844 externalSubnetVpn = externalSubnetId.getValue();
1845 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, externalSubnetVpn,
1846 router.getExtGwMacAddress(), removeFlowInvTx);
1849 if (externalSubnetVpn == null) {
1850 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnName,
1851 router.getExtGwMacAddress(), removeFlowInvTx);
1853 // Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained
1854 // for the router ID.
1855 LOG.debug("handleDisableSnat : Remove the Internal to external IP address maintained for the "
1856 + "router ID {} in the DS", routerId);
1857 naptManager.removeMapping(routerId);
1858 } catch (InterruptedException | ExecutionException e) {
1859 LOG.error("handleDisableSnat : Exception while handling disableSNAT for router :{}", routerName, e);
1861 LOG.info("handleDisableSnat : Exit");
1864 // TODO Clean up the exception handling
1865 @SuppressWarnings("checkstyle:IllegalCatch")
1866 public void handleDisableSnatInternetVpn(String routerName, Uint32 routerId, Uuid networkUuid,
1867 @NonNull Collection<String> externalIps,
1868 String vpnId, TypedReadWriteTransaction<Configuration> writeFlowInvTx) {
1869 LOG.debug("handleDisableSnatInternetVpn: Started to process handle disable snat for router {} "
1870 + "with internet vpn {}", routerName, vpnId);
1872 Uint64 naptSwitchDpnId = null;
1873 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch =
1874 NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1875 Optional<RouterToNaptSwitch> rtrToNapt;
1877 rtrToNapt = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1878 LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1879 } catch (ReadFailedException e) {
1880 LOG.error("Failed to read NAPT switch for router {}", routerName, e);
1881 rtrToNapt = Optional.absent();
1883 if (rtrToNapt.isPresent()) {
1884 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1886 LOG.debug("handleDisableSnatInternetVpn : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1888 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId,
1891 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
1892 if (extGwMacAddress != null) {
1893 LOG.debug("handleDisableSnatInternetVpn : External Gateway MAC address {} found for "
1894 + "External Router ID {}", extGwMacAddress, routerId);
1896 LOG.error("handleDisableSnatInternetVpn : No External Gateway MAC address found for "
1897 + "External Router ID {}", routerId);
1900 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId, extGwMacAddress,
1902 } catch (Exception ex) {
1903 LOG.error("handleDisableSnatInternetVpn : Failed to remove fib entries for routerId {} "
1904 + "in naptSwitchDpnId {}", routerId, naptSwitchDpnId, ex);
1906 if (NatUtil.releaseId(idManager, NatConstants.ODL_VNI_POOL_NAME, vpnId) == NatConstants.INVALID_ID) {
1907 LOG.error("handleDisableSnatInternetVpn : Unable to release VNI for vpnId {} ", vpnId);
1909 } catch (InterruptedException | ExecutionException e) {
1910 LOG.error("handleDisableSnatInternetVpn: Exception while handling disableSNATInternetVpn for router {} "
1911 + "with internet vpn {}", routerName, vpnId, e);
1913 LOG.debug("handleDisableSnatInternetVpn: Processed handle disable snat for router {} with internet vpn {}",
1917 // TODO Clean up the exception handling
1918 @SuppressWarnings("checkstyle:IllegalCatch")
1919 public void updateNaptSwitch(String routerName, Uint64 naptSwitchId) {
1920 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().withKey(new RouterToNaptSwitchKey(routerName))
1921 .setPrimarySwitchId(naptSwitchId).build();
1923 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1924 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1925 } catch (Exception ex) {
1926 LOG.error("updateNaptSwitch : Failed to write naptSwitch {} for router {} in ds",
1927 naptSwitchId, routerName);
1929 LOG.debug("updateNaptSwitch : Successfully updated naptSwitch {} for router {} in ds",
1930 naptSwitchId, routerName);
1933 protected void removeNaptSwitch(String routerName) {
1934 // Remove router and switch from model
1935 InstanceIdentifier<RouterToNaptSwitch> id =
1936 InstanceIdentifier.builder(NaptSwitches.class)
1937 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1938 LOG.debug("removeNaptSwitch : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1939 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1940 //Release allocated router_lPort_tag from the ID Manager if Router is on L3VPNOverVxlan
1941 NatEvpnUtil.releaseLPortTagForRouter(dataBroker, idManager, routerName);
1944 public void removeNaptFlowsFromActiveSwitch(Uint32 routerId, String routerName,
1945 Uint64 dpnId, Uuid networkId, String vpnName,
1946 @NonNull Collection<String> externalIps,
1947 Collection<Uuid> externalSubnetList,
1948 TypedReadWriteTransaction<Configuration> confTx,
1949 ProviderTypes extNwProvType)
1950 throws InterruptedException, ExecutionException {
1952 LOG.debug("removeNaptFlowsFromActiveSwitch : Remove NAPT flows from Active switch");
1953 Uint64 cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1955 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1956 // traffic which comes from the VMs of the NAPT switches)
1957 String preSnatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1958 FlowEntity preSnatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, preSnatFlowRef);
1961 "removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active switch with the DPN ID {} "
1962 + "and router ID {}", NwConstants.PSNAT_TABLE, dpnId, routerId);
1963 mdsalManager.removeFlow(confTx, preSnatFlowEntity);
1965 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1966 // traffic which comes from the VMs of the non NAPT switches)
1967 Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil,
1968 elanManager, idManager, routerId, routerName);
1969 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, Uint32.valueOf(tunnelId.longValue()));
1970 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1972 "removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active switch with the DPN ID {} "
1973 + "and router ID {}", NwConstants.INTERNAL_TUNNEL_TABLE, dpnId, routerId);
1974 mdsalManager.removeFlow(confTx, tsNatFlowEntity);
1976 //Remove the flow table 25->44 from NAPT Switch
1977 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
1978 NatUtil.removePreDnatToSnatTableEntry(confTx, mdsalManager, dpnId);
1981 //Remove the Outbound flow entry which forwards the packet to FIB Table
1983 "removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active switch with the DPN ID {}"
1984 + " and router ID {}", NwConstants.OUTBOUND_NAPT_TABLE, dpnId, routerId);
1986 String outboundTcpNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId,
1987 NwConstants.IP_PROT_TCP);
1988 FlowEntity outboundTcpNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
1989 outboundTcpNatFlowRef);
1990 mdsalManager.removeFlow(confTx, outboundTcpNatFlowEntity);
1992 String outboundUdpNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId,
1993 NwConstants.IP_PROT_UDP);
1994 FlowEntity outboundUdpNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
1995 outboundUdpNatFlowRef);
1996 mdsalManager.removeFlow(confTx, outboundUdpNatFlowEntity);
1998 String icmpDropFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId,
1999 NwConstants.IP_PROT_ICMP);
2000 FlowEntity icmpDropFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
2002 mdsalManager.removeFlow(confTx, icmpDropFlowEntity);
2003 boolean lastRouterOnExternalNetwork =
2004 !NatUtil.checkForRoutersWithSameExtNetAndNaptSwitch(dataBroker, networkId, routerName, dpnId);
2005 if (lastRouterOnExternalNetwork) {
2006 removeNaptFibExternalOutputFlows(routerId, dpnId, networkId, externalIps, confTx);
2008 //Remove the NAPT PFIB TABLE (47->21) which forwards the incoming packet to FIB Table matching on the
2009 // External Subnet Vpn Id.
2010 for (Uuid externalSubnetId : externalSubnetList) {
2011 Uint32 subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
2012 if (subnetVpnId != NatConstants.INVALID_ID && !NatUtil.checkForRoutersWithSameExtSubnetAndNaptSwitch(
2013 dataBroker, externalSubnetId, routerName, dpnId)) {
2014 String natPfibSubnetFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, subnetVpnId);
2015 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE,
2016 natPfibSubnetFlowRef);
2017 mdsalManager.removeFlow(confTx, natPfibFlowEntity);
2018 LOG.debug("removeNaptFlowsFromActiveSwitch : Removed the flow in table {} with external subnet "
2019 + "Vpn Id {} as metadata on Napt Switch {}", NwConstants.NAPT_PFIB_TABLE,
2020 subnetVpnId, dpnId);
2024 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
2025 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
2026 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
2029 "removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active switch with the DPN ID {} "
2030 + "and router ID {}", NwConstants.NAPT_PFIB_TABLE, dpnId, routerId);
2031 mdsalManager.removeFlow(confTx, natPfibFlowEntity);
2033 if (lastRouterOnExternalNetwork) {
2034 // Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2035 // - This does not work since ext-routers is deleted already - no network info
2036 //Get the VPN ID from the ExternalNetworks model
2037 Uint32 vpnId = NatConstants.INVALID_ID;
2038 if (vpnName == null || vpnName.isEmpty()) {
2039 // ie called from router delete cases
2040 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
2041 LOG.debug("removeNaptFlowsFromActiveSwitch : vpnUuid is {}", vpnUuid);
2042 if (vpnUuid != null) {
2043 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
2044 LOG.debug("removeNaptFlowsFromActiveSwitch : vpnId {} for external network {} router delete "
2045 + "or disableSNAT scenario", vpnId, networkId);
2048 // ie called from disassociate vpn case
2049 LOG.debug("removeNaptFlowsFromActiveSwitch : This is disassociate nw with vpn case with vpnName {}",
2051 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
2052 LOG.debug("removeNaptFlowsFromActiveSwitch : vpnId for disassociate nw with vpn scenario {}",
2056 if (vpnId != NatConstants.INVALID_ID) {
2057 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2058 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
2059 FlowEntity natPfibVpnFlowEntity =
2060 NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
2061 LOG.info("removeNaptFlowsFromActiveSwitch : Remove the flow in {} for the active switch with the "
2062 + "DPN ID {} and VPN ID {}", NwConstants.NAPT_PFIB_TABLE, dpnId, vpnId);
2063 mdsalManager.removeFlow(confTx, natPfibVpnFlowEntity);
2067 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2068 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2069 if (ipPortMapping == null) {
2070 LOG.error("removeNaptFlowsFromActiveSwitch : Unable to retrieve the IpPortMapping");
2074 for (IntextIpProtocolType intextIpProtocolType : ipPortMapping.nonnullIntextIpProtocolType()) {
2075 String protocol = intextIpProtocolType.getProtocol().name();
2076 for (IpPortMap ipPortMap : intextIpProtocolType.nonnullIpPortMap()) {
2077 String ipPortInternal = ipPortMap.getIpPortInternal();
2078 String[] ipPortParts = ipPortInternal.split(":");
2079 if (ipPortParts.length != 2) {
2080 LOG.error("removeNaptFlowsFromActiveSwitch : Unable to retrieve the Internal IP and port");
2083 String internalIp = ipPortParts[0];
2084 String internalPort = ipPortParts[1];
2086 //Build the flow for the outbound NAPT table
2087 naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR + internalIp
2088 + NatConstants.COLON_SEPARATOR + internalPort);
2089 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
2090 String.valueOf(routerId), internalIp, Integer.parseInt(internalPort), protocol);
2091 FlowEntity outboundNaptFlowEntity =
2092 NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
2094 LOG.info("removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active switch "
2095 + "with the DPN ID {} and router ID {}", NwConstants.OUTBOUND_NAPT_TABLE, dpnId, routerId);
2096 mdsalManager.removeFlow(confTx, outboundNaptFlowEntity);
2098 //Build the flow for the inbound NAPT table
2099 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE,
2100 String.valueOf(routerId), internalIp, Integer.parseInt(internalPort), protocol);
2101 FlowEntity inboundNaptFlowEntity =
2102 NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
2104 LOG.info("removeNaptFlowsFromActiveSwitch : Remove the flow in the {} for the active active switch "
2105 + "with the DPN ID {} and router ID {}", NwConstants.INBOUND_NAPT_TABLE, dpnId, routerId);
2106 mdsalManager.removeFlow(confTx, inboundNaptFlowEntity);
2111 protected void removeNaptFibExternalOutputFlows(Uint32 routerId, Uint64 dpnId, Uuid networkId,
2112 @NonNull Collection<String> externalIps,
2113 TypedReadWriteTransaction<Configuration> writeFlowInvTx)
2114 throws ExecutionException, InterruptedException {
2115 Uint32 extVpnId = NatConstants.INVALID_ID;
2116 if (networkId != null) {
2117 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
2118 if (vpnUuid != null) {
2119 extVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
2121 LOG.debug("removeNaptFibExternalOutputFlows : vpnUuid is null");
2124 LOG.debug("removeNaptFibExternalOutputFlows : networkId is null");
2125 extVpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
2127 if (extVpnId == NatConstants.INVALID_ID) {
2128 LOG.warn("removeNaptFibExternalOutputFlows : extVpnId not found for routerId {}", routerId);
2129 extVpnId = routerId;
2131 for (String ip : externalIps) {
2132 String extIp = removeMaskFromIp(ip);
2133 String naptFlowRef = getFlowRefNaptPreFib(dpnId, NwConstants.NAPT_PFIB_TABLE, extVpnId);
2134 LOG.info("removeNaptFlowsFromActiveSwitch : Remove the flow in table {} for the active switch"
2135 + " with the DPN ID {} and router ID {} and IP {} flowRef {}",
2136 NwConstants.NAPT_PFIB_TABLE, dpnId, routerId, extIp, naptFlowRef);
2137 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, naptFlowRef);
2138 mdsalManager.removeFlow(writeFlowInvTx, natPfibVpnFlowEntity);
2142 private String removeMaskFromIp(String ip) {
2143 if (ip != null && !ip.trim().isEmpty()) {
2144 return ip.split("/")[0];
2149 public void removeNaptFlowsFromActiveSwitchInternetVpn(Uint32 routerId, String routerName,
2150 Uint64 dpnId, Uuid networkId, String vpnName,
2151 TypedReadWriteTransaction<Configuration> writeFlowInvTx)
2152 throws ExecutionException, InterruptedException {
2153 LOG.debug("removeNaptFlowsFromActiveSwitchInternetVpn : Remove NAPT flows from Active switch Internet Vpn");
2154 Uint64 cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
2156 //Remove the NAPT PFIB TABLE entry
2157 Uint32 vpnId = NatConstants.INVALID_ID;
2158 if (vpnName != null) {
2159 // ie called from disassociate vpn case
2160 LOG.debug("removeNaptFlowsFromActiveSwitchInternetVpn : This is disassociate nw with vpn case "
2161 + "with vpnName {}", vpnName);
2162 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
2163 LOG.debug("removeNaptFlowsFromActiveSwitchInternetVpn : vpnId for disassociate nw with vpn scenario {}",
2167 if (vpnId != NatConstants.INVALID_ID && !NatUtil.checkForRoutersWithSameExtNetAndNaptSwitch(dataBroker,
2168 networkId, routerName, dpnId)) {
2169 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2170 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
2171 FlowEntity natPfibVpnFlowEntity =
2172 NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
2173 LOG.info("removeNaptFlowsFromActiveSwitchInternetVpn : Remove the flow in the {} for the active switch "
2174 + "with the DPN ID {} and VPN ID {}", NwConstants.NAPT_PFIB_TABLE, dpnId, vpnId);
2175 mdsalManager.removeFlow(writeFlowInvTx, natPfibVpnFlowEntity);
2177 // Remove IP-PORT active NAPT entries and release port from IdManager
2178 // For the router ID get the internal IP , internal port and the corresponding
2179 // external IP and external Port.
2180 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2181 if (ipPortMapping == null) {
2182 LOG.error("removeNaptFlowsFromActiveSwitchInternetVpn : Unable to retrieve the IpPortMapping");
2185 for (IntextIpProtocolType intextIpProtocolType : ipPortMapping.nonnullIntextIpProtocolType()) {
2186 String protocol = intextIpProtocolType.getProtocol().name();
2187 for (IpPortMap ipPortMap : intextIpProtocolType.nonnullIpPortMap()) {
2188 String ipPortInternal = ipPortMap.getIpPortInternal();
2189 String[] ipPortParts = ipPortInternal.split(":");
2190 if (ipPortParts.length != 2) {
2191 LOG.error("removeNaptFlowsFromActiveSwitchInternetVpn : Unable to retrieve the Internal IP "
2195 String internalIp = ipPortParts[0];
2196 String internalPort = ipPortParts[1];
2198 //Build the flow for the outbound NAPT table
2199 naptPacketInHandler.removeIncomingPacketMap(routerId + NatConstants.COLON_SEPARATOR + internalIp
2200 + NatConstants.COLON_SEPARATOR + internalPort);
2201 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE,
2202 String.valueOf(routerId), internalIp, Integer.parseInt(internalPort), protocol);
2203 FlowEntity outboundNaptFlowEntity =
2204 NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
2206 LOG.info("removeNaptFlowsFromActiveSwitchInternetVpn : Remove the flow in the {} for the "
2207 + "active switch with the DPN ID {} and router ID {}",
2208 NwConstants.OUTBOUND_NAPT_TABLE, dpnId, routerId);
2209 mdsalManager.removeFlow(writeFlowInvTx, outboundNaptFlowEntity);
2211 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
2212 final String externalIp = ipPortExternal.getIpAddress();
2214 //Build the flow for the inbound NAPT table
2215 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE,
2216 String.valueOf(routerId), internalIp, Integer.parseInt(internalPort), protocol);
2217 FlowEntity inboundNaptFlowEntity =
2218 NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
2220 LOG.info("removeNaptFlowsFromActiveSwitchInternetVpn : Remove the flow in the {} for the "
2221 + "active active switch with the DPN ID {} and router ID {}",
2222 NwConstants.INBOUND_NAPT_TABLE, dpnId, routerId);
2223 mdsalManager.removeFlow(writeFlowInvTx, inboundNaptFlowEntity);
2225 // Finally release port from idmanager
2226 String internalIpPort = internalIp + ":" + internalPort;
2227 naptManager.removePortFromPool(internalIpPort, externalIp);
2229 //Remove sessions from models
2230 naptManager.removeIpPortMappingForRouterID(routerId);
2231 naptManager.removeIntIpPortMappingForRouterID(routerId);
2235 LOG.error("removeNaptFlowsFromActiveSwitchInternetVpn : Invalid vpnId {}", vpnId);
2239 public void removeFlowsFromNonActiveSwitches(Uint32 routerId, String routerName,
2240 Uint64 naptSwitchDpnId, TypedReadWriteTransaction<Configuration> removeFlowInvTx)
2241 throws ExecutionException, InterruptedException {
2242 LOG.debug("removeFlowsFromNonActiveSwitches : Remove NAPT related flows from non active switches");
2244 // Remove the flows from the other switches which points to the primary and secondary switches
2245 // for the flows related the router ID.
2246 List<Uint64> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
2247 if (allSwitchList.isEmpty()) {
2248 LOG.error("removeFlowsFromNonActiveSwitches : Unable to get the swithces for the router {}", routerName);
2251 for (Uint64 dpnId : allSwitchList) {
2252 if (!naptSwitchDpnId.equals(dpnId)) {
2253 LOG.info("removeFlowsFromNonActiveSwitches : Handle Ordinary switch");
2255 //Remove the PSNAT entry which forwards the packet to Terminating Service table
2256 String preSnatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
2257 FlowEntity preSnatFlowEntity =
2258 NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, preSnatFlowRef);
2260 LOG.info("removeFlowsFromNonActiveSwitches : Remove the flow in the {} for the non active switch "
2261 + "with the DPN ID {} and router ID {}", NwConstants.PSNAT_TABLE, dpnId, routerId);
2262 mdsalManager.removeFlow(removeFlowInvTx, preSnatFlowEntity);
2264 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
2265 Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
2266 NatUtil.getGroupIdKey(routerName));
2267 if (groupId != NatConstants.INVALID_ID) {
2269 "removeFlowsFromNonActiveSwitches : Remove the group {} for the non active switch with "
2270 + "the DPN ID {} and router ID {}", groupId, dpnId, routerId);
2271 mdsalManager.removeGroup(removeFlowInvTx, dpnId, groupId.longValue());
2273 LOG.error("removeFlowsFromNonActiveSwitches: Unable to obtained groupID for router:{}", routerName);
2279 public void clrRtsFromBgpAndDelFibTs(final Uint64 dpnId, Uint32 routerId, @Nullable Uuid networkUuid,
2280 @NonNull Collection<String> externalIps, @Nullable String vpnName,
2281 String extGwMacAddress, TypedReadWriteTransaction<Configuration> confTx)
2282 throws ExecutionException, InterruptedException {
2283 //Withdraw the corresponding routes from the BGP.
2284 //Get the network ID using the router ID.
2285 LOG.debug("clrRtsFromBgpAndDelFibTs : Advertise to BGP and remove routes for externalIps {} with routerId {},"
2286 + "network Id {} and vpnName {}", externalIps, routerId, networkUuid, vpnName);
2287 if (networkUuid == null) {
2288 LOG.error("clrRtsFromBgpAndDelFibTs : networkId is null");
2292 if (externalIps.isEmpty()) {
2293 LOG.error("clrRtsFromBgpAndDelFibTs : externalIps is empty");
2297 if (vpnName == null) {
2298 //Get the VPN Name using the network ID
2299 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid);
2300 if (vpnName == null) {
2301 LOG.error("clrRtsFromBgpAndDelFibTs : No VPN associated with ext nw {} for the router {}",
2302 networkUuid, routerId);
2306 LOG.debug("clrRtsFromBgpAndDelFibTs : Retrieved vpnName {} for networkId {}", vpnName, networkUuid);
2308 //Remove custom FIB routes
2309 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
2310 for (String extIp : externalIps) {
2311 extIp = NatUtil.validateAndAddNetworkMask(extIp);
2312 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName, networkUuid, extGwMacAddress, confTx);
2316 protected void clrRtsFromBgpAndDelFibTs(final Uint64 dpnId, Uint32 routerId, String extIp, final String vpnName,
2317 final Uuid networkUuid, String extGwMacAddress,
2318 TypedReadWriteTransaction<Configuration> removeFlowInvTx)
2319 throws ExecutionException, InterruptedException {
2320 clearBgpRoutes(extIp, vpnName);
2321 delFibTsAndReverseTraffic(dpnId, routerId, extIp, vpnName, networkUuid, extGwMacAddress, false,
2325 protected void delFibTsAndReverseTraffic(final Uint64 dpnId, String routerName, Uint32 routerId, String extIp,
2326 String vpnName, Uuid extNetworkId, Uint32 tempLabel,
2327 String gwMacAddress, boolean switchOver,
2328 TypedReadWriteTransaction<Configuration> removeFlowInvTx)
2329 throws ExecutionException, InterruptedException {
2330 LOG.debug("delFibTsAndReverseTraffic : Removing fib entry for externalIp {} in routerId {}", extIp, routerId);
2331 //String routerName = NatUtil.getRouterName(dataBroker,routerId);
2332 if (routerName == null) {
2333 LOG.error("delFibTsAndReverseTraffic : Could not retrieve Router Name from Router ID {} ", routerId);
2336 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkId);
2337 if (extNwProvType == null) {
2338 LOG.error("delFibTsAndReverseTraffic : External Network Provider Type Missing");
2341 /* Remove the flow table19->44 and table36->44 entries for SNAT reverse traffic flow if the
2342 * external network provided type is VxLAN
2344 if (extNwProvType == ProviderTypes.VXLAN) {
2345 evpnSnatFlowProgrammer.evpnDelFibTsAndReverseTraffic(dpnId, routerId, extIp, vpnName, gwMacAddress
2349 if (tempLabel.longValue() < 0) {
2350 LOG.error("delFibTsAndReverseTraffic : Label not found for externalIp {} with router id {}",
2354 final Uint32 label = tempLabel;
2355 final String externalIp = NatUtil.validateAndAddNetworkMask(extIp);
2356 RemoveFibEntryInput input = null;
2357 if (extNwProvType == ProviderTypes.FLAT || extNwProvType == ProviderTypes.VLAN) {
2358 LOG.debug("delFibTsAndReverseTraffic : Using extSubnetId as vpnName for FLAT/VLAN use-cases");
2359 Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
2360 Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIp,
2363 Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker,
2366 if (externalSubnet.isPresent()) {
2367 vpnName = externalSubnetId.getValue();
2370 final String externalVpn = vpnName;
2371 if (label != null && label.toJava() <= 0) {
2372 LOG.error("delFibTsAndReverseTraffic : Label not found for externalIp {} with router id {}",
2374 input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
2375 .setSourceDpid(dpnId).setIpAddress(externalIp)
2376 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.ExternalFixedIP).build();
2378 input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
2379 .setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label)
2380 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.ExternalFixedIP).build();
2381 removeTunnelTableEntry(dpnId, label, removeFlowInvTx);
2382 removeLFibTableEntry(dpnId, label, removeFlowInvTx);
2384 ListenableFuture<RpcResult<RemoveFibEntryOutput>> future = fibService.removeFibEntry(input);
2386 removeTunnelTableEntry(dpnId, label, removeFlowInvTx);
2387 removeLFibTableEntry(dpnId, label, removeFlowInvTx);
2388 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
2389 //Remove the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
2390 NatUtil.removePreDnatToSnatTableEntry(removeFlowInvTx, mdsalManager, dpnId);
2393 ListenableFuture<RpcResult<RemoveVpnLabelOutput>> labelFuture =
2394 Futures.transformAsync(future, result -> {
2396 if (result.isSuccessful() && label != null && label.toJava() > 0) {
2397 NatUtil.removePreDnatToSnatTableEntry(removeFlowInvTx, mdsalManager, dpnId);
2398 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder()
2399 .setVpnName(externalVpn).setIpPrefix(externalIp).build();
2400 Future<RpcResult<RemoveVpnLabelOutput>> labelFuture1 = vpnService.removeVpnLabel(labelInput);
2401 if (labelFuture1.get() == null || !labelFuture1.get().isSuccessful()) {
2402 String errMsg = String.format(
2403 "ExternalRoutersListener: RPC call to remove VPN label "
2404 + "on dpn %s for prefix %s failed for vpn %s - %s",
2405 dpnId, externalIp, result.getErrors());
2407 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
2409 return JdkFutureAdapters.listenInPoolThread(labelFuture1);
2412 String.format("RPC call to remove custom FIB entries on dpn %s for "
2413 + "prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
2415 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
2417 }, MoreExecutors.directExecutor());
2419 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<RemoveVpnLabelOutput>>() {
2422 public void onFailure(@NonNull Throwable error) {
2423 LOG.error("delFibTsAndReverseTraffic : Error in removing the label:{} or custom fib entries"
2424 + "got external ip {}", label, extIp, error);
2428 public void onSuccess(@NonNull RpcResult<RemoveVpnLabelOutput> result) {
2429 if (result.isSuccessful()) {
2430 LOG.debug("delFibTsAndReverseTraffic : Successfully removed the label for the prefix {} "
2431 + "from VPN {}", externalIp, externalVpn);
2433 LOG.error("delFibTsAndReverseTraffic : Error in removing the label for prefix {} "
2434 + " from VPN {}, {}", externalIp, externalVpn, result.getErrors());
2437 }, MoreExecutors.directExecutor());
2439 LOG.debug("delFibTsAndReverseTraffic: switch-over is happened on DpnId {}. No need to release allocated "
2440 + "label {} for external fixed ip {} for router {}", dpnId, label, externalIp, routerId);
2444 private void delFibTsAndReverseTraffic(final Uint64 dpnId, Uint32 routerId, String extIp, final String vpnName,
2445 final Uuid networkUuid, String extGwMacAddress, boolean switchOver,
2446 TypedReadWriteTransaction<Configuration> removeFlowInvTx)
2447 throws ExecutionException, InterruptedException {
2448 LOG.debug("delFibTsAndReverseTraffic : Removing fib entry for externalIp {} in routerId {}", extIp, routerId);
2449 String routerName = NatUtil.getRouterName(dataBroker,routerId);
2450 if (routerName == null) {
2451 LOG.error("delFibTsAndReverseTraffic : Could not retrieve Router Name from Router ID {} ", routerId);
2454 //Get the external network provider type from networkId
2455 ProviderTypes extNwProvType = NatUtil.getProviderTypefromNetworkId(dataBroker, networkUuid);
2456 if (extNwProvType == null) {
2457 LOG.error("delFibTsAndReverseTraffic : Could not retrieve provider type for external network {} ",
2461 /* Remove the flow table19->44 and table36->44 entries for SNAT reverse traffic flow if the
2462 * external network provided type is VxLAN
2464 if (extNwProvType == ProviderTypes.VXLAN) {
2465 evpnSnatFlowProgrammer.evpnDelFibTsAndReverseTraffic(dpnId, routerId, extIp, vpnName, extGwMacAddress);
2468 //Get IPMaps from the DB for the router ID
2469 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
2470 if (dbIpMaps.isEmpty()) {
2471 LOG.error("delFibTsAndReverseTraffic : IPMaps not found for router {}", routerId);
2475 Uint32 tempLabel = NatConstants.INVALID_ID;
2476 for (IpMap dbIpMap : dbIpMaps) {
2477 String dbExternalIp = dbIpMap.getExternalIp();
2478 LOG.debug("delFibTsAndReverseTraffic : Retrieved dbExternalIp {} for router id {}", dbExternalIp, routerId);
2479 //Select the IPMap, whose external IP is the IP for which FIB is installed
2480 if (extIp.equals(dbExternalIp)) {
2481 tempLabel = dbIpMap.getLabel();
2482 LOG.debug("delFibTsAndReverseTraffic : Retrieved label {} for dbExternalIp {} with router id {}",
2483 tempLabel, dbExternalIp, routerId);
2487 if (tempLabel == NatConstants.INVALID_ID) {
2488 LOG.error("delFibTsAndReverseTraffic : Label not found for externalIp {} with router id {}",
2493 final Uint32 label = tempLabel;
2494 final String externalIp = NatUtil.validateAndAddNetworkMask(extIp);
2495 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder()
2496 .setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp)
2497 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.ExternalFixedIP).setServiceId(label).build();
2498 ListenableFuture<RpcResult<RemoveFibEntryOutput>> future = fibService.removeFibEntry(input);
2500 removeTunnelTableEntry(dpnId, label, removeFlowInvTx);
2501 removeLFibTableEntry(dpnId, label, removeFlowInvTx);
2502 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
2503 //Remove the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
2504 NatUtil.removePreDnatToSnatTableEntry(removeFlowInvTx, mdsalManager, dpnId);
2507 ListenableFuture<RpcResult<RemoveVpnLabelOutput>> labelFuture =
2508 Futures.transformAsync(future, result -> {
2510 if (result.isSuccessful()) {
2511 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder()
2512 .setVpnName(vpnName).setIpPrefix(externalIp).build();
2513 Future<RpcResult<RemoveVpnLabelOutput>> labelFuture1 = vpnService
2514 .removeVpnLabel(labelInput);
2515 if (labelFuture1.get() == null || !labelFuture1.get().isSuccessful()) {
2516 String errMsg = String.format(
2517 "RPC call to remove VPN label on dpn %s for prefix %s "
2518 + "failed for vpn %s - %s", dpnId, externalIp, vpnName,
2519 result.getErrors());
2521 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
2523 return JdkFutureAdapters.listenInPoolThread(labelFuture1);
2526 String.format("RPC call to remove custom FIB entries on dpn %s for "
2527 + "prefix %s Failed - %s",
2528 dpnId, externalIp, result.getErrors());
2530 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
2532 }, MoreExecutors.directExecutor());
2534 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<RemoveVpnLabelOutput>>() {
2537 public void onFailure(@NonNull Throwable error) {
2538 LOG.error("delFibTsAndReverseTraffic : Error in removing the label or custom fib entries", error);
2542 public void onSuccess(@NonNull RpcResult<RemoveVpnLabelOutput> result) {
2543 if (result.isSuccessful()) {
2544 LOG.debug("delFibTsAndReverseTraffic : Successfully removed the label for the prefix {} "
2545 + "from VPN {}", externalIp, vpnName);
2547 LOG.error("delFibTsAndReverseTraffic : Error in removing the label for prefix {} "
2548 + " from VPN {}, {}", externalIp, vpnName, result.getErrors());
2551 }, MoreExecutors.directExecutor());
2553 LOG.debug("delFibTsAndReverseTraffic: switch-over is happened on DpnId {}. No need to release allocated "
2554 + "label {} for external fixed ip {} for router {}", dpnId, label, externalIp, routerId);
2558 protected void clearFibTsAndReverseTraffic(final Uint64 dpnId, Uint32 routerId, Uuid networkUuid,
2559 List<String> externalIps, @Nullable String vpnName, String extGwMacAddress,
2560 TypedReadWriteTransaction<Configuration> writeFlowInvTx) throws ExecutionException, InterruptedException {
2561 //Withdraw the corresponding routes from the BGP.
2562 //Get the network ID using the router ID.
2563 LOG.debug("clearFibTsAndReverseTraffic : for externalIps {} with routerId {},"
2564 + "network Id {} and vpnName {}", externalIps, routerId, networkUuid, vpnName);
2565 if (networkUuid == null) {
2566 LOG.error("clearFibTsAndReverseTraffic : networkId is null");
2570 if (externalIps == null || externalIps.isEmpty()) {
2571 LOG.error("clearFibTsAndReverseTraffic : externalIps is null");
2575 if (vpnName == null) {
2576 //Get the VPN Name using the network ID
2577 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid);
2578 if (vpnName == null) {
2579 LOG.error("clearFibTsAndReverseTraffic : No VPN associated with ext nw {} for the router {}",
2580 networkUuid, routerId);
2584 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkUuid);
2586 //Remove custom FIB routes
2587 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
2588 for (String extIp : externalIps) {
2589 delFibTsAndReverseTraffic(dpnId, routerId, extIp, vpnName, networkUuid, extGwMacAddress, false,
2594 protected void clearBgpRoutes(String externalIp, final String vpnName) {
2595 //Inform BGP about the route removal
2596 LOG.info("clearBgpRoutes : Informing BGP to remove route for externalIP {} of vpn {}", externalIp, vpnName);
2597 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
2598 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, externalIp, vpnName);
2599 NatUtil.deletePrefixToInterface(dataBroker, NatUtil.getVpnId(dataBroker, vpnName), externalIp);
2602 private void removeTunnelTableEntry(Uint64 dpnId, Uint32 serviceId,
2603 TypedReadWriteTransaction<Configuration> writeFlowInvTx) throws ExecutionException, InterruptedException {
2604 LOG.info("removeTunnelTableEntry : called with DpnId = {} and label = {}", dpnId, serviceId);
2605 mdsalManager.removeFlow(writeFlowInvTx, dpnId,
2606 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), NwConstants.INTERNAL_TUNNEL_TABLE);
2607 LOG.debug("removeTunnelTableEntry : dpID {} : label : {} removed successfully", dpnId, serviceId);
2610 private void removeLFibTableEntry(Uint64 dpnId, Uint32 serviceId,
2611 TypedReadWriteTransaction<Configuration> writeFlowInvTx) throws ExecutionException, InterruptedException {
2612 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
2613 LOG.debug("removeLFibTableEntry : with flow ref {}", flowRef);
2614 mdsalManager.removeFlow(writeFlowInvTx, dpnId, flowRef, NwConstants.L3_LFIB_TABLE);
2615 LOG.debug("removeLFibTableEntry : dpID : {} label : {} removed successfully", dpnId, serviceId);
2619 * router association to vpn.
2621 * @param routerName - Name of router
2622 * @param routerId - router id
2623 * @param bgpVpnName BGP VPN name
2625 public void changeLocalVpnIdToBgpVpnId(String routerName, Uint32 routerId, String extNetwork, String bgpVpnName,
2626 TypedWriteTransaction<Configuration> writeFlowInvTx, ProviderTypes extNwProvType) {
2627 LOG.debug("changeLocalVpnIdToBgpVpnId : Router associated to BGP VPN");
2628 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2629 Uint32 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2631 LOG.debug("changeLocalVpnIdToBgpVpnId : BGP VPN ID value {} ", bgpVpnId);
2633 if (bgpVpnId != NatConstants.INVALID_ID) {
2634 LOG.debug("changeLocalVpnIdToBgpVpnId : Populate the router-id-name container with the "
2635 + "mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
2636 RouterIds rtrs = new RouterIdsBuilder().withKey(new RouterIdsKey(bgpVpnId))
2637 .setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
2638 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2639 getRoutersIdentifier(bgpVpnId), rtrs);
2641 // Get the allocated Primary NAPT Switch for this router
2642 LOG.debug("changeLocalVpnIdToBgpVpnId : Update the Router ID {} to the BGP VPN ID {} ",
2643 routerId, bgpVpnId);
2644 addDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, bgpVpnId, writeFlowInvTx);
2647 Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2648 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, new Uuid(extNetwork),
2649 true, writeFlowInvTx, extNwProvType);
2655 * router disassociation from vpn.
2657 * @param routerName - Name of router
2658 * @param routerId - router id
2659 * @param bgpVpnName BGP VPN name
2661 public void changeBgpVpnIdToLocalVpnId(String routerName, Uint32 routerId, String bgpVpnName, String extNetwork,
2662 TypedWriteTransaction<Configuration> writeFlowInvTx, ProviderTypes extNwProvType) {
2663 LOG.debug("changeBgpVpnIdToLocalVpnId : Router dissociated from BGP VPN");
2664 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2665 Uint32 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2666 LOG.debug("changeBgpVpnIdToLocalVpnId : BGP VPN ID value {} ", bgpVpnId);
2668 // Get the allocated Primary NAPT Switch for this router
2669 LOG.debug("changeBgpVpnIdToLocalVpnId : Router ID value {} ", routerId);
2671 LOG.debug("changeBgpVpnIdToLocalVpnId : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2672 addDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, NatConstants.INVALID_ID, writeFlowInvTx);
2675 Uint64 primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2676 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId,
2677 new Uuid(extNetwork), true, writeFlowInvTx, extNwProvType);
2681 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid) {
2682 InstanceIdentifier<Routers> routerInstanceIndentifier =
2683 InstanceIdentifier.builder(ExtRouters.class)
2684 .child(Routers.class, new RoutersKey(routerUuid.getValue())).build();
2686 Optional<Routers> routerData = SingleTransactionDataBroker
2687 .syncReadOptional(dataBroker,
2688 LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2689 return routerData.isPresent() && routerData.get().isEnableSnat();
2690 } catch (ReadFailedException e) {
2691 LOG.error("Failed to read data for router id {}", routerUuid, e);
2696 public void installFlowsWithUpdatedVpnId(Uint64 primarySwitchId, String routerName, Uint32 bgpVpnId,
2697 Uint32 routerId, Uuid extNwUuid, boolean isSnatCfgd,
2698 TypedWriteTransaction<Configuration> confTx, ProviderTypes extNwProvType) {
2700 Uint32 changedVpnId = bgpVpnId;
2701 String idType = "BGP VPN";
2702 if (bgpVpnId == NatConstants.INVALID_ID) {
2703 changedVpnId = routerId;
2707 List<Uint64> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2708 if (switches.isEmpty()) {
2709 LOG.error("installFlowsWithUpdatedVpnId : No switches found for router {}", routerName);
2712 for (Uint64 dpnId : switches) {
2713 // Update the BGP VPN ID in the SNAT miss entry to group
2714 if (!dpnId.equals(primarySwitchId)) {
2715 LOG.debug("installFlowsWithUpdatedVpnId : Install group in non NAPT switch {}", dpnId);
2716 List<BucketInfo> bucketInfoForNonNaptSwitches =
2717 getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName, routerId);
2718 Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
2719 NatUtil.getGroupIdKey(routerName));
2720 if (groupId != NatConstants.INVALID_ID) {
2722 installGroup(dpnId, routerName, groupId, bucketInfoForNonNaptSwitches);
2725 "installFlowsWithUpdatedVpnId : Update the {} ID {} in the SNAT miss entry pointing to group "
2726 + "{} in the non NAPT switch {}", idType, changedVpnId, groupId, dpnId);
2727 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName,
2728 groupId, changedVpnId);
2729 mdsalManager.addFlow(confTx, flowEntity);
2731 LOG.error("installFlowsWithUpdatedVpnId: Unable to get groupId for router:{}", routerName);
2735 "installFlowsWithUpdatedVpnId : Update the {} ID {} in the SNAT miss entry pointing to group "
2736 + "in the primary switch {}", idType, changedVpnId, primarySwitchId);
2737 FlowEntity flowEntity =
2738 buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2739 mdsalManager.addFlow(confTx, flowEntity);
2742 "installFlowsWithUpdatedVpnId : Update the {} ID {} in the Terminating Service table (table "
2743 + "ID 36) which forwards the packet to the table 46 in the Primary switch {}",
2744 idType, changedVpnId, primarySwitchId);
2745 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, routerId,
2746 changedVpnId, confTx, extNwProvType);
2749 "installFlowsWithUpdatedVpnId : Update the {} ID {} in the Outbound NAPT table (table ID 46) "
2750 + "which punts the packet to the controller in the Primary switch {}",
2751 idType, changedVpnId, primarySwitchId);
2752 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId, confTx);
2755 "installFlowsWithUpdatedVpnId : Update the {} ID {} in the NAPT PFIB TABLE which forwards the"
2756 + " outgoing packet to FIB Table in the Primary switch {}",
2757 idType, changedVpnId, primarySwitchId);
2758 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId, confTx);
2761 "installFlowsWithUpdatedVpnId : Update the {} ID {} in the NAPT flows for the Outbound NAPT "
2762 + "table (table ID 46) and the INBOUND NAPT table (table ID 44) in the Primary switch"
2763 + " {}", idType, changedVpnId, primarySwitchId);
2764 updateNaptFlowsWithVpnId(primarySwitchId, routerName, routerId, bgpVpnId);
2766 LOG.debug("installFlowsWithUpdatedVpnId : Installing SNAT PFIB flow in the primary switch {}",
2768 //Get the VPN ID from the ExternalNetworks model
2769 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, extNwUuid);
2770 if (vpnUuid != null) {
2771 Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
2772 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table
2773 // matching on the VPN ID.
2774 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2775 installNaptPfibEntry(primarySwitchId, vpnId, confTx);
2778 LOG.error("NAT Service : vpnUuid is null");
2784 public void updateNaptFlowsWithVpnId(Uint64 dpnId, String routerName, Uint32 routerId, Uint32 bgpVpnId) {
2785 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2786 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2787 if (ipPortMapping == null) {
2788 LOG.error("updateNaptFlowsWithVpnId : Unable to retrieve the IpPortMapping");
2791 // Get the External Gateway MAC Address
2792 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
2793 if (extGwMacAddress != null) {
2794 LOG.debug("updateNaptFlowsWithVpnId : External Gateway MAC address {} found for External Router ID {}",
2795 extGwMacAddress, routerId);
2797 LOG.error("updateNaptFlowsWithVpnId : No External Gateway MAC address found for External Router ID {}",
2801 for (IntextIpProtocolType intextIpProtocolType : ipPortMapping.nonnullIntextIpProtocolType()) {
2802 for (IpPortMap ipPortMap : intextIpProtocolType.nonnullIpPortMap()) {
2803 String ipPortInternal = ipPortMap.getIpPortInternal();
2804 String[] ipPortParts = ipPortInternal.split(":");
2805 if (ipPortParts.length != 2) {
2806 LOG.error("updateNaptFlowsWithVpnId : Unable to retrieve the Internal IP and port");
2809 String internalIp = ipPortParts[0];
2810 String internalPort = ipPortParts[1];
2811 LOG.debug("updateNaptFlowsWithVpnId : Found Internal IP {} and Internal Port {}",
2812 internalIp, internalPort);
2813 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2814 NAPTEntryEvent.Protocol protocol;
2815 switch (protocolTypes) {
2817 protocol = NAPTEntryEvent.Protocol.TCP;
2820 protocol = NAPTEntryEvent.Protocol.UDP;
2823 protocol = NAPTEntryEvent.Protocol.TCP;
2825 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.parseInt(internalPort));
2826 SessionAddress externalAddress =
2827 naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2828 Uint32 internetVpnid = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
2829 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid,
2830 routerId, bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress);
2831 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid,
2832 routerId, bgpVpnId, internalAddress, externalAddress, protocol, extGwMacAddress);
2837 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(Uint64 dpId, String routerName, Uint32 groupId,
2838 Uint32 changedVpnId) {
2840 LOG.debug("buildSnatFlowEntityWithUpdatedVpnId : called for dpId {}, routerName {} groupId {} "
2841 + "changed VPN ID {}", dpId, routerName, groupId, changedVpnId);
2842 List<MatchInfo> matches = new ArrayList<>();
2843 matches.add(MatchEthernetType.IPV4);
2844 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
2845 MetaDataUtil.METADATA_MASK_VRFID));
2847 List<ActionInfo> actionsInfo = new ArrayList<>();
2848 Uint64 tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil,
2849 elanManager, idManager, changedVpnId, routerName);
2850 actionsInfo.add(new ActionSetFieldTunnelId(tunnelId));
2851 LOG.debug("buildSnatFlowEntityWithUpdatedVpnId : Setting the tunnel to the list of action infos {}",
2853 actionsInfo.add(new ActionGroup(groupId.longValue()));
2854 List<InstructionInfo> instructions = new ArrayList<>();
2855 instructions.add(new InstructionApplyActions(actionsInfo));
2856 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2857 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2858 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2859 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2861 LOG.debug("buildSnatFlowEntityWithUpdatedVpnId : Returning SNAT Flow Entity {}", flowEntity);
2865 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(Uint64 dpId, String routerName,
2866 Uint32 changedVpnId) {
2868 LOG.debug("buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch : called for dpId {}, routerName {} "
2869 + "changed VPN ID {}", dpId, routerName, changedVpnId);
2870 List<MatchInfo> matches = new ArrayList<>();
2871 matches.add(MatchEthernetType.IPV4);
2872 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
2873 MetaDataUtil.METADATA_MASK_VRFID));
2875 List<InstructionInfo> instructions = new ArrayList<>();
2876 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
2878 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2879 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2880 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2881 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2883 LOG.debug("buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch : Returning SNAT Flow Entity {}", flowEntity);
2887 // TODO : Replace this with ITM Rpc once its available with full functionality
2888 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(Uint64 dpnId, String routerName,
2889 Uint32 routerId, Uint32 changedVpnId,
2890 TypedWriteTransaction<Configuration> confTx,
2891 ProviderTypes extNwProvType) {
2893 LOG.debug("installTerminatingServiceTblEntryWithUpdatedVpnId : called for switch {}, "
2894 + "routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2895 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, routerId, changedVpnId,
2897 mdsalManager.addFlow(confTx, flowEntity);
2900 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(Uint64 dpId, String routerName,
2901 Uint32 routerIdLongVal, Uint32 changedVpnId,
2902 ProviderTypes extNwProvType) {
2903 LOG.debug("buildTsFlowEntityWithUpdatedVpnId : called for switch {}, routerName {}, BGP VPN ID {}",
2904 dpId, routerName, changedVpnId);
2905 List<MatchInfo> matches = new ArrayList<>();
2906 matches.add(MatchEthernetType.IPV4);
2908 Uint64 tunnelId = Uint64.valueOf(changedVpnId);
2909 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
2910 tunnelId = natOverVxlanUtil.getRouterVni(routerName, changedVpnId);
2912 matches.add(new MatchTunnelId(tunnelId));
2914 List<InstructionInfo> instructions = new ArrayList<>();
2915 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
2916 MetaDataUtil.METADATA_MASK_VRFID));
2917 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
2918 Uint32 routerId = routerIdLongVal;
2919 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
2920 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2921 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2922 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2926 public void createOutboundTblEntryWithBgpVpn(Uint64 dpnId, Uint32 routerId, Uint32 changedVpnId,
2927 TypedWriteTransaction<Configuration> writeFlowInvTx) {
2928 LOG.debug("createOutboundTblEntryWithBgpVpn : called for dpId {} and routerId {}, BGP VPN ID {}",
2929 dpnId, routerId, changedVpnId);
2930 FlowEntity tcpFlowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId,
2931 NwConstants.IP_PROT_TCP);
2932 LOG.debug("createOutboundTblEntryWithBgpVpn : Installing tcp flow {}", tcpFlowEntity);
2933 mdsalManager.addFlow(writeFlowInvTx, tcpFlowEntity);
2935 FlowEntity udpFlowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId,
2936 NwConstants.IP_PROT_UDP);
2937 LOG.debug("createOutboundTblEntryWithBgpVpn : Installing udp flow {}", udpFlowEntity);
2938 mdsalManager.addFlow(writeFlowInvTx, udpFlowEntity);
2940 FlowEntity icmpDropFlow = buildIcmpDropFlow(dpnId, routerId, changedVpnId);
2941 LOG.debug("createOutboundTblEntry: Installing icmp drop flow {}", icmpDropFlow);
2942 mdsalManager.addFlow(writeFlowInvTx, icmpDropFlow);
2945 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(Uint64 dpId, Uint32 routerId,
2946 Uint32 changedVpnId, int protocol) {
2947 LOG.debug("buildOutboundFlowEntityWithBgpVpn : called for dpId {} and routerId {}, BGP VPN ID {}",
2948 dpId, routerId, changedVpnId);
2949 Uint64 cookie = getCookieOutboundFlow(routerId);
2950 List<MatchInfo> matches = new ArrayList<>();
2951 matches.add(MatchEthernetType.IPV4);
2952 matches.add(new MatchIpProtocol((short)protocol));
2953 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
2954 MetaDataUtil.METADATA_MASK_VRFID));
2956 List<InstructionInfo> instructions = new ArrayList<>();
2957 List<ActionInfo> actionsInfos = new ArrayList<>();
2958 actionsInfos.add(new ActionPuntToController());
2959 if (snatPuntTimeout != 0) {
2960 actionsInfos.add(getLearnActionForPunt(protocol, snatPuntTimeout, cookie));
2962 instructions.add(new InstructionApplyActions(actionsInfos));
2964 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, protocol);
2965 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE,
2966 flowRef, 5, flowRef, 0, 0, cookie, matches, instructions);
2967 LOG.debug("createOutboundTblEntryWithBgpVpn : returning flowEntity {}", flowEntity);
2971 public void installNaptPfibEntryWithBgpVpn(Uint64 dpnId, Uint32 segmentId, Uint32 changedVpnId,
2972 TypedWriteTransaction<Configuration> writeFlowInvTx) {
2973 LOG.debug("installNaptPfibEntryWithBgpVpn : called for dpnId {} and segmentId {} ,BGP VPN ID {}",
2974 dpnId, segmentId, changedVpnId);
2975 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2976 mdsalManager.addFlow(writeFlowInvTx, naptPfibFlowEntity);
2979 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(Uint64 dpId, Uint32 segmentId, Uint32 changedVpnId) {
2981 LOG.debug("buildNaptPfibFlowEntityWithUpdatedVpnId : called for dpId {}, "
2982 + "segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2983 List<MatchInfo> matches = new ArrayList<>();
2984 matches.add(MatchEthernetType.IPV4);
2985 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId.longValue()),
2986 MetaDataUtil.METADATA_MASK_VRFID));
2988 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2989 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2990 listActionInfo.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
2991 listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
2992 instructionInfo.add(new InstructionApplyActions(listActionInfo));
2994 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2995 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2996 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2997 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2998 LOG.debug("buildNaptPfibFlowEntityWithUpdatedVpnId : Returning NaptPFib Flow Entity {}", flowEntity);
3003 protected ExternalRoutersListener getDataTreeChangeListener() {
3004 return ExternalRoutersListener.this;
3007 protected void installNaptPfibEntriesForExternalSubnets(String routerName, Uint64 dpnId,
3008 @Nullable TypedWriteTransaction<Configuration> writeFlowInvTx) {
3009 Collection<Uuid> externalSubnetIdsForRouter = NatUtil.getExternalSubnetIdsForRouter(dataBroker,
3011 for (Uuid externalSubnetId : externalSubnetIdsForRouter) {
3012 Uint32 subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
3013 if (subnetVpnId != NatConstants.INVALID_ID) {
3014 LOG.debug("installNaptPfibEntriesForExternalSubnets : called for dpnId {} "
3015 + "and vpnId {}", dpnId, subnetVpnId);
3016 installNaptPfibEntry(dpnId, subnetVpnId, writeFlowInvTx);