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.net.InetAddress;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.Future;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
29 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
32 import org.opendaylight.genius.mdsalutil.ActionInfo;
33 import org.opendaylight.genius.mdsalutil.ActionType;
34 import org.opendaylight.genius.mdsalutil.BucketInfo;
35 import org.opendaylight.genius.mdsalutil.FlowEntity;
36 import org.opendaylight.genius.mdsalutil.GroupEntity;
37 import org.opendaylight.genius.mdsalutil.InstructionInfo;
38 import org.opendaylight.genius.mdsalutil.InstructionType;
39 import org.opendaylight.genius.mdsalutil.MDSALUtil;
40 import org.opendaylight.genius.mdsalutil.MatchFieldType;
41 import org.opendaylight.genius.mdsalutil.MatchInfo;
42 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
45 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
46 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
47 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
90 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;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
107 import org.opendaylight.yangtools.concepts.ListenerRegistration;
108 import org.opendaylight.yangtools.yang.binding.DataObject;
109 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
110 import org.opendaylight.yangtools.yang.common.RpcResult;
111 import org.slf4j.Logger;
112 import org.slf4j.LoggerFactory;
114 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener> {
115 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
116 private ListenerRegistration<DataChangeListener> listenerRegistration;
117 private final DataBroker dataBroker;
118 private final IMdsalApiManager mdsalManager;
119 private final ItmRpcService itmManager;
120 private final OdlInterfaceRpcService interfaceManager;
121 private final IdManagerService idManager;
122 private final NaptManager naptManager;
123 private final NAPTSwitchSelector naptSwitchSelector;
124 private final IBgpManager bgpManager;
125 private final VpnRpcService vpnService;
126 private final FibRpcService fibService;
127 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
128 private final NaptEventHandler naptEventHandler;
129 private final NaptPacketInHandler naptPacketInHandler;
130 private final IFibManager fibManager;
131 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
132 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
134 public ExternalRoutersListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
135 final ItmRpcService itmManager,
136 final OdlInterfaceRpcService interfaceManager,
137 final IdManagerService idManager,
138 final NaptManager naptManager,
139 final NAPTSwitchSelector naptSwitchSelector,
140 final IBgpManager bgpManager,
141 final VpnRpcService vpnService,
142 final FibRpcService fibService,
143 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
144 final NaptEventHandler naptEventHandler,
145 final NaptPacketInHandler naptPacketInHandler,
146 final IFibManager fibManager) {
147 super(Routers.class, ExternalRoutersListener.class);
148 this.dataBroker = dataBroker;
149 this.mdsalManager = mdsalManager;
150 this.itmManager = itmManager;
151 this.interfaceManager = interfaceManager;
152 this.idManager = idManager;
153 this.naptManager = naptManager;
154 this.naptSwitchSelector = naptSwitchSelector;
155 this.bgpManager = bgpManager;
156 this.vpnService = vpnService;
157 this.fibService = fibService;
158 this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
159 this.naptEventHandler = naptEventHandler;
160 this.naptPacketInHandler = naptPacketInHandler;
161 this.fibManager = fibManager;
165 LOG.info("{} init", getClass().getSimpleName());
166 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
171 protected InstanceIdentifier<Routers> getWildCardPath() {
172 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
176 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
178 LOG.info("NAT Service : Add external router event for {}", routers.getRouterName());
180 // Populate the router-id-name container
181 String routerName = routers.getRouterName();
182 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
183 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
184 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
186 LOG.info("NAT Service : Installing NAT default route on all dpns part of router {}", routers.getRouterName());
188 addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
189 } catch (Exception ex) {
190 LOG.debug("NAT Service : Exception {} while Installing NAT default route on all dpns part of router {}",ex,routers.getRouterName());
193 if( !routers.isEnableSnat()) {
194 LOG.info("NAT Service : SNAT is disabled for external router {} ", routers.getRouterName());
198 handleEnableSnat(routers);
201 public void handleEnableSnat(Routers routers){
202 String routerName = routers.getRouterName();
203 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
205 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
206 naptManager.initialiseExternalCounter(routers, segmentId);
208 subnetRegisterMapping(routers,segmentId);
210 // Allocate Primary Napt Switch for this router
211 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,segmentId);
212 if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
213 LOG.debug("NAT Service : Primary NAPT switch with DPN ID {} is already elected for router",primarySwitchId,routerName);
216 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
217 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
218 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
219 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
222 LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
224 long bgpVpnId = NatConstants.INVALID_ID;
225 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
226 if (bgpVpnUuid != null) {
227 bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
229 if (bgpVpnId != NatConstants.INVALID_ID){
230 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, segmentId, false);
232 // write metadata and punt
233 installOutboundMissEntry(routerName, primarySwitchId);
234 // Now install entries in SNAT tables to point to Primary for each router
235 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
236 if (switches != null) {
237 for (BigInteger dpnId : switches) {
238 // Handle switches and NAPT switches separately
239 if (!dpnId.equals(primarySwitchId)) {
240 LOG.debug("NAT Service : Handle Ordinary switch");
241 handleSwitches(dpnId, routerName, primarySwitchId);
243 LOG.debug("NAT Service : Handle NAPT switch");
244 handlePrimaryNaptSwitch(dpnId, routerName);
245 installNaptPfibExternalOutputFlow(routers, dpnId);
251 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,segmentId);
252 if (externalIps == null || externalIps.isEmpty()) {
253 LOG.debug("NAT Service : Internal External mapping found for router {}",routerName);
256 for (String externalIpAddrPrefix : externalIps) {
257 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
258 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
262 /*// call registerMapping Api
263 LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
265 List<Uuid> subnetList = null;
266 List<String> externalIps = null;
268 InstanceIdentifier<Routers> id = InstanceIdentifier
269 .builder(ExtRouters.class)
270 .child(Routers.class, new RoutersKey(routerName))
273 Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
275 if(extRouters.isPresent())
277 LOG.debug("NAT Service : Fetching values from extRouters model");
278 Routers routerEntry= extRouters.get();
279 subnetList = routerEntry.getSubnetIds();
280 externalIps = routerEntry.getExternalIps();
282 int extIpCounter = externalIps.size();
283 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
284 for(Uuid subnet : subnetList) {
285 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
286 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
287 .builder(Subnetmaps.class)
288 .child(Subnetmap.class, new SubnetmapKey(subnet))
290 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
293 Subnetmap subnetmapEntry = sn.get();
294 String subnetString = subnetmapEntry.getSubnetIp();
295 String[] subnetSplit = subnetString.split("/");
296 String subnetIp = subnetSplit[0];
297 String subnetPrefix = "0";
298 if(subnetSplit.length == 2) {
299 subnetPrefix = subnetSplit[1];
301 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
302 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
304 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
305 if(extIpCounter != 0) {
306 if(counter < extIpCounter) {
307 String[] IpSplit = externalIps.get(counter).split("/");
308 String externalIp = IpSplit[0];
309 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
310 if(IpSplit.length==2) {
311 extPrefix = IpSplit[1];
313 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
314 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
315 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
316 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
317 externalIp, extPrefix);
319 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
320 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
321 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
324 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
325 LOG.debug("NAT Service : Counter on externalIps got reset");
326 String[] IpSplit = externalIps.get(counter).split("/");
327 String externalIp = IpSplit[0];
328 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
329 if(IpSplit.length==2) {
330 extPrefix = IpSplit[1];
332 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
333 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
334 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
335 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
336 externalIp, extPrefix);
338 String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
339 LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
340 handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
345 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
348 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
352 LOG.info("NAT Service : handleEnableSnat() Exit");
355 private void installNaptPfibExternalOutputFlow(Routers routers, BigInteger dpnId) {
356 Long extVpnId = NatUtil.getVpnId(dataBroker, routers.getNetworkId().getValue());
358 String ip = getExternalIpFromRouter(routers);
359 Uuid subnetId = getSubnetIdOfIp(ip);
361 if (subnetId != null) {
362 FlowEntity postNaptFlowEntity = buildNaptFibExternalOutputFlowEntity(dpnId, extVpnId, subnetId, ip);
363 mdsalManager.installFlow(postNaptFlowEntity);
367 private Uuid getSubnetIdOfIp(String ip) {
369 IpAddress externalIpv4Address = new IpAddress(new Ipv4Address(ip));
370 Port port = NatUtil.getNeutronPortForRouterGetewayIp(dataBroker, externalIpv4Address);
371 Uuid subnetId = NatUtil.getSubnetIdForFloatingIp(port, externalIpv4Address);
377 private String getExternalIpFromRouter(Routers routers) {
378 List<String> extIps = routers.getExternalIps();
379 if (extIps != null && !extIps.isEmpty()) {
380 return extIps.get(0);
385 private void subnetRegisterMapping(Routers routerEntry,Long segmentId) {
386 List<Uuid> subnetList = null;
387 List<String> externalIps = null;
388 LOG.debug("NAT Service : Fetching values from extRouters model");
389 subnetList = routerEntry.getSubnetIds();
390 externalIps = routerEntry.getExternalIps();
392 int extIpCounter = externalIps.size();
393 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
394 for(Uuid subnet : subnetList) {
395 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
396 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
397 .builder(Subnetmaps.class)
398 .child(Subnetmap.class, new SubnetmapKey(subnet))
400 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
403 Subnetmap subnetmapEntry = sn.get();
404 String subnetString = subnetmapEntry.getSubnetIp();
405 String[] subnetSplit = subnetString.split("/");
406 String subnetIp = subnetSplit[0];
407 String subnetPrefix = "0";
408 if(subnetSplit.length == 2) {
409 subnetPrefix = subnetSplit[1];
411 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
412 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
414 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
415 if(extIpCounter != 0) {
416 if(counter < extIpCounter) {
417 String[] IpSplit = externalIps.get(counter).split("/");
418 String externalIp = IpSplit[0];
419 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
420 if(IpSplit.length==2) {
421 extPrefix = IpSplit[1];
423 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
424 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
425 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
426 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
427 externalIp, extPrefix);
429 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
430 LOG.debug("NAT Service : Counter on externalIps got reset");
431 String[] IpSplit = externalIps.get(counter).split("/");
432 String externalIp = IpSplit[0];
433 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
434 if(IpSplit.length==2) {
435 extPrefix = IpSplit[1];
437 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
438 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
439 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
440 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
441 externalIp, extPrefix);
445 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
447 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
452 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
453 //Check if BGP VPN exists. If exists then invoke the new method.
454 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
455 if(bgpVpnId != NatConstants.INVALID_ID) {
456 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
457 if (bgpVpnUuid != null) {
458 String bgpVpnName = bgpVpnUuid.getValue();
459 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
460 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
461 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
463 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
467 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
468 addOrDelDefaultFibRouteForSNAT(routerName, create);
471 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
472 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
473 if (switches == null || switches.isEmpty()) {
474 LOG.debug("No switches found for router {}",routerName);
477 long routerId = NatUtil.readVpnId(dataBroker, routerName);
478 if (routerId == NatConstants.INVALID_ID) {
479 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
482 for (BigInteger dpnId : switches) {
484 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
485 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
487 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
488 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
493 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
494 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
495 if(dpnIds == null || dpnIds.isEmpty()) {
496 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
499 long routerId = NatUtil.getVpnId(dataBroker, routerName);
500 for (BigInteger dpnId : dpnIds) {
502 if (bgpVpnId != NatConstants.INVALID_ID) {
503 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
504 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
506 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
507 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
510 if (bgpVpnId != NatConstants.INVALID_ID) {
511 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
512 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
514 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
515 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
521 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
523 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
525 Optional<T> result = Optional.absent();
528 result = tx.read(datastoreType, path).get();
532 throw new RuntimeException(e);
539 public void close() throws Exception
541 if (listenerRegistration != null)
545 listenerRegistration.close();
547 catch (final Exception e)
549 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
552 listenerRegistration = null;
554 LOG.debug("ExternalRoutersListener Closed");
557 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
558 long routerId = NatUtil.getVpnId(dataBroker, routerName);
559 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
560 if(routerId != NatConstants.INVALID_ID) {
561 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
562 createOutboundTblEntry(primarySwitchId, routerId);
564 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
568 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
569 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
570 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
573 private String getFlowRefNaptFib(BigInteger dpnId, short tableId, long routerID, String externalIp) {
574 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
575 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).
576 append(NatConstants.FLOWID_SEPARATOR).append(externalIp).toString();
579 public BigInteger getCookieOutboundFlow(long routerId) {
580 return NwConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
581 BigInteger.valueOf(routerId));
584 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
585 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
586 List<MatchInfo> matches = new ArrayList<>();
587 matches.add(new MatchInfo(MatchFieldType.eth_type,
588 new long[] { 0x0800L }));
589 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
590 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
592 List<InstructionInfo> instructions = new ArrayList<>();
593 List<ActionInfo> actionsInfos = new ArrayList<>();
594 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
595 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
596 instructions.add(new InstructionInfo(InstructionType.write_metadata,
597 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
599 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
600 BigInteger cookie = getCookieOutboundFlow(routerId);
601 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
603 cookie, matches, instructions);
604 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
608 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
609 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
610 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
611 LOG.debug("NAT Service : Installing flow {}", flowEntity);
612 mdsalManager.installFlow(flowEntity);
615 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
616 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
617 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
619 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
620 .setSourceDpid(srcDpId)
621 .setDestinationDpid(dstDpId)
622 .setTunnelType(tunType)
624 rpcResult = result.get();
625 if(!rpcResult.isSuccessful()) {
626 tunType = TunnelTypeGre.class ;
627 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
628 .setSourceDpid(srcDpId)
629 .setDestinationDpid(dstDpId)
630 .setTunnelType(tunType)
632 rpcResult = result.get();
633 if(!rpcResult.isSuccessful()) {
634 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
636 return rpcResult.getResult().getInterfaceName();
638 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
640 return rpcResult.getResult().getInterfaceName();
642 } catch (InterruptedException | ExecutionException | NullPointerException e) {
643 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
649 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
650 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAOT switch dpnId {} ", dpnId);
651 // Install miss entry pointing to group
652 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
653 mdsalManager.installFlow(flowEntity);
656 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
657 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
658 // Install the select group
659 long groupId = createGroupId(getGroupIdKey(routerName));
660 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
661 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
662 mdsalManager.installGroup(groupEntity);
663 // Install miss entry pointing to group
664 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
665 mdsalManager.installFlow(flowEntity);
668 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
669 long groupId = createGroupId(getGroupIdKey(routerName));
670 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
671 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
672 mdsalManager.installGroup(groupEntity);
676 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
678 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
679 long routerId = NatUtil.getVpnId(dataBroker, routerName);
680 List<MatchInfo> matches = new ArrayList<>();
681 matches.add(new MatchInfo(MatchFieldType.eth_type,
682 new long[] { 0x0800L }));
683 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
684 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
687 List<InstructionInfo> instructions = new ArrayList<>();
688 List<ActionInfo> actionsInfo = new ArrayList<>();
690 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
691 BigInteger.valueOf(routerId)}) ;
692 actionsInfo.add(actionSetField);
693 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
694 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
695 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
696 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
697 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
698 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
699 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
701 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
705 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
707 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
709 long routerId = NatUtil.getVpnId(dataBroker, routerName);
710 List<MatchInfo> matches = new ArrayList<MatchInfo>();
711 matches.add(new MatchInfo(MatchFieldType.eth_type,
712 new long[] { 0x0800L }));
713 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
714 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
716 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
717 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
718 { NwConstants.OUTBOUND_NAPT_TABLE }));
720 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
721 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
722 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
723 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
725 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
729 // TODO : Replace this with ITM Rpc once its available with full functionality
730 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
731 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
732 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
733 mdsalManager.installFlow(flowEntity);
737 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
739 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
740 List<MatchInfo> matches = new ArrayList<>();
741 matches.add(new MatchInfo(MatchFieldType.eth_type,
742 new long[] { 0x0800L }));
743 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
745 List<InstructionInfo> instructions = new ArrayList<>();
746 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
747 { MetaDataUtil.getVpnIdMetadata(routerId.longValue()), MetaDataUtil.METADATA_MASK_VRFID }));
748 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
749 { NwConstants.OUTBOUND_NAPT_TABLE }));
750 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
751 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
752 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
753 NwConstants.COOKIE_TS_TABLE, matches, instructions);
757 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
758 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
759 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
762 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
763 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
764 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
767 private String getGroupIdKey(String routerName){
768 String groupIdKey = new String("snatmiss." + routerName);
772 protected long createGroupId(String groupIdKey) {
773 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
774 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
777 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
778 RpcResult<AllocateIdOutput> rpcResult = result.get();
779 return rpcResult.getResult().getIdValue();
780 } catch (NullPointerException | InterruptedException | ExecutionException e) {
786 protected void createGroupIdPool() {
787 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
788 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
789 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
790 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
793 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
794 if ((result != null) && (result.get().isSuccessful())) {
795 LOG.debug("NAT Service : Created GroupIdPool");
797 LOG.error("NAT Service : Unable to create GroupIdPool");
799 } catch (InterruptedException | ExecutionException e) {
800 LOG.error("Failed to create PortPool for NAPT Service",e);
804 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
805 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
806 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
807 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
808 List<BucketInfo> listBucketInfo = new ArrayList<>();
809 long routerId = NatUtil.getVpnId(dataBroker, routerName);
811 if(ifNamePrimary != null) {
812 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
813 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
815 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
817 listBucketInfo.add(0, bucketPrimary);
818 installSnatMissEntry(dpnId, listBucketInfo, routerName);
821 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
822 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
823 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
824 List<BucketInfo> listBucketInfo = new ArrayList<>();
825 long routerId = NatUtil.getVpnId(dataBroker, routerName);
827 if (ifNamePrimary != null) {
828 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
829 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
831 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
833 listBucketInfo.add(0, bucketPrimary);
834 return listBucketInfo;
836 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
839 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
842 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
845 List<BucketInfo> listBucketInfo = new ArrayList<>();
846 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
847 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
848 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
849 listBucketInfo.add(0, bucketPrimary);
852 long routerId = NatUtil.getVpnId(dataBroker, routerName);
854 installSnatMissEntryForPrimrySwch(dpnId, routerName);
855 installTerminatingServiceTblEntry(dpnId, routerName);
856 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
857 installNaptPfibEntry(dpnId, routerId);
858 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
859 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
860 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
861 installNaptPfibEntry(dpnId, vpnId);
865 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
866 List<BucketInfo> listBucketInfo = new ArrayList<>();
867 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
868 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NwConstants.INTERNAL_TUNNEL_TABLE)}));
869 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
870 listBucketInfo.add(0, bucketPrimary);
871 return listBucketInfo;
874 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
875 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
876 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
877 mdsalManager.installFlow(naptPfibFlowEntity);
880 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
882 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
883 List<MatchInfo> matches = new ArrayList<>();
884 matches.add(new MatchInfo(MatchFieldType.eth_type,
885 new long[] { 0x0800L }));
886 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
887 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
889 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
890 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
891 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
892 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
894 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
895 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
896 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
897 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
899 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
903 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
904 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
905 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
906 if(networkId == null) {
907 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
910 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
911 if(vpnName == null) {
912 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
913 networkId, externalIp, routerId);
916 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
917 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
920 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
921 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
923 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
924 //Generate VPN label for the external IP
925 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
926 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
928 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
929 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
932 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
933 if (result.isSuccessful()) {
934 LOG.debug("NAT Service : inside apply with result success");
935 GenerateVpnLabelOutput output = result.getResult();
936 final long label = output.getLabel();
938 int externalIpInDsFlag = 0;
939 //Get IPMaps from the DB for the router ID
940 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
941 if (dbIpMaps != null) {
942 for (IpMap dbIpMap : dbIpMaps) {
943 String dbExternalIp = dbIpMap.getExternalIp();
944 //Select the IPMap, whose external IP is the IP for which FIB is installed
945 if (externalIp.equals(dbExternalIp)) {
946 String dbInternalIp = dbIpMap.getInternalIp();
947 IpMapKey dbIpMapKey = dbIpMap.getKey();
948 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
949 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
950 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
951 externalIpInDsFlag++;
954 if (externalIpInDsFlag <=0) {
955 LOG.debug("NAT Service : External Ip {} not found in DS,Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
956 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", externalIp, label, routerId);
957 return Futures.immediateFailedFuture(new Exception(errMsg));
960 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
965 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
966 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
967 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
969 //Install custom FIB routes
970 List<Instruction> customInstructions = new ArrayList<>();
971 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
972 makeTunnelTableEntry(dpnId, label, customInstructions);
973 makeLFibTableEntry(dpnId, label, tableId);
975 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
976 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
977 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
978 return JdkFutureAdapters.listenInPoolThread(future);
980 LOG.error("NAT Service : inside apply with result failed");
981 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
982 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
987 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
990 public void onFailure(Throwable error) {
991 log.error("NAT Service : Error in generate label or fib install process", error);
995 public void onSuccess(RpcResult<Void> result) {
996 if (result.isSuccessful()) {
997 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
999 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1005 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
1006 List<MatchInfo> matches = new ArrayList<>();
1007 matches.add(new MatchInfo(MatchFieldType.eth_type,
1008 new long[]{0x8847L}));
1009 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1011 List<Instruction> instructions = new ArrayList<>();
1012 List<ActionInfo> actionsInfos = new ArrayList<>();
1013 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
1014 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
1015 instructions.add(writeInstruction);
1016 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
1018 // Install the flow entry in L3_LFIB_TABLE
1019 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1021 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1023 COOKIE_VM_LFIB_TABLE, matches, instructions);
1025 mdsalManager.installFlow(dpId, flowEntity);
1027 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
1030 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
1031 List<MatchInfo> mkMatches = new ArrayList<>();
1033 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
1035 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1037 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1038 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
1039 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1041 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1044 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1045 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1046 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1050 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1051 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1052 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1053 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1057 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1058 String routerName = original.getRouterName();
1059 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1060 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1061 Uuid networkId = original.getNetworkId();
1063 // Check if its update on SNAT flag
1064 boolean originalSNATEnabled = original.isEnableSnat();
1065 boolean updatedSNATEnabled = update.isEnableSnat();
1066 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1067 if(originalSNATEnabled != updatedSNATEnabled) {
1068 if(originalSNATEnabled) {
1069 //SNAT disabled for the router
1070 Uuid networkUuid = original.getNetworkId();
1071 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1072 if (routerId == NatConstants.INVALID_ID) {
1073 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1076 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1077 handleDisableSnat(routerName, networkUuid, externalIps, false, null);
1079 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1080 handleEnableSnat(original);
1084 //Check if the Update is on External IPs
1085 LOG.debug("NAT Service : Checking if this is update on External IPs");
1086 List<String> originalExternalIpsList = original.getExternalIps();
1087 List<String> updatedExternalIpsList = update.getExternalIps();
1088 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1089 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1091 //Check if the External IPs are added during the update.
1092 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1093 if(addedExternalIps.size() != 0) {
1094 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1095 for (String addedExternalIp : addedExternalIps) {
1097 1) Do nothing in the IntExtIp model.
1098 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1100 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1101 String externalIp = externalIpParts[0];
1102 String externalIpPrefix = externalIpParts[1];
1103 String externalpStr = externalIp + "/" + externalIpPrefix;
1104 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1105 externalpStr, routerId);
1106 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1108 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1111 //Check if the External IPs are removed during the update.
1112 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1113 if(removedExternalIps.size() > 0) {
1114 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1115 List<String> removedExternalIpsAsList = new ArrayList<>();
1116 for (String removedExternalIp : removedExternalIps) {
1118 1) Remove the mappings in the IntExt IP model which has external IP.
1119 2) Remove the external IP in the ExternalCounter model.
1120 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1121 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1122 4) Increase the count of the allocated external IP by one.
1123 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.
1124 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1125 7) Advertise to the BGP for removing the route for the removed external IPs.
1128 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1129 String externalIp = externalIpParts[0];
1130 String externalIpPrefix = externalIpParts[1];
1131 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1133 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1134 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1135 String vpnName = "";
1136 if(vpnUuId != null){
1137 vpnName = vpnUuId.getValue();
1139 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1141 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1142 //Get the internal IPs which are associated to the removed external IPs
1143 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1144 List<String> removedInternalIps = new ArrayList<>();
1145 for(IpMap ipMap : ipMaps){
1146 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1147 removedInternalIps.add(ipMap.getInternalIp());
1151 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1152 for(String removedInternalIp : removedInternalIps){
1153 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1154 removedInternalIp, routerId);
1155 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1158 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1159 externalIpAddrStr, routerId );
1160 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1161 removedExternalIpsAsList.add(externalIpAddrStr);
1163 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1164 for(String removedInternalIp : removedInternalIps) {
1165 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1168 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1169 //Get the internalIP and internal Port which were associated to the removed external IP.
1170 List<Integer> externalPorts = new ArrayList<>();
1171 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1172 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1173 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1174 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1175 if (ipPortMapping.isPresent()) {
1176 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1177 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1178 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1179 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1180 for(IpPortMap ipPortMap : ipPortMaps){
1181 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1182 if(ipPortExternal.getIpAddress().equals(externalIp)){
1183 externalPorts.add(ipPortExternal.getPortNum());
1184 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1185 if(removedInternalIpPorts != null){
1186 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1187 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1189 removedInternalIpPorts = new ArrayList<>();
1190 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1191 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1198 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1199 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1200 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1201 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1202 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1203 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1204 for(String removedInternalIpPort : removedInternalIpPorts){
1205 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1206 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1207 //Remove the IP port incomint packer map.
1208 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1209 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1210 if(removedInternalIpPortParts.length == 2){
1211 String removedInternalIp = removedInternalIpPortParts[0];
1212 String removedInternalPort = removedInternalIpPortParts[1];
1213 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1214 if (removedInternalPortsList != null){
1215 removedInternalPortsList.add(removedInternalPort);
1216 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1218 removedInternalPortsList = new ArrayList<>();
1219 removedInternalPortsList.add(removedInternalPort);
1220 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1226 // Delete the entry from SnatIntIpPortMap DS
1227 Set<String> internalIps = internalIpPortMap.keySet();
1228 for(String internalIp : internalIps){
1229 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1230 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1233 naptManager.removeNaptPortPool(externalIp);
1235 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1236 for(Integer externalPort : externalPorts) {
1237 //Remove the NAPT translation entries from Inbound NAPT table
1238 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1241 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1242 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1243 String internalIp = internalIpPort.getKey();
1244 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1245 List<String> internalPorts = internalIpPort.getValue();
1246 for(String internalPort : internalPorts){
1247 //Remove the NAPT translation entries from Outbound NAPT table
1248 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1252 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1255 //Check if its Update on subnets
1256 LOG.debug("NAT Service : Checking if this is update on subnets");
1257 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1258 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1259 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1260 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1261 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1263 //Check if the Subnet IDs are added during the update.
1264 if(addedSubnetIds.size() != 0){
1265 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1266 for(Uuid addedSubnetId : addedSubnetIds){
1268 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.
1269 2) Increase the count of the selected external IP by one.
1270 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.
1272 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1273 if(subnetIp != null) {
1274 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1277 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1280 //Check if the Subnet IDs are removed during the update.
1281 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1282 if(removedSubnetIds.size() != 0){
1283 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1284 for(Uuid removedSubnetId : removedSubnetIds){
1285 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1286 if(subnetAddr != null){
1288 1) Remove the subnet IP and the external IP in the IntExtIp map
1289 2) Decrease the count of the coresponding external IP by one.
1290 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1293 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1294 if (externalIp == null) {
1295 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1299 naptManager.updateCounter(routerId, externalIp, false);
1300 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1301 if (!isExternalIpAllocated(externalIp)) {
1302 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1303 List<String> externalIps = new ArrayList<>();
1304 externalIps.add(externalIp);
1305 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1306 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1307 dpnId,routerId,networkId,externalIps);
1310 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1311 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1314 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1318 private boolean isExternalIpAllocated(String externalIp) {
1319 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1320 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1321 if (externalCountersData.isPresent()) {
1322 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1323 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1324 for(ExternalCounters ext : externalCounters) {
1325 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1326 if (externalIpCount.getExternalIp().equals(externalIp)) {
1327 if (externalIpCount.getCounter() != 0) {
1338 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1339 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1340 if (leastLoadedExtIpAddr != null) {
1341 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1342 String leastLoadedExtIp = externalIpParts[0];
1343 String leastLoadedExtIpPrefix = externalIpParts[1];
1344 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1345 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1346 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1347 subnetIp = subnetIpParts[0];
1348 String subnetIpPrefix = subnetIpParts[1];
1349 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1350 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1351 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1352 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1355 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1356 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1357 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1360 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1361 IpMapKey ipMapKey = new IpMapKey(internalIp);
1362 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1363 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1364 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1368 //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.
1369 //Get the VPN Name using the network ID
1370 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1371 if (vpnName != null) {
1372 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1373 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1374 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1375 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1377 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1378 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1383 protected Long checkExternalIpLabel(long routerId, String externalIp){
1384 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1385 for(IpMap ipMap : ipMaps){
1386 if(ipMap.getExternalIp().equals(externalIp)){
1387 if (ipMap.getLabel() != null){
1388 return ipMap.getLabel();
1396 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1397 LOG.trace("NAT Service : Router delete method");
1400 ROUTER DELETE SCENARIO
1401 1) Get the router ID from the event.
1402 2) Build the cookie information from the router ID.
1403 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1404 4) Build the flow with the cookie value.
1405 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1406 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1407 7) Get the list of external IP address maintained for the router ID.
1408 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1409 9) Withdraw the corresponding routes from the BGP.
1412 if (identifier == null || router == null) {
1413 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1417 String routerName = router.getRouterName();
1418 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1419 addOrDelDefFibRouteToSNAT(routerName, false);
1420 Uuid networkUuid = router.getNetworkId();
1421 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1422 if (routerId == NatConstants.INVALID_ID) {
1423 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1426 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1427 handleDisableSnat(routerName, networkUuid, externalIps, true, null);
1431 public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1432 LOG.info("NAT Service : handleDisableSnat() Entry");
1434 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1436 BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1437 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1438 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1439 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1442 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId, externalIps);
1443 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1445 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1446 } catch (Exception ex) {
1447 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1450 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1451 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1452 naptManager.removeMapping(routerId);
1455 removeNaptSwitch(routerName);
1457 updateNaptSwitch(routerName, BigInteger.ZERO);
1460 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1461 naptManager.removeExternalCounter(routerId);
1462 } catch (Exception ex) {
1463 LOG.error("Exception while handling disableSNAT : {}", ex);
1465 LOG.info("NAT Service : handleDisableSnat() Exit");
1468 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1469 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1471 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1472 BigInteger naptSwitchDpnId = null;
1473 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1474 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1475 if (rtrToNapt.isPresent()) {
1476 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1478 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1480 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1482 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1483 } catch (Exception ex) {
1484 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1486 } catch (Exception ex) {
1487 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1489 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1492 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1493 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1494 .setPrimarySwitchId(naptSwitchId).build();
1496 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1497 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1498 } catch (Exception ex) {
1499 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1500 naptSwitchId,routerName);
1502 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1503 naptSwitchId,routerName);
1506 protected void removeNaptSwitch(String routerName){
1507 // Remove router and switch from model
1508 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1509 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1510 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1513 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName, List<String> externalIps){
1515 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1516 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1518 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1519 // traffic which comes from the VMs of the NAPT switches)
1520 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1521 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1523 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);
1524 mdsalManager.removeFlow(pSNatFlowEntity);
1526 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1527 // traffic which comes from the VMs of the non NAPT switches)
1528 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1529 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1531 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);
1532 mdsalManager.removeFlow(tsNatFlowEntity);
1534 //Remove the Outbound flow entry which forwards the packet to FIB Table
1535 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1536 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1538 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);
1539 mdsalManager.removeFlow(outboundNatFlowEntity);
1541 removeNaptFibExternalOutputFlows(routerId, dpnId, externalIps);
1543 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1544 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1545 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1547 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);
1548 mdsalManager.removeFlow(natPfibFlowEntity);
1550 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1551 //Get the VPN ID from the ExternalNetworks model
1553 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1554 // ie called from router delete cases
1555 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1556 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1557 if(vpnUuid != null) {
1558 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1559 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1562 // ie called from disassociate vpn case
1563 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1564 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1565 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1568 if(vpnId != NatConstants.INVALID_ID){
1569 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1570 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1571 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1572 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);
1573 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1576 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1577 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1578 if(ipPortMapping == null){
1579 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1583 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1584 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1585 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1586 for(IpPortMap ipPortMap : ipPortMaps){
1587 String ipPortInternal = ipPortMap.getIpPortInternal();
1588 String[] ipPortParts = ipPortInternal.split(":");
1589 if(ipPortParts.length != 2) {
1590 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1593 String internalIp = ipPortParts[0];
1594 String internalPort = ipPortParts[1];
1596 //Build the flow for the outbound NAPT table
1597 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1598 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1600 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);
1601 mdsalManager.removeFlow(outboundNaptFlowEntity);
1603 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1604 String externalIp = ipPortExternal.getIpAddress();
1605 int externalPort = ipPortExternal.getPortNum();
1607 //Build the flow for the inbound NAPT table
1608 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1609 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1611 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);
1612 mdsalManager.removeFlow(inboundNaptFlowEntity);
1617 private void removeNaptFibExternalOutputFlows(long routerId, BigInteger dpnId, List<String> externalIps) {
1618 for (String ip : externalIps) {
1619 String extIp = removeMaskFromIp(ip);
1620 String postNaptFlowRef = getFlowRefNaptFib(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId, extIp);
1621 LOG.info("NAT Service : Remove the flow in the " + NwConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and router ID {} and IP {}", dpnId, routerId, extIp);
1622 mdsalManager.removeFlow(NatUtil.buildFlowEntity(dpnId,NwConstants.NAPT_PFIB_TABLE, postNaptFlowRef));
1626 private String removeMaskFromIp(String ip) {
1627 if (ip != null && !ip.trim().isEmpty()) {
1628 return ip.split("/")[0];
1633 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1635 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1636 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1638 //Remove the NAPT PFIB TABLE entry
1640 if(vpnName != null) {
1641 // ie called from disassociate vpn case
1642 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1643 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1644 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1647 if(vpnId != NatConstants.INVALID_ID){
1648 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1649 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1650 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1651 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);
1652 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1654 // Remove IP-PORT active NAPT entries and release port from IdManager
1655 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1656 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1657 if(ipPortMapping == null){
1658 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1661 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1662 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1663 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1664 for(IpPortMap ipPortMap : ipPortMaps){
1665 String ipPortInternal = ipPortMap.getIpPortInternal();
1666 String[] ipPortParts = ipPortInternal.split(":");
1667 if(ipPortParts.length != 2) {
1668 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1671 String internalIp = ipPortParts[0];
1672 String internalPort = ipPortParts[1];
1674 //Build the flow for the outbound NAPT table
1675 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1676 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1678 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);
1679 mdsalManager.removeFlow(outboundNaptFlowEntity);
1681 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1682 String externalIp = ipPortExternal.getIpAddress();
1683 int externalPort = ipPortExternal.getPortNum();
1685 //Build the flow for the inbound NAPT table
1686 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1687 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1689 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);
1690 mdsalManager.removeFlow(inboundNaptFlowEntity);
1692 // Finally release port from idmanager
1693 String internalIpPort = internalIp +":"+internalPort;
1694 naptManager.removePortFromPool(internalIpPort, externalIp);
1696 //Remove sessions from models
1697 naptManager.removeIpPortMappingForRouterID(routerId);
1698 naptManager.removeIntIpPortMappingForRouterID(routerId);
1702 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1706 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1707 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1709 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1710 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1711 if(allSwitchList == null || allSwitchList.isEmpty()){
1712 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1715 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1716 for (BigInteger dpnId : allSwitchList) {
1717 if (!naptSwitchDpnId.equals(dpnId)) {
1718 LOG.info("NAT Service : Handle Ordinary switch");
1720 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1721 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1722 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1724 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1725 mdsalManager.removeFlow(pSNatFlowEntity);
1727 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1728 long groupId = createGroupId(getGroupIdKey(routerName));
1729 List<BucketInfo> listBucketInfo = new ArrayList<>();
1730 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1732 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1733 mdsalManager.removeGroup(pSNatGroupEntity);
1739 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1740 //Withdraw the corresponding routes from the BGP.
1741 //Get the network ID using the router ID.
1742 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1743 externalIps,routerId,networkUuid, vpnName);
1744 if(networkUuid == null ){
1745 LOG.error("NAT Service : networkId is null");
1749 if (externalIps == null || externalIps.isEmpty()) {
1750 LOG.debug("NAT Service : externalIps is null");
1754 if(vpnName ==null) {
1755 //Get the VPN Name using the network ID
1756 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1757 if (vpnName == null) {
1758 LOG.error("No VPN associated with ext nw {} for the router {}",
1759 networkUuid, routerId);
1763 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1765 //Remove custom FIB routes
1766 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1767 for (String extIp : externalIps) {
1768 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1772 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1773 clearBgpRoutes(extIp,vpnName);
1774 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1777 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1778 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1780 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1781 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1785 final long label = tempLabel;
1786 final String externalIp = extIp;
1788 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1789 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1791 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1794 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1796 if (result.isSuccessful()) {
1797 removeTunnelTableEntry(dpnId, label);
1798 removeLFibTableEntry(dpnId, label);
1799 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1800 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1801 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1803 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1805 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1811 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1814 public void onFailure(Throwable error) {
1815 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1819 public void onSuccess(RpcResult<Void> result) {
1820 if (result.isSuccessful()) {
1821 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1823 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1829 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1830 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1831 //Get IPMaps from the DB for the router ID
1832 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1833 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1834 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1838 long tempLabel = NatConstants.INVALID_ID;
1839 for (IpMap dbIpMap : dbIpMaps) {
1840 String dbExternalIp = dbIpMap.getExternalIp();
1841 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1842 //Select the IPMap, whose external IP is the IP for which FIB is installed
1843 if (extIp.equals(dbExternalIp)) {
1844 tempLabel = dbIpMap.getLabel();
1845 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1849 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1850 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1854 final long label = tempLabel;
1855 final String externalIp = extIp;
1857 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1858 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1860 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1863 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1865 if (result.isSuccessful()) {
1866 removeTunnelTableEntry(dpnId, label);
1867 removeLFibTableEntry(dpnId, label);
1868 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1869 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1870 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1872 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1874 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1880 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1883 public void onFailure(Throwable error) {
1884 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1888 public void onSuccess(RpcResult<Void> result) {
1889 if (result.isSuccessful()) {
1890 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1892 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1898 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1899 //Withdraw the corresponding routes from the BGP.
1900 //Get the network ID using the router ID.
1901 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1902 externalIps,routerId,networkUuid, vpnName);
1903 if (networkUuid == null) {
1904 LOG.error("NAT Service : networkId is null");
1908 if (externalIps == null || externalIps.isEmpty()) {
1909 LOG.debug("NAT Service : externalIps is null");
1913 if (vpnName == null) {
1914 //Get the VPN Name using the network ID
1915 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1916 if (vpnName == null) {
1917 LOG.error("No VPN associated with ext nw {} for the router {}",
1918 networkUuid, routerId);
1922 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1924 //Remove custom FIB routes
1925 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1926 for (String extIp : externalIps) {
1927 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1931 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1932 //Inform BGP about the route removal
1933 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1934 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1935 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
1938 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1939 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1940 List<MatchInfo> mkMatches = new ArrayList<>();
1941 // Matching metadata
1942 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1943 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1944 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1945 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1946 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1947 mdsalManager.removeFlow(dpnId, flowEntity);
1948 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1951 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1952 List<MatchInfo> matches = new ArrayList<>();
1953 matches.add(new MatchInfo(MatchFieldType.eth_type,
1954 new long[] { 0x8847L }));
1955 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1957 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1959 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
1961 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1963 COOKIE_VM_LFIB_TABLE, matches, null);
1965 mdsalManager.removeFlow(dpnId, flowEntity);
1967 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
1971 * router association to vpn
1972 *@param routerName - Name of router
1973 *@param bgpVpnName BGP VPN name
1975 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
1976 LOG.debug("NAT Service : Router associated to BGP VPN");
1977 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
1978 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
1980 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
1982 if(bgpVpnId != NatConstants.INVALID_ID){
1983 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
1984 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
1985 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
1987 // Get the allocated Primary NAPT Switch for this router
1988 long routerId = NatUtil.getVpnId(dataBroker, routerName);
1989 LOG.debug("Router ID value {} ", routerId);
1990 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1992 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
1993 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
1996 long groupId = createGroupId(getGroupIdKey(routerName));
1997 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2003 * router disassociation from vpn
2004 *@param routerName - Name of router
2005 *@param bgpVpnName BGP VPN name
2007 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2008 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2009 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2010 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2011 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2013 // Get the allocated Primary NAPT Switch for this router
2014 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2015 LOG.debug("Router ID value {} ", routerId);
2016 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2018 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2019 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2022 long groupId = createGroupId(getGroupIdKey(routerName));
2023 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2027 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2028 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2029 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2030 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2031 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2036 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2037 routerId, boolean isSnatCfgd){
2038 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, isSnatCfgd, null);
2041 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2042 routerId, boolean isSnatCfgd, Routers router){
2043 long changedVpnId = bgpVpnId;
2044 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2045 if (bgpVpnId == NatConstants.INVALID_ID){
2046 changedVpnId = routerId;
2047 logMsg = "NAT Service : Update the router ID {}";
2050 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2051 if (switches == null || switches.isEmpty()) {
2052 LOG.debug("No switches found for router {}",routerName);
2055 for(BigInteger dpnId : switches) {
2056 // Update the BGP VPN ID in the SNAT miss entry to group
2057 if( !dpnId.equals(primarySwitchId) ) {
2058 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2059 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2060 long groupId = createGroupId(getGroupIdKey(routerName));
2062 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2065 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2066 changedVpnId, groupId, dpnId);
2067 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2068 mdsalManager.installFlow(flowEntity);
2071 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2072 changedVpnId, primarySwitchId);
2073 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2074 mdsalManager.installFlow(flowEntity);
2076 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2077 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2078 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2080 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2081 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2082 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2084 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2085 changedVpnId, primarySwitchId);
2086 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2088 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2089 " in the Primary switch {}", changedVpnId, primarySwitchId);
2090 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2092 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2093 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2094 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2095 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2096 installNaptPfibEntry(primarySwitchId, vpnId);
2102 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2103 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2104 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2105 if(ipPortMapping == null){
2106 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2110 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2111 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2112 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2113 for(IpPortMap ipPortMap : ipPortMaps){
2114 String ipPortInternal = ipPortMap.getIpPortInternal();
2115 String[] ipPortParts = ipPortInternal.split(":");
2116 if(ipPortParts.length != 2) {
2117 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2120 String internalIp = ipPortParts[0];
2121 String internalPort = ipPortParts[1];
2123 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2124 NAPTEntryEvent.Protocol protocol;
2125 switch (protocolTypes){
2127 protocol = NAPTEntryEvent.Protocol.TCP;
2130 protocol = NAPTEntryEvent.Protocol.UDP;
2133 protocol = NAPTEntryEvent.Protocol.TCP;
2135 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2136 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2137 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2138 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2139 internalAddress, externalAddress, protocol);
2140 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2141 externalAddress, internalAddress, protocol);
2147 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2149 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2150 List<MatchInfo> matches = new ArrayList<>();
2151 matches.add(new MatchInfo(MatchFieldType.eth_type,
2152 new long[] { 0x0800L }));
2153 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2154 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2156 List<InstructionInfo> instructions = new ArrayList<>();
2157 List<ActionInfo> actionsInfo = new ArrayList<>();
2159 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2160 BigInteger.valueOf(changedVpnId)}) ;
2161 actionsInfo.add(actionSetField);
2162 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2163 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2164 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
2165 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2166 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2167 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2168 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2170 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2174 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2176 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2177 List<MatchInfo> matches = new ArrayList<>();
2178 matches.add(new MatchInfo(MatchFieldType.eth_type,
2179 new long[] { 0x0800L }));
2180 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2181 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2183 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2184 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2185 { NwConstants.OUTBOUND_NAPT_TABLE }));
2187 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2188 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2189 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2190 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2192 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2196 // TODO : Replace this with ITM Rpc once its available with full functionality
2197 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2198 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2199 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2200 mdsalManager.installFlow(flowEntity);
2204 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2205 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2206 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2207 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2208 List<MatchInfo> matches = new ArrayList<>();
2209 matches.add(new MatchInfo(MatchFieldType.eth_type,
2210 new long[] { 0x0800L }));
2211 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2213 List<InstructionInfo> instructions = new ArrayList<>();
2214 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2215 { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2216 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2217 { NwConstants.OUTBOUND_NAPT_TABLE }));
2218 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2219 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2220 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2221 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2225 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2226 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2227 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2228 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2229 mdsalManager.installFlow(flowEntity);
2232 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2233 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2234 List<MatchInfo> matches = new ArrayList<>();
2235 matches.add(new MatchInfo(MatchFieldType.eth_type,
2236 new long[]{0x0800L}));
2237 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2238 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2240 List<InstructionInfo> instructions = new ArrayList<>();
2241 List<ActionInfo> actionsInfos = new ArrayList<>();
2242 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2243 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2244 instructions.add(new InstructionInfo(InstructionType.write_metadata,
2245 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2247 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2248 BigInteger cookie = getCookieOutboundFlow(routerId);
2249 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2250 cookie, matches, instructions);
2251 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2255 protected FlowEntity buildNaptFibExternalOutputFlowEntity(BigInteger dpId, long extVpnId, Uuid subnetId, String externalIp) {
2256 LOG.debug("NAT Service : buildPostSnatFlowEntity called for dpId {}, routerId {}, srcIp {}", dpId, extVpnId,
2259 List<MatchInfo> matches = new ArrayList<>();
2260 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 }));
2261 matches.add(new MatchInfo(MatchFieldType.metadata,
2262 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(extVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2263 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] { externalIp , "32" }));
2265 List<InstructionInfo> instructions = new ArrayList<>();
2266 List<ActionInfo> actionsInfos = new ArrayList<>();
2267 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2268 instructions.add(new InstructionInfo(InstructionType.write_metadata,
2269 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(extVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2271 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetId.getValue()), idManager);
2272 actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
2274 String flowRef = getFlowRefNaptFib(dpId, NwConstants.NAPT_PFIB_TABLE, extVpnId, externalIp);
2275 BigInteger cookie = getCookieOutboundFlow(extVpnId);
2276 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef, 6, flowRef, 0,
2277 0, cookie, matches, instructions);
2278 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2282 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2283 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2284 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2285 mdsalManager.installFlow(naptPfibFlowEntity);
2288 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2290 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2291 List<MatchInfo> matches = new ArrayList<>();
2292 matches.add(new MatchInfo(MatchFieldType.eth_type,
2293 new long[] { 0x0800L }));
2294 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2295 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2297 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2298 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2299 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
2300 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2302 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2303 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2304 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2305 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2307 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2312 protected ExternalRoutersListener getDataTreeChangeListener()
2314 return ExternalRoutersListener.this;