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);
533 public void close() throws Exception
535 if (listenerRegistration != null)
539 listenerRegistration.close();
541 catch (final Exception e)
543 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
546 listenerRegistration = null;
548 LOG.debug("ExternalRoutersListener Closed");
551 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
552 long routerId = NatUtil.getVpnId(dataBroker, routerName);
553 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
554 if(routerId != NatConstants.INVALID_ID) {
555 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
556 createOutboundTblEntry(primarySwitchId, routerId);
558 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
562 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
563 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
564 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
567 public BigInteger getCookieOutboundFlow(long routerId) {
568 return NwConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
569 BigInteger.valueOf(routerId));
572 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
573 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
574 List<MatchInfo> matches = new ArrayList<>();
575 matches.add(new MatchInfo(MatchFieldType.eth_type,
576 new long[] { 0x0800L }));
577 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
578 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
580 List<InstructionInfo> instructions = new ArrayList<>();
581 List<ActionInfo> actionsInfos = new ArrayList<>();
582 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
583 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
584 instructions.add(new InstructionInfo(InstructionType.write_metadata,
585 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
587 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
588 BigInteger cookie = getCookieOutboundFlow(routerId);
589 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
591 cookie, matches, instructions);
592 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
596 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
597 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
598 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
599 LOG.debug("NAT Service : Installing flow {}", flowEntity);
600 mdsalManager.installFlow(flowEntity);
603 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
604 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
605 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
607 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
608 .setSourceDpid(srcDpId)
609 .setDestinationDpid(dstDpId)
610 .setTunnelType(tunType)
612 rpcResult = result.get();
613 if(!rpcResult.isSuccessful()) {
614 tunType = TunnelTypeGre.class ;
615 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
616 .setSourceDpid(srcDpId)
617 .setDestinationDpid(dstDpId)
618 .setTunnelType(tunType)
620 rpcResult = result.get();
621 if(!rpcResult.isSuccessful()) {
622 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
624 return rpcResult.getResult().getInterfaceName();
626 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
628 return rpcResult.getResult().getInterfaceName();
630 } catch (InterruptedException | ExecutionException | NullPointerException e) {
631 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
637 protected List<ActionInfo> getEgressActionsForInterface(String ifName, long routerId) {
638 LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
639 List<ActionInfo> listActionInfo = new ArrayList<>();
641 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
642 interfaceManager.getEgressActionsForInterface(
643 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(routerId).build());
644 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
645 if(!rpcResult.isSuccessful()) {
646 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
648 List<Action> actions =
649 rpcResult.getResult().getAction();
650 for (Action action : actions) {
651 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
652 if (actionClass instanceof OutputActionCase) {
653 listActionInfo.add(new ActionInfo(ActionType.output,
654 new String[] {((OutputActionCase)actionClass).getOutputAction()
655 .getOutputNodeConnector().getValue()}));
656 } else if (actionClass instanceof PushVlanActionCase) {
657 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
658 } else if (actionClass instanceof SetFieldCase) {
659 if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
660 int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
661 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
662 new String[] { Long.toString(vlanVid) }));
667 } catch (InterruptedException | ExecutionException e) {
668 LOG.warn("Exception when egress actions for interface {}", ifName, e);
670 return listActionInfo;
673 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
674 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAOT switch dpnId {} ", dpnId);
675 // Install miss entry pointing to group
676 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
677 mdsalManager.installFlow(flowEntity);
680 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
681 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
682 // Install the select group
683 long groupId = createGroupId(getGroupIdKey(routerName));
684 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
685 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
686 mdsalManager.installGroup(groupEntity);
687 // Install miss entry pointing to group
688 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
689 mdsalManager.installFlow(flowEntity);
692 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
693 long groupId = createGroupId(getGroupIdKey(routerName));
694 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
695 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
696 mdsalManager.installGroup(groupEntity);
700 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
702 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
703 long routerId = NatUtil.getVpnId(dataBroker, routerName);
704 List<MatchInfo> matches = new ArrayList<>();
705 matches.add(new MatchInfo(MatchFieldType.eth_type,
706 new long[] { 0x0800L }));
707 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
708 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
711 List<InstructionInfo> instructions = new ArrayList<>();
712 List<ActionInfo> actionsInfo = new ArrayList<>();
714 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
715 BigInteger.valueOf(routerId)}) ;
716 actionsInfo.add(actionSetField);
717 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
718 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
719 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
720 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
721 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
722 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
723 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
725 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
729 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
731 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
733 long routerId = NatUtil.getVpnId(dataBroker, routerName);
734 List<MatchInfo> matches = new ArrayList<MatchInfo>();
735 matches.add(new MatchInfo(MatchFieldType.eth_type,
736 new long[] { 0x0800L }));
737 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
738 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
740 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
741 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
742 { NwConstants.OUTBOUND_NAPT_TABLE }));
744 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
745 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
746 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
747 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
749 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
753 // TODO : Replace this with ITM Rpc once its available with full functionality
754 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
755 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
756 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
757 mdsalManager.installFlow(flowEntity);
761 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
763 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
764 List<MatchInfo> matches = new ArrayList<>();
765 matches.add(new MatchInfo(MatchFieldType.eth_type,
766 new long[] { 0x0800L }));
767 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
769 List<InstructionInfo> instructions = new ArrayList<>();
770 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
771 { MetaDataUtil.getVpnIdMetadata(routerId.longValue()), MetaDataUtil.METADATA_MASK_VRFID }));
772 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
773 { NwConstants.OUTBOUND_NAPT_TABLE }));
774 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
775 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
776 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
777 NwConstants.COOKIE_TS_TABLE, matches, instructions);
781 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
782 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
783 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
786 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
787 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
788 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
791 private String getGroupIdKey(String routerName){
792 String groupIdKey = new String("snatmiss." + routerName);
796 protected long createGroupId(String groupIdKey) {
797 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
798 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
801 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
802 RpcResult<AllocateIdOutput> rpcResult = result.get();
803 return rpcResult.getResult().getIdValue();
804 } catch (NullPointerException | InterruptedException | ExecutionException e) {
810 protected void createGroupIdPool() {
811 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
812 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
813 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
814 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
817 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
818 if ((result != null) && (result.get().isSuccessful())) {
819 LOG.debug("NAT Service : Created GroupIdPool");
821 LOG.error("NAT Service : Unable to create GroupIdPool");
823 } catch (InterruptedException | ExecutionException e) {
824 LOG.error("Failed to create PortPool for NAPT Service",e);
828 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
829 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
830 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
831 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
832 List<BucketInfo> listBucketInfo = new ArrayList<>();
833 long routerId = NatUtil.getVpnId(dataBroker, routerName);
835 if(ifNamePrimary != null) {
836 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
837 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
839 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
841 listBucketInfo.add(0, bucketPrimary);
842 installSnatMissEntry(dpnId, listBucketInfo, routerName);
845 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
846 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
847 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
848 List<BucketInfo> listBucketInfo = new ArrayList<>();
849 long routerId = NatUtil.getVpnId(dataBroker, routerName);
851 if (ifNamePrimary != null) {
852 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
853 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
855 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
857 listBucketInfo.add(0, bucketPrimary);
858 return listBucketInfo;
860 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
863 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
866 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
869 List<BucketInfo> listBucketInfo = new ArrayList<>();
870 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
871 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
872 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
873 listBucketInfo.add(0, bucketPrimary);
876 long routerId = NatUtil.getVpnId(dataBroker, routerName);
878 installSnatMissEntryForPrimrySwch(dpnId, routerName);
879 installTerminatingServiceTblEntry(dpnId, routerName);
880 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
881 installNaptPfibEntry(dpnId, routerId);
882 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
883 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
884 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
885 installNaptPfibEntry(dpnId, vpnId);
889 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
890 List<BucketInfo> listBucketInfo = new ArrayList<>();
891 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
892 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NwConstants.INTERNAL_TUNNEL_TABLE)}));
893 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
894 listBucketInfo.add(0, bucketPrimary);
895 return listBucketInfo;
898 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
899 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
900 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
901 mdsalManager.installFlow(naptPfibFlowEntity);
904 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
906 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
907 List<MatchInfo> matches = new ArrayList<>();
908 matches.add(new MatchInfo(MatchFieldType.eth_type,
909 new long[] { 0x0800L }));
910 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
911 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
913 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
914 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
915 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
916 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
918 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
919 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
920 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
921 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
923 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
927 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
928 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
929 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
930 if(networkId == null) {
931 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
934 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
935 if(vpnName == null) {
936 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
937 networkId, externalIp, routerId);
940 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
941 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
944 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
945 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
947 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
948 //Generate VPN label for the external IP
949 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
950 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
952 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
953 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
956 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
957 if (result.isSuccessful()) {
958 LOG.debug("NAT Service : inside apply with result success");
959 GenerateVpnLabelOutput output = result.getResult();
960 final long label = output.getLabel();
962 int externalIpInDsFlag = 0;
963 //Get IPMaps from the DB for the router ID
964 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
965 if (dbIpMaps != null) {
966 for (IpMap dbIpMap : dbIpMaps) {
967 String dbExternalIp = dbIpMap.getExternalIp();
968 //Select the IPMap, whose external IP is the IP for which FIB is installed
969 if (externalIp.equals(dbExternalIp)) {
970 String dbInternalIp = dbIpMap.getInternalIp();
971 IpMapKey dbIpMapKey = dbIpMap.getKey();
972 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
973 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
974 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
975 externalIpInDsFlag++;
978 if (externalIpInDsFlag <=0) {
979 LOG.debug("NAT Service : External Ip {} not found in DS,Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
980 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", externalIp, label, routerId);
981 return Futures.immediateFailedFuture(new Exception(errMsg));
984 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
989 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
990 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
991 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
993 //Install custom FIB routes
994 List<Instruction> customInstructions = new ArrayList<>();
995 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
996 makeTunnelTableEntry(dpnId, label, customInstructions);
997 makeLFibTableEntry(dpnId, label, tableId);
999 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
1000 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
1001 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
1002 return JdkFutureAdapters.listenInPoolThread(future);
1004 LOG.error("NAT Service : inside apply with result failed");
1005 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
1006 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1011 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
1014 public void onFailure(Throwable error) {
1015 log.error("NAT Service : Error in generate label or fib install process", error);
1019 public void onSuccess(RpcResult<Void> result) {
1020 if (result.isSuccessful()) {
1021 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
1023 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1029 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
1030 List<MatchInfo> matches = new ArrayList<>();
1031 matches.add(new MatchInfo(MatchFieldType.eth_type,
1032 new long[]{0x8847L}));
1033 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1035 List<Instruction> instructions = new ArrayList<>();
1036 List<ActionInfo> actionsInfos = new ArrayList<>();
1037 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
1038 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
1039 instructions.add(writeInstruction);
1040 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
1042 // Install the flow entry in L3_LFIB_TABLE
1043 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1045 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1047 COOKIE_VM_LFIB_TABLE, matches, instructions);
1049 mdsalManager.installFlow(dpId, flowEntity);
1051 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
1054 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
1055 List<MatchInfo> mkMatches = new ArrayList<>();
1057 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
1059 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1061 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1062 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
1063 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1065 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1068 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1069 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1070 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1074 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1075 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1076 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1077 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1081 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1082 String routerName = original.getRouterName();
1083 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1084 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1085 Uuid networkId = original.getNetworkId();
1087 // Check if its update on SNAT flag
1088 boolean originalSNATEnabled = original.isEnableSnat();
1089 boolean updatedSNATEnabled = update.isEnableSnat();
1090 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1091 if(originalSNATEnabled != updatedSNATEnabled) {
1092 if(originalSNATEnabled) {
1093 //SNAT disabled for the router
1094 Uuid networkUuid = original.getNetworkId();
1095 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1096 if (routerId == NatConstants.INVALID_ID) {
1097 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1100 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1101 handleDisableSnat(routerName, networkUuid, externalIps, false, null);
1103 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1104 handleEnableSnat(original);
1108 //Check if the Update is on External IPs
1109 LOG.debug("NAT Service : Checking if this is update on External IPs");
1110 List<String> originalExternalIpsList = original.getExternalIps();
1111 List<String> updatedExternalIpsList = update.getExternalIps();
1112 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1113 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1115 //Check if the External IPs are added during the update.
1116 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1117 if(addedExternalIps.size() != 0) {
1118 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1119 for (String addedExternalIp : addedExternalIps) {
1121 1) Do nothing in the IntExtIp model.
1122 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1124 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1125 String externalIp = externalIpParts[0];
1126 String externalIpPrefix = externalIpParts[1];
1127 String externalpStr = externalIp + "/" + externalIpPrefix;
1128 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1129 externalpStr, routerId);
1130 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1132 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1135 //Check if the External IPs are removed during the update.
1136 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1137 if(removedExternalIps.size() > 0) {
1138 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1139 List<String> removedExternalIpsAsList = new ArrayList<>();
1140 for (String removedExternalIp : removedExternalIps) {
1142 1) Remove the mappings in the IntExt IP model which has external IP.
1143 2) Remove the external IP in the ExternalCounter model.
1144 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1145 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1146 4) Increase the count of the allocated external IP by one.
1147 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.
1148 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1149 7) Advertise to the BGP for removing the route for the removed external IPs.
1152 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1153 String externalIp = externalIpParts[0];
1154 String externalIpPrefix = externalIpParts[1];
1155 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1157 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1158 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1159 String vpnName = "";
1160 if(vpnUuId != null){
1161 vpnName = vpnUuId.getValue();
1163 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1165 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1166 //Get the internal IPs which are associated to the removed external IPs
1167 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1168 List<String> removedInternalIps = new ArrayList<>();
1169 for(IpMap ipMap : ipMaps){
1170 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1171 removedInternalIps.add(ipMap.getInternalIp());
1175 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1176 for(String removedInternalIp : removedInternalIps){
1177 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1178 removedInternalIp, routerId);
1179 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1182 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1183 externalIpAddrStr, routerId );
1184 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1185 removedExternalIpsAsList.add(externalIpAddrStr);
1187 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1188 for(String removedInternalIp : removedInternalIps) {
1189 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1192 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1193 //Get the internalIP and internal Port which were associated to the removed external IP.
1194 List<Integer> externalPorts = new ArrayList<>();
1195 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1196 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1197 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1198 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1199 if (ipPortMapping.isPresent()) {
1200 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1201 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1202 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1203 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1204 for(IpPortMap ipPortMap : ipPortMaps){
1205 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1206 if(ipPortExternal.getIpAddress().equals(externalIp)){
1207 externalPorts.add(ipPortExternal.getPortNum());
1208 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1209 if(removedInternalIpPorts != null){
1210 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1211 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1213 removedInternalIpPorts = new ArrayList<>();
1214 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1215 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1222 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1223 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1224 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1225 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1226 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1227 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1228 for(String removedInternalIpPort : removedInternalIpPorts){
1229 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1230 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1231 //Remove the IP port incomint packer map.
1232 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1233 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1234 if(removedInternalIpPortParts.length == 2){
1235 String removedInternalIp = removedInternalIpPortParts[0];
1236 String removedInternalPort = removedInternalIpPortParts[1];
1237 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1238 if (removedInternalPortsList != null){
1239 removedInternalPortsList.add(removedInternalPort);
1240 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1242 removedInternalPortsList = new ArrayList<>();
1243 removedInternalPortsList.add(removedInternalPort);
1244 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1250 // Delete the entry from SnatIntIpPortMap DS
1251 Set<String> internalIps = internalIpPortMap.keySet();
1252 for(String internalIp : internalIps){
1253 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1254 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1257 naptManager.removeNaptPortPool(externalIp);
1259 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1260 for(Integer externalPort : externalPorts) {
1261 //Remove the NAPT translation entries from Inbound NAPT table
1262 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1265 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1266 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1267 String internalIp = internalIpPort.getKey();
1268 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1269 List<String> internalPorts = internalIpPort.getValue();
1270 for(String internalPort : internalPorts){
1271 //Remove the NAPT translation entries from Outbound NAPT table
1272 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1276 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1279 //Check if its Update on subnets
1280 LOG.debug("NAT Service : Checking if this is update on subnets");
1281 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1282 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1283 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1284 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1285 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1287 //Check if the Subnet IDs are added during the update.
1288 if(addedSubnetIds.size() != 0){
1289 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1290 for(Uuid addedSubnetId : addedSubnetIds){
1292 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.
1293 2) Increase the count of the selected external IP by one.
1294 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.
1296 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1297 if(subnetIp != null) {
1298 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1301 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1304 //Check if the Subnet IDs are removed during the update.
1305 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1306 if(removedSubnetIds.size() != 0){
1307 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1308 for(Uuid removedSubnetId : removedSubnetIds){
1309 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1310 if(subnetAddr != null){
1312 1) Remove the subnet IP and the external IP in the IntExtIp map
1313 2) Decrease the count of the coresponding external IP by one.
1314 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1317 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1318 if (externalIp == null) {
1319 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1323 naptManager.updateCounter(routerId, externalIp, false);
1324 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1325 if (!isExternalIpAllocated(externalIp)) {
1326 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1327 List<String> externalIps = new ArrayList<>();
1328 externalIps.add(externalIp);
1329 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1330 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1331 dpnId,routerId,networkId,externalIps);
1334 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1335 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1338 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1342 private boolean isExternalIpAllocated(String externalIp) {
1343 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1344 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1345 if (externalCountersData.isPresent()) {
1346 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1347 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1348 for(ExternalCounters ext : externalCounters) {
1349 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1350 if (externalIpCount.getExternalIp().equals(externalIp)) {
1351 if (externalIpCount.getCounter() != 0) {
1362 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1363 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1364 if (leastLoadedExtIpAddr != null) {
1365 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1366 String leastLoadedExtIp = externalIpParts[0];
1367 String leastLoadedExtIpPrefix = externalIpParts[1];
1368 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1369 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1370 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1371 subnetIp = subnetIpParts[0];
1372 String subnetIpPrefix = subnetIpParts[1];
1373 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1374 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1375 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1376 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1379 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1380 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1381 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1384 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1385 IpMapKey ipMapKey = new IpMapKey(internalIp);
1386 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1387 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1388 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1392 //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.
1393 //Get the VPN Name using the network ID
1394 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1395 if (vpnName != null) {
1396 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1397 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1398 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1399 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1401 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1402 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1407 private Long checkExternalIpLabel(long routerId, String externalIp){
1408 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1409 for(IpMap ipMap : ipMaps){
1410 if(ipMap.getExternalIp().equals(externalIp)){
1411 if (ipMap.getLabel() != null){
1412 return ipMap.getLabel();
1420 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1421 LOG.trace("NAT Service : Router delete method");
1424 ROUTER DELETE SCENARIO
1425 1) Get the router ID from the event.
1426 2) Build the cookie information from the router ID.
1427 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1428 4) Build the flow with the cookie value.
1429 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1430 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1431 7) Get the list of external IP address maintained for the router ID.
1432 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1433 9) Withdraw the corresponding routes from the BGP.
1436 if (identifier == null || router == null) {
1437 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1441 String routerName = router.getRouterName();
1442 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1443 addOrDelDefFibRouteToSNAT(routerName, false);
1444 Uuid networkUuid = router.getNetworkId();
1445 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1446 if (routerId == NatConstants.INVALID_ID) {
1447 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1450 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1451 handleDisableSnat(routerName, networkUuid, externalIps, true, null);
1455 public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1456 LOG.info("NAT Service : handleDisableSnat() Entry");
1458 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1460 BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1461 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1462 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1463 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1466 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1467 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1469 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1470 } catch (Exception ex) {
1471 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1474 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1475 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1476 naptManager.removeMapping(routerId);
1479 removeNaptSwitch(routerName);
1481 updateNaptSwitch(routerName, BigInteger.ZERO);
1484 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1485 naptManager.removeExternalCounter(routerId);
1486 } catch (Exception ex) {
1487 LOG.error("Exception while handling disableSNAT : {}", ex);
1489 LOG.info("NAT Service : handleDisableSnat() Exit");
1492 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1493 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1495 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1496 BigInteger naptSwitchDpnId = null;
1497 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1498 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1499 if (rtrToNapt.isPresent()) {
1500 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1502 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1504 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1506 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1507 } catch (Exception ex) {
1508 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1510 } catch (Exception ex) {
1511 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1513 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1516 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1517 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1518 .setPrimarySwitchId(naptSwitchId).build();
1520 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1521 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1522 } catch (Exception ex) {
1523 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1524 naptSwitchId,routerName);
1526 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1527 naptSwitchId,routerName);
1530 protected void removeNaptSwitch(String routerName){
1531 // Remove router and switch from model
1532 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1533 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1534 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1537 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1539 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1540 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1542 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1543 // traffic which comes from the VMs of the NAPT switches)
1544 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1545 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1547 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);
1548 mdsalManager.removeFlow(pSNatFlowEntity);
1550 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1551 // traffic which comes from the VMs of the non NAPT switches)
1552 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1553 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1555 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);
1556 mdsalManager.removeFlow(tsNatFlowEntity);
1558 //Remove the Outbound flow entry which forwards the packet to FIB Table
1559 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1560 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1562 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);
1563 mdsalManager.removeFlow(outboundNatFlowEntity);
1565 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1566 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1567 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1569 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);
1570 mdsalManager.removeFlow(natPfibFlowEntity);
1572 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1573 //Get the VPN ID from the ExternalNetworks model
1575 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1576 // ie called from router delete cases
1577 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1578 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1579 if(vpnUuid != null) {
1580 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1581 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1584 // ie called from disassociate vpn case
1585 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1586 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1587 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1590 if(vpnId != NatConstants.INVALID_ID){
1591 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1592 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1593 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1594 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);
1595 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1598 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1599 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1600 if(ipPortMapping == null){
1601 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1605 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1606 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1607 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1608 for(IpPortMap ipPortMap : ipPortMaps){
1609 String ipPortInternal = ipPortMap.getIpPortInternal();
1610 String[] ipPortParts = ipPortInternal.split(":");
1611 if(ipPortParts.length != 2) {
1612 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1615 String internalIp = ipPortParts[0];
1616 String internalPort = ipPortParts[1];
1618 //Build the flow for the outbound NAPT table
1619 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1620 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1622 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);
1623 mdsalManager.removeFlow(outboundNaptFlowEntity);
1625 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1626 String externalIp = ipPortExternal.getIpAddress();
1627 int externalPort = ipPortExternal.getPortNum();
1629 //Build the flow for the inbound NAPT table
1630 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1631 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1633 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);
1634 mdsalManager.removeFlow(inboundNaptFlowEntity);
1639 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1641 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1642 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1644 //Remove the NAPT PFIB TABLE entry
1646 if(vpnName != null) {
1647 // ie called from disassociate vpn case
1648 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1649 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1650 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1653 if(vpnId != NatConstants.INVALID_ID){
1654 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1655 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1656 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1657 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);
1658 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1660 // Remove IP-PORT active NAPT entries and release port from IdManager
1661 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1662 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1663 if(ipPortMapping == null){
1664 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1667 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1668 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1669 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1670 for(IpPortMap ipPortMap : ipPortMaps){
1671 String ipPortInternal = ipPortMap.getIpPortInternal();
1672 String[] ipPortParts = ipPortInternal.split(":");
1673 if(ipPortParts.length != 2) {
1674 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1677 String internalIp = ipPortParts[0];
1678 String internalPort = ipPortParts[1];
1680 //Build the flow for the outbound NAPT table
1681 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1682 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1684 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);
1685 mdsalManager.removeFlow(outboundNaptFlowEntity);
1687 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1688 String externalIp = ipPortExternal.getIpAddress();
1689 int externalPort = ipPortExternal.getPortNum();
1691 //Build the flow for the inbound NAPT table
1692 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1693 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1695 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);
1696 mdsalManager.removeFlow(inboundNaptFlowEntity);
1698 // Finally release port from idmanager
1699 String internalIpPort = internalIp +":"+internalPort;
1700 naptManager.removePortFromPool(internalIpPort, externalIp);
1702 //Remove sessions from models
1703 naptManager.removeIpPortMappingForRouterID(routerId);
1704 naptManager.removeIntIpPortMappingForRouterID(routerId);
1708 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1712 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1713 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1715 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1716 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1717 if(allSwitchList == null || allSwitchList.isEmpty()){
1718 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1721 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1722 for (BigInteger dpnId : allSwitchList) {
1723 if (!naptSwitchDpnId.equals(dpnId)) {
1724 LOG.info("NAT Service : Handle Ordinary switch");
1726 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1727 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1728 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1730 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1731 mdsalManager.removeFlow(pSNatFlowEntity);
1733 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1734 long groupId = createGroupId(getGroupIdKey(routerName));
1735 List<BucketInfo> listBucketInfo = new ArrayList<>();
1736 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1738 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1739 mdsalManager.removeGroup(pSNatGroupEntity);
1745 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1746 //Withdraw the corresponding routes from the BGP.
1747 //Get the network ID using the router ID.
1748 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1749 externalIps,routerId,networkUuid, vpnName);
1750 if(networkUuid == null ){
1751 LOG.error("NAT Service : networkId is null");
1755 if (externalIps == null || externalIps.isEmpty()) {
1756 LOG.debug("NAT Service : externalIps is null");
1760 if(vpnName ==null) {
1761 //Get the VPN Name using the network ID
1762 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1763 if (vpnName == null) {
1764 LOG.error("No VPN associated with ext nw {} for the router {}",
1765 networkUuid, routerId);
1769 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1771 //Remove custom FIB routes
1772 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1773 for (String extIp : externalIps) {
1774 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1778 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1779 clearBgpRoutes(extIp,vpnName);
1780 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1783 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1784 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1786 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1787 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1791 final long label = tempLabel;
1792 final String externalIp = extIp;
1794 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1795 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1797 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1800 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1802 if (result.isSuccessful()) {
1803 removeTunnelTableEntry(dpnId, label);
1804 removeLFibTableEntry(dpnId, label);
1805 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1806 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1807 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1809 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1811 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1817 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1820 public void onFailure(Throwable error) {
1821 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1825 public void onSuccess(RpcResult<Void> result) {
1826 if (result.isSuccessful()) {
1827 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1829 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1835 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1836 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1837 //Get IPMaps from the DB for the router ID
1838 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1839 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1840 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1844 long tempLabel = NatConstants.INVALID_ID;
1845 for (IpMap dbIpMap : dbIpMaps) {
1846 String dbExternalIp = dbIpMap.getExternalIp();
1847 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1848 //Select the IPMap, whose external IP is the IP for which FIB is installed
1849 if (extIp.equals(dbExternalIp)) {
1850 tempLabel = dbIpMap.getLabel();
1851 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1855 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1856 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1860 final long label = tempLabel;
1861 final String externalIp = extIp;
1863 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1864 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1866 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1869 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1871 if (result.isSuccessful()) {
1872 removeTunnelTableEntry(dpnId, label);
1873 removeLFibTableEntry(dpnId, label);
1874 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1875 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1876 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1878 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1880 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1886 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1889 public void onFailure(Throwable error) {
1890 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1894 public void onSuccess(RpcResult<Void> result) {
1895 if (result.isSuccessful()) {
1896 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1898 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1904 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1905 //Withdraw the corresponding routes from the BGP.
1906 //Get the network ID using the router ID.
1907 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1908 externalIps,routerId,networkUuid, vpnName);
1909 if (networkUuid == null) {
1910 LOG.error("NAT Service : networkId is null");
1914 if (externalIps == null || externalIps.isEmpty()) {
1915 LOG.debug("NAT Service : externalIps is null");
1919 if (vpnName == null) {
1920 //Get the VPN Name using the network ID
1921 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1922 if (vpnName == null) {
1923 LOG.error("No VPN associated with ext nw {} for the router {}",
1924 networkUuid, routerId);
1928 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1930 //Remove custom FIB routes
1931 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1932 for (String extIp : externalIps) {
1933 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1937 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1938 //Inform BGP about the route removal
1939 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1940 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1941 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
1944 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1945 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1946 List<MatchInfo> mkMatches = new ArrayList<>();
1947 // Matching metadata
1948 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1949 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1950 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1951 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1952 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1953 mdsalManager.removeFlow(dpnId, flowEntity);
1954 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1957 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1958 List<MatchInfo> matches = new ArrayList<>();
1959 matches.add(new MatchInfo(MatchFieldType.eth_type,
1960 new long[] { 0x8847L }));
1961 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1963 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1965 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
1967 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1969 COOKIE_VM_LFIB_TABLE, matches, null);
1971 mdsalManager.removeFlow(dpnId, flowEntity);
1973 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
1977 protected InstanceIdentifier<Routers> getWildCardPath()
1979 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
1984 * router association to vpn
1987 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
1988 LOG.debug("NAT Service : Router associated to BGP VPN");
1989 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1990 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1992 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1994 if(bgpVpnId != NatConstants.INVALID_ID){
1995 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
1996 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
1997 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
1999 // Get the allocated Primary NAPT Switch for this router
2000 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2001 LOG.debug("Router ID value {} ", routerId);
2002 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2004 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
2005 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
2008 long groupId = createGroupId(getGroupIdKey(routerName));
2009 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2015 * router disassociation from vpn
2018 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2019 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2020 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2021 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2022 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2024 // Get the allocated Primary NAPT Switch for this router
2025 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2026 LOG.debug("Router ID value {} ", routerId);
2027 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2029 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2030 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2033 long groupId = createGroupId(getGroupIdKey(routerName));
2034 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2038 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2039 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2040 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2041 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2042 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2048 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2049 routerId, boolean isSnatCfgd){
2050 long changedVpnId = bgpVpnId;
2051 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2052 if (bgpVpnId == NatConstants.INVALID_ID){
2053 changedVpnId = routerId;
2054 logMsg = "NAT Service : Update the router ID {}";
2057 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2058 if (switches == null || switches.isEmpty()) {
2059 LOG.debug("No switches found for router {}",routerName);
2062 for(BigInteger dpnId : switches) {
2063 // Update the BGP VPN ID in the SNAT miss entry to group
2064 if( !dpnId.equals(primarySwitchId) ) {
2065 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2066 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2067 long groupId = createGroupId(getGroupIdKey(routerName));
2069 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2072 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2073 changedVpnId, groupId, dpnId);
2074 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2075 mdsalManager.installFlow(flowEntity);
2078 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2079 changedVpnId, primarySwitchId);
2080 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2081 mdsalManager.installFlow(flowEntity);
2083 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2084 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2085 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2087 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2088 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2089 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2091 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2092 changedVpnId, primarySwitchId);
2093 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2095 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2096 " in the Primary switch {}", changedVpnId, primarySwitchId);
2097 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2099 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2100 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2101 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2102 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2103 installNaptPfibEntry(primarySwitchId, vpnId);
2109 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2110 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2111 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2112 if(ipPortMapping == null){
2113 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2117 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2118 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2119 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2120 for(IpPortMap ipPortMap : ipPortMaps){
2121 String ipPortInternal = ipPortMap.getIpPortInternal();
2122 String[] ipPortParts = ipPortInternal.split(":");
2123 if(ipPortParts.length != 2) {
2124 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2127 String internalIp = ipPortParts[0];
2128 String internalPort = ipPortParts[1];
2130 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2131 NAPTEntryEvent.Protocol protocol;
2132 switch (protocolTypes){
2134 protocol = NAPTEntryEvent.Protocol.TCP;
2137 protocol = NAPTEntryEvent.Protocol.UDP;
2140 protocol = NAPTEntryEvent.Protocol.TCP;
2142 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2143 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2144 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2145 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2146 internalAddress, externalAddress, protocol);
2147 naptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2148 externalAddress, internalAddress, protocol);
2154 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2156 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2157 List<MatchInfo> matches = new ArrayList<>();
2158 matches.add(new MatchInfo(MatchFieldType.eth_type,
2159 new long[] { 0x0800L }));
2160 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2161 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2163 List<InstructionInfo> instructions = new ArrayList<>();
2164 List<ActionInfo> actionsInfo = new ArrayList<>();
2166 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2167 BigInteger.valueOf(changedVpnId)}) ;
2168 actionsInfo.add(actionSetField);
2169 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2170 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2171 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
2172 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2173 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2174 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2175 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2177 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2181 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2183 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2184 List<MatchInfo> matches = new ArrayList<>();
2185 matches.add(new MatchInfo(MatchFieldType.eth_type,
2186 new long[] { 0x0800L }));
2187 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2188 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2190 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2191 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2192 { NwConstants.OUTBOUND_NAPT_TABLE }));
2194 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2195 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2196 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2197 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2199 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2203 // TODO : Replace this with ITM Rpc once its available with full functionality
2204 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2205 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2206 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2207 mdsalManager.installFlow(flowEntity);
2211 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2212 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2213 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2214 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2215 List<MatchInfo> matches = new ArrayList<>();
2216 matches.add(new MatchInfo(MatchFieldType.eth_type,
2217 new long[] { 0x0800L }));
2218 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2220 List<InstructionInfo> instructions = new ArrayList<>();
2221 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2222 { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2223 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2224 { NwConstants.OUTBOUND_NAPT_TABLE }));
2225 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2226 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2227 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2228 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2232 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2233 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2234 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2235 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2236 mdsalManager.installFlow(flowEntity);
2239 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2240 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2241 List<MatchInfo> matches = new ArrayList<>();
2242 matches.add(new MatchInfo(MatchFieldType.eth_type,
2243 new long[]{0x0800L}));
2244 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2245 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2247 List<InstructionInfo> instructions = new ArrayList<>();
2248 List<ActionInfo> actionsInfos = new ArrayList<>();
2249 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2250 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2251 instructions.add(new InstructionInfo(InstructionType.write_metadata,
2252 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2254 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2255 BigInteger cookie = getCookieOutboundFlow(routerId);
2256 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2257 cookie, matches, instructions);
2258 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2262 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2263 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2264 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2265 mdsalManager.installFlow(naptPfibFlowEntity);
2268 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2270 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2271 List<MatchInfo> matches = new ArrayList<>();
2272 matches.add(new MatchInfo(MatchFieldType.eth_type,
2273 new long[] { 0x0800L }));
2274 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2275 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2277 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2278 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2279 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
2280 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2282 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2283 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2284 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2285 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2287 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2292 protected ExternalRoutersListener getDataTreeChangeListener()
2294 return ExternalRoutersListener.this;