2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.natservice.internal;
11 import java.math.BigInteger;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
16 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
17 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
18 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
36 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;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
48 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
49 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
50 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
51 import org.opendaylight.genius.mdsalutil.ActionInfo;
52 import org.opendaylight.genius.mdsalutil.ActionType;
53 import org.opendaylight.genius.mdsalutil.BucketInfo;
54 import org.opendaylight.genius.mdsalutil.FlowEntity;
55 import org.opendaylight.genius.mdsalutil.GroupEntity;
56 import org.opendaylight.genius.mdsalutil.InstructionInfo;
57 import org.opendaylight.genius.mdsalutil.InstructionType;
58 import org.opendaylight.genius.mdsalutil.MDSALUtil;
59 import org.opendaylight.genius.mdsalutil.MatchFieldType;
60 import org.opendaylight.genius.mdsalutil.MatchInfo;
61 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
62 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
63 import org.opendaylight.genius.mdsalutil.NwConstants;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
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.RouterIdName;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
98 import org.opendaylight.yangtools.concepts.ListenerRegistration;
99 import org.opendaylight.yangtools.yang.binding.DataObject;
100 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
101 import org.opendaylight.yangtools.yang.common.RpcResult;
102 import org.slf4j.Logger;
103 import org.slf4j.LoggerFactory;
105 import com.google.common.base.Optional;
106 import com.google.common.collect.Sets;
107 import com.google.common.collect.Sets.SetView;
108 import com.google.common.util.concurrent.AsyncFunction;
109 import com.google.common.util.concurrent.FutureCallback;
110 import com.google.common.util.concurrent.Futures;
111 import com.google.common.util.concurrent.JdkFutureAdapters;
112 import com.google.common.util.concurrent.ListenableFuture;
115 * Created by EYUGSAR on 2/20/2016.
118 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener>{
120 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
121 private static long label;
122 private ListenerRegistration<DataChangeListener> listenerRegistration;
123 private final DataBroker dataBroker;
124 private IMdsalApiManager mdsalManager;
125 private ItmRpcService itmManager;
126 private OdlInterfaceRpcService interfaceManager;
127 private IdManagerService idManager;
128 private NaptManager naptManager;
129 private NAPTSwitchSelector naptSwitchSelector;
130 private IBgpManager bgpManager;
131 private VpnRpcService vpnService;
132 private FibRpcService fibService;
133 private SNATDefaultRouteProgrammer defaultRouteProgrammer;
134 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
135 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
136 private NaptEventHandler naptEventHandler;
137 private NaptPacketInHandler naptPacketInHandler;
138 private IFibManager fibManager;
140 public void setNaptEventHandler(NaptEventHandler naptEventHandler) {
141 this.naptEventHandler = naptEventHandler;
144 public void setNaptPacketInHandler(NaptPacketInHandler naptPacketInHandler) {
145 this.naptPacketInHandler = naptPacketInHandler;
148 public void setMdsalManager(IMdsalApiManager mdsalManager) {
149 this.mdsalManager = mdsalManager;
152 public void setItmManager(ItmRpcService itmManager) {
153 this.itmManager = itmManager;
156 public void setIdManager(IdManagerService idManager) {
157 this.idManager = idManager;
161 void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
162 this.defaultRouteProgrammer = defaultRouteProgrammer;
166 public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
167 this.interfaceManager = interfaceManager;
170 public void setNaptManager(NaptManager naptManager) {
171 this.naptManager = naptManager;
174 public void setNaptSwitchSelector(NAPTSwitchSelector naptSwitchSelector) {
175 this.naptSwitchSelector = naptSwitchSelector;
178 public void setBgpManager(IBgpManager bgpManager) {
179 this.bgpManager = bgpManager;
182 public void setVpnService(VpnRpcService vpnService) {
183 this.vpnService = vpnService;
186 public void setFibService(FibRpcService fibService) {
187 this.fibService = fibService;
190 public void setFibManager(IFibManager fibManager) {
191 this.fibManager = fibManager;
194 public ExternalRoutersListener(DataBroker dataBroker )
196 super( Routers.class, ExternalRoutersListener.class );
197 this.dataBroker = dataBroker;
201 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
203 LOG.info("NAT Service : Add external router event for {}", routers.getRouterName());
205 // Populate the router-id-name container
206 String routerName = routers.getRouterName();
207 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
208 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
209 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
211 LOG.info("NAT Service : Installing NAT default route on all dpns part of router {}", routers.getRouterName());
213 addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
214 } catch (Exception ex) {
215 LOG.debug("NAT Service : Exception {} while Installing NAT default route on all dpns part of router {}",ex,routers.getRouterName());
218 if( !routers.isEnableSnat()) {
219 LOG.info("NAT Service : SNAT is disabled for external router {} ", routers.getRouterName());
223 handleEnableSnat(routers);
226 public void handleEnableSnat(Routers routers){
227 String routerName = routers.getRouterName();
228 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
230 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
231 naptManager.initialiseExternalCounter(routers, segmentId);
233 subnetRegisterMapping(routers,segmentId);
235 // Allocate Primary Napt Switch for this router
236 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,segmentId);
237 if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
238 LOG.debug("NAT Service : Primary NAPT switch with DPN ID {} is already elected for router",primarySwitchId,routerName);
241 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
242 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
243 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
244 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
247 LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
249 long bgpVpnId = NatConstants.INVALID_ID;
250 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
251 if (bgpVpnUuid != null) {
252 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
254 if (bgpVpnId != NatConstants.INVALID_ID){
255 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, segmentId, false);
257 // write metadata and punt
258 installOutboundMissEntry(routerName, primarySwitchId);
259 // Now install entries in SNAT tables to point to Primary for each router
260 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
261 if (switches != null) {
262 for (BigInteger dpnId : switches) {
263 // Handle switches and NAPT switches separately
264 if (!dpnId.equals(primarySwitchId)) {
265 LOG.debug("NAT Service : Handle Ordinary switch");
266 handleSwitches(dpnId, routerName, primarySwitchId);
268 LOG.debug("NAT Service : Handle NAPT switch");
269 handlePrimaryNaptSwitch(dpnId, routerName);
275 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,segmentId);
276 if (externalIps == null || externalIps.isEmpty()) {
277 LOG.debug("NAT Service : Internal External mapping found for router {}",routerName);
280 for (String externalIpAddrPrefix : externalIps) {
281 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
282 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
286 /*// call registerMapping Api
287 LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
289 List<Uuid> subnetList = null;
290 List<String> externalIps = null;
292 InstanceIdentifier<Routers> id = InstanceIdentifier
293 .builder(ExtRouters.class)
294 .child(Routers.class, new RoutersKey(routerName))
297 Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
299 if(extRouters.isPresent())
301 LOG.debug("NAT Service : Fetching values from extRouters model");
302 Routers routerEntry= extRouters.get();
303 subnetList = routerEntry.getSubnetIds();
304 externalIps = routerEntry.getExternalIps();
306 int extIpCounter = externalIps.size();
307 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
308 for(Uuid subnet : subnetList) {
309 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
310 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
311 .builder(Subnetmaps.class)
312 .child(Subnetmap.class, new SubnetmapKey(subnet))
314 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
317 Subnetmap subnetmapEntry = sn.get();
318 String subnetString = subnetmapEntry.getSubnetIp();
319 String[] subnetSplit = subnetString.split("/");
320 String subnetIp = subnetSplit[0];
321 String subnetPrefix = "0";
322 if(subnetSplit.length == 2) {
323 subnetPrefix = subnetSplit[1];
325 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
326 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
328 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
329 if(extIpCounter != 0) {
330 if(counter < extIpCounter) {
331 String[] IpSplit = externalIps.get(counter).split("/");
332 String externalIp = IpSplit[0];
333 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
334 if(IpSplit.length==2) {
335 extPrefix = IpSplit[1];
337 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
338 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
339 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
340 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
341 externalIp, extPrefix);
343 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
344 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
345 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
348 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
349 LOG.debug("NAT Service : Counter on externalIps got reset");
350 String[] IpSplit = externalIps.get(counter).split("/");
351 String externalIp = IpSplit[0];
352 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
353 if(IpSplit.length==2) {
354 extPrefix = IpSplit[1];
356 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
357 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
358 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
359 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
360 externalIp, extPrefix);
362 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
363 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
364 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
369 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
372 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
376 LOG.info("NAT Service : handleEnableSnat() Exit");
379 private void subnetRegisterMapping(Routers routerEntry,Long segmentId) {
380 List<Uuid> subnetList = null;
381 List<String> externalIps = null;
382 LOG.debug("NAT Service : Fetching values from extRouters model");
383 subnetList = routerEntry.getSubnetIds();
384 externalIps = routerEntry.getExternalIps();
386 int extIpCounter = externalIps.size();
387 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
388 for(Uuid subnet : subnetList) {
389 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
390 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
391 .builder(Subnetmaps.class)
392 .child(Subnetmap.class, new SubnetmapKey(subnet))
394 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
397 Subnetmap subnetmapEntry = sn.get();
398 String subnetString = subnetmapEntry.getSubnetIp();
399 String[] subnetSplit = subnetString.split("/");
400 String subnetIp = subnetSplit[0];
401 String subnetPrefix = "0";
402 if(subnetSplit.length == 2) {
403 subnetPrefix = subnetSplit[1];
405 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
406 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
408 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
409 if(extIpCounter != 0) {
410 if(counter < extIpCounter) {
411 String[] IpSplit = externalIps.get(counter).split("/");
412 String externalIp = IpSplit[0];
413 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
414 if(IpSplit.length==2) {
415 extPrefix = IpSplit[1];
417 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
418 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
419 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
420 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
421 externalIp, extPrefix);
423 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
424 LOG.debug("NAT Service : Counter on externalIps got reset");
425 String[] IpSplit = externalIps.get(counter).split("/");
426 String externalIp = IpSplit[0];
427 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
428 if(IpSplit.length==2) {
429 extPrefix = IpSplit[1];
431 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
432 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
433 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
434 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
435 externalIp, extPrefix);
439 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
441 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
446 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
447 //Check if BGP VPN exists. If exists then invoke the new method.
448 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
449 if(bgpVpnId != NatConstants.INVALID_ID) {
450 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
451 if (bgpVpnUuid != null) {
452 String bgpVpnName = bgpVpnUuid.getValue();
453 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
454 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
455 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
457 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
461 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
462 addOrDelDefaultFibRouteForSNAT(routerName, create);
465 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
466 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
467 if (switches == null || switches.isEmpty()) {
468 LOG.debug("No switches found for router {}",routerName);
471 long routerId = NatUtil.readVpnId(dataBroker, routerName);
472 if (routerId == NatConstants.INVALID_ID) {
473 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
476 for (BigInteger dpnId : switches) {
478 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
479 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
481 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
482 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
487 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
488 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
489 if(dpnIds == null || dpnIds.isEmpty()) {
490 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
493 long routerId = NatUtil.getVpnId(dataBroker, routerName);
494 for (BigInteger dpnId : dpnIds) {
496 if (bgpVpnId != NatConstants.INVALID_ID) {
497 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
498 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
500 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
501 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
504 if (bgpVpnId != NatConstants.INVALID_ID) {
505 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
506 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
508 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
509 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
515 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
517 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
519 Optional<T> result = Optional.absent();
522 result = tx.read(datastoreType, path).get();
526 throw new RuntimeException(e);
532 public void close() throws Exception
534 if (listenerRegistration != null)
538 listenerRegistration.close();
540 catch (final Exception e)
542 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
545 listenerRegistration = null;
547 LOG.debug("ExternalRoutersListener Closed");
550 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
551 long routerId = NatUtil.getVpnId(dataBroker, routerName);
552 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
553 if(routerId != NatConstants.INVALID_ID) {
554 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
555 createOutboundTblEntry(primarySwitchId, routerId);
557 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
561 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
562 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
563 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
566 public BigInteger getCookieOutboundFlow(long routerId) {
567 return NatConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
568 BigInteger.valueOf(routerId));
571 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
572 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
573 List<MatchInfo> matches = new ArrayList<>();
574 matches.add(new MatchInfo(MatchFieldType.eth_type,
575 new long[] { 0x0800L }));
576 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
577 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
579 List<InstructionInfo> instructions = new ArrayList<>();
580 List<ActionInfo> actionsInfos = new ArrayList<>();
581 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
582 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
583 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
585 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
586 BigInteger cookie = getCookieOutboundFlow(routerId);
587 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
589 cookie, matches, instructions);
590 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
594 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
595 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
596 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
597 LOG.debug("NAT Service : Installing flow {}", flowEntity);
598 mdsalManager.installFlow(flowEntity);
601 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
602 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
603 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
605 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
606 .setSourceDpid(srcDpId)
607 .setDestinationDpid(dstDpId)
608 .setTunnelType(tunType)
610 rpcResult = result.get();
611 if(!rpcResult.isSuccessful()) {
612 tunType = TunnelTypeGre.class ;
613 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
614 .setSourceDpid(srcDpId)
615 .setDestinationDpid(dstDpId)
616 .setTunnelType(tunType)
618 rpcResult = result.get();
619 if(!rpcResult.isSuccessful()) {
620 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
622 return rpcResult.getResult().getInterfaceName();
624 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
626 return rpcResult.getResult().getInterfaceName();
628 } catch (InterruptedException | ExecutionException | NullPointerException e) {
629 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
635 protected List<ActionInfo> getEgressActionsForInterface(String ifName, long routerId) {
636 LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
637 List<ActionInfo> listActionInfo = new ArrayList<>();
639 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
640 interfaceManager.getEgressActionsForInterface(
641 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(routerId).build());
642 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
643 if(!rpcResult.isSuccessful()) {
644 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
646 List<Action> actions =
647 rpcResult.getResult().getAction();
648 for (Action action : actions) {
649 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
650 if (actionClass instanceof OutputActionCase) {
651 listActionInfo.add(new ActionInfo(ActionType.output,
652 new String[] {((OutputActionCase)actionClass).getOutputAction()
653 .getOutputNodeConnector().getValue()}));
654 } else if (actionClass instanceof PushVlanActionCase) {
655 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
656 } else if (actionClass instanceof SetFieldCase) {
657 if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
658 int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
659 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
660 new String[] { Long.toString(vlanVid) }));
665 } catch (InterruptedException | ExecutionException e) {
666 LOG.warn("Exception when egress actions for interface {}", ifName, e);
668 return listActionInfo;
671 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
672 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAOT switch dpnId {} ", dpnId);
673 // Install miss entry pointing to group
674 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
675 mdsalManager.installFlow(flowEntity);
678 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
679 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
680 // Install the select group
681 long groupId = createGroupId(getGroupIdKey(routerName));
682 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
683 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
684 mdsalManager.installGroup(groupEntity);
685 // Install miss entry pointing to group
686 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
687 mdsalManager.installFlow(flowEntity);
690 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
691 long groupId = createGroupId(getGroupIdKey(routerName));
692 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
693 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
694 mdsalManager.installGroup(groupEntity);
698 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
700 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
701 long routerId = NatUtil.getVpnId(dataBroker, routerName);
702 List<MatchInfo> matches = new ArrayList<>();
703 matches.add(new MatchInfo(MatchFieldType.eth_type,
704 new long[] { 0x0800L }));
705 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
706 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
709 List<InstructionInfo> instructions = new ArrayList<>();
710 List<ActionInfo> actionsInfo = new ArrayList<>();
712 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
713 BigInteger.valueOf(routerId)}) ;
714 actionsInfo.add(actionSetField);
715 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
716 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
717 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
718 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
719 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
720 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
721 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
723 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
727 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
729 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
731 long routerId = NatUtil.getVpnId(dataBroker, routerName);
732 List<MatchInfo> matches = new ArrayList<MatchInfo>();
733 matches.add(new MatchInfo(MatchFieldType.eth_type,
734 new long[] { 0x0800L }));
735 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
736 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
738 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
739 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
740 { NwConstants.OUTBOUND_NAPT_TABLE }));
742 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
743 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
744 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
745 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
747 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
751 // TODO : Replace this with ITM Rpc once its available with full functionality
752 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
753 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
754 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
755 mdsalManager.installFlow(flowEntity);
759 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
761 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
762 List<MatchInfo> matches = new ArrayList<>();
763 matches.add(new MatchInfo(MatchFieldType.eth_type,
764 new long[] { 0x0800L }));
765 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
767 List<InstructionInfo> instructions = new ArrayList<>();
768 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
769 { routerId, MetaDataUtil.METADATA_MASK_VRFID }));
770 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
771 { NwConstants.OUTBOUND_NAPT_TABLE }));
772 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
773 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
774 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
775 NwConstants.COOKIE_TS_TABLE, matches, instructions);
779 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
780 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
781 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
784 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
785 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
786 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
789 private String getGroupIdKey(String routerName){
790 String groupIdKey = new String("snatmiss." + routerName);
794 protected long createGroupId(String groupIdKey) {
795 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
796 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
799 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
800 RpcResult<AllocateIdOutput> rpcResult = result.get();
801 return rpcResult.getResult().getIdValue();
802 } catch (NullPointerException | InterruptedException | ExecutionException e) {
808 protected void createGroupIdPool() {
809 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
810 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
811 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
812 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
815 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
816 if ((result != null) && (result.get().isSuccessful())) {
817 LOG.debug("NAT Service : Created GroupIdPool");
819 LOG.error("NAT Service : Unable to create GroupIdPool");
821 } catch (InterruptedException | ExecutionException e) {
822 LOG.error("Failed to create PortPool for NAPT Service",e);
826 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
827 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
828 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
829 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
830 List<BucketInfo> listBucketInfo = new ArrayList<>();
831 long routerId = NatUtil.getVpnId(dataBroker, routerName);
833 if(ifNamePrimary != null) {
834 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
835 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
837 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
839 listBucketInfo.add(0, bucketPrimary);
840 installSnatMissEntry(dpnId, listBucketInfo, routerName);
843 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
844 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
845 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
846 List<BucketInfo> listBucketInfo = new ArrayList<>();
847 long routerId = NatUtil.getVpnId(dataBroker, routerName);
849 if (ifNamePrimary != null) {
850 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
851 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
853 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
855 listBucketInfo.add(0, bucketPrimary);
856 return listBucketInfo;
858 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
861 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
864 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
867 List<BucketInfo> listBucketInfo = new ArrayList<>();
868 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
869 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
870 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
871 listBucketInfo.add(0, bucketPrimary);
874 long routerId = NatUtil.getVpnId(dataBroker, routerName);
876 installSnatMissEntryForPrimrySwch(dpnId, routerName);
877 installTerminatingServiceTblEntry(dpnId, routerName);
878 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
879 installNaptPfibEntry(dpnId, routerId);
880 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
881 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
882 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
883 installNaptPfibEntry(dpnId, vpnId);
887 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
888 List<BucketInfo> listBucketInfo = new ArrayList<>();
889 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
890 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NwConstants.INTERNAL_TUNNEL_TABLE)}));
891 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
892 listBucketInfo.add(0, bucketPrimary);
893 return listBucketInfo;
896 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
897 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
898 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
899 mdsalManager.installFlow(naptPfibFlowEntity);
902 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
904 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
905 List<MatchInfo> matches = new ArrayList<>();
906 matches.add(new MatchInfo(MatchFieldType.eth_type,
907 new long[] { 0x0800L }));
908 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
909 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
911 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
912 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
913 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
914 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
916 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
917 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
918 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
919 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
921 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
925 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
926 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
927 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
928 if(networkId == null) {
929 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
932 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
933 if(vpnName == null) {
934 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
935 networkId, externalIp, routerId);
938 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
939 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
942 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
943 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
945 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
946 //Generate VPN label for the external IP
947 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
948 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
950 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
951 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
954 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
955 if (result.isSuccessful()) {
956 LOG.debug("NAT Service : inside apply with result success");
957 GenerateVpnLabelOutput output = result.getResult();
958 final long label = output.getLabel();
960 int externalIpInDsFlag = 0;
961 //Get IPMaps from the DB for the router ID
962 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
963 if (dbIpMaps != null) {
964 for (IpMap dbIpMap : dbIpMaps) {
965 String dbExternalIp = dbIpMap.getExternalIp();
966 //Select the IPMap, whose external IP is the IP for which FIB is installed
967 if (externalIp.equals(dbExternalIp)) {
968 String dbInternalIp = dbIpMap.getInternalIp();
969 IpMapKey dbIpMapKey = dbIpMap.getKey();
970 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
971 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
972 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
973 externalIpInDsFlag++;
976 if (externalIpInDsFlag <=0) {
977 LOG.debug("NAT Service : External Ip {} not found in DS,Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
978 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", externalIp, label, routerId);
979 return Futures.immediateFailedFuture(new Exception(errMsg));
982 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
987 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
988 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
989 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
991 //Install custom FIB routes
992 List<Instruction> customInstructions = new ArrayList<>();
993 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
994 makeTunnelTableEntry(dpnId, label, customInstructions);
995 makeLFibTableEntry(dpnId, label, tableId);
997 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
998 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
999 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
1000 return JdkFutureAdapters.listenInPoolThread(future);
1002 LOG.error("NAT Service : inside apply with result failed");
1003 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
1004 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1009 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
1012 public void onFailure(Throwable error) {
1013 log.error("NAT Service : Error in generate label or fib install process", error);
1017 public void onSuccess(RpcResult<Void> result) {
1018 if (result.isSuccessful()) {
1019 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
1021 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1027 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
1028 List<MatchInfo> matches = new ArrayList<>();
1029 matches.add(new MatchInfo(MatchFieldType.eth_type,
1030 new long[]{0x8847L}));
1031 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1033 List<Instruction> instructions = new ArrayList<>();
1034 List<ActionInfo> actionsInfos = new ArrayList<>();
1035 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
1036 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
1037 instructions.add(writeInstruction);
1038 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
1040 // Install the flow entry in L3_LFIB_TABLE
1041 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1043 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1045 COOKIE_VM_LFIB_TABLE, matches, instructions);
1047 mdsalManager.installFlow(dpId, flowEntity);
1049 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
1052 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
1053 List<MatchInfo> mkMatches = new ArrayList<>();
1055 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
1057 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1059 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1060 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
1061 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1063 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1066 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1067 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1068 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1072 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1073 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1074 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1075 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1079 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1080 String routerName = original.getRouterName();
1081 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1082 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1083 Uuid networkId = original.getNetworkId();
1085 // Check if its update on SNAT flag
1086 boolean originalSNATEnabled = original.isEnableSnat();
1087 boolean updatedSNATEnabled = update.isEnableSnat();
1088 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1089 if(originalSNATEnabled != updatedSNATEnabled) {
1090 if(originalSNATEnabled) {
1091 //SNAT disabled for the router
1092 Uuid networkUuid = original.getNetworkId();
1093 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1094 if (routerId == NatConstants.INVALID_ID) {
1095 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1098 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1099 handleDisableSnat(routerName, networkUuid, externalIps, false, null);
1101 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1102 handleEnableSnat(original);
1106 //Check if the Update is on External IPs
1107 LOG.debug("NAT Service : Checking if this is update on External IPs");
1108 List<String> originalExternalIpsList = original.getExternalIps();
1109 List<String> updatedExternalIpsList = update.getExternalIps();
1110 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1111 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1113 //Check if the External IPs are added during the update.
1114 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1115 if(addedExternalIps.size() != 0) {
1116 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1117 for (String addedExternalIp : addedExternalIps) {
1119 1) Do nothing in the IntExtIp model.
1120 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1122 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1123 String externalIp = externalIpParts[0];
1124 String externalIpPrefix = externalIpParts[1];
1125 String externalpStr = externalIp + "/" + externalIpPrefix;
1126 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1127 externalpStr, routerId);
1128 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1130 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1133 //Check if the External IPs are removed during the update.
1134 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1135 if(removedExternalIps.size() > 0) {
1136 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1137 List<String> removedExternalIpsAsList = new ArrayList<>();
1138 for (String removedExternalIp : removedExternalIps) {
1140 1) Remove the mappings in the IntExt IP model which has external IP.
1141 2) Remove the external IP in the ExternalCounter model.
1142 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1143 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1144 4) Increase the count of the allocated external IP by one.
1145 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.
1146 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1147 7) Advertise to the BGP for removing the route for the removed external IPs.
1150 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1151 String externalIp = externalIpParts[0];
1152 String externalIpPrefix = externalIpParts[1];
1153 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1155 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1156 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1157 String vpnName = "";
1158 if(vpnUuId != null){
1159 vpnName = vpnUuId.getValue();
1161 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1163 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1164 //Get the internal IPs which are associated to the removed external IPs
1165 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1166 List<String> removedInternalIps = new ArrayList<>();
1167 for(IpMap ipMap : ipMaps){
1168 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1169 removedInternalIps.add(ipMap.getInternalIp());
1173 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1174 for(String removedInternalIp : removedInternalIps){
1175 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1176 removedInternalIp, routerId);
1177 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1180 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1181 externalIpAddrStr, routerId );
1182 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1183 removedExternalIpsAsList.add(externalIpAddrStr);
1185 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1186 for(String removedInternalIp : removedInternalIps) {
1187 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1190 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1191 //Get the internalIP and internal Port which were associated to the removed external IP.
1192 List<Integer> externalPorts = new ArrayList<>();
1193 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1194 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1195 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1196 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1197 if (ipPortMapping.isPresent()) {
1198 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1199 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1200 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1201 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1202 for(IpPortMap ipPortMap : ipPortMaps){
1203 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1204 if(ipPortExternal.getIpAddress().equals(externalIp)){
1205 externalPorts.add(ipPortExternal.getPortNum());
1206 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1207 if(removedInternalIpPorts != null){
1208 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1209 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1211 removedInternalIpPorts = new ArrayList<>();
1212 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1213 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1220 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1221 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1222 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1223 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1224 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1225 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1226 for(String removedInternalIpPort : removedInternalIpPorts){
1227 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1228 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1229 //Remove the IP port incomint packer map.
1230 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1231 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1232 if(removedInternalIpPortParts.length == 2){
1233 String removedInternalIp = removedInternalIpPortParts[0];
1234 String removedInternalPort = removedInternalIpPortParts[1];
1235 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1236 if (removedInternalPortsList != null){
1237 removedInternalPortsList.add(removedInternalPort);
1238 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1240 removedInternalPortsList = new ArrayList<>();
1241 removedInternalPortsList.add(removedInternalPort);
1242 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1248 // Delete the entry from SnatIntIpPortMap DS
1249 Set<String> internalIps = internalIpPortMap.keySet();
1250 for(String internalIp : internalIps){
1251 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1252 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1255 naptManager.removeNaptPortPool(externalIp);
1257 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1258 for(Integer externalPort : externalPorts) {
1259 //Remove the NAPT translation entries from Inbound NAPT table
1260 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1263 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1264 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1265 String internalIp = internalIpPort.getKey();
1266 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1267 List<String> internalPorts = internalIpPort.getValue();
1268 for(String internalPort : internalPorts){
1269 //Remove the NAPT translation entries from Outbound NAPT table
1270 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1274 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1277 //Check if its Update on subnets
1278 LOG.debug("NAT Service : Checking if this is update on subnets");
1279 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1280 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1281 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1282 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1283 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1285 //Check if the Subnet IDs are added during the update.
1286 if(addedSubnetIds.size() != 0){
1287 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1288 for(Uuid addedSubnetId : addedSubnetIds){
1290 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.
1291 2) Increase the count of the selected external IP by one.
1292 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.
1294 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1295 if(subnetIp != null) {
1296 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1299 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1302 //Check if the Subnet IDs are removed during the update.
1303 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1304 if(removedSubnetIds.size() != 0){
1305 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1306 for(Uuid removedSubnetId : removedSubnetIds){
1307 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1308 if(subnetAddr != null){
1310 1) Remove the subnet IP and the external IP in the IntExtIp map
1311 2) Decrease the count of the coresponding external IP by one.
1312 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1315 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1316 if (externalIp == null) {
1317 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1321 naptManager.updateCounter(routerId, externalIp, false);
1322 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1323 if (!isExternalIpAllocated(externalIp)) {
1324 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1325 List<String> externalIps = new ArrayList<>();
1326 externalIps.add(externalIp);
1327 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1328 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1329 dpnId,routerId,networkId,externalIps);
1332 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1333 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1336 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1340 private boolean isExternalIpAllocated(String externalIp) {
1341 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1342 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1343 if (externalCountersData.isPresent()) {
1344 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1345 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1346 for(ExternalCounters ext : externalCounters) {
1347 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1348 if (externalIpCount.getExternalIp().equals(externalIp)) {
1349 if (externalIpCount.getCounter() != 0) {
1360 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1361 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1362 if (leastLoadedExtIpAddr != null) {
1363 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1364 String leastLoadedExtIp = externalIpParts[0];
1365 String leastLoadedExtIpPrefix = externalIpParts[1];
1366 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1367 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1368 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1369 subnetIp = subnetIpParts[0];
1370 String subnetIpPrefix = subnetIpParts[1];
1371 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1372 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1373 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1374 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1377 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1378 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1379 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1382 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1383 IpMapKey ipMapKey = new IpMapKey(internalIp);
1384 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1385 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1386 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1390 //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.
1391 //Get the VPN Name using the network ID
1392 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1393 if (vpnName != null) {
1394 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1395 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1396 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1397 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1399 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1400 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1405 private Long checkExternalIpLabel(long routerId, String externalIp){
1406 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1407 for(IpMap ipMap : ipMaps){
1408 if(ipMap.getExternalIp().equals(externalIp)){
1409 if (ipMap.getLabel() != null){
1410 return ipMap.getLabel();
1418 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1419 LOG.trace("NAT Service : Router delete method");
1422 ROUTER DELETE SCENARIO
1423 1) Get the router ID from the event.
1424 2) Build the cookie information from the router ID.
1425 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1426 4) Build the flow with the cookie value.
1427 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1428 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1429 7) Get the list of external IP address maintained for the router ID.
1430 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1431 9) Withdraw the corresponding routes from the BGP.
1434 if (identifier == null || router == null) {
1435 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1439 String routerName = router.getRouterName();
1440 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1441 addOrDelDefFibRouteToSNAT(routerName, false);
1442 Uuid networkUuid = router.getNetworkId();
1443 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1444 if (routerId == NatConstants.INVALID_ID) {
1445 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1448 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1449 handleDisableSnat(routerName, networkUuid, externalIps, true, null);
1453 public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1454 LOG.info("NAT Service : handleDisableSnat() Entry");
1456 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1458 BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1459 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1460 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1461 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1464 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1465 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1467 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1468 } catch (Exception ex) {
1469 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1472 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1473 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1474 naptManager.removeMapping(routerId);
1477 removeNaptSwitch(routerName);
1479 updateNaptSwitch(routerName, BigInteger.ZERO);
1482 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1483 naptManager.removeExternalCounter(routerId);
1484 } catch (Exception ex) {
1485 LOG.error("Exception while handling disableSNAT : {}", ex);
1487 LOG.info("NAT Service : handleDisableSnat() Exit");
1490 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1491 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1493 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1494 BigInteger naptSwitchDpnId = null;
1495 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1496 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1497 if (rtrToNapt.isPresent()) {
1498 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1500 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1502 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1504 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1505 } catch (Exception ex) {
1506 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1508 } catch (Exception ex) {
1509 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1511 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1514 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1515 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1516 .setPrimarySwitchId(naptSwitchId).build();
1518 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1519 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1520 } catch (Exception ex) {
1521 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1522 naptSwitchId,routerName);
1524 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1525 naptSwitchId,routerName);
1528 protected void removeNaptSwitch(String routerName){
1529 // Remove router and switch from model
1530 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1531 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1532 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1535 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1537 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1538 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1540 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1541 // traffic which comes from the VMs of the NAPT switches)
1542 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1543 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1545 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);
1546 mdsalManager.removeFlow(pSNatFlowEntity);
1548 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1549 // traffic which comes from the VMs of the non NAPT switches)
1550 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1551 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1553 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);
1554 mdsalManager.removeFlow(tsNatFlowEntity);
1556 //Remove the Outbound flow entry which forwards the packet to FIB Table
1557 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1558 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1560 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);
1561 mdsalManager.removeFlow(outboundNatFlowEntity);
1563 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1564 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1565 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1567 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);
1568 mdsalManager.removeFlow(natPfibFlowEntity);
1570 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1571 //Get the VPN ID from the ExternalNetworks model
1573 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1574 // ie called from router delete cases
1575 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1576 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1577 if(vpnUuid != null) {
1578 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1579 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1582 // ie called from disassociate vpn case
1583 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1584 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1585 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1588 if(vpnId != NatConstants.INVALID_ID){
1589 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1590 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1591 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1592 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);
1593 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1596 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1597 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1598 if(ipPortMapping == null){
1599 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1603 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1604 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1605 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1606 for(IpPortMap ipPortMap : ipPortMaps){
1607 String ipPortInternal = ipPortMap.getIpPortInternal();
1608 String[] ipPortParts = ipPortInternal.split(":");
1609 if(ipPortParts.length != 2) {
1610 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1613 String internalIp = ipPortParts[0];
1614 String internalPort = ipPortParts[1];
1616 //Build the flow for the outbound NAPT table
1617 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1618 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1620 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);
1621 mdsalManager.removeFlow(outboundNaptFlowEntity);
1623 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1624 String externalIp = ipPortExternal.getIpAddress();
1625 int externalPort = ipPortExternal.getPortNum();
1627 //Build the flow for the inbound NAPT table
1628 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1629 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1631 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);
1632 mdsalManager.removeFlow(inboundNaptFlowEntity);
1637 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1639 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1640 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1642 //Remove the NAPT PFIB TABLE entry
1644 if(vpnName != null) {
1645 // ie called from disassociate vpn case
1646 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1647 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1648 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1651 if(vpnId != NatConstants.INVALID_ID){
1652 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1653 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1654 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1655 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);
1656 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1658 // Remove IP-PORT active NAPT entries and release port from IdManager
1659 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1660 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1661 if(ipPortMapping == null){
1662 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1665 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1666 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1667 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1668 for(IpPortMap ipPortMap : ipPortMaps){
1669 String ipPortInternal = ipPortMap.getIpPortInternal();
1670 String[] ipPortParts = ipPortInternal.split(":");
1671 if(ipPortParts.length != 2) {
1672 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1675 String internalIp = ipPortParts[0];
1676 String internalPort = ipPortParts[1];
1678 //Build the flow for the outbound NAPT table
1679 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1680 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1682 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);
1683 mdsalManager.removeFlow(outboundNaptFlowEntity);
1685 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1686 String externalIp = ipPortExternal.getIpAddress();
1687 int externalPort = ipPortExternal.getPortNum();
1689 //Build the flow for the inbound NAPT table
1690 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1691 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1693 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);
1694 mdsalManager.removeFlow(inboundNaptFlowEntity);
1696 // Finally release port from idmanager
1697 String internalIpPort = internalIp +":"+internalPort;
1698 naptManager.removePortFromPool(internalIpPort, externalIp);
1700 //Remove sessions from models
1701 naptManager.removeIpPortMappingForRouterID(routerId);
1702 naptManager.removeIntIpPortMappingForRouterID(routerId);
1706 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1710 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1711 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1713 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1714 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1715 if(allSwitchList == null || allSwitchList.isEmpty()){
1716 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1719 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1720 for (BigInteger dpnId : allSwitchList) {
1721 if (!naptSwitchDpnId.equals(dpnId)) {
1722 LOG.info("NAT Service : Handle Ordinary switch");
1724 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1725 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1726 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1728 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1729 mdsalManager.removeFlow(pSNatFlowEntity);
1731 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1732 long groupId = createGroupId(getGroupIdKey(routerName));
1733 List<BucketInfo> listBucketInfo = new ArrayList<>();
1734 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1736 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1737 mdsalManager.removeGroup(pSNatGroupEntity);
1743 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1744 //Withdraw the corresponding routes from the BGP.
1745 //Get the network ID using the router ID.
1746 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1747 externalIps,routerId,networkUuid, vpnName);
1748 if(networkUuid == null ){
1749 LOG.error("NAT Service : networkId is null");
1753 if (externalIps == null || externalIps.isEmpty()) {
1754 LOG.debug("NAT Service : externalIps is null");
1758 if(vpnName ==null) {
1759 //Get the VPN Name using the network ID
1760 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1761 if (vpnName == null) {
1762 LOG.error("No VPN associated with ext nw {} for the router {}",
1763 networkUuid, routerId);
1767 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1769 //Remove custom FIB routes
1770 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1771 for (String extIp : externalIps) {
1772 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1776 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1777 clearBgpRoutes(extIp,vpnName);
1778 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1781 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1782 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1784 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1785 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1789 final long label = tempLabel;
1790 final String externalIp = extIp;
1792 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1793 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1795 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1798 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1800 if (result.isSuccessful()) {
1801 removeTunnelTableEntry(dpnId, label);
1802 removeLFibTableEntry(dpnId, label);
1803 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1804 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1805 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1807 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1809 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1815 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1818 public void onFailure(Throwable error) {
1819 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1823 public void onSuccess(RpcResult<Void> result) {
1824 if (result.isSuccessful()) {
1825 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1827 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1833 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1834 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1835 //Get IPMaps from the DB for the router ID
1836 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1837 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1838 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1842 long tempLabel = NatConstants.INVALID_ID;
1843 for (IpMap dbIpMap : dbIpMaps) {
1844 String dbExternalIp = dbIpMap.getExternalIp();
1845 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1846 //Select the IPMap, whose external IP is the IP for which FIB is installed
1847 if (extIp.equals(dbExternalIp)) {
1848 tempLabel = dbIpMap.getLabel();
1849 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1853 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1854 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1858 final long label = tempLabel;
1859 final String externalIp = extIp;
1861 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1862 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1864 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1867 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1869 if (result.isSuccessful()) {
1870 removeTunnelTableEntry(dpnId, label);
1871 removeLFibTableEntry(dpnId, label);
1872 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1873 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1874 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1876 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1878 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1884 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1887 public void onFailure(Throwable error) {
1888 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1892 public void onSuccess(RpcResult<Void> result) {
1893 if (result.isSuccessful()) {
1894 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1896 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1902 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1903 //Withdraw the corresponding routes from the BGP.
1904 //Get the network ID using the router ID.
1905 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1906 externalIps,routerId,networkUuid, vpnName);
1907 if (networkUuid == null) {
1908 LOG.error("NAT Service : networkId is null");
1912 if (externalIps == null || externalIps.isEmpty()) {
1913 LOG.debug("NAT Service : externalIps is null");
1917 if (vpnName == null) {
1918 //Get the VPN Name using the network ID
1919 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1920 if (vpnName == null) {
1921 LOG.error("No VPN associated with ext nw {} for the router {}",
1922 networkUuid, routerId);
1926 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1928 //Remove custom FIB routes
1929 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1930 for (String extIp : externalIps) {
1931 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1935 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1936 //Inform BGP about the route removal
1937 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1938 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1939 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
1942 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1943 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1944 List<MatchInfo> mkMatches = new ArrayList<>();
1945 // Matching metadata
1946 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1947 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1948 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1949 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1950 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1951 mdsalManager.removeFlow(dpnId, flowEntity);
1952 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1955 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1956 List<MatchInfo> matches = new ArrayList<>();
1957 matches.add(new MatchInfo(MatchFieldType.eth_type,
1958 new long[] { 0x8847L }));
1959 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1961 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1963 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
1965 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1967 COOKIE_VM_LFIB_TABLE, matches, null);
1969 mdsalManager.removeFlow(dpnId, flowEntity);
1971 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
1974 protected InstanceIdentifier<Routers> getWildCardPath()
1976 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
1981 * router association to vpn
1984 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
1985 LOG.debug("NAT Service : Router associated to BGP VPN");
1986 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1987 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1989 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1991 if(bgpVpnId != NatConstants.INVALID_ID){
1992 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
1993 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
1994 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
1996 // Get the allocated Primary NAPT Switch for this router
1997 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1998 LOG.debug("Router ID value {} ", routerId);
1999 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2001 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
2002 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
2005 long groupId = createGroupId(getGroupIdKey(routerName));
2006 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2012 * router disassociation from vpn
2015 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2016 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2017 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2018 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2019 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2021 // Get the allocated Primary NAPT Switch for this router
2022 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2023 LOG.debug("Router ID value {} ", routerId);
2024 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2026 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2027 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2030 long groupId = createGroupId(getGroupIdKey(routerName));
2031 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2035 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2036 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2037 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2038 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2039 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2045 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2046 routerId, boolean isSnatCfgd){
2047 long changedVpnId = bgpVpnId;
2048 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2049 if (bgpVpnId == NatConstants.INVALID_ID){
2050 changedVpnId = routerId;
2051 logMsg = "NAT Service : Update the router ID {}";
2054 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2055 if (switches == null || switches.isEmpty()) {
2056 LOG.debug("No switches found for router {}",routerName);
2059 for(BigInteger dpnId : switches) {
2060 // Update the BGP VPN ID in the SNAT miss entry to group
2061 if( !dpnId.equals(primarySwitchId) ) {
2062 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2063 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2064 long groupId = createGroupId(getGroupIdKey(routerName));
2066 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2069 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2070 changedVpnId, groupId, dpnId);
2071 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2072 mdsalManager.installFlow(flowEntity);
2075 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2076 changedVpnId, primarySwitchId);
2077 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2078 mdsalManager.installFlow(flowEntity);
2080 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2081 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2082 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2084 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2085 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2086 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2088 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2089 changedVpnId, primarySwitchId);
2090 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2092 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2093 " in the Primary switch {}", changedVpnId, primarySwitchId);
2094 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2096 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2097 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2098 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2099 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2100 installNaptPfibEntry(primarySwitchId, vpnId);
2106 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2107 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2108 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2109 if(ipPortMapping == null){
2110 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2114 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2115 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2116 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2117 for(IpPortMap ipPortMap : ipPortMaps){
2118 String ipPortInternal = ipPortMap.getIpPortInternal();
2119 String[] ipPortParts = ipPortInternal.split(":");
2120 if(ipPortParts.length != 2) {
2121 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2124 String internalIp = ipPortParts[0];
2125 String internalPort = ipPortParts[1];
2127 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2128 NAPTEntryEvent.Protocol protocol;
2129 switch (protocolTypes){
2131 protocol = NAPTEntryEvent.Protocol.TCP;
2134 protocol = NAPTEntryEvent.Protocol.UDP;
2137 protocol = NAPTEntryEvent.Protocol.TCP;
2139 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2140 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2141 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2142 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2143 internalAddress, externalAddress, protocol);
2144 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2145 externalAddress, internalAddress, protocol);
2151 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2153 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2154 List<MatchInfo> matches = new ArrayList<>();
2155 matches.add(new MatchInfo(MatchFieldType.eth_type,
2156 new long[] { 0x0800L }));
2157 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2158 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2160 List<InstructionInfo> instructions = new ArrayList<>();
2161 List<ActionInfo> actionsInfo = new ArrayList<>();
2163 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2164 BigInteger.valueOf(changedVpnId)}) ;
2165 actionsInfo.add(actionSetField);
2166 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2167 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2168 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
2169 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2170 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2171 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2172 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2174 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2178 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2180 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2181 List<MatchInfo> matches = new ArrayList<>();
2182 matches.add(new MatchInfo(MatchFieldType.eth_type,
2183 new long[] { 0x0800L }));
2184 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2185 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2187 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2188 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2189 { NwConstants.OUTBOUND_NAPT_TABLE }));
2191 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2192 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2193 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2194 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2196 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2200 // TODO : Replace this with ITM Rpc once its available with full functionality
2201 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2202 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2203 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2204 mdsalManager.installFlow(flowEntity);
2208 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2209 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2210 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2211 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2212 List<MatchInfo> matches = new ArrayList<>();
2213 matches.add(new MatchInfo(MatchFieldType.eth_type,
2214 new long[] { 0x0800L }));
2215 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2217 List<InstructionInfo> instructions = new ArrayList<>();
2218 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2219 { bgpVpnIdAsBigInt, MetaDataUtil.METADATA_MASK_VRFID }));
2220 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2221 { NwConstants.OUTBOUND_NAPT_TABLE }));
2222 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2223 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2224 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2225 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2229 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2230 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2231 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2232 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2233 mdsalManager.installFlow(flowEntity);
2236 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2237 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2238 List<MatchInfo> matches = new ArrayList<>();
2239 matches.add(new MatchInfo(MatchFieldType.eth_type,
2240 new long[]{0x0800L}));
2241 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2242 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2244 List<InstructionInfo> instructions = new ArrayList<>();
2245 List<ActionInfo> actionsInfos = new ArrayList<>();
2246 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2247 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2248 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2250 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2251 BigInteger cookie = getCookieOutboundFlow(routerId);
2252 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2253 cookie, matches, instructions);
2254 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2258 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2259 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2260 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2261 mdsalManager.installFlow(naptPfibFlowEntity);
2264 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2266 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2267 List<MatchInfo> matches = new ArrayList<>();
2268 matches.add(new MatchInfo(MatchFieldType.eth_type,
2269 new long[] { 0x0800L }));
2270 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2271 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2273 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2274 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2275 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
2276 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2278 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2279 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2280 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2281 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2283 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2288 protected ExternalRoutersListener getDataTreeChangeListener()
2290 return ExternalRoutersListener.this;