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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.*;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
35 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;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
47 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
48 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
49 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
50 import org.opendaylight.genius.mdsalutil.ActionInfo;
51 import org.opendaylight.genius.mdsalutil.ActionType;
52 import org.opendaylight.genius.mdsalutil.BucketInfo;
53 import org.opendaylight.genius.mdsalutil.FlowEntity;
54 import org.opendaylight.genius.mdsalutil.GroupEntity;
55 import org.opendaylight.genius.mdsalutil.InstructionInfo;
56 import org.opendaylight.genius.mdsalutil.InstructionType;
57 import org.opendaylight.genius.mdsalutil.MDSALUtil;
58 import org.opendaylight.genius.mdsalutil.MatchFieldType;
59 import org.opendaylight.genius.mdsalutil.MatchInfo;
60 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
61 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
62 import org.opendaylight.genius.mdsalutil.NwConstants;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
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.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
99 import org.opendaylight.yangtools.concepts.ListenerRegistration;
100 import org.opendaylight.yangtools.yang.binding.DataObject;
101 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
102 import org.opendaylight.yangtools.yang.common.RpcResult;
103 import org.slf4j.Logger;
104 import org.slf4j.LoggerFactory;
106 import com.google.common.base.Optional;
107 import com.google.common.collect.Sets;
108 import com.google.common.collect.Sets.SetView;
109 import com.google.common.util.concurrent.AsyncFunction;
110 import com.google.common.util.concurrent.FutureCallback;
111 import com.google.common.util.concurrent.Futures;
112 import com.google.common.util.concurrent.JdkFutureAdapters;
113 import com.google.common.util.concurrent.ListenableFuture;
116 * Created by EYUGSAR on 2/20/2016.
119 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener>{
121 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
122 private static long label;
123 private ListenerRegistration<DataChangeListener> listenerRegistration;
124 private final DataBroker dataBroker;
125 private IMdsalApiManager mdsalManager;
126 private ItmRpcService itmManager;
127 private OdlInterfaceRpcService interfaceManager;
128 private IdManagerService idManager;
129 private NaptManager naptManager;
130 private NAPTSwitchSelector naptSwitchSelector;
131 private IBgpManager bgpManager;
132 private VpnRpcService vpnService;
133 private FibRpcService fibService;
134 private SNATDefaultRouteProgrammer defaultRouteProgrammer;
135 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
136 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
137 private NaptEventHandler naptEventHandler;
138 private NaptPacketInHandler naptPacketInHandler;
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 ExternalRoutersListener(DataBroker dataBroker )
192 super( Routers.class, ExternalRoutersListener.class );
193 this.dataBroker = dataBroker;
197 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
199 LOG.info("NAT Service : Add external router event for {}", routers.getRouterName());
201 // Populate the router-id-name container
202 String routerName = routers.getRouterName();
203 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
204 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
205 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
207 LOG.info("NAT Service : Installing NAT default route on all dpns part of router {}", routers.getRouterName());
209 addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
210 } catch (Exception ex) {
211 LOG.debug("NAT Service : Exception {} while Installing NAT default route on all dpns part of router {}",ex,routers.getRouterName());
214 if( !routers.isEnableSnat()) {
215 LOG.info("NAT Service : SNAT is disabled for external router {} ", routers.getRouterName());
219 handleEnableSnat(routers);
222 public void handleEnableSnat(Routers routers){
223 String routerName = routers.getRouterName();
224 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
226 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
227 naptManager.initialiseExternalCounter(routers, segmentId);
229 subnetRegisterMapping(routers,segmentId);
231 // Allocate Primary Napt Switch for this router
232 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,segmentId);
233 if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
234 LOG.debug("NAT Service : Primary NAPT switch with DPN ID {} is already elected for router",primarySwitchId,routerName);
237 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
238 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
239 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
240 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
243 LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
245 long bgpVpnId = NatConstants.INVALID_ID;
246 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
247 if (bgpVpnUuid != null) {
248 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
250 if (bgpVpnId != NatConstants.INVALID_ID){
251 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, segmentId, false);
253 // write metadata and punt
254 installOutboundMissEntry(routerName, primarySwitchId);
255 // Now install entries in SNAT tables to point to Primary for each router
256 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
257 if (switches != null) {
258 for (BigInteger dpnId : switches) {
259 // Handle switches and NAPT switches separately
260 if (!dpnId.equals(primarySwitchId)) {
261 LOG.debug("NAT Service : Handle Ordinary switch");
262 handleSwitches(dpnId, routerName, primarySwitchId);
264 LOG.debug("NAT Service : Handle NAPT switch");
265 handlePrimaryNaptSwitch(dpnId, routerName);
271 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,segmentId);
272 if (externalIps == null || externalIps.isEmpty()) {
273 LOG.debug("NAT Service : Internal External mapping found for router {}",routerName);
276 for (String externalIpAddrPrefix : externalIps) {
277 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
278 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
282 /*// call registerMapping Api
283 LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
285 List<Uuid> subnetList = null;
286 List<String> externalIps = null;
288 InstanceIdentifier<Routers> id = InstanceIdentifier
289 .builder(ExtRouters.class)
290 .child(Routers.class, new RoutersKey(routerName))
293 Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
295 if(extRouters.isPresent())
297 LOG.debug("NAT Service : Fetching values from extRouters model");
298 Routers routerEntry= extRouters.get();
299 subnetList = routerEntry.getSubnetIds();
300 externalIps = routerEntry.getExternalIps();
302 int extIpCounter = externalIps.size();
303 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
304 for(Uuid subnet : subnetList) {
305 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
306 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
307 .builder(Subnetmaps.class)
308 .child(Subnetmap.class, new SubnetmapKey(subnet))
310 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
313 Subnetmap subnetmapEntry = sn.get();
314 String subnetString = subnetmapEntry.getSubnetIp();
315 String[] subnetSplit = subnetString.split("/");
316 String subnetIp = subnetSplit[0];
317 String subnetPrefix = "0";
318 if(subnetSplit.length == 2) {
319 subnetPrefix = subnetSplit[1];
321 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
322 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
324 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
325 if(extIpCounter != 0) {
326 if(counter < extIpCounter) {
327 String[] IpSplit = externalIps.get(counter).split("/");
328 String externalIp = IpSplit[0];
329 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
330 if(IpSplit.length==2) {
331 extPrefix = IpSplit[1];
333 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
334 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
335 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
336 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
337 externalIp, extPrefix);
339 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
340 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
341 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
344 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
345 LOG.debug("NAT Service : Counter on externalIps got reset");
346 String[] IpSplit = externalIps.get(counter).split("/");
347 String externalIp = IpSplit[0];
348 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
349 if(IpSplit.length==2) {
350 extPrefix = IpSplit[1];
352 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
353 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
354 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
355 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
356 externalIp, extPrefix);
358 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
359 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
360 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
365 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
368 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
372 LOG.info("NAT Service : handleEnableSnat() Exit");
375 private void subnetRegisterMapping(Routers routerEntry,Long segmentId) {
376 List<Uuid> subnetList = null;
377 List<String> externalIps = null;
378 LOG.debug("NAT Service : Fetching values from extRouters model");
379 subnetList = routerEntry.getSubnetIds();
380 externalIps = routerEntry.getExternalIps();
382 int extIpCounter = externalIps.size();
383 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
384 for(Uuid subnet : subnetList) {
385 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
386 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
387 .builder(Subnetmaps.class)
388 .child(Subnetmap.class, new SubnetmapKey(subnet))
390 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
393 Subnetmap subnetmapEntry = sn.get();
394 String subnetString = subnetmapEntry.getSubnetIp();
395 String[] subnetSplit = subnetString.split("/");
396 String subnetIp = subnetSplit[0];
397 String subnetPrefix = "0";
398 if(subnetSplit.length == 2) {
399 subnetPrefix = subnetSplit[1];
401 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
402 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
404 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
405 if(extIpCounter != 0) {
406 if(counter < extIpCounter) {
407 String[] IpSplit = externalIps.get(counter).split("/");
408 String externalIp = IpSplit[0];
409 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
410 if(IpSplit.length==2) {
411 extPrefix = IpSplit[1];
413 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
414 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
415 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
416 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
417 externalIp, extPrefix);
419 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
420 LOG.debug("NAT Service : Counter on externalIps got reset");
421 String[] IpSplit = externalIps.get(counter).split("/");
422 String externalIp = IpSplit[0];
423 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
424 if(IpSplit.length==2) {
425 extPrefix = IpSplit[1];
427 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
428 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
429 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
430 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
431 externalIp, extPrefix);
435 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
437 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
442 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
443 //Check if BGP VPN exists. If exists then invoke the new method.
444 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
445 if(bgpVpnId != NatConstants.INVALID_ID) {
446 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
447 if (bgpVpnUuid != null) {
448 String bgpVpnName = bgpVpnUuid.getValue();
449 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
450 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
451 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
453 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
457 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
458 addOrDelDefaultFibRouteForSNAT(routerName, create);
461 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
462 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
463 if (switches == null || switches.isEmpty()) {
464 LOG.debug("No switches found for router {}",routerName);
467 long routerId = NatUtil.readVpnId(dataBroker, routerName);
468 if (routerId == NatConstants.INVALID_ID) {
469 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
472 for (BigInteger dpnId : switches) {
473 if (create == true) {
474 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
475 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
477 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
478 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
483 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
484 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
485 if(dpnIds == null || dpnIds.isEmpty()) {
486 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
489 long routerId = NatUtil.getVpnId(dataBroker, routerName);
490 for (BigInteger dpnId : dpnIds) {
491 if (create == true) {
492 if (bgpVpnId != NatConstants.INVALID_ID) {
493 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
494 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
496 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
497 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
500 if (bgpVpnId != NatConstants.INVALID_ID) {
501 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
502 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
504 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
505 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
511 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
513 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
515 Optional<T> result = Optional.absent();
518 result = tx.read(datastoreType, path).get();
522 throw new RuntimeException(e);
528 public void close() throws Exception
530 if (listenerRegistration != null)
534 listenerRegistration.close();
536 catch (final Exception e)
538 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
541 listenerRegistration = null;
543 LOG.debug("ExternalRoutersListener Closed");
546 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
547 long routerId = NatUtil.getVpnId(dataBroker, routerName);
548 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
549 if(routerId != NatConstants.INVALID_ID) {
550 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
551 createOutboundTblEntry(primarySwitchId, routerId);
553 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
557 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
558 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
559 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
562 public BigInteger getCookieOutboundFlow(long routerId) {
563 return NatConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
564 BigInteger.valueOf(routerId));
567 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
568 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
569 List<MatchInfo> matches = new ArrayList<MatchInfo>();
570 matches.add(new MatchInfo(MatchFieldType.eth_type,
571 new long[] { 0x0800L }));
572 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
573 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
575 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
576 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
577 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
578 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
579 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
581 String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
582 BigInteger cookie = getCookieOutboundFlow(routerId);
583 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
585 cookie, matches, instructions);
586 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
590 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
591 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
592 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
593 LOG.debug("NAT Service : Installing flow {}", flowEntity);
594 mdsalManager.installFlow(flowEntity);
597 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
598 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
599 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
601 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
602 .setSourceDpid(srcDpId)
603 .setDestinationDpid(dstDpId)
604 .setTunnelType(tunType)
606 rpcResult = result.get();
607 if(!rpcResult.isSuccessful()) {
608 tunType = TunnelTypeGre.class ;
609 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
610 .setSourceDpid(srcDpId)
611 .setDestinationDpid(dstDpId)
612 .setTunnelType(tunType)
614 rpcResult = result.get();
615 if(!rpcResult.isSuccessful()) {
616 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
618 return rpcResult.getResult().getInterfaceName();
620 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
622 return rpcResult.getResult().getInterfaceName();
624 } catch (InterruptedException | ExecutionException | NullPointerException e) {
625 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
631 protected List<ActionInfo> getEgressActionsForInterface(String ifName, long routerId) {
632 LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
633 List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
635 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
636 interfaceManager.getEgressActionsForInterface(
637 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(routerId).build());
638 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
639 if(!rpcResult.isSuccessful()) {
640 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
642 List<Action> actions =
643 rpcResult.getResult().getAction();
644 for (Action action : actions) {
645 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
646 if (actionClass instanceof OutputActionCase) {
647 listActionInfo.add(new ActionInfo(ActionType.output,
648 new String[] {((OutputActionCase)actionClass).getOutputAction()
649 .getOutputNodeConnector().getValue()}));
650 } else if (actionClass instanceof PushVlanActionCase) {
651 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
652 } else if (actionClass instanceof SetFieldCase) {
653 if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
654 int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
655 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
656 new String[] { Long.toString(vlanVid) }));
661 } catch (InterruptedException | ExecutionException e) {
662 LOG.warn("Exception when egress actions for interface {}", ifName, e);
664 return listActionInfo;
667 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
668 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAOT switch dpnId {} ", dpnId);
669 // Install miss entry pointing to group
670 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
671 mdsalManager.installFlow(flowEntity);
674 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
675 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
676 // Install the select group
677 long groupId = createGroupId(getGroupIdKey(routerName));
678 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
679 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
680 mdsalManager.installGroup(groupEntity);
681 // Install miss entry pointing to group
682 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
683 mdsalManager.installFlow(flowEntity);
686 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
687 long groupId = createGroupId(getGroupIdKey(routerName));
688 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
689 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
690 mdsalManager.installGroup(groupEntity);
694 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
696 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
697 long routerId = NatUtil.getVpnId(dataBroker, routerName);
698 List<MatchInfo> matches = new ArrayList<MatchInfo>();
699 matches.add(new MatchInfo(MatchFieldType.eth_type,
700 new long[] { 0x0800L }));
701 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
702 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
705 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
706 List<ActionInfo> actionsInfo = new ArrayList<ActionInfo>();
708 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
709 BigInteger.valueOf(routerId)}) ;
710 actionsInfo.add(actionSetField);
711 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
712 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
713 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
714 String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
715 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
716 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
717 NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
719 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
723 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
725 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
727 long routerId = NatUtil.getVpnId(dataBroker, routerName);
728 List<MatchInfo> matches = new ArrayList<MatchInfo>();
729 matches.add(new MatchInfo(MatchFieldType.eth_type,
730 new long[] { 0x0800L }));
731 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
732 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
734 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
735 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
736 { NatConstants.OUTBOUND_NAPT_TABLE }));
738 String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
739 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
740 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
741 NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
743 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
747 // TODO : Replace this with ITM Rpc once its available with full functionality
748 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
749 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
750 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
751 mdsalManager.installFlow(flowEntity);
755 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
757 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
758 List<MatchInfo> matches = new ArrayList<MatchInfo>();
759 matches.add(new MatchInfo(MatchFieldType.eth_type,
760 new long[] { 0x0800L }));
761 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
763 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
764 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
765 { routerId, MetaDataUtil.METADATA_MASK_VRFID }));
766 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
767 { NatConstants.OUTBOUND_NAPT_TABLE }));
768 String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
769 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
770 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
771 NatConstants.COOKIE_TS_TABLE, matches, instructions);
775 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
776 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
777 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
780 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
781 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
782 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
785 private String getGroupIdKey(String routerName){
786 String groupIdKey = new String("snatmiss." + routerName);
790 protected long createGroupId(String groupIdKey) {
791 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
792 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
795 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
796 RpcResult<AllocateIdOutput> rpcResult = result.get();
797 return rpcResult.getResult().getIdValue();
798 } catch (NullPointerException | InterruptedException | ExecutionException e) {
804 protected void createGroupIdPool() {
805 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
806 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
807 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
808 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
811 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
812 if ((result != null) && (result.get().isSuccessful())) {
813 LOG.debug("NAT Service : Created GroupIdPool");
815 LOG.error("NAT Service : Unable to create GroupIdPool");
817 } catch (InterruptedException | ExecutionException e) {
818 LOG.error("Failed to create PortPool for NAPT Service",e);
822 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
823 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
824 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
825 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
826 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
827 long routerId = NatUtil.getVpnId(dataBroker, routerName);
829 if(ifNamePrimary != null) {
830 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
831 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
833 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
835 listBucketInfo.add(0, bucketPrimary);
836 installSnatMissEntry(dpnId, listBucketInfo, routerName);
839 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
840 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
841 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
842 List<BucketInfo> listBucketInfo = new ArrayList<>();
843 long routerId = NatUtil.getVpnId(dataBroker, routerName);
845 if (ifNamePrimary != null) {
846 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
847 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
849 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
851 listBucketInfo.add(0, bucketPrimary);
852 return listBucketInfo;
854 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
857 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
860 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
863 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
864 List<ActionInfo> listActionInfoPrimary = new ArrayList<ActionInfo>();
865 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
866 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
867 listBucketInfo.add(0, bucketPrimary);
870 long routerId = NatUtil.getVpnId(dataBroker, routerName);
872 installSnatMissEntryForPrimrySwch(dpnId, routerName);
873 installTerminatingServiceTblEntry(dpnId, routerName);
874 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
875 installNaptPfibEntry(dpnId, routerId);
876 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
877 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
878 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
879 installNaptPfibEntry(dpnId, vpnId);
883 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
884 List<BucketInfo> listBucketInfo = new ArrayList<>();
885 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
886 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
887 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
888 listBucketInfo.add(0, bucketPrimary);
889 return listBucketInfo;
892 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
893 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
894 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
895 mdsalManager.installFlow(naptPfibFlowEntity);
898 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
900 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
901 List<MatchInfo> matches = new ArrayList<MatchInfo>();
902 matches.add(new MatchInfo(MatchFieldType.eth_type,
903 new long[] { 0x0800L }));
904 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
905 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
907 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
908 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
909 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
910 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
912 String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
913 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
914 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
915 NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
917 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
921 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
922 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
923 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
924 if(networkId == null) {
925 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
928 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
929 if(vpnName == null) {
930 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
931 networkId, externalIp, routerId);
934 advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
935 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
938 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
939 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
941 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
942 //Generate VPN label for the external IP
943 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
944 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
946 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
947 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
950 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
951 if (result.isSuccessful()) {
952 LOG.debug("NAT Service : inside apply with result success");
953 GenerateVpnLabelOutput output = result.getResult();
954 final long label = output.getLabel();
956 int externalIpInDsFlag = 0;
957 //Get IPMaps from the DB for the router ID
958 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
959 if (dbIpMaps != null) {
960 for (IpMap dbIpMap : dbIpMaps) {
961 String dbExternalIp = dbIpMap.getExternalIp();
962 //Select the IPMap, whose external IP is the IP for which FIB is installed
963 if (externalIp.equals(dbExternalIp)) {
964 String dbInternalIp = dbIpMap.getInternalIp();
965 IpMapKey dbIpMapKey = dbIpMap.getKey();
966 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
967 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
968 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
969 externalIpInDsFlag++;
972 if (externalIpInDsFlag <=0) {
973 LOG.debug("NAT Service : External Ip {} not found in DS,Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
974 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", externalIp, label, routerId);
975 return Futures.immediateFailedFuture(new Exception(errMsg));
978 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
983 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
984 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
985 NatUtil.addPrefixToBGP(bgpManager, rd, externalIp, nextHopIp, label, log);
987 //Install custom FIB routes
988 List<Instruction> customInstructions = new ArrayList<>();
989 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
990 makeTunnelTableEntry(dpnId, label, customInstructions);
991 makeLFibTableEntry(dpnId, label, tableId);
993 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
994 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
995 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
996 return JdkFutureAdapters.listenInPoolThread(future);
998 LOG.error("NAT Service : inside apply with result failed");
999 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
1000 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1005 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
1008 public void onFailure(Throwable error) {
1009 log.error("NAT Service : Error in generate label or fib install process", error);
1013 public void onSuccess(RpcResult<Void> result) {
1014 if (result.isSuccessful()) {
1015 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
1017 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1023 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
1024 List<MatchInfo> matches = new ArrayList<MatchInfo>();
1025 matches.add(new MatchInfo(MatchFieldType.eth_type,
1026 new long[]{0x8847L}));
1027 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1029 List<Instruction> instructions = new ArrayList<Instruction>();
1030 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
1031 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
1032 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
1033 instructions.add(writeInstruction);
1034 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
1036 // Install the flow entry in L3_LFIB_TABLE
1037 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1039 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1041 COOKIE_VM_LFIB_TABLE, matches, instructions);
1043 mdsalManager.installFlow(dpId, flowEntity);
1045 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
1048 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
1049 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1051 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
1053 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1055 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1056 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
1057 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1059 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1062 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1063 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1064 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1068 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1069 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1070 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1071 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1075 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1076 String routerName = original.getRouterName();
1077 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1078 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1079 Uuid networkId = original.getNetworkId();
1081 // Check if its update on SNAT flag
1082 boolean originalSNATEnabled = original.isEnableSnat();
1083 boolean updatedSNATEnabled = update.isEnableSnat();
1084 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1085 if(originalSNATEnabled != updatedSNATEnabled) {
1086 if(originalSNATEnabled) {
1087 //SNAT disabled for the router
1088 Uuid networkUuid = original.getNetworkId();
1089 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1090 if (routerId == NatConstants.INVALID_ID) {
1091 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1094 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1095 handleDisableSnat(routerName, networkUuid, externalIps, false, null);
1097 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1098 handleEnableSnat(original);
1102 //Check if the Update is on External IPs
1103 LOG.debug("NAT Service : Checking if this is update on External IPs");
1104 List<String> originalExternalIpsList = original.getExternalIps();
1105 List<String> updatedExternalIpsList = update.getExternalIps();
1106 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1107 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1109 //Check if the External IPs are added during the update.
1110 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1111 if(addedExternalIps.size() != 0) {
1112 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1113 for (String addedExternalIp : addedExternalIps) {
1115 1) Do nothing in the IntExtIp model.
1116 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1118 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1119 String externalIp = externalIpParts[0];
1120 String externalIpPrefix = externalIpParts[1];
1121 String externalpStr = externalIp + "/" + externalIpPrefix;
1122 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1123 externalpStr, routerId);
1124 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1126 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1129 //Check if the External IPs are removed during the update.
1130 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1131 if(removedExternalIps.size() > 0) {
1132 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1133 List<String> removedExternalIpsAsList = new ArrayList<>();
1134 for (String removedExternalIp : removedExternalIps) {
1136 1) Remove the mappings in the IntExt IP model which has external IP.
1137 2) Remove the external IP in the ExternalCounter model.
1138 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1139 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1140 4) Increase the count of the allocated external IP by one.
1141 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.
1142 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1143 7) Advertise to the BGP for removing the route for the removed external IPs.
1146 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1147 String externalIp = externalIpParts[0];
1148 String externalIpPrefix = externalIpParts[1];
1149 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1151 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1152 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1153 String vpnName = "";
1154 if(vpnUuId != null){
1155 vpnName = vpnUuId.getValue();
1157 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1159 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1160 //Get the internal IPs which are associated to the removed external IPs
1161 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1162 List<String> removedInternalIps = new ArrayList<>();
1163 for(IpMap ipMap : ipMaps){
1164 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1165 removedInternalIps.add(ipMap.getInternalIp());
1169 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1170 for(String removedInternalIp : removedInternalIps){
1171 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1172 removedInternalIp, routerId);
1173 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1176 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1177 externalIpAddrStr, routerId );
1178 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1179 removedExternalIpsAsList.add(externalIpAddrStr);
1181 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1182 for(String removedInternalIp : removedInternalIps) {
1183 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1186 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1187 //Get the internalIP and internal Port which were associated to the removed external IP.
1188 List<Integer> externalPorts = new ArrayList<>();
1189 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1190 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1191 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1192 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1193 if (ipPortMapping.isPresent()) {
1194 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1195 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1196 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1197 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1198 for(IpPortMap ipPortMap : ipPortMaps){
1199 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1200 if(ipPortExternal.getIpAddress().equals(externalIp)){
1201 externalPorts.add(ipPortExternal.getPortNum());
1202 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1203 if(removedInternalIpPorts != null){
1204 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1205 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1207 removedInternalIpPorts = new ArrayList<>();
1208 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1209 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1216 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1217 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1218 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1219 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1220 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1221 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1222 for(String removedInternalIpPort : removedInternalIpPorts){
1223 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1224 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1225 //Remove the IP port incomint packer map.
1226 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1227 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1228 if(removedInternalIpPortParts.length == 2){
1229 String removedInternalIp = removedInternalIpPortParts[0];
1230 String removedInternalPort = removedInternalIpPortParts[1];
1231 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1232 if (removedInternalPortsList != null){
1233 removedInternalPortsList.add(removedInternalPort);
1234 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1236 removedInternalPortsList = new ArrayList<>();
1237 removedInternalPortsList.add(removedInternalPort);
1238 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1244 // Delete the entry from SnatIntIpPortMap DS
1245 Set<String> internalIps = internalIpPortMap.keySet();
1246 for(String internalIp : internalIps){
1247 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1248 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1251 naptManager.removeNaptPortPool(externalIp);
1253 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1254 for(Integer externalPort : externalPorts) {
1255 //Remove the NAPT translation entries from Inbound NAPT table
1256 naptEventHandler.removeNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1259 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1260 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1261 String internalIp = internalIpPort.getKey();
1262 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1263 List<String> internalPorts = internalIpPort.getValue();
1264 for(String internalPort : internalPorts){
1265 //Remove the NAPT translation entries from Outbound NAPT table
1266 naptEventHandler.removeNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1270 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1273 //Check if its Update on subnets
1274 LOG.debug("NAT Service : Checking if this is update on subnets");
1275 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1276 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1277 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1278 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1279 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1281 //Check if the Subnet IDs are added during the update.
1282 if(addedSubnetIds.size() != 0){
1283 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1284 for(Uuid addedSubnetId : addedSubnetIds){
1286 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.
1287 2) Increase the count of the selected external IP by one.
1288 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.
1290 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1291 if(subnetIp != null) {
1292 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1295 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1298 //Check if the Subnet IDs are removed during the update.
1299 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1300 if(removedSubnetIds.size() != 0){
1301 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1302 for(Uuid removedSubnetId : removedSubnetIds){
1303 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1304 if(subnetAddr != null){
1306 1) Remove the subnet IP and the external IP in the IntExtIp map
1307 2) Decrease the count of the coresponding external IP by one.
1308 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1311 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1312 if (externalIp == null) {
1313 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1317 naptManager.updateCounter(routerId, externalIp, false);
1318 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1319 if (!isExternalIpAllocated(externalIp)) {
1320 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1321 List<String> externalIps = new ArrayList<>();
1322 externalIps.add(externalIp);
1323 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1324 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1325 dpnId,routerId,networkId,externalIps);
1328 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1329 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1332 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1336 private boolean isExternalIpAllocated(String externalIp) {
1337 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1338 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1339 if (externalCountersData.isPresent()) {
1340 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1341 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1342 for(ExternalCounters ext : externalCounters) {
1343 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1344 if (externalIpCount.getExternalIp().equals(externalIp)) {
1345 if (externalIpCount.getCounter() != 0) {
1356 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1357 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1358 if (leastLoadedExtIpAddr != null) {
1359 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1360 String leastLoadedExtIp = externalIpParts[0];
1361 String leastLoadedExtIpPrefix = externalIpParts[1];
1362 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1363 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1364 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1365 subnetIp = subnetIpParts[0];
1366 String subnetIpPrefix = subnetIpParts[1];
1367 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1368 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1369 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1370 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1373 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1374 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1375 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1378 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1379 IpMapKey ipMapKey = new IpMapKey(internalIp);
1380 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1381 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1382 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1386 //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.
1387 //Get the VPN Name using the network ID
1388 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1389 if (vpnName != null) {
1390 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1391 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1392 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1393 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1395 advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1396 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1401 private Long checkExternalIpLabel(long routerId, String externalIp){
1402 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1403 for(IpMap ipMap : ipMaps){
1404 if(ipMap.getExternalIp().equals(externalIp)){
1405 if (ipMap.getLabel() != null){
1406 return ipMap.getLabel();
1414 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1415 LOG.trace("NAT Service : Router delete method");
1418 ROUTER DELETE SCENARIO
1419 1) Get the router ID from the event.
1420 2) Build the cookie information from the router ID.
1421 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1422 4) Build the flow with the cookie value.
1423 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1424 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1425 7) Get the list of external IP address maintained for the router ID.
1426 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1427 9) Withdraw the corresponding routes from the BGP.
1430 if (identifier == null || router == null) {
1431 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1435 String routerName = router.getRouterName();
1436 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1437 addOrDelDefFibRouteToSNAT(routerName, false);
1438 Uuid networkUuid = router.getNetworkId();
1439 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1440 if (routerId == NatConstants.INVALID_ID) {
1441 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1444 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1445 handleDisableSnat(routerName, networkUuid, externalIps, true, null);
1449 public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1450 LOG.info("NAT Service : handleDisableSnat() Entry");
1452 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1454 BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1455 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1456 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1457 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1460 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1461 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1463 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1464 } catch (Exception ex) {
1465 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1468 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1469 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1470 naptManager.removeMapping(routerId);
1473 removeNaptSwitch(routerName);
1475 updateNaptSwitch(routerName, BigInteger.ZERO);
1478 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1479 naptManager.removeExternalCounter(routerId);
1480 } catch (Exception ex) {
1481 LOG.error("Exception while handling disableSNAT : {}", ex);
1483 LOG.info("NAT Service : handleDisableSnat() Exit");
1486 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1487 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1489 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1490 BigInteger naptSwitchDpnId = null;
1491 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1492 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1493 if (rtrToNapt.isPresent()) {
1494 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1496 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1498 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1500 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1501 } catch (Exception ex) {
1502 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1504 } catch (Exception ex) {
1505 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1507 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1510 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1511 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1512 .setPrimarySwitchId(naptSwitchId).build();
1514 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1515 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1516 } catch (Exception ex) {
1517 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1518 naptSwitchId,routerName);
1520 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1521 naptSwitchId,routerName);
1524 protected void removeNaptSwitch(String routerName){
1525 // Remove router and switch from model
1526 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1527 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1528 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1531 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1533 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1534 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1536 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1537 // traffic which comes from the VMs of the NAPT switches)
1538 String pSNatFlowRef = getFlowRefSnat(dpnId, NatConstants.PSNAT_TABLE, routerName);
1539 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.PSNAT_TABLE, pSNatFlowRef);
1541 LOG.info("NAT Service : Remove the flow in the " + NatConstants.PSNAT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1542 mdsalManager.removeFlow(pSNatFlowEntity);
1544 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1545 // traffic which comes from the VMs of the non NAPT switches)
1546 String tsFlowRef = getFlowRefTs(dpnId, NatConstants.TERMINATING_SERVICE_TABLE, routerId);
1547 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.TERMINATING_SERVICE_TABLE, tsFlowRef);
1549 LOG.info("NAT Service : Remove the flow in the " + NatConstants.TERMINATING_SERVICE_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1550 mdsalManager.removeFlow(tsNatFlowEntity);
1552 //Remove the Outbound flow entry which forwards the packet to FIB Table
1553 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
1554 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1556 LOG.info("NAT Service : Remove the flow in the " + NatConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1557 mdsalManager.removeFlow(outboundNatFlowEntity);
1559 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1560 String natPfibFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, routerId);
1561 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1563 LOG.info("NAT Service : Remove the flow in the " + NatConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1564 mdsalManager.removeFlow(natPfibFlowEntity);
1566 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1567 //Get the VPN ID from the ExternalNetworks model
1569 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1570 // ie called from router delete cases
1571 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1572 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1573 if(vpnUuid != null) {
1574 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1575 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1578 // ie called from disassociate vpn case
1579 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1580 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1581 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1584 if(vpnId != NatConstants.INVALID_ID){
1585 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1586 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, vpnId);
1587 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1588 LOG.info("NAT Service : Remove the flow in the " + NatConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
1589 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1592 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1593 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1594 if(ipPortMapping == null){
1595 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1599 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1600 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1601 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1602 for(IpPortMap ipPortMap : ipPortMaps){
1603 String ipPortInternal = ipPortMap.getIpPortInternal();
1604 String[] ipPortParts = ipPortInternal.split(":");
1605 if(ipPortParts.length != 2) {
1606 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1609 String internalIp = ipPortParts[0];
1610 String internalPort = ipPortParts[1];
1612 //Build the flow for the outbound NAPT table
1613 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1614 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1616 LOG.info("NAT Service : Remove the flow in the " + NatConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1617 mdsalManager.removeFlow(outboundNaptFlowEntity);
1619 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1620 String externalIp = ipPortExternal.getIpAddress();
1621 int externalPort = ipPortExternal.getPortNum();
1623 //Build the flow for the inbound NAPT table
1624 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1625 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1627 LOG.info("NAT Service : Remove the flow in the " + NatConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1628 mdsalManager.removeFlow(inboundNaptFlowEntity);
1633 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1635 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1636 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1638 //Remove the NAPT PFIB TABLE entry
1640 if(vpnName != null) {
1641 // ie called from disassociate vpn case
1642 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1643 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1644 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1647 if(vpnId != NatConstants.INVALID_ID){
1648 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1649 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, vpnId);
1650 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1651 LOG.info("NAT Service : Remove the flow in the " + NatConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
1652 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1654 // Remove IP-PORT active NAPT entries and release port from IdManager
1655 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1656 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1657 if(ipPortMapping == null){
1658 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1661 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1662 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1663 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1664 for(IpPortMap ipPortMap : ipPortMaps){
1665 String ipPortInternal = ipPortMap.getIpPortInternal();
1666 String[] ipPortParts = ipPortInternal.split(":");
1667 if(ipPortParts.length != 2) {
1668 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1671 String internalIp = ipPortParts[0];
1672 String internalPort = ipPortParts[1];
1674 //Build the flow for the outbound NAPT table
1675 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1676 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1678 LOG.info("NAT Service : Remove the flow in the " + NatConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1679 mdsalManager.removeFlow(outboundNaptFlowEntity);
1681 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1682 String externalIp = ipPortExternal.getIpAddress();
1683 int externalPort = ipPortExternal.getPortNum();
1685 //Build the flow for the inbound NAPT table
1686 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1687 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1689 LOG.info("NAT Service : Remove the flow in the " + NatConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1690 mdsalManager.removeFlow(inboundNaptFlowEntity);
1692 // Finally release port from idmanager
1693 String internalIpPort = internalIp +":"+internalPort;
1694 naptManager.removePortFromPool(internalIpPort, externalIp);
1696 //Remove sessions from models
1697 naptManager.removeIpPortMappingForRouterID(routerId);
1698 naptManager.removeIntIpPortMappingForRouterID(routerId);
1702 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1706 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1707 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1709 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1710 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1711 if(allSwitchList == null || allSwitchList.isEmpty()){
1712 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1715 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1716 for (BigInteger dpnId : allSwitchList) {
1717 if (!naptSwitchDpnId.equals(dpnId)) {
1718 LOG.info("NAT Service : Handle Ordinary switch");
1720 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1721 String pSNatFlowRef = getFlowRefSnat(dpnId, NatConstants.PSNAT_TABLE, String.valueOf(routerName));
1722 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.PSNAT_TABLE, pSNatFlowRef);
1724 LOG.info("Remove the flow in the " + NatConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1725 mdsalManager.removeFlow(pSNatFlowEntity);
1727 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1728 long groupId = createGroupId(getGroupIdKey(routerName));
1729 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
1730 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1732 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1733 mdsalManager.removeGroup(pSNatGroupEntity);
1739 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1740 //Withdraw the corresponding routes from the BGP.
1741 //Get the network ID using the router ID.
1742 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1743 externalIps,routerId,networkUuid, vpnName);
1744 if(networkUuid == null ){
1745 LOG.error("NAT Service : networkId is null");
1749 if (externalIps == null || externalIps.isEmpty()) {
1750 LOG.debug("NAT Service : externalIps is null");
1754 if(vpnName ==null) {
1755 //Get the VPN Name using the network ID
1756 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1757 if (vpnName == null) {
1758 LOG.error("No VPN associated with ext nw {} for the router {}",
1759 networkUuid, routerId);
1763 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1765 //Remove custom FIB routes
1766 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1767 for (String extIp : externalIps) {
1768 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1772 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1773 clearBgpRoutes(extIp,vpnName);
1774 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1777 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1778 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1780 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1781 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1785 final long label = tempLabel;
1786 final String externalIp = extIp;
1788 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1789 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1791 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1794 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1796 if (result.isSuccessful()) {
1797 removeTunnelTableEntry(dpnId, label);
1798 removeLFibTableEntry(dpnId, label);
1799 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1800 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1801 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1803 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1805 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1811 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1814 public void onFailure(Throwable error) {
1815 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1819 public void onSuccess(RpcResult<Void> result) {
1820 if (result.isSuccessful()) {
1821 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1823 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1829 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1830 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1831 //Get IPMaps from the DB for the router ID
1832 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1833 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1834 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1838 long tempLabel = NatConstants.INVALID_ID;
1839 for (IpMap dbIpMap : dbIpMaps) {
1840 String dbExternalIp = dbIpMap.getExternalIp();
1841 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1842 //Select the IPMap, whose external IP is the IP for which FIB is installed
1843 if (extIp.equals(dbExternalIp)) {
1844 tempLabel = dbIpMap.getLabel();
1845 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1849 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1850 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1854 final long label = tempLabel;
1855 final String externalIp = extIp;
1857 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1858 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1860 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1863 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1865 if (result.isSuccessful()) {
1866 removeTunnelTableEntry(dpnId, label);
1867 removeLFibTableEntry(dpnId, label);
1868 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1869 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1870 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1872 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1874 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1880 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1883 public void onFailure(Throwable error) {
1884 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1888 public void onSuccess(RpcResult<Void> result) {
1889 if (result.isSuccessful()) {
1890 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1892 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1898 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1899 //Withdraw the corresponding routes from the BGP.
1900 //Get the network ID using the router ID.
1901 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1902 externalIps,routerId,networkUuid, vpnName);
1903 if (networkUuid == null) {
1904 LOG.error("NAT Service : networkId is null");
1908 if (externalIps == null || externalIps.isEmpty()) {
1909 LOG.debug("NAT Service : externalIps is null");
1913 if (vpnName == null) {
1914 //Get the VPN Name using the network ID
1915 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1916 if (vpnName == null) {
1917 LOG.error("No VPN associated with ext nw {} for the router {}",
1918 networkUuid, routerId);
1922 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1924 //Remove custom FIB routes
1925 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1926 for (String extIp : externalIps) {
1927 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1931 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1932 //Inform BGP about the route removal
1933 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1934 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1935 NatUtil.removePrefixFromBGP(bgpManager, rd, externalIp, LOG);
1938 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1939 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1940 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1941 // Matching metadata
1942 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1943 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1944 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1945 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1946 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1947 mdsalManager.removeFlow(dpnId, flowEntity);
1948 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1951 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1952 List<MatchInfo> matches = new ArrayList<MatchInfo>();
1953 matches.add(new MatchInfo(MatchFieldType.eth_type,
1954 new long[] { 0x8847L }));
1955 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1957 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1959 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
1961 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1963 COOKIE_VM_LFIB_TABLE, matches, null);
1965 mdsalManager.removeFlow(dpnId, flowEntity);
1967 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
1970 protected InstanceIdentifier<Routers> getWildCardPath()
1972 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
1977 * router association to vpn
1980 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
1981 LOG.debug("NAT Service : Router associated to BGP VPN");
1982 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1983 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1985 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1987 if(bgpVpnId != NatConstants.INVALID_ID){
1988 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
1989 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
1990 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
1992 // Get the allocated Primary NAPT Switch for this router
1993 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1994 LOG.debug("Router ID value {} ", routerId);
1995 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1997 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
1998 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
2001 long groupId = createGroupId(getGroupIdKey(routerName));
2002 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2008 * router disassociation from vpn
2011 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2012 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2013 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2014 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2015 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2017 // Get the allocated Primary NAPT Switch for this router
2018 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2019 LOG.debug("Router ID value {} ", routerId);
2020 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2022 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2023 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2026 long groupId = createGroupId(getGroupIdKey(routerName));
2027 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2031 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2032 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2033 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2034 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2035 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2041 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2042 routerId, boolean isSnatCfgd){
2043 long changedVpnId = bgpVpnId;
2044 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2045 if (bgpVpnId == NatConstants.INVALID_ID){
2046 changedVpnId = routerId;
2047 logMsg = "NAT Service : Update the router ID {}";
2050 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2051 if (switches == null || switches.isEmpty()) {
2052 LOG.debug("No switches found for router {}",routerName);
2055 for(BigInteger dpnId : switches) {
2056 // Update the BGP VPN ID in the SNAT miss entry to group
2057 if( !dpnId.equals(primarySwitchId) ) {
2058 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2059 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2060 long groupId = createGroupId(getGroupIdKey(routerName));
2062 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2065 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2066 changedVpnId, groupId, dpnId);
2067 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2068 mdsalManager.installFlow(flowEntity);
2071 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2072 changedVpnId, primarySwitchId);
2073 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2074 mdsalManager.installFlow(flowEntity);
2076 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2077 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2078 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2080 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2081 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2082 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2084 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2085 changedVpnId, primarySwitchId);
2086 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2088 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2089 " in the Primary switch {}", changedVpnId, primarySwitchId);
2090 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2092 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2093 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2094 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2095 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2096 installNaptPfibEntry(primarySwitchId, vpnId);
2102 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2103 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2104 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2105 if(ipPortMapping == null){
2106 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2110 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2111 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2112 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2113 for(IpPortMap ipPortMap : ipPortMaps){
2114 String ipPortInternal = ipPortMap.getIpPortInternal();
2115 String[] ipPortParts = ipPortInternal.split(":");
2116 if(ipPortParts.length != 2) {
2117 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2120 String internalIp = ipPortParts[0];
2121 String internalPort = ipPortParts[1];
2123 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2124 NAPTEntryEvent.Protocol protocol;
2125 switch (protocolTypes){
2127 protocol = NAPTEntryEvent.Protocol.TCP;
2130 protocol = NAPTEntryEvent.Protocol.UDP;
2133 protocol = NAPTEntryEvent.Protocol.TCP;
2135 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2136 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2137 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2138 naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2139 internalAddress, externalAddress, protocol);
2140 naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2141 externalAddress, internalAddress, protocol);
2147 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2149 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2150 List<MatchInfo> matches = new ArrayList<>();
2151 matches.add(new MatchInfo(MatchFieldType.eth_type,
2152 new long[] { 0x0800L }));
2153 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2154 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2156 List<InstructionInfo> instructions = new ArrayList<>();
2157 List<ActionInfo> actionsInfo = new ArrayList<>();
2159 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2160 BigInteger.valueOf(changedVpnId)}) ;
2161 actionsInfo.add(actionSetField);
2162 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2163 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2164 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
2165 String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
2166 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
2167 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2168 NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
2170 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2174 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2176 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2177 List<MatchInfo> matches = new ArrayList<>();
2178 matches.add(new MatchInfo(MatchFieldType.eth_type,
2179 new long[] { 0x0800L }));
2180 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2181 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2183 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2184 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2185 { NatConstants.OUTBOUND_NAPT_TABLE }));
2187 String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
2188 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
2189 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2190 NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
2192 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2196 // TODO : Replace this with ITM Rpc once its available with full functionality
2197 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2198 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2199 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2200 mdsalManager.installFlow(flowEntity);
2204 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2205 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2206 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2207 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2208 List<MatchInfo> matches = new ArrayList<>();
2209 matches.add(new MatchInfo(MatchFieldType.eth_type,
2210 new long[] { 0x0800L }));
2211 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2213 List<InstructionInfo> instructions = new ArrayList<>();
2214 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2215 { bgpVpnIdAsBigInt, MetaDataUtil.METADATA_MASK_VRFID }));
2216 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2217 { NatConstants.OUTBOUND_NAPT_TABLE }));
2218 String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
2219 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
2220 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2221 NatConstants.COOKIE_TS_TABLE, matches, instructions);
2225 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2226 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2227 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2228 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2229 mdsalManager.installFlow(flowEntity);
2232 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2233 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2234 List<MatchInfo> matches = new ArrayList<>();
2235 matches.add(new MatchInfo(MatchFieldType.eth_type,
2236 new long[]{0x0800L}));
2237 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2238 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2240 List<InstructionInfo> instructions = new ArrayList<>();
2241 List<ActionInfo> actionsInfos = new ArrayList<>();
2242 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2243 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2244 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2246 String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
2247 BigInteger cookie = getCookieOutboundFlow(routerId);
2248 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
2250 cookie, matches, instructions);
2251 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2255 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2256 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2257 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2258 mdsalManager.installFlow(naptPfibFlowEntity);
2261 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2263 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2264 List<MatchInfo> matches = new ArrayList<>();
2265 matches.add(new MatchInfo(MatchFieldType.eth_type,
2266 new long[] { 0x0800L }));
2267 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2268 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2270 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2271 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2272 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
2273 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2275 String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
2276 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
2277 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2278 NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2280 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2285 protected ExternalRoutersListener getDataTreeChangeListener()
2287 return ExternalRoutersListener.this;