2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.natservice.internal;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.Sets;
12 import com.google.common.collect.Sets.SetView;
13 import com.google.common.util.concurrent.AsyncFunction;
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 java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
23 import java.util.Objects;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.Future;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
29 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
33 import org.opendaylight.genius.mdsalutil.ActionInfo;
34 import org.opendaylight.genius.mdsalutil.BucketInfo;
35 import org.opendaylight.genius.mdsalutil.FlowEntity;
36 import org.opendaylight.genius.mdsalutil.GroupEntity;
37 import org.opendaylight.genius.mdsalutil.InstructionInfo;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.mdsalutil.MatchFieldType;
40 import org.opendaylight.genius.mdsalutil.MatchInfo;
41 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
42 import org.opendaylight.genius.mdsalutil.NwConstants;
43 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
44 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
45 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
46 import org.opendaylight.genius.mdsalutil.actions.ActionPopMpls;
47 import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
48 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
49 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
50 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
51 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
52 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
53 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
54 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
55 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
56 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
98 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;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
115 import org.opendaylight.yangtools.concepts.ListenerRegistration;
116 import org.opendaylight.yangtools.yang.binding.DataObject;
117 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
118 import org.opendaylight.yangtools.yang.common.RpcResult;
119 import org.slf4j.Logger;
120 import org.slf4j.LoggerFactory;
122 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener> {
123 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
124 private ListenerRegistration<DataChangeListener> listenerRegistration;
125 private final DataBroker dataBroker;
126 private final IMdsalApiManager mdsalManager;
127 private final ItmRpcService itmManager;
128 private final OdlInterfaceRpcService interfaceManager;
129 private final IdManagerService idManager;
130 private final NaptManager naptManager;
131 private final NAPTSwitchSelector naptSwitchSelector;
132 private final IBgpManager bgpManager;
133 private final VpnRpcService vpnService;
134 private final FibRpcService fibService;
135 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
136 private final NaptEventHandler naptEventHandler;
137 private final NaptPacketInHandler naptPacketInHandler;
138 private final IFibManager fibManager;
139 private final IVpnManager vpnManager;
140 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
141 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
143 public ExternalRoutersListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
144 final ItmRpcService itmManager,
145 final OdlInterfaceRpcService interfaceManager,
146 final IdManagerService idManager,
147 final NaptManager naptManager,
148 final NAPTSwitchSelector naptSwitchSelector,
149 final IBgpManager bgpManager,
150 final VpnRpcService vpnService,
151 final FibRpcService fibService,
152 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
153 final NaptEventHandler naptEventHandler,
154 final NaptPacketInHandler naptPacketInHandler,
155 final IFibManager fibManager,
156 final IVpnManager vpnManager) {
157 super(Routers.class, ExternalRoutersListener.class);
158 this.dataBroker = dataBroker;
159 this.mdsalManager = mdsalManager;
160 this.itmManager = itmManager;
161 this.interfaceManager = interfaceManager;
162 this.idManager = idManager;
163 this.naptManager = naptManager;
164 this.naptSwitchSelector = naptSwitchSelector;
165 this.bgpManager = bgpManager;
166 this.vpnService = vpnService;
167 this.fibService = fibService;
168 this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
169 this.naptEventHandler = naptEventHandler;
170 this.naptPacketInHandler = naptPacketInHandler;
171 this.fibManager = fibManager;
172 this.vpnManager = vpnManager;
177 LOG.info("{} init", getClass().getSimpleName());
178 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
183 protected InstanceIdentifier<Routers> getWildCardPath() {
184 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
188 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
189 // Populate the router-id-name container
190 String routerName = routers.getRouterName();
191 LOG.info("NAT Service : Add external router event for {}", routerName);
192 NatUtil.createRouterIdsConfigDS(dataBroker, routerName);
194 LOG.info("NAT Service : Installing NAT default route on all dpns part of router {}", routerName);
196 addOrDelDefFibRouteToSNAT(routerName, true);
197 } catch (Exception ex) {
198 LOG.debug("NAT Service : Exception {} while Installing NAT default route on all dpns part of router {}",
202 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
203 // Allocate Primary Napt Switch for this router
204 BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName, segmentId);
205 if (primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)) {
206 LOG.error("NAT Service: Failed to get or allocated NAPT switch");
210 handleRouterGwFlows(routers, primarySwitchId, NwConstants.ADD_FLOW);
211 if (!routers.isEnableSnat()) {
212 LOG.info("NAT Service : SNAT is disabled for external router {} ", routerName);
216 handleEnableSnat(routers, segmentId, primarySwitchId);
219 public void handleEnableSnat(Routers routers, long segmentId, BigInteger primarySwitchId) {
220 String routerName = routers.getRouterName();
221 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
223 naptManager.initialiseExternalCounter(routers, segmentId);
224 subnetRegisterMapping(routers,segmentId);
226 LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
228 long bgpVpnId = NatConstants.INVALID_ID;
229 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
230 if (bgpVpnUuid != null) {
231 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
233 if (bgpVpnId != NatConstants.INVALID_ID){
234 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, segmentId, false);
236 // write metadata and punt
237 installOutboundMissEntry(routerName, primarySwitchId);
238 // Now install entries in SNAT tables to point to Primary for each router
239 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
240 if (switches != null) {
241 for (BigInteger dpnId : switches) {
242 // Handle switches and NAPT switches separately
243 if (!dpnId.equals(primarySwitchId)) {
244 LOG.debug("NAT Service : Handle Ordinary switch");
245 handleSwitches(dpnId, routerName, primarySwitchId);
247 LOG.debug("NAT Service : Handle NAPT switch");
248 handlePrimaryNaptSwitch(dpnId, routerName);
249 installNaptPfibExternalOutputFlow(routers, dpnId);
255 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,segmentId);
256 if (externalIps == null || externalIps.isEmpty()) {
257 LOG.debug("NAT Service : Internal External mapping found for router {}",routerName);
260 for (String externalIpAddrPrefix : externalIps) {
261 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
262 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
266 /*// call registerMapping Api
267 LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
269 List<Uuid> subnetList = null;
270 List<String> externalIps = null;
272 InstanceIdentifier<Routers> id = InstanceIdentifier
273 .builder(ExtRouters.class)
274 .child(Routers.class, new RoutersKey(routerName))
277 Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
279 if(extRouters.isPresent())
281 LOG.debug("NAT Service : Fetching values from extRouters model");
282 Routers routerEntry= extRouters.get();
283 subnetList = routerEntry.getSubnetIds();
284 externalIps = routerEntry.getExternalIps();
286 int extIpCounter = externalIps.size();
287 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
288 for(Uuid subnet : subnetList) {
289 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
290 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
291 .builder(Subnetmaps.class)
292 .child(Subnetmap.class, new SubnetmapKey(subnet))
294 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
297 Subnetmap subnetmapEntry = sn.get();
298 String subnetString = subnetmapEntry.getSubnetIp();
299 String[] subnetSplit = subnetString.split("/");
300 String subnetIp = subnetSplit[0];
301 String subnetPrefix = "0";
302 if(subnetSplit.length == 2) {
303 subnetPrefix = subnetSplit[1];
305 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
306 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
308 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
309 if(extIpCounter != 0) {
310 if(counter < extIpCounter) {
311 String[] IpSplit = externalIps.get(counter).split("/");
312 String externalIp = IpSplit[0];
313 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
314 if(IpSplit.length==2) {
315 extPrefix = IpSplit[1];
317 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
318 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
319 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
320 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
321 externalIp, extPrefix);
323 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
324 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
325 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
328 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
329 LOG.debug("NAT Service : Counter on externalIps got reset");
330 String[] IpSplit = externalIps.get(counter).split("/");
331 String externalIp = IpSplit[0];
332 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
333 if(IpSplit.length==2) {
334 extPrefix = IpSplit[1];
336 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
337 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
338 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
339 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
340 externalIp, extPrefix);
342 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
343 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
344 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
349 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
352 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
356 LOG.info("NAT Service : handleEnableSnat() Exit");
359 private BigInteger getPrimaryNaptSwitch(String routerName, long segmentId) {
360 // Allocate Primary Napt Switch for this router
361 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
362 if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
363 LOG.debug("NAT Service : Primary NAPT switch with DPN ID {} is already elected for router",primarySwitchId,routerName);
364 return primarySwitchId;
367 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
368 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
369 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
370 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
373 return primarySwitchId;
376 private void installNaptPfibExternalOutputFlow(Routers routers, BigInteger dpnId) {
377 Long extVpnId = NatUtil.getVpnId(dataBroker, routers.getNetworkId().getValue());
378 List<String> extIps = routers.getExternalIps();
379 installNaptPfibExternalOutputFlow(dpnId, extVpnId, extIps);
382 protected void installNaptPfibExternalOutputFlow(String routerName, Long routerId, BigInteger dpnId) {
383 Long extVpnId = NatUtil.getVpnId(dataBroker, routerId);
384 if (extVpnId == null || extVpnId == NatConstants.INVALID_ID) {
385 LOG.debug("installNaptPfibExternalOutputFlow - not found extVpnId for router {}", routerId);
388 List<String> externalIps = NatUtil.getExternalIpsFromRouter(dataBroker, routerName);
389 installNaptPfibExternalOutputFlow(dpnId, extVpnId, externalIps);
392 private void installNaptPfibExternalOutputFlow(BigInteger dpnId, Long extVpnId, List<String> externalIps) {
393 if (externalIps == null || externalIps.isEmpty()) {
394 LOG.debug("installNaptPfibExternalOutputFlow - empty external Ips list for dpnId {} extVpnId {}",
398 for (String ip : externalIps) {
399 Uuid subnetId = getSubnetIdForFixedIp(ip);
400 if (subnetId != null) {
401 LOG.debug("installNaptPfibExternalOutputFlow - dpnId {} extVpnId {} subnetId {} ip {}",
402 dpnId, extVpnId, subnetId, ip);
403 FlowEntity postNaptFlowEntity = buildNaptFibExternalOutputFlowEntity(dpnId, extVpnId, subnetId, ip);
404 mdsalManager.installFlow(postNaptFlowEntity);
409 private Uuid getSubnetIdForFixedIp(String ip) {
411 IpAddress externalIpv4Address = new IpAddress(new Ipv4Address(ip));
412 Port port = NatUtil.getNeutronPortForRouterGetewayIp(dataBroker, externalIpv4Address);
413 Uuid subnetId = NatUtil.getSubnetIdForFloatingIp(port, externalIpv4Address);
419 protected void subnetRegisterMapping(Routers routerEntry,Long segmentId) {
420 List<Uuid> subnetList = null;
421 List<String> externalIps = null;
422 LOG.debug("NAT Service : Fetching values from extRouters model");
423 subnetList = routerEntry.getSubnetIds();
424 externalIps = routerEntry.getExternalIps();
426 int extIpCounter = externalIps.size();
427 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
428 for(Uuid subnet : subnetList) {
429 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
430 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
431 .builder(Subnetmaps.class)
432 .child(Subnetmap.class, new SubnetmapKey(subnet))
434 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
437 Subnetmap subnetmapEntry = sn.get();
438 String subnetString = subnetmapEntry.getSubnetIp();
439 String[] subnetSplit = subnetString.split("/");
440 String subnetIp = subnetSplit[0];
441 String subnetPrefix = "0";
442 if(subnetSplit.length == 2) {
443 subnetPrefix = subnetSplit[1];
445 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
446 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
448 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
449 if(extIpCounter != 0) {
450 if(counter < extIpCounter) {
451 String[] IpSplit = externalIps.get(counter).split("/");
452 String externalIp = IpSplit[0];
453 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
454 if(IpSplit.length==2) {
455 extPrefix = IpSplit[1];
457 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
458 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
459 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
460 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
461 externalIp, extPrefix);
463 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
464 LOG.debug("NAT Service : Counter on externalIps got reset");
465 String[] IpSplit = externalIps.get(counter).split("/");
466 String externalIp = IpSplit[0];
467 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
468 if(IpSplit.length==2) {
469 extPrefix = IpSplit[1];
471 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
472 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
473 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
474 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
475 externalIp, extPrefix);
479 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
481 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
486 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
487 //Check if BGP VPN exists. If exists then invoke the new method.
488 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
489 if(bgpVpnId != NatConstants.INVALID_ID) {
490 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
491 if (bgpVpnUuid != null) {
492 String bgpVpnName = bgpVpnUuid.getValue();
493 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
494 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
495 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
497 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
501 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
502 addOrDelDefaultFibRouteForSNAT(routerName, create);
505 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
506 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
507 if (switches == null || switches.isEmpty()) {
508 LOG.debug("No switches found for router {}",routerName);
511 long routerId = NatUtil.readVpnId(dataBroker, routerName);
512 if (routerId == NatConstants.INVALID_ID) {
513 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
516 for (BigInteger dpnId : switches) {
518 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
519 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
521 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
522 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
527 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
528 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
529 if(dpnIds == null || dpnIds.isEmpty()) {
530 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
533 long routerId = NatUtil.getVpnId(dataBroker, routerName);
534 for (BigInteger dpnId : dpnIds) {
536 if (bgpVpnId != NatConstants.INVALID_ID) {
537 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
538 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
540 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
541 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
544 if (bgpVpnId != NatConstants.INVALID_ID) {
545 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
546 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
548 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
549 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
555 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
557 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
559 Optional<T> result = Optional.absent();
562 result = tx.read(datastoreType, path).get();
566 throw new RuntimeException(e);
573 public void close() throws Exception
575 if (listenerRegistration != null)
579 listenerRegistration.close();
581 catch (final Exception e)
583 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
586 listenerRegistration = null;
588 LOG.debug("ExternalRoutersListener Closed");
591 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
592 long routerId = NatUtil.getVpnId(dataBroker, routerName);
593 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
594 if(routerId != NatConstants.INVALID_ID) {
595 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
596 createOutboundTblEntry(primarySwitchId, routerId);
598 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
602 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
603 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
604 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
607 private String getFlowRefNaptFib(BigInteger dpnId, short tableId, long routerID, String externalIp) {
608 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
609 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).
610 append(NatConstants.FLOWID_SEPARATOR).append(externalIp).toString();
613 public BigInteger getCookieOutboundFlow(long routerId) {
614 return NwConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
615 BigInteger.valueOf(routerId));
618 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
619 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
620 List<MatchInfo> matches = new ArrayList<>();
621 matches.add(new MatchInfo(MatchFieldType.eth_type,
622 new long[] { 0x0800L }));
623 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
624 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
626 List<InstructionInfo> instructions = new ArrayList<>();
627 List<ActionInfo> actionsInfos = new ArrayList<>();
628 actionsInfos.add(new ActionPuntToController());
629 instructions.add(new InstructionApplyActions(actionsInfos));
630 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId),
631 MetaDataUtil.METADATA_MASK_VRFID));
633 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
634 BigInteger cookie = getCookieOutboundFlow(routerId);
635 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
637 cookie, matches, instructions);
638 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
642 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
643 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
644 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
645 LOG.debug("NAT Service : Installing flow {}", flowEntity);
646 mdsalManager.installFlow(flowEntity);
649 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
650 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
651 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
653 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
654 .setSourceDpid(srcDpId)
655 .setDestinationDpid(dstDpId)
656 .setTunnelType(tunType)
658 rpcResult = result.get();
659 if(!rpcResult.isSuccessful()) {
660 tunType = TunnelTypeGre.class ;
661 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
662 .setSourceDpid(srcDpId)
663 .setDestinationDpid(dstDpId)
664 .setTunnelType(tunType)
666 rpcResult = result.get();
667 if(!rpcResult.isSuccessful()) {
668 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
670 return rpcResult.getResult().getInterfaceName();
672 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
674 return rpcResult.getResult().getInterfaceName();
676 } catch (InterruptedException | ExecutionException | NullPointerException e) {
677 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
683 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
684 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAPT switch dpnId {} ", dpnId);
685 // Install miss entry pointing to group
686 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
687 mdsalManager.installFlow(flowEntity);
690 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
691 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
692 // Install the select group
693 long groupId = createGroupId(getGroupIdKey(routerName));
694 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
695 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
696 mdsalManager.syncInstallGroup(groupEntity, 0);
697 // Install miss entry pointing to group
698 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
699 mdsalManager.installFlow(flowEntity);
702 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
703 long groupId = createGroupId(getGroupIdKey(routerName));
704 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
705 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
706 mdsalManager.syncInstallGroup(groupEntity, 0);
710 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
712 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
713 long routerId = NatUtil.getVpnId(dataBroker, routerName);
714 List<MatchInfo> matches = new ArrayList<>();
715 matches.add(new MatchInfo(MatchFieldType.eth_type,
716 new long[] { 0x0800L }));
717 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
718 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
721 List<InstructionInfo> instructions = new ArrayList<>();
722 List<ActionInfo> actionsInfo = new ArrayList<>();
724 actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(routerId)));
725 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
726 actionsInfo.add(new ActionGroup(groupId));
727 instructions.add(new InstructionApplyActions(actionsInfo));
728 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
729 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
730 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
731 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
733 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
737 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
739 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
741 long routerId = NatUtil.getVpnId(dataBroker, routerName);
742 List<MatchInfo> matches = new ArrayList<MatchInfo>();
743 matches.add(new MatchInfo(MatchFieldType.eth_type,
744 new long[] { 0x0800L }));
745 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
746 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
748 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
749 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
751 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
752 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
753 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
754 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
756 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
760 // TODO : Replace this with ITM Rpc once its available with full functionality
761 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
762 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
763 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
764 mdsalManager.installFlow(flowEntity);
768 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
770 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
771 List<MatchInfo> matches = new ArrayList<>();
772 matches.add(new MatchInfo(MatchFieldType.eth_type,
773 new long[] { 0x0800L }));
774 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
776 List<InstructionInfo> instructions = new ArrayList<>();
777 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(routerId.longValue()),
778 MetaDataUtil.METADATA_MASK_VRFID));
779 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
780 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
781 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
782 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
783 NwConstants.COOKIE_TS_TABLE, matches, instructions);
787 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
788 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
789 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
792 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
793 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
794 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
797 private String getGroupIdKey(String routerName){
798 String groupIdKey = new String("snatmiss." + routerName);
802 protected long createGroupId(String groupIdKey) {
803 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
804 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
807 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
808 RpcResult<AllocateIdOutput> rpcResult = result.get();
809 return rpcResult.getResult().getIdValue();
810 } catch (NullPointerException | InterruptedException | ExecutionException e) {
816 protected void createGroupIdPool() {
817 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
818 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
819 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
820 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
823 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
824 if ((result != null) && (result.get().isSuccessful())) {
825 LOG.debug("NAT Service : Created GroupIdPool");
827 LOG.error("NAT Service : Unable to create GroupIdPool");
829 } catch (InterruptedException | ExecutionException e) {
830 LOG.error("Failed to create PortPool for NAPT Service",e);
834 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
835 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
836 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
837 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
838 List<BucketInfo> listBucketInfo = new ArrayList<>();
839 long routerId = NatUtil.getVpnId(dataBroker, routerName);
841 if(ifNamePrimary != null) {
842 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
843 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
845 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
847 listBucketInfo.add(0, bucketPrimary);
848 installSnatMissEntry(dpnId, listBucketInfo, routerName);
851 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
852 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
853 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
854 List<BucketInfo> listBucketInfo = new ArrayList<>();
855 long routerId = NatUtil.getVpnId(dataBroker, routerName);
857 if (ifNamePrimary != null) {
858 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
859 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
861 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
863 listBucketInfo.add(0, bucketPrimary);
864 return listBucketInfo;
866 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
869 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
872 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
875 List<BucketInfo> listBucketInfo = new ArrayList<>();
876 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
877 listActionInfoPrimary.add(new ActionNxResubmit(NatConstants.TERMINATING_SERVICE_TABLE));
878 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
879 listBucketInfo.add(0, bucketPrimary);
882 long routerId = NatUtil.getVpnId(dataBroker, routerName);
884 installSnatMissEntryForPrimrySwch(dpnId, routerName);
885 installTerminatingServiceTblEntry(dpnId, routerName);
886 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
887 installNaptPfibEntry(dpnId, routerId);
888 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
889 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
890 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
891 installNaptPfibEntry(dpnId, vpnId);
895 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
896 List<BucketInfo> listBucketInfo = new ArrayList<>();
897 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
898 listActionInfoPrimary.add(new ActionNxResubmit(NwConstants.INTERNAL_TUNNEL_TABLE));
899 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
900 listBucketInfo.add(0, bucketPrimary);
901 return listBucketInfo;
904 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
905 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
906 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
907 mdsalManager.installFlow(naptPfibFlowEntity);
910 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
912 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
913 List<MatchInfo> matches = new ArrayList<>();
914 matches.add(new MatchInfo(MatchFieldType.eth_type,
915 new long[] { 0x0800L }));
916 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
917 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
919 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
920 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
921 listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
922 listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
923 instructionInfo.add(new InstructionApplyActions(listActionInfo));
925 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
926 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
927 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
928 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
930 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
934 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
935 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
936 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
937 if(networkId == null) {
938 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
941 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
942 if(vpnName == null) {
943 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
944 networkId, externalIp, routerId);
947 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
948 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
951 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
952 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
954 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
955 //Generate VPN label for the external IP
956 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
957 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
959 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
960 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
963 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
964 if (result.isSuccessful()) {
965 LOG.debug("NAT Service : inside apply with result success");
966 GenerateVpnLabelOutput output = result.getResult();
967 final long label = output.getLabel();
969 int externalIpInDsFlag = 0;
970 //Get IPMaps from the DB for the router ID
971 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
972 if (dbIpMaps != null) {
973 for (IpMap dbIpMap : dbIpMaps) {
974 String dbExternalIp = dbIpMap.getExternalIp();
975 //Select the IPMap, whose external IP is the IP for which FIB is installed
976 if (dbExternalIp.contains(externalIp)) {
977 String dbInternalIp = dbIpMap.getInternalIp();
978 IpMapKey dbIpMapKey = dbIpMap.getKey();
979 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
980 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
981 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
982 externalIpInDsFlag++;
985 if (externalIpInDsFlag <= 0) {
986 LOG.debug("NAT Service : External Ip {} not found in DS, Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
987 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", label, externalIp, routerId);
988 return Futures.immediateFailedFuture(new Exception(errMsg));
991 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
996 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
997 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
998 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
1000 //Install custom FIB routes
1001 List<Instruction> customInstructions = new ArrayList<>();
1002 customInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
1003 makeTunnelTableEntry(dpnId, label, customInstructions);
1004 makeLFibTableEntry(dpnId, label, tableId);
1006 String fibExternalIp = externalIp.contains("/32") ? externalIp : (externalIp + "/32");
1007 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
1008 .setIpAddress(fibExternalIp).setServiceId(label).setInstruction(customInstructions).build();
1009 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
1010 return JdkFutureAdapters.listenInPoolThread(future);
1012 LOG.error("NAT Service : inside apply with result failed");
1013 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
1014 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1019 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
1022 public void onFailure(Throwable error) {
1023 log.error("NAT Service : Error in generate label or fib install process", error);
1027 public void onSuccess(RpcResult<Void> result) {
1028 if (result.isSuccessful()) {
1029 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
1031 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1037 private void makeLFibTableEntry(BigInteger dpId, long serviceId, short tableId) {
1038 List<MatchInfo> matches = new ArrayList<>();
1039 matches.add(new MatchInfo(MatchFieldType.eth_type,
1040 new long[]{0x8847L}));
1041 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1043 List<Instruction> instructions = new ArrayList<>();
1044 List<ActionInfo> actionsInfos = new ArrayList<>();
1045 actionsInfos.add(new ActionPopMpls());
1046 Instruction writeInstruction = new InstructionApplyActions(actionsInfos).buildInstruction(0);
1047 instructions.add(writeInstruction);
1048 instructions.add(new InstructionGotoTable(tableId).buildInstruction(1));
1050 // Install the flow entry in L3_LFIB_TABLE
1051 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1053 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1055 COOKIE_VM_LFIB_TABLE, matches, instructions);
1057 mdsalManager.installFlow(dpId, flowEntity);
1059 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
1062 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
1063 List<MatchInfo> mkMatches = new ArrayList<>();
1065 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
1067 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1069 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1070 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
1071 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1073 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1076 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1077 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1078 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1082 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1083 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1084 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1085 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1089 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1090 String routerName = original.getRouterName();
1091 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1092 if (routerId == NatConstants.INVALID_ID) {
1093 LOG.error("NAT Service : Update external router event - Invalid routerId for routerName {}", routerName);
1096 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
1097 Uuid networkId = original.getNetworkId();
1099 // Check if its update on SNAT flag
1100 boolean originalSNATEnabled = original.isEnableSnat();
1101 boolean updatedSNATEnabled = update.isEnableSnat();
1102 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1103 if (originalSNATEnabled != updatedSNATEnabled) {
1104 if(originalSNATEnabled) {
1105 //SNAT disabled for the router
1106 Uuid networkUuid = original.getNetworkId();
1107 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1108 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1109 handleDisableSnat(original, networkUuid, externalIps, false, null, dpnId);
1111 // Allocate Primary Napt Switch for existing router
1112 BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName, routerId);
1113 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
1114 LOG.error("NAT Service: Failed to get or allocated NAPT switch in ExternalRouterListener.Update()");
1117 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1118 handleEnableSnat(original, routerId, primarySwitchId);
1122 if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
1123 handleRouterGwFlows(original, dpnId, NwConstants.DEL_FLOW);
1124 handleRouterGwFlows(update, dpnId, NwConstants.ADD_FLOW);
1127 //Check if the Update is on External IPs
1128 LOG.debug("NAT Service : Checking if this is update on External IPs");
1129 List<String> originalExternalIpsList = original.getExternalIps();
1130 List<String> updatedExternalIpsList = update.getExternalIps();
1131 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1132 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1134 //Check if the External IPs are added during the update.
1135 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1136 if(addedExternalIps.size() != 0) {
1137 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1138 vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps, update.getExtGwMacAddress(), dpnId,
1139 update.getNetworkId(), null, NwConstants.ADD_FLOW);
1141 for (String addedExternalIp : addedExternalIps) {
1143 1) Do nothing in the IntExtIp model.
1144 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1146 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1147 String externalIp = externalIpParts[0];
1148 String externalIpPrefix = externalIpParts[1];
1149 String externalpStr = externalIp + "/" + externalIpPrefix;
1150 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1151 externalpStr, routerId);
1152 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1154 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1157 //Check if the External IPs are removed during the update.
1158 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1159 if(removedExternalIps.size() > 0) {
1160 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1161 vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerName, removedExternalIps, original.getExtGwMacAddress(),
1162 dpnId, networkId, null, NwConstants.DEL_FLOW);
1164 List<String> removedExternalIpsAsList = new ArrayList<>();
1165 for (String removedExternalIp : removedExternalIps) {
1167 1) Remove the mappings in the IntExt IP model which has external IP.
1168 2) Remove the external IP in the ExternalCounter model.
1169 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1170 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1171 4) Increase the count of the allocated external IP by one.
1172 5) Advertise to the BGP if external IP is allocated for the first time for the router i.e. the route for the external IP is absent.
1173 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1174 7) Advertise to the BGP for removing the route for the removed external IPs.
1177 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1178 String externalIp = externalIpParts[0];
1179 String externalIpPrefix = externalIpParts[1];
1180 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1182 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1183 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1184 String vpnName = "";
1185 if(vpnUuId != null){
1186 vpnName = vpnUuId.getValue();
1188 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1190 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1191 //Get the internal IPs which are associated to the removed external IPs
1192 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1193 List<String> removedInternalIps = new ArrayList<>();
1194 for(IpMap ipMap : ipMaps){
1195 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1196 removedInternalIps.add(ipMap.getInternalIp());
1200 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1201 for(String removedInternalIp : removedInternalIps){
1202 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1203 removedInternalIp, routerId);
1204 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1207 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1208 externalIpAddrStr, routerId );
1209 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1210 removedExternalIpsAsList.add(externalIpAddrStr);
1212 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1213 for(String removedInternalIp : removedInternalIps) {
1214 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1217 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1218 //Get the internalIP and internal Port which were associated to the removed external IP.
1219 List<Integer> externalPorts = new ArrayList<>();
1220 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1221 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1222 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1223 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1224 if (ipPortMapping.isPresent()) {
1225 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1226 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1227 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1228 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1229 for(IpPortMap ipPortMap : ipPortMaps){
1230 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1231 if(ipPortExternal.getIpAddress().equals(externalIp)){
1232 externalPorts.add(ipPortExternal.getPortNum());
1233 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1234 if(removedInternalIpPorts != null){
1235 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1236 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1238 removedInternalIpPorts = new ArrayList<>();
1239 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1240 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1247 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1248 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1249 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1250 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1251 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1252 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1253 for(String removedInternalIpPort : removedInternalIpPorts){
1254 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1255 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1256 //Remove the IP port incomint packer map.
1257 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1258 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1259 if(removedInternalIpPortParts.length == 2){
1260 String removedInternalIp = removedInternalIpPortParts[0];
1261 String removedInternalPort = removedInternalIpPortParts[1];
1262 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1263 if (removedInternalPortsList != null){
1264 removedInternalPortsList.add(removedInternalPort);
1265 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1267 removedInternalPortsList = new ArrayList<>();
1268 removedInternalPortsList.add(removedInternalPort);
1269 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1275 // Delete the entry from SnatIntIpPortMap DS
1276 Set<String> internalIps = internalIpPortMap.keySet();
1277 for(String internalIp : internalIps){
1278 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1279 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1282 naptManager.removeNaptPortPool(externalIp);
1284 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1285 for(Integer externalPort : externalPorts) {
1286 //Remove the NAPT translation entries from Inbound NAPT table
1287 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1290 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1291 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1292 String internalIp = internalIpPort.getKey();
1293 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1294 List<String> internalPorts = internalIpPort.getValue();
1295 for(String internalPort : internalPorts){
1296 //Remove the NAPT translation entries from Outbound NAPT table
1297 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1301 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1304 //Check if its Update on subnets
1305 LOG.debug("NAT Service : Checking if this is update on subnets");
1306 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1307 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1308 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1309 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1310 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1312 //Check if the Subnet IDs are added during the update.
1313 if(addedSubnetIds.size() != 0){
1314 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1315 for(Uuid addedSubnetId : addedSubnetIds){
1317 1) Select the least loaded external IP for the subnet and store the mapping of the subnet IP and the external IP in the IntExtIp model.
1318 2) Increase the count of the selected external IP by one.
1319 3) Advertise to the BGP if external IP is allocated for the first time for the router i.e. the route for the external IP is absent.
1321 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1322 if(subnetIp != null) {
1323 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1326 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1329 //Check if the Subnet IDs are removed during the update.
1330 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1331 if(removedSubnetIds.size() != 0){
1332 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1333 for(Uuid removedSubnetId : removedSubnetIds){
1334 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1335 if(subnetAddr != null){
1337 1) Remove the subnet IP and the external IP in the IntExtIp map
1338 2) Decrease the count of the coresponding external IP by one.
1339 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1342 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1343 if (externalIp == null) {
1344 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1348 naptManager.updateCounter(routerId, externalIp, false);
1349 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1350 if (!isExternalIpAllocated(externalIp)) {
1351 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1352 List<String> externalIps = new ArrayList<>();
1353 externalIps.add(externalIp);
1354 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1355 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1356 dpnId,routerId,networkId,externalIps);
1359 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1360 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1363 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1367 private boolean isExternalIpAllocated(String externalIp) {
1368 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1369 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1370 if (externalCountersData.isPresent()) {
1371 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1372 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1373 for(ExternalCounters ext : externalCounters) {
1374 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1375 if (externalIpCount.getExternalIp().equals(externalIp)) {
1376 if (externalIpCount.getCounter() != 0) {
1387 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1388 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1389 if (leastLoadedExtIpAddr != null) {
1390 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1391 String leastLoadedExtIp = externalIpParts[0];
1392 String leastLoadedExtIpPrefix = externalIpParts[1];
1393 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1394 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1395 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1396 subnetIp = subnetIpParts[0];
1397 String subnetIpPrefix = subnetIpParts[1];
1398 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1399 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1400 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1401 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1404 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1405 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1406 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1409 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1410 IpMapKey ipMapKey = new IpMapKey(internalIp);
1411 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1412 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1413 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1417 //Re-advertise to the BGP for the external IP, which is allocated to the subnet for the first time and hence not having a route.
1418 //Get the VPN Name using the network ID
1419 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1420 if (vpnName != null) {
1421 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1422 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1423 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1424 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1426 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1427 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1432 protected Long checkExternalIpLabel(long routerId, String externalIp){
1433 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1434 for(IpMap ipMap : ipMaps){
1435 if(ipMap.getExternalIp().equals(externalIp)){
1436 if (ipMap.getLabel() != null){
1437 return ipMap.getLabel();
1445 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1446 LOG.trace("NAT Service : Router delete method");
1449 ROUTER DELETE SCENARIO
1450 1) Get the router ID from the event.
1451 2) Build the cookie information from the router ID.
1452 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1453 4) Build the flow with the cookie value.
1454 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1455 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1456 7) Get the list of external IP address maintained for the router ID.
1457 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1458 9) Withdraw the corresponding routes from the BGP.
1461 if (identifier == null || router == null) {
1462 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1466 String routerName = router.getRouterName();
1467 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1468 addOrDelDefFibRouteToSNAT(routerName, false);
1469 Uuid networkUuid = router.getNetworkId();
1470 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1471 if (routerId == NatConstants.INVALID_ID) {
1472 LOG.error("NAT Service : Remove external router event - Invalid routerId for routerName {}", routerName);
1476 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
1477 handleRouterGwFlows(router, primarySwitchId, NwConstants.DEL_FLOW);
1478 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1479 handleDisableSnat(router, networkUuid, externalIps, true, null, primarySwitchId);
1483 private void handleRouterGwFlows(Routers router, BigInteger primarySwitchId, int addOrRemove) {
1484 WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
1485 vpnManager.setupRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
1486 router.getNetworkId(), writeTx, addOrRemove);
1487 vpnManager.setupArpResponderFlowsToExternalNetworkIps(router.getRouterName(), router.getExternalIps(),
1488 router.getExtGwMacAddress(), primarySwitchId, router.getNetworkId(), writeTx, addOrRemove);
1492 public void handleDisableSnat(Routers router, Uuid networkUuid, List<String> externalIps, boolean routerFlag,
1493 String vpnId, BigInteger naptSwitchDpnId) {
1494 LOG.info("NAT Service : handleDisableSnat() Entry");
1495 String routerName = router.getRouterName();
1497 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1498 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1499 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1500 naptManager.removeMapping(routerId);
1503 removeNaptSwitch(routerName);
1505 updateNaptSwitch(routerName, BigInteger.ZERO);
1508 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1509 naptManager.removeExternalCounter(routerId);
1511 LOG.debug("NAT Service : got primarySwitch as dpnId {}", naptSwitchDpnId);
1512 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)) {
1513 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1516 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId, externalIps);
1517 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1519 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1520 } catch (Exception ex) {
1521 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1524 } catch (Exception ex) {
1525 LOG.error("Exception while handling disableSNAT : {}", ex);
1527 LOG.info("NAT Service : handleDisableSnat() Exit");
1530 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1531 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1533 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1534 BigInteger naptSwitchDpnId = null;
1535 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1536 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1537 if (rtrToNapt.isPresent()) {
1538 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1540 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1542 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1544 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1545 } catch (Exception ex) {
1546 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1548 } catch (Exception ex) {
1549 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1551 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1554 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1555 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1556 .setPrimarySwitchId(naptSwitchId).build();
1558 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1559 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1560 } catch (Exception ex) {
1561 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1562 naptSwitchId,routerName);
1564 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1565 naptSwitchId,routerName);
1568 protected void removeNaptSwitch(String routerName){
1569 // Remove router and switch from model
1570 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1571 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1572 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1575 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName, List<String> externalIps){
1577 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1578 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1580 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1581 // traffic which comes from the VMs of the NAPT switches)
1582 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1583 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1585 LOG.info("NAT Service : Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1586 mdsalManager.removeFlow(pSNatFlowEntity);
1588 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1589 // traffic which comes from the VMs of the non NAPT switches)
1590 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1591 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1593 LOG.info("NAT Service : Remove the flow in the " + NwConstants.INTERNAL_TUNNEL_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1594 mdsalManager.removeFlow(tsNatFlowEntity);
1596 //Remove the Outbound flow entry which forwards the packet to FIB Table
1597 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1598 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1600 LOG.info("NAT Service : Remove the flow in the " + NwConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1601 mdsalManager.removeFlow(outboundNatFlowEntity);
1603 removeNaptFibExternalOutputFlows(routerId, dpnId, networkId, externalIps);
1605 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1606 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1607 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1609 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1610 mdsalManager.removeFlow(natPfibFlowEntity);
1612 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1613 //Get the VPN ID from the ExternalNetworks model
1615 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1616 // ie called from router delete cases
1617 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1618 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1619 if(vpnUuid != null) {
1620 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1621 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1624 // ie called from disassociate vpn case
1625 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1626 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1627 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1630 if(vpnId != NatConstants.INVALID_ID){
1631 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1632 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1633 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1634 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
1635 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1638 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1639 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1640 if(ipPortMapping == null){
1641 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1645 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1646 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1647 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1648 for(IpPortMap ipPortMap : ipPortMaps){
1649 String ipPortInternal = ipPortMap.getIpPortInternal();
1650 String[] ipPortParts = ipPortInternal.split(":");
1651 if(ipPortParts.length != 2) {
1652 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1655 String internalIp = ipPortParts[0];
1656 String internalPort = ipPortParts[1];
1658 //Build the flow for the outbound NAPT table
1659 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1660 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1662 LOG.info("NAT Service : Remove the flow in the " + NwConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1663 mdsalManager.removeFlow(outboundNaptFlowEntity);
1665 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1666 String externalIp = ipPortExternal.getIpAddress();
1667 int externalPort = ipPortExternal.getPortNum();
1669 //Build the flow for the inbound NAPT table
1670 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1671 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1673 LOG.info("NAT Service : Remove the flow in the " + NwConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1674 mdsalManager.removeFlow(inboundNaptFlowEntity);
1679 protected void removeNaptFibExternalOutputFlows(long routerId, BigInteger dpnId, Uuid networkId,
1680 List<String> externalIps) {
1681 Long extVpnId = null;
1682 if (networkId != null) {
1683 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1684 if (vpnUuid != null) {
1685 extVpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1687 LOG.debug("NAT Service: removeNaptFibExternalOutputFlows - vpnUuid is null");
1690 LOG.debug("NAT Service: removeNaptFibExternalOutputFlows - networkId is null");
1691 extVpnId = NatUtil.getVpnId(dataBroker, routerId);
1693 if (extVpnId == null || extVpnId == NatConstants.INVALID_ID) {
1694 LOG.debug("removeNaptFibExternalOutputFlows - extVpnId not found for routerId {}", routerId);
1695 extVpnId = routerId;
1697 for (String ip : externalIps) {
1698 String extIp = removeMaskFromIp(ip);
1699 String naptFlowRef = getFlowRefNaptFib(dpnId, NwConstants.NAPT_PFIB_TABLE, extVpnId, extIp);
1700 LOG.info("NAT Service: Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch"
1701 + " with the DPN ID {} and router ID {} and IP {} flowRef {}", dpnId, routerId, extIp, naptFlowRef);
1702 mdsalManager.removeFlow(NatUtil.buildFlowEntity(dpnId,NwConstants.NAPT_PFIB_TABLE, naptFlowRef));
1706 private String removeMaskFromIp(String ip) {
1707 if (ip != null && !ip.trim().isEmpty()) {
1708 return ip.split("/")[0];
1713 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1715 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1716 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1718 //Remove the NAPT PFIB TABLE entry
1720 if(vpnName != null) {
1721 // ie called from disassociate vpn case
1722 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1723 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1724 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1727 if(vpnId != NatConstants.INVALID_ID){
1728 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1729 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1730 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1731 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
1732 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1734 // Remove IP-PORT active NAPT entries and release port from IdManager
1735 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1736 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1737 if(ipPortMapping == null){
1738 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1741 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1742 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1743 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1744 for(IpPortMap ipPortMap : ipPortMaps){
1745 String ipPortInternal = ipPortMap.getIpPortInternal();
1746 String[] ipPortParts = ipPortInternal.split(":");
1747 if(ipPortParts.length != 2) {
1748 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1751 String internalIp = ipPortParts[0];
1752 String internalPort = ipPortParts[1];
1754 //Build the flow for the outbound NAPT table
1755 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1756 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1758 LOG.info("NAT Service : Remove the flow in the " + NwConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1759 mdsalManager.removeFlow(outboundNaptFlowEntity);
1761 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1762 String externalIp = ipPortExternal.getIpAddress();
1763 int externalPort = ipPortExternal.getPortNum();
1765 //Build the flow for the inbound NAPT table
1766 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1767 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1769 LOG.info("NAT Service : Remove the flow in the " + NwConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1770 mdsalManager.removeFlow(inboundNaptFlowEntity);
1772 // Finally release port from idmanager
1773 String internalIpPort = internalIp +":"+internalPort;
1774 naptManager.removePortFromPool(internalIpPort, externalIp);
1776 //Remove sessions from models
1777 naptManager.removeIpPortMappingForRouterID(routerId);
1778 naptManager.removeIntIpPortMappingForRouterID(routerId);
1782 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1786 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1787 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1789 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1790 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1791 if(allSwitchList == null || allSwitchList.isEmpty()){
1792 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1795 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1796 for (BigInteger dpnId : allSwitchList) {
1797 if (!naptSwitchDpnId.equals(dpnId)) {
1798 LOG.info("NAT Service : Handle Ordinary switch");
1800 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1801 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1802 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1804 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1805 mdsalManager.removeFlow(pSNatFlowEntity);
1807 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1808 long groupId = createGroupId(getGroupIdKey(routerName));
1809 List<BucketInfo> listBucketInfo = new ArrayList<>();
1810 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1812 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1813 mdsalManager.removeGroup(pSNatGroupEntity);
1819 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1820 //Withdraw the corresponding routes from the BGP.
1821 //Get the network ID using the router ID.
1822 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1823 externalIps,routerId,networkUuid, vpnName);
1824 if(networkUuid == null ){
1825 LOG.error("NAT Service : networkId is null");
1829 if (externalIps == null || externalIps.isEmpty()) {
1830 LOG.debug("NAT Service : externalIps is null");
1834 if(vpnName ==null) {
1835 //Get the VPN Name using the network ID
1836 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1837 if (vpnName == null) {
1838 LOG.error("No VPN associated with ext nw {} for the router {}",
1839 networkUuid, routerId);
1843 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1845 //Remove custom FIB routes
1846 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1847 for (String extIp : externalIps) {
1848 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1852 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1853 clearBgpRoutes(extIp,vpnName);
1854 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1857 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1858 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1860 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1861 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1865 final long label = tempLabel;
1866 final String externalIp = extIp;
1868 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1869 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1871 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1874 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1876 if (result.isSuccessful()) {
1877 removeTunnelTableEntry(dpnId, label);
1878 removeLFibTableEntry(dpnId, label);
1879 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1880 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1881 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1883 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1885 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1891 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1894 public void onFailure(Throwable error) {
1895 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1899 public void onSuccess(RpcResult<Void> result) {
1900 if (result.isSuccessful()) {
1901 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1903 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1909 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1910 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1911 //Get IPMaps from the DB for the router ID
1912 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1913 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1914 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1918 long tempLabel = NatConstants.INVALID_ID;
1919 for (IpMap dbIpMap : dbIpMaps) {
1920 String dbExternalIp = dbIpMap.getExternalIp();
1921 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1922 //Select the IPMap, whose external IP is the IP for which FIB is installed
1923 if (extIp.equals(dbExternalIp)) {
1924 tempLabel = dbIpMap.getLabel();
1925 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1929 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1930 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1934 final long label = tempLabel;
1935 final String externalIp = extIp;
1937 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1938 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1940 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1943 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1945 if (result.isSuccessful()) {
1946 removeTunnelTableEntry(dpnId, label);
1947 removeLFibTableEntry(dpnId, label);
1948 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1949 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1950 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1952 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1954 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1960 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1963 public void onFailure(Throwable error) {
1964 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1968 public void onSuccess(RpcResult<Void> result) {
1969 if (result.isSuccessful()) {
1970 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1972 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1978 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1979 //Withdraw the corresponding routes from the BGP.
1980 //Get the network ID using the router ID.
1981 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1982 externalIps,routerId,networkUuid, vpnName);
1983 if (networkUuid == null) {
1984 LOG.error("NAT Service : networkId is null");
1988 if (externalIps == null || externalIps.isEmpty()) {
1989 LOG.debug("NAT Service : externalIps is null");
1993 if (vpnName == null) {
1994 //Get the VPN Name using the network ID
1995 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1996 if (vpnName == null) {
1997 LOG.error("No VPN associated with ext nw {} for the router {}",
1998 networkUuid, routerId);
2002 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
2004 //Remove custom FIB routes
2005 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
2006 for (String extIp : externalIps) {
2007 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
2011 protected void clearBgpRoutes(String externalIp, final String vpnName) {
2012 //Inform BGP about the route removal
2013 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
2014 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
2015 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
2018 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
2019 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
2020 List<MatchInfo> mkMatches = new ArrayList<>();
2021 // Matching metadata
2022 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
2023 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
2024 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
2025 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
2026 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
2027 mdsalManager.removeFlow(dpnId, flowEntity);
2028 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
2031 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
2032 List<MatchInfo> matches = new ArrayList<>();
2033 matches.add(new MatchInfo(MatchFieldType.eth_type,
2034 new long[] { 0x8847L }));
2035 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
2037 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
2039 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
2041 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
2043 COOKIE_VM_LFIB_TABLE, matches, null);
2045 mdsalManager.removeFlow(dpnId, flowEntity);
2047 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
2051 * router association to vpn
2052 *@param routerName - Name of router
2053 *@param bgpVpnName BGP VPN name
2055 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
2056 LOG.debug("NAT Service : Router associated to BGP VPN");
2057 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2058 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2060 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2062 if(bgpVpnId != NatConstants.INVALID_ID){
2063 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
2064 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
2065 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
2067 // Get the allocated Primary NAPT Switch for this router
2068 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2069 LOG.debug("Router ID value {} ", routerId);
2070 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2072 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
2073 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
2076 long groupId = createGroupId(getGroupIdKey(routerName));
2077 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2083 * router disassociation from vpn
2084 *@param routerName - Name of router
2085 *@param bgpVpnName BGP VPN name
2087 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2088 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2089 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2090 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2091 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2093 // Get the allocated Primary NAPT Switch for this router
2094 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2095 LOG.debug("Router ID value {} ", routerId);
2096 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2098 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2099 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2102 long groupId = createGroupId(getGroupIdKey(routerName));
2103 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2107 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2108 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2109 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2110 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2111 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2116 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2117 routerId, boolean isSnatCfgd){
2118 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, isSnatCfgd, null);
2121 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2122 routerId, boolean isSnatCfgd, Routers router){
2123 long changedVpnId = bgpVpnId;
2124 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2125 if (bgpVpnId == NatConstants.INVALID_ID){
2126 changedVpnId = routerId;
2127 logMsg = "NAT Service : Update the router ID {}";
2130 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2131 if (switches == null || switches.isEmpty()) {
2132 LOG.debug("No switches found for router {}",routerName);
2135 for(BigInteger dpnId : switches) {
2136 // Update the BGP VPN ID in the SNAT miss entry to group
2137 if( !dpnId.equals(primarySwitchId) ) {
2138 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2139 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2140 long groupId = createGroupId(getGroupIdKey(routerName));
2142 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2145 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2146 changedVpnId, groupId, dpnId);
2147 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2148 mdsalManager.installFlow(flowEntity);
2151 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2152 changedVpnId, primarySwitchId);
2153 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2154 mdsalManager.installFlow(flowEntity);
2156 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2157 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2158 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2160 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2161 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2162 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2164 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2165 changedVpnId, primarySwitchId);
2166 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2168 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2169 " in the Primary switch {}", changedVpnId, primarySwitchId);
2170 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2172 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2173 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2174 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2175 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2176 installNaptPfibEntry(primarySwitchId, vpnId);
2182 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2183 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2184 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2185 if(ipPortMapping == null){
2186 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2189 // Get the External Gateway MAC Address
2190 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
2191 if (extGwMacAddress != null) {
2192 LOG.debug("External Gateway MAC address {} found for External Router ID {}", extGwMacAddress, routerId);
2194 LOG.error("No External Gateway MAC address found for External Router ID {}", routerId);
2197 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2198 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2199 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2200 for(IpPortMap ipPortMap : ipPortMaps){
2201 String ipPortInternal = ipPortMap.getIpPortInternal();
2202 String[] ipPortParts = ipPortInternal.split(":");
2203 if(ipPortParts.length != 2) {
2204 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2207 String internalIp = ipPortParts[0];
2208 String internalPort = ipPortParts[1];
2209 LOG.debug("NAT Service : Found Internal IP {} and Internal Port {}",internalIp, internalPort);
2210 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2211 NAPTEntryEvent.Protocol protocol;
2212 switch (protocolTypes){
2214 protocol = NAPTEntryEvent.Protocol.TCP;
2217 protocol = NAPTEntryEvent.Protocol.UDP;
2220 protocol = NAPTEntryEvent.Protocol.TCP;
2222 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2223 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2224 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2225 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid,
2226 routerId, bgpVpnId, internalAddress, externalAddress, protocol, extGwMacAddress);
2227 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId,
2228 bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress);
2234 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2236 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2237 List<MatchInfo> matches = new ArrayList<>();
2238 matches.add(new MatchInfo(MatchFieldType.eth_type,
2239 new long[] { 0x0800L }));
2240 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2241 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2243 List<InstructionInfo> instructions = new ArrayList<>();
2244 List<ActionInfo> actionsInfo = new ArrayList<>();
2246 actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(changedVpnId)));
2247 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2248 actionsInfo.add(new ActionGroup(groupId));
2249 instructions.add(new InstructionApplyActions(actionsInfo));
2250 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2251 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2252 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2253 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2255 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2259 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2261 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2262 List<MatchInfo> matches = new ArrayList<>();
2263 matches.add(new MatchInfo(MatchFieldType.eth_type,
2264 new long[] { 0x0800L }));
2265 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2266 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2268 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2269 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
2271 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2272 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2273 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2274 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2276 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2280 // TODO : Replace this with ITM Rpc once its available with full functionality
2281 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2282 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2283 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2284 mdsalManager.installFlow(flowEntity);
2288 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2289 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2290 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2291 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2292 List<MatchInfo> matches = new ArrayList<>();
2293 matches.add(new MatchInfo(MatchFieldType.eth_type,
2294 new long[] { 0x0800L }));
2295 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2297 List<InstructionInfo> instructions = new ArrayList<>();
2298 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId),
2299 MetaDataUtil.METADATA_MASK_VRFID));
2300 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
2301 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2302 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2303 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2304 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2308 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2309 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2310 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2311 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2312 mdsalManager.installFlow(flowEntity);
2315 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2316 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2317 List<MatchInfo> matches = new ArrayList<>();
2318 matches.add(new MatchInfo(MatchFieldType.eth_type,
2319 new long[]{0x0800L}));
2320 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2321 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2323 List<InstructionInfo> instructions = new ArrayList<>();
2324 List<ActionInfo> actionsInfos = new ArrayList<>();
2325 actionsInfos.add(new ActionPuntToController());
2326 instructions.add(new InstructionApplyActions(actionsInfos));
2327 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId),
2328 MetaDataUtil.METADATA_MASK_VRFID));
2330 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2331 BigInteger cookie = getCookieOutboundFlow(routerId);
2332 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2333 cookie, matches, instructions);
2334 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2338 protected FlowEntity buildNaptFibExternalOutputFlowEntity(BigInteger dpId, long extVpnId, Uuid subnetId, String externalIp) {
2339 LOG.debug("NAT Service : buildNaptFibExternalOutputFlowEntity called for dpId {}, routerId {}, srcIp {}", dpId, extVpnId,
2342 List<MatchInfo> matches = new ArrayList<>();
2343 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 }));
2344 matches.add(new MatchInfo(MatchFieldType.metadata,
2345 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(extVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2346 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] { externalIp , "32" }));
2348 List<InstructionInfo> instructions = new ArrayList<>();
2349 List<ActionInfo> actionsInfos = new ArrayList<>();
2350 instructions.add(new InstructionApplyActions(actionsInfos));
2351 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetId.getValue()), idManager);
2352 actionsInfos.add(new ActionGroup(groupId));
2354 String flowRef = getFlowRefNaptFib(dpId, NwConstants.NAPT_PFIB_TABLE, extVpnId, externalIp);
2355 BigInteger cookie = getCookieOutboundFlow(extVpnId);
2356 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef, 6, flowRef, 0,
2357 0, cookie, matches, instructions);
2358 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2362 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2363 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2364 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2365 mdsalManager.installFlow(naptPfibFlowEntity);
2368 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2370 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2371 List<MatchInfo> matches = new ArrayList<>();
2372 matches.add(new MatchInfo(MatchFieldType.eth_type,
2373 new long[] { 0x0800L }));
2374 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2375 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2377 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2378 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2379 listActionInfo.add(new ActionNxLoadInPort(BigInteger.ZERO));
2380 listActionInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
2381 instructionInfo.add(new InstructionApplyActions(listActionInfo));
2383 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2384 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2385 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2386 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2388 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2393 protected ExternalRoutersListener getDataTreeChangeListener()
2395 return ExternalRoutersListener.this;