2 * Copyright (c) 2015 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.vpnservice.natservice.internal;
11 import java.math.BigInteger;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
16 import org.opendaylight.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.vpnservice.fib.rpc.rev160121.FibRpcService;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpPortMap;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ProtocolTypes;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.*;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.RemoveVpnLabelInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
42 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
43 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
44 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
45 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
46 import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
47 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
48 import org.opendaylight.vpnservice.mdsalutil.ActionType;
49 import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
50 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
51 import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
52 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
53 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
54 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
55 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
56 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
57 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
58 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
59 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInputBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.RouterIdName;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIds;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIdsBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIdsKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
96 import org.opendaylight.yangtools.concepts.ListenerRegistration;
97 import org.opendaylight.yangtools.yang.binding.DataObject;
98 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
99 import org.opendaylight.yangtools.yang.common.RpcResult;
100 import org.slf4j.Logger;
101 import org.slf4j.LoggerFactory;
103 import com.google.common.base.Optional;
104 import com.google.common.collect.Sets;
105 import com.google.common.collect.Sets.SetView;
106 import com.google.common.util.concurrent.AsyncFunction;
107 import com.google.common.util.concurrent.FutureCallback;
108 import com.google.common.util.concurrent.Futures;
109 import com.google.common.util.concurrent.JdkFutureAdapters;
110 import com.google.common.util.concurrent.ListenableFuture;
113 * Created by EYUGSAR on 2/20/2016.
116 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener>{
118 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
119 private static long label;
120 private ListenerRegistration<DataChangeListener> listenerRegistration;
121 private final DataBroker dataBroker;
122 private IMdsalApiManager mdsalManager;
123 private ItmRpcService itmManager;
124 private OdlInterfaceRpcService interfaceManager;
125 private IdManagerService idManager;
126 private NaptManager naptManager;
127 private NAPTSwitchSelector naptSwitchSelector;
128 private IBgpManager bgpManager;
129 private VpnRpcService vpnService;
130 private FibRpcService fibService;
131 private SNATDefaultRouteProgrammer defaultRouteProgrammer;
132 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
133 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
134 private NaptEventHandler naptEventHandler;
135 private NaptPacketInHandler naptPacketInHandler;
137 public void setNaptEventHandler(NaptEventHandler naptEventHandler) {
138 this.naptEventHandler = naptEventHandler;
141 public void setNaptPacketInHandler(NaptPacketInHandler naptPacketInHandler) {
142 this.naptPacketInHandler = naptPacketInHandler;
145 public void setMdsalManager(IMdsalApiManager mdsalManager) {
146 this.mdsalManager = mdsalManager;
149 public void setItmManager(ItmRpcService itmManager) {
150 this.itmManager = itmManager;
153 public void setIdManager(IdManagerService idManager) {
154 this.idManager = idManager;
158 void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
159 this.defaultRouteProgrammer = defaultRouteProgrammer;
163 public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
164 this.interfaceManager = interfaceManager;
167 public void setNaptManager(NaptManager naptManager) {
168 this.naptManager = naptManager;
171 public void setNaptSwitchSelector(NAPTSwitchSelector naptSwitchSelector) {
172 this.naptSwitchSelector = naptSwitchSelector;
175 public void setBgpManager(IBgpManager bgpManager) {
176 this.bgpManager = bgpManager;
179 public void setVpnService(VpnRpcService vpnService) {
180 this.vpnService = vpnService;
183 public void setFibService(FibRpcService fibService) {
184 this.fibService = fibService;
187 public ExternalRoutersListener(DataBroker dataBroker )
189 super( Routers.class, ExternalRoutersListener.class );
190 this.dataBroker = dataBroker;
194 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
196 LOG.info( "NAT Service : Add external router event for {}", routers.getRouterName() );
198 LOG.info("Installing NAT default route on all dpns part of router {}", routers.getRouterName());
199 addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
201 if( !routers.isEnableSnat()) {
202 LOG.info( "SNAT is disabled for external router {} ", routers.getRouterName());
206 // Populate the router-id-name container
207 String routerName = routers.getRouterName();
208 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
209 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
210 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
212 handleEnableSnat(routers);
215 public void handleEnableSnat(Routers routers){
216 String routerName = routers.getRouterName();
217 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
219 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
220 naptManager.initialiseExternalCounter(routers, segmentId);
222 // Allocate Primary Napt Switch for this router
223 BigInteger primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
224 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
225 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
226 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
228 LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
230 long bgpVpnId = NatConstants.INVALID_ID;
231 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
232 if(bgpVpnUuid != null){
233 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
235 if(bgpVpnId != NatConstants.INVALID_ID){
237 String bgpVpnName = bgpVpnUuid.getValue();
238 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
239 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
240 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
243 long routerId = NatUtil.getVpnId(dataBroker, routerName);
244 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
245 if(switches == null){
246 LOG.error("NAT Service : No DPNS associated for the router {}", routerName);
249 for (BigInteger dpnId : switches) {
250 // Handle switches and NAPT switches separately
251 if (!dpnId.equals(primarySwitchId)) {
252 LOG.debug("NAT Service : Install group in Ordinary switch {}", dpnId);
253 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
254 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
256 LOG.debug("NAT Service : Install group in Primary switch {}", dpnId);
257 List<BucketInfo> bucketInfoForNaptSwitches = getBucketInfoForPrimaryNaptSwitch();
258 groupId = installGroup(dpnId, routerName, bucketInfoForNaptSwitches);
260 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
261 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
262 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
263 installNaptPfibEntry(dpnId, vpnId);
267 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, bgpVpnId, routerId);
270 // write metadata and punt
271 installOutboundMissEntry(routerName, primarySwitchId);
272 // Now install entries in SNAT tables to point to Primary for each router
273 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
274 for (BigInteger dpnId : switches) {
275 // Handle switches and NAPT switches separately
276 if (!dpnId.equals(primarySwitchId)) {
277 LOG.debug("NAT Service : Handle Ordinary switch");
278 handleSwitches(dpnId, routerName, primarySwitchId);
280 LOG.debug("NAT Service : Handle NAPT switch");
281 handlePrimaryNaptSwitch(dpnId, routerName, primarySwitchId);
286 // call registerMapping Api
287 LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
289 List<Uuid> subnetList = null;
290 List<String> externalIps = null;
292 InstanceIdentifier<Routers> id = InstanceIdentifier
293 .builder(ExtRouters.class)
294 .child(Routers.class, new RoutersKey(routerName))
297 Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
299 if(extRouters.isPresent())
301 LOG.debug("NAT Service : Fetching values from extRouters model");
302 Routers routerEntry= extRouters.get();
303 subnetList = routerEntry.getSubnetIds();
304 externalIps = routerEntry.getExternalIps();
306 int extIpCounter = externalIps.size();
307 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
308 for(Uuid subnet : subnetList) {
309 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
310 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
311 .builder(Subnetmaps.class)
312 .child(Subnetmap.class, new SubnetmapKey(subnet))
314 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
317 Subnetmap subnetmapEntry = sn.get();
318 String subnetString = subnetmapEntry.getSubnetIp();
319 String[] subnetSplit = subnetString.split("/");
320 String subnetIp = subnetSplit[0];
321 String subnetPrefix = "0";
322 if(subnetSplit.length == 2) {
323 subnetPrefix = subnetSplit[1];
325 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
326 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
328 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
329 if(extIpCounter != 0) {
330 if(counter < extIpCounter) {
331 String[] IpSplit = externalIps.get(counter).split("/");
332 String externalIp = IpSplit[0];
333 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
334 if(IpSplit.length==2) {
335 extPrefix = IpSplit[1];
337 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
338 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
339 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
340 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
341 externalIp, extPrefix);
343 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
344 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
345 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
348 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
349 LOG.debug("NAT Service : Counter on externalIps got reset");
350 String[] IpSplit = externalIps.get(counter).split("/");
351 String externalIp = IpSplit[0];
352 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
353 if(IpSplit.length==2) {
354 extPrefix = IpSplit[1];
356 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
357 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
358 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
359 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
360 externalIp, extPrefix);
362 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
363 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
364 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
369 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
372 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
377 LOG.info("NAT Service : handleEnableSnat() Exit");
380 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
381 //Check if BGP VPN exists. If exists then invoke the new method.
382 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
383 if(bgpVpnId != NatConstants.INVALID_ID) {
384 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
388 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
389 addOrDelDefaultFibRouteForSNAT(routerName, create);
390 /* InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(routerName);
391 Optional<VpnInstanceOpDataEntry> vpnInstOp = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
392 if (vpnInstOp.isPresent()) {
393 addOrDelDefaultFibRouteForSNAT(routerName, create);
395 //Check if this router is associated with any external VPN
396 LOG.debug("Checking if router {} is associated with BGP VPN", routerName);
397 Uuid vpnId = NatUtil.getVpnForRouter(dataBroker, routerName);
399 String vpnName = vpnId.getValue();
400 LOG.debug("Router {} is associated with VPN {}", routerName, vpnName);
401 InstanceIdentifier<VpnInstanceOpDataEntry> vid = NatUtil.getVpnInstanceOpDataIdentifier(vpnName);
402 vpnInstOp = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, vid);
403 if (vpnInstOp.isPresent()) {
404 addOrDelDefaultFibRouteForSNAT(routerName, vpnInstOp.get(), create);
410 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
412 List<VpnToDpnList> dpnListInVpn = vpnInstOp.getVpnToDpnList();
413 List<BigInteger> switches = new ArrayList<>();
414 if(dpnListInVpn == null || dpnListInVpn.isEmpty()) {
415 LOG.debug("NAT Service : Unable to get the switches for the router {} from the VPNInstanceOpData", routerName);
416 switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
417 if(switches == null || switches.isEmpty()){
418 LOG.error("NAT Service : addOrDelDefaultFibRouteForSNAT : NO SWITCHES ARE PART OF ROUTER {}", routerName);
422 for (VpnToDpnList dpn : dpnListInVpn) {
423 switches.add(dpn.getDpnId());
427 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
428 long routerId = NatUtil.readVpnId(dataBroker, routerName);
429 if(routerId == NatConstants.INVALID_ID) {
430 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
433 for (BigInteger dpnId : switches) {
434 if (create == true) {
435 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
437 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
442 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
443 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
444 if(dpnIds == null || dpnIds.isEmpty()) {
445 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
448 long routerId = NatUtil.getVpnId(dataBroker, routerName);
449 for (BigInteger dpnId : dpnIds) {
450 if (create == true) {
451 if(bgpVpnId != NatConstants.INVALID_ID) {
452 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
454 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
457 if(bgpVpnId != NatConstants.INVALID_ID) {
458 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
460 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
466 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
468 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
470 Optional<T> result = Optional.absent();
473 result = tx.read(datastoreType, path).get();
477 throw new RuntimeException(e);
483 public void close() throws Exception
485 if (listenerRegistration != null)
489 listenerRegistration.close();
491 catch (final Exception e)
493 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
496 listenerRegistration = null;
498 LOG.debug("ExternalRoutersListener Closed");
501 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
502 long routerId = NatUtil.getVpnId(dataBroker, routerName);
503 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
504 if(routerId != NatConstants.INVALID_ID) {
505 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
506 createOutboundTblEntry(primarySwitchId, routerId);
508 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
512 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
513 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
514 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
517 public BigInteger getCookieOutboundFlow(long routerId) {
518 return NatConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
519 BigInteger.valueOf(routerId));
522 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
523 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
524 List<MatchInfo> matches = new ArrayList<MatchInfo>();
525 matches.add(new MatchInfo(MatchFieldType.eth_type,
526 new long[] { 0x0800L }));
527 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
528 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
530 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
531 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
532 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
533 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
534 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
536 String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
537 BigInteger cookie = getCookieOutboundFlow(routerId);
538 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
540 cookie, matches, instructions);
541 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
545 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
546 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
547 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
548 LOG.debug("NAT Service : Installing flow {}", flowEntity);
549 mdsalManager.installFlow(flowEntity);
552 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
553 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
554 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
556 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
557 .setSourceDpid(srcDpId)
558 .setDestinationDpid(dstDpId)
559 // .setTunnelType(tunType)
561 rpcResult = result.get();
562 if(!rpcResult.isSuccessful()) {
563 tunType = TunnelTypeGre.class ;
564 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
565 .setSourceDpid(srcDpId)
566 .setDestinationDpid(dstDpId)
567 // .setTunnelType(tunType)
569 rpcResult = result.get();
570 if(!rpcResult.isSuccessful()) {
571 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
573 return rpcResult.getResult().getInterfaceName();
575 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
577 return rpcResult.getResult().getInterfaceName();
579 } catch (InterruptedException | ExecutionException | NullPointerException e) {
580 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
586 protected List<ActionInfo> getEgressActionsForInterface(String ifName, long routerId) {
587 LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
588 List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
590 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
591 interfaceManager.getEgressActionsForInterface(
592 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(routerId).build());
593 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
594 if(!rpcResult.isSuccessful()) {
595 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
597 List<Action> actions =
598 rpcResult.getResult().getAction();
599 for (Action action : actions) {
600 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
601 if (actionClass instanceof OutputActionCase) {
602 listActionInfo.add(new ActionInfo(ActionType.output,
603 new String[] {((OutputActionCase)actionClass).getOutputAction()
604 .getOutputNodeConnector().getValue()}));
605 } else if (actionClass instanceof PushVlanActionCase) {
606 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
607 } else if (actionClass instanceof SetFieldCase) {
608 if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
609 int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
610 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
611 new String[] { Long.toString(vlanVid) }));
616 } catch (InterruptedException | ExecutionException e) {
617 LOG.warn("Exception when egress actions for interface {}", ifName, e);
619 return listActionInfo;
622 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
623 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
624 // Install the select group
625 long groupId = createGroupId(getGroupIdKey(routerName));
626 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
627 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
628 mdsalManager.installGroup(groupEntity);
629 // Install miss entry pointing to group
630 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
631 mdsalManager.installFlow(flowEntity);
634 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
635 long groupId = createGroupId(getGroupIdKey(routerName));
636 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
637 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
638 mdsalManager.installGroup(groupEntity);
642 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
644 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
645 long routerId = NatUtil.getVpnId(dataBroker, routerName);
646 List<MatchInfo> matches = new ArrayList<MatchInfo>();
647 matches.add(new MatchInfo(MatchFieldType.eth_type,
648 new long[] { 0x0800L }));
649 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
650 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
653 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
654 List<ActionInfo> actionsInfo = new ArrayList<ActionInfo>();
656 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
657 BigInteger.valueOf(routerId)}) ;
658 actionsInfo.add(actionSetField);
659 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
660 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
661 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
662 String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
663 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
664 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
665 NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
667 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
671 // TODO : Replace this with ITM Rpc once its available with full functionality
672 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
673 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
674 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
675 mdsalManager.installFlow(flowEntity);
679 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
681 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
682 List<MatchInfo> matches = new ArrayList<MatchInfo>();
683 matches.add(new MatchInfo(MatchFieldType.eth_type,
684 new long[] { 0x0800L }));
685 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
687 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
688 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
689 { routerId, MetaDataUtil.METADATA_MASK_VRFID }));
690 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
691 { NatConstants.OUTBOUND_NAPT_TABLE }));
692 String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
693 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
694 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
695 NatConstants.COOKIE_TS_TABLE, matches, instructions);
699 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
700 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
701 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
704 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
705 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
706 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
709 private String getGroupIdKey(String routerName){
710 String groupIdKey = new String("snatmiss." + routerName);
714 protected long createGroupId(String groupIdKey) {
715 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
716 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
719 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
720 RpcResult<AllocateIdOutput> rpcResult = result.get();
721 return rpcResult.getResult().getIdValue();
722 } catch (NullPointerException | InterruptedException | ExecutionException e) {
728 protected void createGroupIdPool() {
729 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
730 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
731 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
732 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
735 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
736 if ((result != null) && (result.get().isSuccessful())) {
737 LOG.debug("NAT Service : Created GroupIdPool");
739 LOG.error("NAT Service : Unable to create GroupIdPool");
741 } catch (InterruptedException | ExecutionException e) {
742 LOG.error("Failed to create PortPool for NAPT Service",e);
746 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
747 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
748 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
749 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
750 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
751 long routerId = NatUtil.getVpnId(dataBroker, routerName);
753 if(ifNamePrimary != null) {
754 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
755 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
757 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
759 listBucketInfo.add(0, bucketPrimary);
760 installSnatMissEntry(dpnId, listBucketInfo, routerName);
763 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
764 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
765 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
766 List<BucketInfo> listBucketInfo = new ArrayList<>();
767 long routerId = NatUtil.getVpnId(dataBroker, routerName);
769 if (ifNamePrimary != null) {
770 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
771 listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
773 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
775 listBucketInfo.add(0, bucketPrimary);
776 return listBucketInfo;
778 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
781 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
784 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
786 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
787 List<ActionInfo> listActionInfoPrimary = new ArrayList<ActionInfo>();
788 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
789 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
790 listBucketInfo.add(0, bucketPrimary);
792 long routerId = NatUtil.getVpnId(dataBroker, routerName);
794 installSnatMissEntry(dpnId, listBucketInfo, routerName);
795 installTerminatingServiceTblEntry(dpnId, routerName);
796 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
797 installNaptPfibEntry(dpnId, routerId);
798 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
799 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
800 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
801 installNaptPfibEntry(dpnId, vpnId);
805 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
806 List<BucketInfo> listBucketInfo = new ArrayList<>();
807 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
808 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
809 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
810 listBucketInfo.add(0, bucketPrimary);
811 return listBucketInfo;
814 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
815 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
816 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
817 mdsalManager.installFlow(naptPfibFlowEntity);
820 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
822 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
823 List<MatchInfo> matches = new ArrayList<MatchInfo>();
824 matches.add(new MatchInfo(MatchFieldType.eth_type,
825 new long[] { 0x0800L }));
826 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
827 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
829 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
830 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
831 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
832 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
834 String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
835 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
836 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
837 NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
839 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
843 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
844 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
845 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
846 if(networkId == null) {
847 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
850 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
851 if(vpnName == null) {
852 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
853 networkId, externalIp, routerId);
856 advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
857 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
860 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
861 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
863 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
864 //Generate VPN label for the external IP
865 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
866 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
868 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
869 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
872 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
873 if (result.isSuccessful()) {
874 LOG.debug("NAT Service : inside apply with result success");
875 GenerateVpnLabelOutput output = result.getResult();
876 long label = output.getLabel();
879 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
880 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
881 NatUtil.addPrefixToBGP(bgpManager, rd, externalIp, nextHopIp, label, log);
883 //Get IPMaps from the DB for the router ID
884 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
885 if (dbIpMaps != null) {
886 for (IpMap dbIpMap : dbIpMaps) {
887 String dbExternalIp = dbIpMap.getExternalIp();
888 //Select the IPMap, whose external IP is the IP for which FIB is installed
889 if (externalIp.equals(dbExternalIp)) {
890 String dbInternalIp = dbIpMap.getInternalIp();
891 IpMapKey dbIpMapKey = dbIpMap.getKey();
892 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
893 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
894 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
899 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
902 //Install custom FIB routes
903 List<Instruction> customInstructions = new ArrayList<>();
904 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
905 makeTunnelTableEntry(dpnId, label, customInstructions);
906 makeLFibTableEntry(dpnId, label, tableId);
908 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
909 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
910 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
911 return JdkFutureAdapters.listenInPoolThread(future);
913 LOG.error("NAT Service : inside apply with result failed");
914 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
915 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
920 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
923 public void onFailure(Throwable error) {
924 log.error("NAT Service : Error in generate label or fib install process", error);
928 public void onSuccess(RpcResult<Void> result) {
929 if (result.isSuccessful()) {
930 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
932 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
938 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
939 List<MatchInfo> matches = new ArrayList<MatchInfo>();
940 matches.add(new MatchInfo(MatchFieldType.eth_type,
941 new long[]{0x8847L}));
942 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
944 List<Instruction> instructions = new ArrayList<Instruction>();
945 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
946 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
947 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
948 instructions.add(writeInstruction);
949 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
951 // Install the flow entry in L3_LFIB_TABLE
952 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
954 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
956 COOKIE_VM_LFIB_TABLE, matches, instructions);
958 mdsalManager.installFlow(dpId, flowEntity);
960 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
963 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
964 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
966 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
968 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
970 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
971 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
972 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
974 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
977 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
978 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
979 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
983 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
984 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
985 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
986 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
990 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
991 String routerName = original.getRouterName();
992 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
993 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
994 Uuid networkId = original.getNetworkId();
996 // Check if its update on SNAT flag
997 boolean originalSNATEnabled = original.isEnableSnat();
998 boolean updatedSNATEnabled = update.isEnableSnat();
999 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1000 if(originalSNATEnabled != updatedSNATEnabled) {
1001 if(originalSNATEnabled) {
1002 //SNAT disabled for the router
1003 Uuid networkUuid = original.getNetworkId();
1004 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1005 if (routerId == NatConstants.INVALID_ID) {
1006 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1009 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1010 handleDisableSnat(routerName, networkUuid, externalIps, false, null);
1012 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1013 handleEnableSnat(original);
1017 //Check if the Update is on External IPs
1018 LOG.debug("NAT Service : Checking if this is update on External IPs");
1019 List<String> originalExternalIpsList = original.getExternalIps();
1020 List<String> updatedExternalIpsList = update.getExternalIps();
1021 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1022 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1024 //Check if the External IPs are added during the update.
1025 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1026 if(addedExternalIps.size() != 0) {
1027 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1028 for (String addedExternalIp : addedExternalIps) {
1030 1) Do nothing in the IntExtIp model.
1031 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1033 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1034 String externalIp = externalIpParts[0];
1035 String externalIpPrefix = externalIpParts[1];
1036 String externalpStr = externalIp + "/" + externalIpPrefix;
1037 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1038 externalpStr, routerId);
1039 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1041 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1044 //Check if the External IPs are removed during the update.
1045 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1046 if(removedExternalIps.size() > 0) {
1047 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1048 List<String> removedExternalIpsAsList = new ArrayList<>();
1049 for (String removedExternalIp : removedExternalIps) {
1051 1) Remove the mappings in the IntExt IP model which has external IP.
1052 2) Remove the external IP in the ExternalCounter model.
1053 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1054 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1055 4) Increase the count of the allocated external IP by one.
1056 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.
1057 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1058 7) Advertise to the BGP for removing the route for the removed external IPs.
1061 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1062 String externalIp = externalIpParts[0];
1063 String externalIpPrefix = externalIpParts[1];
1064 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1066 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1067 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1068 String vpnName = "";
1069 if(vpnUuId != null){
1070 vpnName = vpnUuId.getValue();
1072 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1074 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1075 //Get the internal IPs which are associated to the removed external IPs
1076 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1077 List<String> removedInternalIps = new ArrayList<>();
1078 for(IpMap ipMap : ipMaps){
1079 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1080 removedInternalIps.add(ipMap.getInternalIp());
1084 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1085 for(String removedInternalIp : removedInternalIps){
1086 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1087 removedInternalIp, routerId);
1088 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1091 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1092 externalIpAddrStr, routerId );
1093 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1094 removedExternalIpsAsList.add(externalIpAddrStr);
1096 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1097 for(String removedInternalIp : removedInternalIps) {
1098 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1101 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1102 //Get the internalIP and internal Port which were associated to the removed external IP.
1103 List<Integer> externalPorts = new ArrayList<>();
1104 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1105 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1106 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1107 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1108 if (ipPortMapping.isPresent()) {
1109 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1110 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1111 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1112 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1113 for(IpPortMap ipPortMap : ipPortMaps){
1114 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1115 if(ipPortExternal.getIpAddress().equals(externalIp)){
1116 externalPorts.add(ipPortExternal.getPortNum());
1117 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1118 if(removedInternalIpPorts != null){
1119 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1120 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1122 removedInternalIpPorts = new ArrayList<>();
1123 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1124 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1131 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1132 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1133 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1134 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1135 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1136 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1137 for(String removedInternalIpPort : removedInternalIpPorts){
1138 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1139 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1140 //Remove the IP port incomint packer map.
1141 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1142 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1143 if(removedInternalIpPortParts.length == 2){
1144 String removedInternalIp = removedInternalIpPortParts[0];
1145 String removedInternalPort = removedInternalIpPortParts[1];
1146 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1147 if (removedInternalPortsList != null){
1148 removedInternalPortsList.add(removedInternalPort);
1149 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1151 removedInternalPortsList = new ArrayList<>();
1152 removedInternalPortsList.add(removedInternalPort);
1153 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1159 // Delete the entry from SnatIntIpPortMap DS
1160 Set<String> internalIps = internalIpPortMap.keySet();
1161 for(String internalIp : internalIps){
1162 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1163 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1166 naptManager.removeNaptPortPool(externalIp);
1168 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1169 for(Integer externalPort : externalPorts) {
1170 //Remove the NAPT translation entries from Inbound NAPT table
1171 naptEventHandler.removeNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1174 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1175 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1176 String internalIp = internalIpPort.getKey();
1177 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1178 List<String> internalPorts = internalIpPort.getValue();
1179 for(String internalPort : internalPorts){
1180 //Remove the NAPT translation entries from Outbound NAPT table
1181 naptEventHandler.removeNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1185 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1188 //Check if its Update on subnets
1189 LOG.debug("NAT Service : Checking if this is update on subnets");
1190 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1191 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1192 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1193 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1194 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1196 //Check if the Subnet IDs are added during the update.
1197 if(addedSubnetIds.size() != 0){
1198 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1199 for(Uuid addedSubnetId : addedSubnetIds){
1201 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.
1202 2) Increase the count of the selected external IP by one.
1203 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.
1205 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1206 if(subnetIp != null) {
1207 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1210 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1213 //Check if the Subnet IDs are removed during the update.
1214 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1215 if(removedSubnetIds.size() != 0){
1216 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1217 for(Uuid removedSubnetId : removedSubnetIds){
1218 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1219 if(subnetAddr != null){
1221 1) Remove the subnet IP and the external IP in the IntExtIp map
1222 2) Decrease the count of the coresponding external IP by one.
1223 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1225 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {}", routerId, subnetAddr[0]);
1226 naptManager.removeFromIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1229 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1233 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1234 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1235 if (leastLoadedExtIpAddr != null) {
1236 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1237 String leastLoadedExtIp = externalIpParts[0];
1238 String leastLoadedExtIpPrefix = externalIpParts[1];
1239 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1240 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1241 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1242 subnetIp = subnetIpParts[0];
1243 String subnetIpPrefix = subnetIpParts[1];
1244 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1245 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1246 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1247 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1250 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1251 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1252 if(checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr)){
1256 //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.
1257 //Get the VPN Name using the network ID
1258 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1259 if (vpnName != null) {
1260 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1261 advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1262 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1267 private boolean checkExternalIpLabel(long routerId, String externalIp){
1268 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1269 for(IpMap ipMap : ipMaps){
1270 if(ipMap.getExternalIp().equals(externalIp)){
1271 if (ipMap.getLabel() != null){
1280 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1281 LOG.trace("NAT Service : Router delete method");
1284 ROUTER DELETE SCENARIO
1285 1) Get the router ID from the event.
1286 2) Build the cookie information from the router ID.
1287 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1288 4) Build the flow with the cookie value.
1289 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1290 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1291 7) Get the list of external IP address maintained for the router ID.
1292 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1293 9) Withdraw the corresponding routes from the BGP.
1296 if (identifier == null || router == null) {
1297 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1301 String routerName = router.getRouterName();
1302 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1303 addOrDelDefFibRouteToSNAT(routerName, false);
1304 Uuid networkUuid = router.getNetworkId();
1305 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1306 if (routerId == NatConstants.INVALID_ID) {
1307 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1310 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1311 handleDisableSnat(routerName, networkUuid, externalIps, true, null);
1315 public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1316 LOG.info("NAT Service : handleDisableSnat() Entry");
1318 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1320 BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1321 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1322 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1323 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1326 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1327 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1329 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1330 } catch (Exception ex) {
1331 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1334 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1335 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1336 naptManager.removeMapping(routerId);
1339 removeNaptSwitch(routerName);
1341 updateNaptSwitch(routerName, BigInteger.ZERO);
1344 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1345 naptManager.removeExternalCounter(routerId);
1346 } catch (Exception ex) {
1347 LOG.error("Exception while handling disableSNAT : {}", ex);
1349 LOG.info("NAT Service : handleDisableSnat() Exit");
1352 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1353 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1355 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1356 BigInteger naptSwitchDpnId = null;
1357 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1358 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch);
1359 if (rtrToNapt.isPresent()) {
1360 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1362 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1364 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1366 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1367 } catch (Exception ex) {
1368 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1370 } catch (Exception ex) {
1371 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1373 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1376 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1377 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1378 .setPrimarySwitchId(naptSwitchId).build();
1380 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
1381 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1382 } catch (Exception ex) {
1383 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1384 naptSwitchId,routerName);
1386 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1387 naptSwitchId,routerName);
1390 protected void removeNaptSwitch(String routerName){
1391 // Remove router and switch from model
1392 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1393 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1394 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1397 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1399 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1400 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1402 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1403 String pSNatFlowRef = getFlowRefSnat(dpnId, NatConstants.PSNAT_TABLE, routerName);
1404 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.PSNAT_TABLE, pSNatFlowRef);
1406 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);
1407 mdsalManager.removeFlow(pSNatFlowEntity);
1409 //Remove the group entry which resubmits the packet to the Terminating Service table or to the out port accordingly.
1410 long groupId = createGroupId(getGroupIdKey(routerName));
1411 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
1412 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1414 LOG.info("NAT Service : Remove the group {} for the active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1415 mdsalManager.removeGroup(pSNatGroupEntity);
1417 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
1418 String tsFlowRef = getFlowRefTs(dpnId, NatConstants.TERMINATING_SERVICE_TABLE, routerId);
1419 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.TERMINATING_SERVICE_TABLE, tsFlowRef);
1421 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);
1422 mdsalManager.removeFlow(tsNatFlowEntity);
1424 //Remove the Outbound flow entry which forwards the packet to FIB Table
1425 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
1426 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1428 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);
1429 mdsalManager.removeFlow(outboundNatFlowEntity);
1431 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1432 String natPfibFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, routerId);
1433 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1435 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);
1436 mdsalManager.removeFlow(natPfibFlowEntity);
1438 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1439 //Get the VPN ID from the ExternalNetworks model
1441 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1442 // ie called from router delete cases
1443 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1444 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1445 if(vpnUuid != null) {
1446 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1447 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1450 // ie called from disassociate vpn case
1451 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1452 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1453 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1456 if(vpnId != NatConstants.INVALID_ID){
1457 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1458 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, vpnId);
1459 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1460 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);
1461 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1464 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1465 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1466 if(ipPortMapping == null){
1467 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1471 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1472 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1473 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1474 for(IpPortMap ipPortMap : ipPortMaps){
1475 String ipPortInternal = ipPortMap.getIpPortInternal();
1476 String[] ipPortParts = ipPortInternal.split(":");
1477 if(ipPortParts.length != 2) {
1478 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1481 String internalIp = ipPortParts[0];
1482 String internalPort = ipPortParts[1];
1484 //Build the flow for the outbound NAPT table
1485 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1486 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1488 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);
1489 mdsalManager.removeFlow(outboundNaptFlowEntity);
1491 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1492 String externalIp = ipPortExternal.getIpAddress();
1493 int externalPort = ipPortExternal.getPortNum();
1495 //Build the flow for the inbound NAPT table
1496 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1497 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1499 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);
1500 mdsalManager.removeFlow(inboundNaptFlowEntity);
1505 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1507 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1508 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1510 //Remove the NAPT PFIB TABLE entry
1512 if(vpnName != null) {
1513 // ie called from disassociate vpn case
1514 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1515 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1516 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1519 if(vpnId != NatConstants.INVALID_ID){
1520 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1521 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, vpnId);
1522 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1523 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);
1524 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1526 // Remove IP-PORT active NAPT entries and release port from IdManager
1527 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1528 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1529 if(ipPortMapping == null){
1530 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1533 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1534 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1535 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1536 for(IpPortMap ipPortMap : ipPortMaps){
1537 String ipPortInternal = ipPortMap.getIpPortInternal();
1538 String[] ipPortParts = ipPortInternal.split(":");
1539 if(ipPortParts.length != 2) {
1540 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1543 String internalIp = ipPortParts[0];
1544 String internalPort = ipPortParts[1];
1546 //Build the flow for the outbound NAPT table
1547 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1548 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1550 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);
1551 mdsalManager.removeFlow(outboundNaptFlowEntity);
1553 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1554 String externalIp = ipPortExternal.getIpAddress();
1555 int externalPort = ipPortExternal.getPortNum();
1557 //Build the flow for the inbound NAPT table
1558 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1559 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1561 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);
1562 mdsalManager.removeFlow(inboundNaptFlowEntity);
1564 // Finally release port from idmanager
1565 String internalIpPort = internalIp +":"+internalPort;
1566 naptManager.removePortFromPool(internalIpPort, externalIp);
1568 //Remove sessions from models
1569 naptManager.removeIpPortMappingForRouterID(routerId);
1570 naptManager.removeIntIpPortMappingForRouterID(routerId);
1574 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1578 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1579 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1581 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1582 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1583 if(allSwitchList == null || allSwitchList.isEmpty()){
1584 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1587 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1588 for (BigInteger dpnId : allSwitchList) {
1589 if (!naptSwitchDpnId.equals(dpnId)) {
1590 LOG.info("NAT Service : Handle Ordinary switch");
1592 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1593 String pSNatFlowRef = getFlowRefSnat(dpnId, NatConstants.PSNAT_TABLE, String.valueOf(routerName));
1594 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.PSNAT_TABLE, pSNatFlowRef);
1596 LOG.info("Remove the flow in the " + NatConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1597 mdsalManager.removeFlow(pSNatFlowEntity);
1599 //Remove the group entry which resubmits the packet to the Terminating Service table or to the out port accordingly.
1600 long groupId = createGroupId(getGroupIdKey(routerName));
1601 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
1602 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1604 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1605 mdsalManager.removeGroup(pSNatGroupEntity);
1611 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1612 //Withdraw the corresponding routes from the BGP.
1613 //Get the network ID using the router ID.
1614 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1615 externalIps,routerId,networkUuid, vpnName);
1616 if(networkUuid == null ){
1617 LOG.error("NAT Service : networkId is null");
1621 if (externalIps == null || externalIps.isEmpty()) {
1622 LOG.debug("NAT Service : externalIps is null");
1626 if(vpnName ==null) {
1627 //Get the VPN Name using the network ID
1628 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1629 if (vpnName == null) {
1630 LOG.error("No VPN associated with ext nw {} for the router {}",
1631 networkUuid, routerId);
1635 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1637 //Remove custom FIB routes
1638 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1639 for (String extIp : externalIps) {
1640 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1644 private void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName){
1645 //Inform BGP about the route removal
1646 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1647 NatUtil.removePrefixFromBGP(bgpManager, rd, extIp, LOG);
1649 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1650 //Get IPMaps from the DB for the router ID
1651 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1652 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1653 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1657 long tempLabel = NatConstants.INVALID_ID;
1658 for (IpMap dbIpMap : dbIpMaps) {
1659 String dbExternalIp = dbIpMap.getExternalIp();
1660 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1661 //Select the IPMap, whose external IP is the IP for which FIB is installed
1662 if (extIp.equals(dbExternalIp)) {
1663 tempLabel = dbIpMap.getLabel();
1664 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1668 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1669 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1673 final long label = tempLabel;
1674 final String externalIp = extIp;
1676 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1677 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1679 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1682 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1684 if (result.isSuccessful()) {
1685 removeTunnelTableEntry(dpnId, label);
1686 removeLFibTableEntry(dpnId, label);
1687 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1688 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1689 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1691 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1693 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1699 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1702 public void onFailure(Throwable error) {
1703 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1707 public void onSuccess(RpcResult<Void> result) {
1708 if (result.isSuccessful()) {
1709 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1711 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1717 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1718 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1719 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1720 // Matching metadata
1721 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1722 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1723 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1724 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1725 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1726 mdsalManager.removeFlow(dpnId, flowEntity);
1727 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1730 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1731 List<MatchInfo> matches = new ArrayList<MatchInfo>();
1732 matches.add(new MatchInfo(MatchFieldType.eth_type,
1733 new long[] { 0x8847L }));
1734 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1736 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1738 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
1740 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1742 COOKIE_VM_LFIB_TABLE, matches, null);
1744 mdsalManager.removeFlow(dpnId, flowEntity);
1746 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
1749 protected InstanceIdentifier<Routers> getWildCardPath()
1751 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
1756 * router association to vpn
1759 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
1760 LOG.debug("NAT Service : Router associated to BGP VPN");
1761 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1762 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1764 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1766 if(bgpVpnId != NatConstants.INVALID_ID){
1767 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
1768 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
1769 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
1771 // Get the allocated Primary NAPT Switch for this router
1772 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1773 LOG.debug("Router ID value {} ", routerId);
1774 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1776 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
1777 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
1780 long groupId = createGroupId(getGroupIdKey(routerName));
1781 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, bgpVpnId, routerId);
1787 * router disassociation from vpn
1790 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
1791 LOG.debug("NAT Service : Router dissociated from BGP VPN");
1792 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1793 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1794 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1796 // Get the allocated Primary NAPT Switch for this router
1797 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1798 LOG.debug("Router ID value {} ", routerId);
1799 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1801 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
1802 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
1805 long groupId = createGroupId(getGroupIdKey(routerName));
1806 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, NatConstants.INVALID_ID, routerId);
1810 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
1811 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
1812 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
1813 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
1814 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
1820 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long groupId, long bgpVpnId, long routerId){
1821 long changedVpnId = bgpVpnId;
1822 String logMsg = "NAT Service : Update the BGP VPN ID {}";
1823 if (bgpVpnId == NatConstants.INVALID_ID){
1824 changedVpnId = routerId;
1825 logMsg = "NAT Service : Update the router ID {}";
1828 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
1829 changedVpnId, groupId, primarySwitchId);
1830 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(primarySwitchId, routerName, groupId, changedVpnId);
1831 mdsalManager.installFlow(flowEntity);
1833 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
1834 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
1835 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
1837 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
1838 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
1839 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
1841 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
1842 changedVpnId, primarySwitchId);
1843 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
1845 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
1846 " in the Primary switch {}", changedVpnId, primarySwitchId);
1847 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
1849 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
1850 for(BigInteger dpnId : switches) {
1851 // Update the BGP VPN ID in the SNAT miss entry to group
1852 if( !dpnId.equals(primarySwitchId) ) {
1853 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
1854 changedVpnId, groupId, dpnId);
1855 flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
1856 mdsalManager.installFlow(flowEntity);
1861 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
1862 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1863 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1864 if(ipPortMapping == null){
1865 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1869 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1870 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1871 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1872 for(IpPortMap ipPortMap : ipPortMaps){
1873 String ipPortInternal = ipPortMap.getIpPortInternal();
1874 String[] ipPortParts = ipPortInternal.split(":");
1875 if(ipPortParts.length != 2) {
1876 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1879 String internalIp = ipPortParts[0];
1880 String internalPort = ipPortParts[1];
1882 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
1883 NAPTEntryEvent.Protocol protocol;
1884 switch (protocolTypes){
1886 protocol = NAPTEntryEvent.Protocol.TCP;
1889 protocol = NAPTEntryEvent.Protocol.UDP;
1892 protocol = NAPTEntryEvent.Protocol.TCP;
1894 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
1895 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
1896 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
1897 naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
1898 internalAddress, externalAddress, protocol);
1899 naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
1900 externalAddress, internalAddress, protocol);
1906 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
1908 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
1909 List<MatchInfo> matches = new ArrayList<>();
1910 matches.add(new MatchInfo(MatchFieldType.eth_type,
1911 new long[] { 0x0800L }));
1912 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1913 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
1915 List<InstructionInfo> instructions = new ArrayList<>();
1916 List<ActionInfo> actionsInfo = new ArrayList<>();
1918 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
1919 BigInteger.valueOf(changedVpnId)}) ;
1920 actionsInfo.add(actionSetField);
1921 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
1922 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
1923 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
1924 String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
1925 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
1926 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
1927 NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
1929 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
1933 // TODO : Replace this with ITM Rpc once its available with full functionality
1934 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
1935 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
1936 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
1937 mdsalManager.installFlow(flowEntity);
1941 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
1942 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
1943 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
1944 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
1945 List<MatchInfo> matches = new ArrayList<>();
1946 matches.add(new MatchInfo(MatchFieldType.eth_type,
1947 new long[] { 0x0800L }));
1948 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
1950 List<InstructionInfo> instructions = new ArrayList<>();
1951 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
1952 { bgpVpnIdAsBigInt, MetaDataUtil.METADATA_MASK_VRFID }));
1953 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
1954 { NatConstants.OUTBOUND_NAPT_TABLE }));
1955 String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
1956 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
1957 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
1958 NatConstants.COOKIE_TS_TABLE, matches, instructions);
1962 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
1963 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
1964 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
1965 LOG.debug("NAT Service : Installing flow {}", flowEntity);
1966 mdsalManager.installFlow(flowEntity);
1969 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
1970 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
1971 List<MatchInfo> matches = new ArrayList<>();
1972 matches.add(new MatchInfo(MatchFieldType.eth_type,
1973 new long[]{0x0800L}));
1974 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
1975 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
1977 List<InstructionInfo> instructions = new ArrayList<>();
1978 List<ActionInfo> actionsInfos = new ArrayList<>();
1979 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
1980 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
1981 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
1983 String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
1984 BigInteger cookie = getCookieOutboundFlow(routerId);
1985 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
1987 cookie, matches, instructions);
1988 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
1992 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
1993 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
1994 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
1995 mdsalManager.installFlow(naptPfibFlowEntity);
1998 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2000 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2001 List<MatchInfo> matches = new ArrayList<>();
2002 matches.add(new MatchInfo(MatchFieldType.eth_type,
2003 new long[] { 0x0800L }));
2004 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2005 BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2007 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2008 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2009 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
2010 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2012 String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
2013 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
2014 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2015 NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2017 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2022 protected ExternalRoutersListener getDataTreeChangeListener()
2024 return ExternalRoutersListener.this;