2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.natservice.internal;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.Sets;
12 import com.google.common.collect.Sets.SetView;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.JdkFutureAdapters;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.Future;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
28 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
31 import org.opendaylight.genius.mdsalutil.ActionInfo;
32 import org.opendaylight.genius.mdsalutil.ActionType;
33 import org.opendaylight.genius.mdsalutil.BucketInfo;
34 import org.opendaylight.genius.mdsalutil.FlowEntity;
35 import org.opendaylight.genius.mdsalutil.GroupEntity;
36 import org.opendaylight.genius.mdsalutil.InstructionInfo;
37 import org.opendaylight.genius.mdsalutil.InstructionType;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.mdsalutil.MatchFieldType;
40 import org.opendaylight.genius.mdsalutil.MatchInfo;
41 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
42 import org.opendaylight.genius.mdsalutil.NwConstants;
43 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
45 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
46 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
103 import org.opendaylight.yangtools.concepts.ListenerRegistration;
104 import org.opendaylight.yangtools.yang.binding.DataObject;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
106 import org.opendaylight.yangtools.yang.common.RpcResult;
107 import org.slf4j.Logger;
108 import org.slf4j.LoggerFactory;
110 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener> {
111 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
112 private ListenerRegistration<DataChangeListener> listenerRegistration;
113 private final DataBroker dataBroker;
114 private final IMdsalApiManager mdsalManager;
115 private final ItmRpcService itmManager;
116 private final OdlInterfaceRpcService interfaceManager;
117 private final IdManagerService idManager;
118 private final NaptManager naptManager;
119 private final NAPTSwitchSelector naptSwitchSelector;
120 private final IBgpManager bgpManager;
121 private final VpnRpcService vpnService;
122 private final FibRpcService fibService;
123 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
124 private final NaptEventHandler naptEventHandler;
125 private final NaptPacketInHandler naptPacketInHandler;
126 private final IFibManager fibManager;
127 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
128 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
130 public ExternalRoutersListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
131 final ItmRpcService itmManager,
132 final OdlInterfaceRpcService interfaceManager,
133 final IdManagerService idManager,
134 final NaptManager naptManager,
135 final NAPTSwitchSelector naptSwitchSelector,
136 final IBgpManager bgpManager,
137 final VpnRpcService vpnService,
138 final FibRpcService fibService,
139 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
140 final NaptEventHandler naptEventHandler,
141 final NaptPacketInHandler naptPacketInHandler,
142 final IFibManager fibManager) {
143 super(Routers.class, ExternalRoutersListener.class);
144 this.dataBroker = dataBroker;
145 this.mdsalManager = mdsalManager;
146 this.itmManager = itmManager;
147 this.interfaceManager = interfaceManager;
148 this.idManager = idManager;
149 this.naptManager = naptManager;
150 this.naptSwitchSelector = naptSwitchSelector;
151 this.bgpManager = bgpManager;
152 this.vpnService = vpnService;
153 this.fibService = fibService;
154 this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
155 this.naptEventHandler = naptEventHandler;
156 this.naptPacketInHandler = naptPacketInHandler;
157 this.fibManager = fibManager;
161 LOG.info("{} init", getClass().getSimpleName());
162 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
167 protected InstanceIdentifier<Routers> getWildCardPath() {
168 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
172 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
174 LOG.info("NAT Service : Add external router event for {}", routers.getRouterName());
176 // Populate the router-id-name container
177 String routerName = routers.getRouterName();
178 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
179 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
180 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
182 LOG.info("NAT Service : Installing NAT default route on all dpns part of router {}", routers.getRouterName());
184 addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
185 } catch (Exception ex) {
186 LOG.debug("NAT Service : Exception {} while Installing NAT default route on all dpns part of router {}",ex,routers.getRouterName());
189 if( !routers.isEnableSnat()) {
190 LOG.info("NAT Service : SNAT is disabled for external router {} ", routers.getRouterName());
194 handleEnableSnat(routers);
197 public void handleEnableSnat(Routers routers){
198 String routerName = routers.getRouterName();
199 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
201 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
202 naptManager.initialiseExternalCounter(routers, segmentId);
204 subnetRegisterMapping(routers,segmentId);
206 // Allocate Primary Napt Switch for this router
207 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,segmentId);
208 if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
209 LOG.debug("NAT Service : Primary NAPT switch with DPN ID {} is already elected for router",primarySwitchId,routerName);
212 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
213 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
214 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
215 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
218 LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
220 long bgpVpnId = NatConstants.INVALID_ID;
221 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
222 if (bgpVpnUuid != null) {
223 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
225 if (bgpVpnId != NatConstants.INVALID_ID){
226 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, segmentId, false);
228 // write metadata and punt
229 installOutboundMissEntry(routerName, primarySwitchId);
230 // Now install entries in SNAT tables to point to Primary for each router
231 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
232 if (switches != null) {
233 for (BigInteger dpnId : switches) {
234 // Handle switches and NAPT switches separately
235 if (!dpnId.equals(primarySwitchId)) {
236 LOG.debug("NAT Service : Handle Ordinary switch");
237 handleSwitches(dpnId, routerName, primarySwitchId);
239 LOG.debug("NAT Service : Handle NAPT switch");
240 handlePrimaryNaptSwitch(dpnId, routerName);
246 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,segmentId);
247 if (externalIps == null || externalIps.isEmpty()) {
248 LOG.debug("NAT Service : Internal External mapping found for router {}",routerName);
251 for (String externalIpAddrPrefix : externalIps) {
252 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
253 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
257 /*// call registerMapping Api
258 LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
260 List<Uuid> subnetList = null;
261 List<String> externalIps = null;
263 InstanceIdentifier<Routers> id = InstanceIdentifier
264 .builder(ExtRouters.class)
265 .child(Routers.class, new RoutersKey(routerName))
268 Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
270 if(extRouters.isPresent())
272 LOG.debug("NAT Service : Fetching values from extRouters model");
273 Routers routerEntry= extRouters.get();
274 subnetList = routerEntry.getSubnetIds();
275 externalIps = routerEntry.getExternalIps();
277 int extIpCounter = externalIps.size();
278 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
279 for(Uuid subnet : subnetList) {
280 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
281 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
282 .builder(Subnetmaps.class)
283 .child(Subnetmap.class, new SubnetmapKey(subnet))
285 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
288 Subnetmap subnetmapEntry = sn.get();
289 String subnetString = subnetmapEntry.getSubnetIp();
290 String[] subnetSplit = subnetString.split("/");
291 String subnetIp = subnetSplit[0];
292 String subnetPrefix = "0";
293 if(subnetSplit.length == 2) {
294 subnetPrefix = subnetSplit[1];
296 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
297 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
299 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
300 if(extIpCounter != 0) {
301 if(counter < extIpCounter) {
302 String[] IpSplit = externalIps.get(counter).split("/");
303 String externalIp = IpSplit[0];
304 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
305 if(IpSplit.length==2) {
306 extPrefix = IpSplit[1];
308 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
309 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
310 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
311 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
312 externalIp, extPrefix);
314 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
315 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
316 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
319 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
320 LOG.debug("NAT Service : Counter on externalIps got reset");
321 String[] IpSplit = externalIps.get(counter).split("/");
322 String externalIp = IpSplit[0];
323 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
324 if(IpSplit.length==2) {
325 extPrefix = IpSplit[1];
327 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
328 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
329 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
330 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
331 externalIp, extPrefix);
333 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
334 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
335 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
340 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
343 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
347 LOG.info("NAT Service : handleEnableSnat() Exit");
350 private void subnetRegisterMapping(Routers routerEntry,Long segmentId) {
351 List<Uuid> subnetList = null;
352 List<String> externalIps = null;
353 LOG.debug("NAT Service : Fetching values from extRouters model");
354 subnetList = routerEntry.getSubnetIds();
355 externalIps = routerEntry.getExternalIps();
357 int extIpCounter = externalIps.size();
358 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
359 for(Uuid subnet : subnetList) {
360 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
361 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
362 .builder(Subnetmaps.class)
363 .child(Subnetmap.class, new SubnetmapKey(subnet))
365 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
368 Subnetmap subnetmapEntry = sn.get();
369 String subnetString = subnetmapEntry.getSubnetIp();
370 String[] subnetSplit = subnetString.split("/");
371 String subnetIp = subnetSplit[0];
372 String subnetPrefix = "0";
373 if(subnetSplit.length == 2) {
374 subnetPrefix = subnetSplit[1];
376 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
377 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
379 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
380 if(extIpCounter != 0) {
381 if(counter < extIpCounter) {
382 String[] IpSplit = externalIps.get(counter).split("/");
383 String externalIp = IpSplit[0];
384 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
385 if(IpSplit.length==2) {
386 extPrefix = IpSplit[1];
388 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
389 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
390 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
391 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
392 externalIp, extPrefix);
394 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
395 LOG.debug("NAT Service : Counter on externalIps got reset");
396 String[] IpSplit = externalIps.get(counter).split("/");
397 String externalIp = IpSplit[0];
398 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
399 if(IpSplit.length==2) {
400 extPrefix = IpSplit[1];
402 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
403 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
404 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
405 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
406 externalIp, extPrefix);
410 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
412 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
417 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
418 //Check if BGP VPN exists. If exists then invoke the new method.
419 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
420 if(bgpVpnId != NatConstants.INVALID_ID) {
421 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
422 if (bgpVpnUuid != null) {
423 String bgpVpnName = bgpVpnUuid.getValue();
424 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
425 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
426 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
428 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
432 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
433 addOrDelDefaultFibRouteForSNAT(routerName, create);
436 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
437 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
438 if (switches == null || switches.isEmpty()) {
439 LOG.debug("No switches found for router {}",routerName);
442 long routerId = NatUtil.readVpnId(dataBroker, routerName);
443 if (routerId == NatConstants.INVALID_ID) {
444 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
447 for (BigInteger dpnId : switches) {
449 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
450 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
452 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
453 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
458 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
459 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
460 if(dpnIds == null || dpnIds.isEmpty()) {
461 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
464 long routerId = NatUtil.getVpnId(dataBroker, routerName);
465 for (BigInteger dpnId : dpnIds) {
467 if (bgpVpnId != NatConstants.INVALID_ID) {
468 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
469 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
471 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
472 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
475 if (bgpVpnId != NatConstants.INVALID_ID) {
476 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
477 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
479 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
480 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
486 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
488 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
490 Optional<T> result = Optional.absent();
493 result = tx.read(datastoreType, path).get();
497 throw new RuntimeException(e);
504 public void close() throws Exception
506 if (listenerRegistration != null)
510 listenerRegistration.close();
512 catch (final Exception e)
514 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
517 listenerRegistration = null;
519 LOG.debug("ExternalRoutersListener Closed");
522 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
523 long routerId = NatUtil.getVpnId(dataBroker, routerName);
524 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
525 if(routerId != NatConstants.INVALID_ID) {
526 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
527 createOutboundTblEntry(primarySwitchId, routerId);
529 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
533 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
534 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
535 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
538 public BigInteger getCookieOutboundFlow(long routerId) {
539 return NwConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
540 BigInteger.valueOf(routerId));
543 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
544 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
545 List<MatchInfo> matches = new ArrayList<>();
546 matches.add(new MatchInfo(MatchFieldType.eth_type,
547 new long[] { 0x0800L }));
548 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
549 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
551 List<InstructionInfo> instructions = new ArrayList<>();
552 List<ActionInfo> actionsInfos = new ArrayList<>();
553 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
554 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
555 instructions.add(new InstructionInfo(InstructionType.write_metadata,
556 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
558 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
559 BigInteger cookie = getCookieOutboundFlow(routerId);
560 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
562 cookie, matches, instructions);
563 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
567 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
568 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
569 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
570 LOG.debug("NAT Service : Installing flow {}", flowEntity);
571 mdsalManager.installFlow(flowEntity);
574 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
575 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
576 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
578 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
579 .setSourceDpid(srcDpId)
580 .setDestinationDpid(dstDpId)
581 .setTunnelType(tunType)
583 rpcResult = result.get();
584 if(!rpcResult.isSuccessful()) {
585 tunType = TunnelTypeGre.class ;
586 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
587 .setSourceDpid(srcDpId)
588 .setDestinationDpid(dstDpId)
589 .setTunnelType(tunType)
591 rpcResult = result.get();
592 if(!rpcResult.isSuccessful()) {
593 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
595 return rpcResult.getResult().getInterfaceName();
597 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
599 return rpcResult.getResult().getInterfaceName();
601 } catch (InterruptedException | ExecutionException | NullPointerException e) {
602 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
608 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
609 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAOT switch dpnId {} ", dpnId);
610 // Install miss entry pointing to group
611 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
612 mdsalManager.installFlow(flowEntity);
615 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
616 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
617 // Install the select group
618 long groupId = createGroupId(getGroupIdKey(routerName));
619 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
620 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
621 mdsalManager.installGroup(groupEntity);
622 // Install miss entry pointing to group
623 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
624 mdsalManager.installFlow(flowEntity);
627 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
628 long groupId = createGroupId(getGroupIdKey(routerName));
629 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
630 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
631 mdsalManager.installGroup(groupEntity);
635 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
637 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
638 long routerId = NatUtil.getVpnId(dataBroker, routerName);
639 List<MatchInfo> matches = new ArrayList<>();
640 matches.add(new MatchInfo(MatchFieldType.eth_type,
641 new long[] { 0x0800L }));
642 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
643 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
646 List<InstructionInfo> instructions = new ArrayList<>();
647 List<ActionInfo> actionsInfo = new ArrayList<>();
649 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
650 BigInteger.valueOf(routerId)}) ;
651 actionsInfo.add(actionSetField);
652 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
653 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
654 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
655 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
656 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
657 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
658 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
660 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
664 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
666 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
668 long routerId = NatUtil.getVpnId(dataBroker, routerName);
669 List<MatchInfo> matches = new ArrayList<MatchInfo>();
670 matches.add(new MatchInfo(MatchFieldType.eth_type,
671 new long[] { 0x0800L }));
672 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
673 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
675 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
676 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
677 { NwConstants.OUTBOUND_NAPT_TABLE }));
679 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
680 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
681 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
682 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
684 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
688 // TODO : Replace this with ITM Rpc once its available with full functionality
689 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
690 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
691 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
692 mdsalManager.installFlow(flowEntity);
696 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
698 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
699 List<MatchInfo> matches = new ArrayList<>();
700 matches.add(new MatchInfo(MatchFieldType.eth_type,
701 new long[] { 0x0800L }));
702 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
704 List<InstructionInfo> instructions = new ArrayList<>();
705 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
706 { MetaDataUtil.getVpnIdMetadata(routerId.longValue()), MetaDataUtil.METADATA_MASK_VRFID }));
707 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
708 { NwConstants.OUTBOUND_NAPT_TABLE }));
709 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
710 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
711 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
712 NwConstants.COOKIE_TS_TABLE, matches, instructions);
716 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
717 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
718 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
721 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
722 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
723 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
726 private String getGroupIdKey(String routerName){
727 String groupIdKey = new String("snatmiss." + routerName);
731 protected long createGroupId(String groupIdKey) {
732 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
733 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
736 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
737 RpcResult<AllocateIdOutput> rpcResult = result.get();
738 return rpcResult.getResult().getIdValue();
739 } catch (NullPointerException | InterruptedException | ExecutionException e) {
745 protected void createGroupIdPool() {
746 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
747 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
748 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
749 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
752 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
753 if ((result != null) && (result.get().isSuccessful())) {
754 LOG.debug("NAT Service : Created GroupIdPool");
756 LOG.error("NAT Service : Unable to create GroupIdPool");
758 } catch (InterruptedException | ExecutionException e) {
759 LOG.error("Failed to create PortPool for NAPT Service",e);
763 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
764 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
765 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
766 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
767 List<BucketInfo> listBucketInfo = new ArrayList<>();
768 long routerId = NatUtil.getVpnId(dataBroker, routerName);
770 if(ifNamePrimary != null) {
771 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
772 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
774 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
776 listBucketInfo.add(0, bucketPrimary);
777 installSnatMissEntry(dpnId, listBucketInfo, routerName);
780 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
781 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
782 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
783 List<BucketInfo> listBucketInfo = new ArrayList<>();
784 long routerId = NatUtil.getVpnId(dataBroker, routerName);
786 if (ifNamePrimary != null) {
787 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
788 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
790 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
792 listBucketInfo.add(0, bucketPrimary);
793 return listBucketInfo;
795 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
798 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
801 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
804 List<BucketInfo> listBucketInfo = new ArrayList<>();
805 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
806 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
807 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
808 listBucketInfo.add(0, bucketPrimary);
811 long routerId = NatUtil.getVpnId(dataBroker, routerName);
813 installSnatMissEntryForPrimrySwch(dpnId, routerName);
814 installTerminatingServiceTblEntry(dpnId, routerName);
815 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
816 installNaptPfibEntry(dpnId, routerId);
817 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
818 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
819 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
820 installNaptPfibEntry(dpnId, vpnId);
824 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
825 List<BucketInfo> listBucketInfo = new ArrayList<>();
826 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
827 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NwConstants.INTERNAL_TUNNEL_TABLE)}));
828 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
829 listBucketInfo.add(0, bucketPrimary);
830 return listBucketInfo;
833 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
834 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
835 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
836 mdsalManager.installFlow(naptPfibFlowEntity);
839 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
841 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
842 List<MatchInfo> matches = new ArrayList<>();
843 matches.add(new MatchInfo(MatchFieldType.eth_type,
844 new long[] { 0x0800L }));
845 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
846 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
848 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
849 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
850 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
851 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
853 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
854 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
855 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
856 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
858 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
862 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
863 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
864 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
865 if(networkId == null) {
866 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
869 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
870 if(vpnName == null) {
871 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
872 networkId, externalIp, routerId);
875 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
876 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
879 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
880 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
882 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
883 //Generate VPN label for the external IP
884 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
885 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
887 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
888 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
891 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
892 if (result.isSuccessful()) {
893 LOG.debug("NAT Service : inside apply with result success");
894 GenerateVpnLabelOutput output = result.getResult();
895 final long label = output.getLabel();
897 int externalIpInDsFlag = 0;
898 //Get IPMaps from the DB for the router ID
899 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
900 if (dbIpMaps != null) {
901 for (IpMap dbIpMap : dbIpMaps) {
902 String dbExternalIp = dbIpMap.getExternalIp();
903 //Select the IPMap, whose external IP is the IP for which FIB is installed
904 if (externalIp.equals(dbExternalIp)) {
905 String dbInternalIp = dbIpMap.getInternalIp();
906 IpMapKey dbIpMapKey = dbIpMap.getKey();
907 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
908 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
909 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
910 externalIpInDsFlag++;
913 if (externalIpInDsFlag <=0) {
914 LOG.debug("NAT Service : External Ip {} not found in DS,Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
915 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", externalIp, label, routerId);
916 return Futures.immediateFailedFuture(new Exception(errMsg));
919 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
924 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
925 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
926 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
928 //Install custom FIB routes
929 List<Instruction> customInstructions = new ArrayList<>();
930 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
931 makeTunnelTableEntry(dpnId, label, customInstructions);
932 makeLFibTableEntry(dpnId, label, tableId);
934 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
935 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
936 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
937 return JdkFutureAdapters.listenInPoolThread(future);
939 LOG.error("NAT Service : inside apply with result failed");
940 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
941 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
946 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
949 public void onFailure(Throwable error) {
950 log.error("NAT Service : Error in generate label or fib install process", error);
954 public void onSuccess(RpcResult<Void> result) {
955 if (result.isSuccessful()) {
956 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
958 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
964 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
965 List<MatchInfo> matches = new ArrayList<>();
966 matches.add(new MatchInfo(MatchFieldType.eth_type,
967 new long[]{0x8847L}));
968 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
970 List<Instruction> instructions = new ArrayList<>();
971 List<ActionInfo> actionsInfos = new ArrayList<>();
972 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
973 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
974 instructions.add(writeInstruction);
975 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
977 // Install the flow entry in L3_LFIB_TABLE
978 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
980 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
982 COOKIE_VM_LFIB_TABLE, matches, instructions);
984 mdsalManager.installFlow(dpId, flowEntity);
986 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
989 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
990 List<MatchInfo> mkMatches = new ArrayList<>();
992 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
994 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
996 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
997 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
998 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1000 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1003 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1004 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1005 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1009 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1010 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1011 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1012 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1016 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1017 String routerName = original.getRouterName();
1018 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1019 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1020 Uuid networkId = original.getNetworkId();
1022 // Check if its update on SNAT flag
1023 boolean originalSNATEnabled = original.isEnableSnat();
1024 boolean updatedSNATEnabled = update.isEnableSnat();
1025 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1026 if(originalSNATEnabled != updatedSNATEnabled) {
1027 if(originalSNATEnabled) {
1028 //SNAT disabled for the router
1029 Uuid networkUuid = original.getNetworkId();
1030 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1031 if (routerId == NatConstants.INVALID_ID) {
1032 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1035 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1036 handleDisableSnat(routerName, networkUuid, externalIps, false, null);
1038 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1039 handleEnableSnat(original);
1043 //Check if the Update is on External IPs
1044 LOG.debug("NAT Service : Checking if this is update on External IPs");
1045 List<String> originalExternalIpsList = original.getExternalIps();
1046 List<String> updatedExternalIpsList = update.getExternalIps();
1047 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1048 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1050 //Check if the External IPs are added during the update.
1051 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1052 if(addedExternalIps.size() != 0) {
1053 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1054 for (String addedExternalIp : addedExternalIps) {
1056 1) Do nothing in the IntExtIp model.
1057 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1059 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1060 String externalIp = externalIpParts[0];
1061 String externalIpPrefix = externalIpParts[1];
1062 String externalpStr = externalIp + "/" + externalIpPrefix;
1063 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1064 externalpStr, routerId);
1065 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1067 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1070 //Check if the External IPs are removed during the update.
1071 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1072 if(removedExternalIps.size() > 0) {
1073 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1074 List<String> removedExternalIpsAsList = new ArrayList<>();
1075 for (String removedExternalIp : removedExternalIps) {
1077 1) Remove the mappings in the IntExt IP model which has external IP.
1078 2) Remove the external IP in the ExternalCounter model.
1079 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1080 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1081 4) Increase the count of the allocated external IP by one.
1082 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.
1083 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1084 7) Advertise to the BGP for removing the route for the removed external IPs.
1087 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1088 String externalIp = externalIpParts[0];
1089 String externalIpPrefix = externalIpParts[1];
1090 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1092 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1093 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1094 String vpnName = "";
1095 if(vpnUuId != null){
1096 vpnName = vpnUuId.getValue();
1098 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1100 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1101 //Get the internal IPs which are associated to the removed external IPs
1102 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1103 List<String> removedInternalIps = new ArrayList<>();
1104 for(IpMap ipMap : ipMaps){
1105 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1106 removedInternalIps.add(ipMap.getInternalIp());
1110 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1111 for(String removedInternalIp : removedInternalIps){
1112 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1113 removedInternalIp, routerId);
1114 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1117 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1118 externalIpAddrStr, routerId );
1119 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1120 removedExternalIpsAsList.add(externalIpAddrStr);
1122 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1123 for(String removedInternalIp : removedInternalIps) {
1124 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1127 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1128 //Get the internalIP and internal Port which were associated to the removed external IP.
1129 List<Integer> externalPorts = new ArrayList<>();
1130 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1131 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1132 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1133 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1134 if (ipPortMapping.isPresent()) {
1135 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1136 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1137 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1138 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1139 for(IpPortMap ipPortMap : ipPortMaps){
1140 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1141 if(ipPortExternal.getIpAddress().equals(externalIp)){
1142 externalPorts.add(ipPortExternal.getPortNum());
1143 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1144 if(removedInternalIpPorts != null){
1145 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1146 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1148 removedInternalIpPorts = new ArrayList<>();
1149 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1150 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1157 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1158 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1159 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1160 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1161 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1162 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1163 for(String removedInternalIpPort : removedInternalIpPorts){
1164 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1165 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1166 //Remove the IP port incomint packer map.
1167 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1168 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1169 if(removedInternalIpPortParts.length == 2){
1170 String removedInternalIp = removedInternalIpPortParts[0];
1171 String removedInternalPort = removedInternalIpPortParts[1];
1172 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1173 if (removedInternalPortsList != null){
1174 removedInternalPortsList.add(removedInternalPort);
1175 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1177 removedInternalPortsList = new ArrayList<>();
1178 removedInternalPortsList.add(removedInternalPort);
1179 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1185 // Delete the entry from SnatIntIpPortMap DS
1186 Set<String> internalIps = internalIpPortMap.keySet();
1187 for(String internalIp : internalIps){
1188 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1189 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1192 naptManager.removeNaptPortPool(externalIp);
1194 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1195 for(Integer externalPort : externalPorts) {
1196 //Remove the NAPT translation entries from Inbound NAPT table
1197 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1200 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1201 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1202 String internalIp = internalIpPort.getKey();
1203 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1204 List<String> internalPorts = internalIpPort.getValue();
1205 for(String internalPort : internalPorts){
1206 //Remove the NAPT translation entries from Outbound NAPT table
1207 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1211 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1214 //Check if its Update on subnets
1215 LOG.debug("NAT Service : Checking if this is update on subnets");
1216 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1217 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1218 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1219 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1220 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1222 //Check if the Subnet IDs are added during the update.
1223 if(addedSubnetIds.size() != 0){
1224 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1225 for(Uuid addedSubnetId : addedSubnetIds){
1227 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.
1228 2) Increase the count of the selected external IP by one.
1229 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.
1231 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1232 if(subnetIp != null) {
1233 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1236 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1239 //Check if the Subnet IDs are removed during the update.
1240 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1241 if(removedSubnetIds.size() != 0){
1242 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1243 for(Uuid removedSubnetId : removedSubnetIds){
1244 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1245 if(subnetAddr != null){
1247 1) Remove the subnet IP and the external IP in the IntExtIp map
1248 2) Decrease the count of the coresponding external IP by one.
1249 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1252 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1253 if (externalIp == null) {
1254 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1258 naptManager.updateCounter(routerId, externalIp, false);
1259 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1260 if (!isExternalIpAllocated(externalIp)) {
1261 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1262 List<String> externalIps = new ArrayList<>();
1263 externalIps.add(externalIp);
1264 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1265 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1266 dpnId,routerId,networkId,externalIps);
1269 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1270 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1273 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1277 private boolean isExternalIpAllocated(String externalIp) {
1278 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1279 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1280 if (externalCountersData.isPresent()) {
1281 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1282 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1283 for(ExternalCounters ext : externalCounters) {
1284 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1285 if (externalIpCount.getExternalIp().equals(externalIp)) {
1286 if (externalIpCount.getCounter() != 0) {
1297 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1298 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1299 if (leastLoadedExtIpAddr != null) {
1300 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1301 String leastLoadedExtIp = externalIpParts[0];
1302 String leastLoadedExtIpPrefix = externalIpParts[1];
1303 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1304 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1305 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1306 subnetIp = subnetIpParts[0];
1307 String subnetIpPrefix = subnetIpParts[1];
1308 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1309 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1310 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1311 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1314 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1315 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1316 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1319 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1320 IpMapKey ipMapKey = new IpMapKey(internalIp);
1321 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1322 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1323 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1327 //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.
1328 //Get the VPN Name using the network ID
1329 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1330 if (vpnName != null) {
1331 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1332 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1333 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1334 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1336 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1337 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1342 private Long checkExternalIpLabel(long routerId, String externalIp){
1343 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1344 for(IpMap ipMap : ipMaps){
1345 if(ipMap.getExternalIp().equals(externalIp)){
1346 if (ipMap.getLabel() != null){
1347 return ipMap.getLabel();
1355 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1356 LOG.trace("NAT Service : Router delete method");
1359 ROUTER DELETE SCENARIO
1360 1) Get the router ID from the event.
1361 2) Build the cookie information from the router ID.
1362 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1363 4) Build the flow with the cookie value.
1364 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1365 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1366 7) Get the list of external IP address maintained for the router ID.
1367 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1368 9) Withdraw the corresponding routes from the BGP.
1371 if (identifier == null || router == null) {
1372 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1376 String routerName = router.getRouterName();
1377 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1378 addOrDelDefFibRouteToSNAT(routerName, false);
1379 Uuid networkUuid = router.getNetworkId();
1380 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1381 if (routerId == NatConstants.INVALID_ID) {
1382 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1385 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1386 handleDisableSnat(routerName, networkUuid, externalIps, true, null);
1390 public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1391 LOG.info("NAT Service : handleDisableSnat() Entry");
1393 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1395 BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1396 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1397 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1398 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1401 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1402 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1404 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1405 } catch (Exception ex) {
1406 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1409 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1410 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1411 naptManager.removeMapping(routerId);
1414 removeNaptSwitch(routerName);
1416 updateNaptSwitch(routerName, BigInteger.ZERO);
1419 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1420 naptManager.removeExternalCounter(routerId);
1421 } catch (Exception ex) {
1422 LOG.error("Exception while handling disableSNAT : {}", ex);
1424 LOG.info("NAT Service : handleDisableSnat() Exit");
1427 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1428 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1430 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1431 BigInteger naptSwitchDpnId = null;
1432 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1433 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1434 if (rtrToNapt.isPresent()) {
1435 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1437 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1439 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1441 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1442 } catch (Exception ex) {
1443 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1445 } catch (Exception ex) {
1446 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1448 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1451 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1452 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1453 .setPrimarySwitchId(naptSwitchId).build();
1455 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1456 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1457 } catch (Exception ex) {
1458 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1459 naptSwitchId,routerName);
1461 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1462 naptSwitchId,routerName);
1465 protected void removeNaptSwitch(String routerName){
1466 // Remove router and switch from model
1467 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1468 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1469 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1472 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1474 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1475 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1477 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1478 // traffic which comes from the VMs of the NAPT switches)
1479 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1480 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1482 LOG.info("NAT Service : Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1483 mdsalManager.removeFlow(pSNatFlowEntity);
1485 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1486 // traffic which comes from the VMs of the non NAPT switches)
1487 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1488 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1490 LOG.info("NAT Service : Remove the flow in the " + NwConstants.INTERNAL_TUNNEL_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1491 mdsalManager.removeFlow(tsNatFlowEntity);
1493 //Remove the Outbound flow entry which forwards the packet to FIB Table
1494 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1495 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1497 LOG.info("NAT Service : Remove the flow in the " + NwConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1498 mdsalManager.removeFlow(outboundNatFlowEntity);
1500 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1501 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1502 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1504 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1505 mdsalManager.removeFlow(natPfibFlowEntity);
1507 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1508 //Get the VPN ID from the ExternalNetworks model
1510 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1511 // ie called from router delete cases
1512 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1513 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1514 if(vpnUuid != null) {
1515 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1516 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1519 // ie called from disassociate vpn case
1520 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1521 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1522 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1525 if(vpnId != NatConstants.INVALID_ID){
1526 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1527 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1528 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1529 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
1530 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1533 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1534 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1535 if(ipPortMapping == null){
1536 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1540 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1541 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1542 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1543 for(IpPortMap ipPortMap : ipPortMaps){
1544 String ipPortInternal = ipPortMap.getIpPortInternal();
1545 String[] ipPortParts = ipPortInternal.split(":");
1546 if(ipPortParts.length != 2) {
1547 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1550 String internalIp = ipPortParts[0];
1551 String internalPort = ipPortParts[1];
1553 //Build the flow for the outbound NAPT table
1554 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1555 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1557 LOG.info("NAT Service : Remove the flow in the " + NwConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1558 mdsalManager.removeFlow(outboundNaptFlowEntity);
1560 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1561 String externalIp = ipPortExternal.getIpAddress();
1562 int externalPort = ipPortExternal.getPortNum();
1564 //Build the flow for the inbound NAPT table
1565 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1566 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1568 LOG.info("NAT Service : Remove the flow in the " + NwConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1569 mdsalManager.removeFlow(inboundNaptFlowEntity);
1574 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1576 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1577 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1579 //Remove the NAPT PFIB TABLE entry
1581 if(vpnName != null) {
1582 // ie called from disassociate vpn case
1583 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1584 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1585 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1588 if(vpnId != NatConstants.INVALID_ID){
1589 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1590 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1591 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1592 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
1593 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1595 // Remove IP-PORT active NAPT entries and release port from IdManager
1596 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1597 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1598 if(ipPortMapping == null){
1599 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1602 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1603 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1604 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1605 for(IpPortMap ipPortMap : ipPortMaps){
1606 String ipPortInternal = ipPortMap.getIpPortInternal();
1607 String[] ipPortParts = ipPortInternal.split(":");
1608 if(ipPortParts.length != 2) {
1609 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1612 String internalIp = ipPortParts[0];
1613 String internalPort = ipPortParts[1];
1615 //Build the flow for the outbound NAPT table
1616 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1617 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1619 LOG.info("NAT Service : Remove the flow in the " + NwConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1620 mdsalManager.removeFlow(outboundNaptFlowEntity);
1622 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1623 String externalIp = ipPortExternal.getIpAddress();
1624 int externalPort = ipPortExternal.getPortNum();
1626 //Build the flow for the inbound NAPT table
1627 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1628 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1630 LOG.info("NAT Service : Remove the flow in the " + NwConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1631 mdsalManager.removeFlow(inboundNaptFlowEntity);
1633 // Finally release port from idmanager
1634 String internalIpPort = internalIp +":"+internalPort;
1635 naptManager.removePortFromPool(internalIpPort, externalIp);
1637 //Remove sessions from models
1638 naptManager.removeIpPortMappingForRouterID(routerId);
1639 naptManager.removeIntIpPortMappingForRouterID(routerId);
1643 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1647 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1648 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1650 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1651 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1652 if(allSwitchList == null || allSwitchList.isEmpty()){
1653 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1656 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1657 for (BigInteger dpnId : allSwitchList) {
1658 if (!naptSwitchDpnId.equals(dpnId)) {
1659 LOG.info("NAT Service : Handle Ordinary switch");
1661 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1662 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1663 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1665 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1666 mdsalManager.removeFlow(pSNatFlowEntity);
1668 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1669 long groupId = createGroupId(getGroupIdKey(routerName));
1670 List<BucketInfo> listBucketInfo = new ArrayList<>();
1671 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1673 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1674 mdsalManager.removeGroup(pSNatGroupEntity);
1680 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1681 //Withdraw the corresponding routes from the BGP.
1682 //Get the network ID using the router ID.
1683 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1684 externalIps,routerId,networkUuid, vpnName);
1685 if(networkUuid == null ){
1686 LOG.error("NAT Service : networkId is null");
1690 if (externalIps == null || externalIps.isEmpty()) {
1691 LOG.debug("NAT Service : externalIps is null");
1695 if(vpnName ==null) {
1696 //Get the VPN Name using the network ID
1697 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1698 if (vpnName == null) {
1699 LOG.error("No VPN associated with ext nw {} for the router {}",
1700 networkUuid, routerId);
1704 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1706 //Remove custom FIB routes
1707 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1708 for (String extIp : externalIps) {
1709 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1713 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1714 clearBgpRoutes(extIp,vpnName);
1715 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1718 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1719 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1721 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1722 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1726 final long label = tempLabel;
1727 final String externalIp = extIp;
1729 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1730 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1732 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1735 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1737 if (result.isSuccessful()) {
1738 removeTunnelTableEntry(dpnId, label);
1739 removeLFibTableEntry(dpnId, label);
1740 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1741 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1742 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1744 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1746 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1752 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1755 public void onFailure(Throwable error) {
1756 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1760 public void onSuccess(RpcResult<Void> result) {
1761 if (result.isSuccessful()) {
1762 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1764 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1770 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1771 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1772 //Get IPMaps from the DB for the router ID
1773 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1774 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1775 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1779 long tempLabel = NatConstants.INVALID_ID;
1780 for (IpMap dbIpMap : dbIpMaps) {
1781 String dbExternalIp = dbIpMap.getExternalIp();
1782 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1783 //Select the IPMap, whose external IP is the IP for which FIB is installed
1784 if (extIp.equals(dbExternalIp)) {
1785 tempLabel = dbIpMap.getLabel();
1786 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1790 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1791 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1795 final long label = tempLabel;
1796 final String externalIp = extIp;
1798 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1799 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1801 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1804 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1806 if (result.isSuccessful()) {
1807 removeTunnelTableEntry(dpnId, label);
1808 removeLFibTableEntry(dpnId, label);
1809 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1810 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1811 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1813 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1815 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1821 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1824 public void onFailure(Throwable error) {
1825 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1829 public void onSuccess(RpcResult<Void> result) {
1830 if (result.isSuccessful()) {
1831 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1833 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1839 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1840 //Withdraw the corresponding routes from the BGP.
1841 //Get the network ID using the router ID.
1842 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1843 externalIps,routerId,networkUuid, vpnName);
1844 if (networkUuid == null) {
1845 LOG.error("NAT Service : networkId is null");
1849 if (externalIps == null || externalIps.isEmpty()) {
1850 LOG.debug("NAT Service : externalIps is null");
1854 if (vpnName == null) {
1855 //Get the VPN Name using the network ID
1856 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1857 if (vpnName == null) {
1858 LOG.error("No VPN associated with ext nw {} for the router {}",
1859 networkUuid, routerId);
1863 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1865 //Remove custom FIB routes
1866 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1867 for (String extIp : externalIps) {
1868 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1872 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1873 //Inform BGP about the route removal
1874 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1875 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1876 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
1879 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1880 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1881 List<MatchInfo> mkMatches = new ArrayList<>();
1882 // Matching metadata
1883 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1884 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1885 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1886 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1887 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1888 mdsalManager.removeFlow(dpnId, flowEntity);
1889 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1892 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1893 List<MatchInfo> matches = new ArrayList<>();
1894 matches.add(new MatchInfo(MatchFieldType.eth_type,
1895 new long[] { 0x8847L }));
1896 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1898 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1900 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
1902 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1904 COOKIE_VM_LFIB_TABLE, matches, null);
1906 mdsalManager.removeFlow(dpnId, flowEntity);
1908 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
1912 * router association to vpn
1915 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
1916 LOG.debug("NAT Service : Router associated to BGP VPN");
1917 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1918 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1920 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1922 if(bgpVpnId != NatConstants.INVALID_ID){
1923 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
1924 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
1925 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
1927 // Get the allocated Primary NAPT Switch for this router
1928 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1929 LOG.debug("Router ID value {} ", routerId);
1930 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1932 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
1933 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
1936 long groupId = createGroupId(getGroupIdKey(routerName));
1937 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
1943 * router disassociation from vpn
1946 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
1947 LOG.debug("NAT Service : Router dissociated from BGP VPN");
1948 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1949 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1950 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1952 // Get the allocated Primary NAPT Switch for this router
1953 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1954 LOG.debug("Router ID value {} ", routerId);
1955 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1957 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
1958 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
1961 long groupId = createGroupId(getGroupIdKey(routerName));
1962 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
1966 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
1967 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
1968 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
1969 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
1970 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
1976 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
1977 routerId, boolean isSnatCfgd){
1978 long changedVpnId = bgpVpnId;
1979 String logMsg = "NAT Service : Update the BGP VPN ID {}";
1980 if (bgpVpnId == NatConstants.INVALID_ID){
1981 changedVpnId = routerId;
1982 logMsg = "NAT Service : Update the router ID {}";
1985 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
1986 if (switches == null || switches.isEmpty()) {
1987 LOG.debug("No switches found for router {}",routerName);
1990 for(BigInteger dpnId : switches) {
1991 // Update the BGP VPN ID in the SNAT miss entry to group
1992 if( !dpnId.equals(primarySwitchId) ) {
1993 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
1994 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
1995 long groupId = createGroupId(getGroupIdKey(routerName));
1997 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2000 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2001 changedVpnId, groupId, dpnId);
2002 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2003 mdsalManager.installFlow(flowEntity);
2006 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2007 changedVpnId, primarySwitchId);
2008 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2009 mdsalManager.installFlow(flowEntity);
2011 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2012 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2013 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2015 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2016 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2017 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2019 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2020 changedVpnId, primarySwitchId);
2021 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2023 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2024 " in the Primary switch {}", changedVpnId, primarySwitchId);
2025 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2027 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2028 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2029 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2030 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2031 installNaptPfibEntry(primarySwitchId, vpnId);
2037 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2038 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2039 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2040 if(ipPortMapping == null){
2041 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2045 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2046 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2047 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2048 for(IpPortMap ipPortMap : ipPortMaps){
2049 String ipPortInternal = ipPortMap.getIpPortInternal();
2050 String[] ipPortParts = ipPortInternal.split(":");
2051 if(ipPortParts.length != 2) {
2052 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2055 String internalIp = ipPortParts[0];
2056 String internalPort = ipPortParts[1];
2058 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2059 NAPTEntryEvent.Protocol protocol;
2060 switch (protocolTypes){
2062 protocol = NAPTEntryEvent.Protocol.TCP;
2065 protocol = NAPTEntryEvent.Protocol.UDP;
2068 protocol = NAPTEntryEvent.Protocol.TCP;
2070 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2071 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2072 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2073 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2074 internalAddress, externalAddress, protocol);
2075 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2076 externalAddress, internalAddress, protocol);
2082 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2084 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2085 List<MatchInfo> matches = new ArrayList<>();
2086 matches.add(new MatchInfo(MatchFieldType.eth_type,
2087 new long[] { 0x0800L }));
2088 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2089 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2091 List<InstructionInfo> instructions = new ArrayList<>();
2092 List<ActionInfo> actionsInfo = new ArrayList<>();
2094 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2095 BigInteger.valueOf(changedVpnId)}) ;
2096 actionsInfo.add(actionSetField);
2097 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2098 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2099 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
2100 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2101 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2102 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2103 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2105 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2109 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2111 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2112 List<MatchInfo> matches = new ArrayList<>();
2113 matches.add(new MatchInfo(MatchFieldType.eth_type,
2114 new long[] { 0x0800L }));
2115 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2116 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2118 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2119 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2120 { NwConstants.OUTBOUND_NAPT_TABLE }));
2122 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2123 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2124 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2125 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2127 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2131 // TODO : Replace this with ITM Rpc once its available with full functionality
2132 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2133 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2134 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2135 mdsalManager.installFlow(flowEntity);
2139 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2140 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2141 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2142 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2143 List<MatchInfo> matches = new ArrayList<>();
2144 matches.add(new MatchInfo(MatchFieldType.eth_type,
2145 new long[] { 0x0800L }));
2146 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2148 List<InstructionInfo> instructions = new ArrayList<>();
2149 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2150 { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2151 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2152 { NwConstants.OUTBOUND_NAPT_TABLE }));
2153 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2154 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2155 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2156 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2160 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2161 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2162 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2163 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2164 mdsalManager.installFlow(flowEntity);
2167 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2168 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2169 List<MatchInfo> matches = new ArrayList<>();
2170 matches.add(new MatchInfo(MatchFieldType.eth_type,
2171 new long[]{0x0800L}));
2172 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2173 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2175 List<InstructionInfo> instructions = new ArrayList<>();
2176 List<ActionInfo> actionsInfos = new ArrayList<>();
2177 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2178 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2179 instructions.add(new InstructionInfo(InstructionType.write_metadata,
2180 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2182 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2183 BigInteger cookie = getCookieOutboundFlow(routerId);
2184 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2185 cookie, matches, instructions);
2186 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2190 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2191 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2192 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2193 mdsalManager.installFlow(naptPfibFlowEntity);
2196 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2198 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2199 List<MatchInfo> matches = new ArrayList<>();
2200 matches.add(new MatchInfo(MatchFieldType.eth_type,
2201 new long[] { 0x0800L }));
2202 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2203 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2205 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2206 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2207 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
2208 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2210 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2211 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2212 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2213 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2215 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2220 protected ExternalRoutersListener getDataTreeChangeListener()
2222 return ExternalRoutersListener.this;