2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.natservice.internal;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.Sets;
12 import com.google.common.collect.Sets.SetView;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.JdkFutureAdapters;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
23 import java.util.Objects;
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.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
33 import org.opendaylight.genius.mdsalutil.ActionInfo;
34 import org.opendaylight.genius.mdsalutil.ActionType;
35 import org.opendaylight.genius.mdsalutil.BucketInfo;
36 import org.opendaylight.genius.mdsalutil.FlowEntity;
37 import org.opendaylight.genius.mdsalutil.GroupEntity;
38 import org.opendaylight.genius.mdsalutil.InstructionInfo;
39 import org.opendaylight.genius.mdsalutil.InstructionType;
40 import org.opendaylight.genius.mdsalutil.MDSALUtil;
41 import org.opendaylight.genius.mdsalutil.MatchFieldType;
42 import org.opendaylight.genius.mdsalutil.MatchInfo;
43 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
44 import org.opendaylight.genius.mdsalutil.NwConstants;
45 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
46 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
47 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
48 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
49 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
91 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;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
108 import org.opendaylight.yangtools.concepts.ListenerRegistration;
109 import org.opendaylight.yangtools.yang.binding.DataObject;
110 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
111 import org.opendaylight.yangtools.yang.common.RpcResult;
112 import org.slf4j.Logger;
113 import org.slf4j.LoggerFactory;
115 public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener> {
116 private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
117 private ListenerRegistration<DataChangeListener> listenerRegistration;
118 private final DataBroker dataBroker;
119 private final IMdsalApiManager mdsalManager;
120 private final ItmRpcService itmManager;
121 private final OdlInterfaceRpcService interfaceManager;
122 private final IdManagerService idManager;
123 private final NaptManager naptManager;
124 private final NAPTSwitchSelector naptSwitchSelector;
125 private final IBgpManager bgpManager;
126 private final VpnRpcService vpnService;
127 private final FibRpcService fibService;
128 private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
129 private final NaptEventHandler naptEventHandler;
130 private final NaptPacketInHandler naptPacketInHandler;
131 private final IFibManager fibManager;
132 private final IVpnManager vpnManager;
133 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
134 static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
136 public ExternalRoutersListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
137 final ItmRpcService itmManager,
138 final OdlInterfaceRpcService interfaceManager,
139 final IdManagerService idManager,
140 final NaptManager naptManager,
141 final NAPTSwitchSelector naptSwitchSelector,
142 final IBgpManager bgpManager,
143 final VpnRpcService vpnService,
144 final FibRpcService fibService,
145 final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
146 final NaptEventHandler naptEventHandler,
147 final NaptPacketInHandler naptPacketInHandler,
148 final IFibManager fibManager,
149 final IVpnManager vpnManager) {
150 super(Routers.class, ExternalRoutersListener.class);
151 this.dataBroker = dataBroker;
152 this.mdsalManager = mdsalManager;
153 this.itmManager = itmManager;
154 this.interfaceManager = interfaceManager;
155 this.idManager = idManager;
156 this.naptManager = naptManager;
157 this.naptSwitchSelector = naptSwitchSelector;
158 this.bgpManager = bgpManager;
159 this.vpnService = vpnService;
160 this.fibService = fibService;
161 this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
162 this.naptEventHandler = naptEventHandler;
163 this.naptPacketInHandler = naptPacketInHandler;
164 this.fibManager = fibManager;
165 this.vpnManager = vpnManager;
170 LOG.info("{} init", getClass().getSimpleName());
171 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
176 protected InstanceIdentifier<Routers> getWildCardPath() {
177 return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
181 protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
183 LOG.info("NAT Service : Add external router event for {}", routers.getRouterName());
185 // Populate the router-id-name container
186 String routerName = routers.getRouterName();
187 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
188 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
189 MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
191 LOG.info("NAT Service : Installing NAT default route on all dpns part of router {}", routers.getRouterName());
193 addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
194 } catch (Exception ex) {
195 LOG.debug("NAT Service : Exception {} while Installing NAT default route on all dpns part of router {}",ex,routers.getRouterName());
198 long segmentId = NatUtil.getVpnId(dataBroker, routerName);
199 // Allocate Primary Napt Switch for this router
200 BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName, segmentId);
201 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
202 LOG.error("NAT Service: Failed to get or allocated NAPT switch");
206 handleRouterGwFlows(routers, primarySwitchId, NwConstants.ADD_FLOW);
207 if( !routers.isEnableSnat()) {
208 LOG.info("NAT Service : SNAT is disabled for external router {} ", routerName);
212 handleEnableSnat(routers, segmentId, primarySwitchId);
215 public void handleEnableSnat(Routers routers, long segmentId, BigInteger primarySwitchId) {
216 String routerName = routers.getRouterName();
217 LOG.info("NAT Service : Handling SNAT for router {}", routerName);
219 naptManager.initialiseExternalCounter(routers, segmentId);
220 subnetRegisterMapping(routers,segmentId);
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 BigInteger getPrimaryNaptSwitch(String routerName, long segmentId) {
356 // Allocate Primary Napt Switch for this router
357 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, segmentId);
358 if (primarySwitchId != null && !primarySwitchId.equals(BigInteger.ZERO)) {
359 LOG.debug("NAT Service : Primary NAPT switch with DPN ID {} is already elected for router",primarySwitchId,routerName);
360 return primarySwitchId;
363 primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
364 LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
365 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
366 LOG.error("NAT Service : Unable to to select the primary NAPT switch");
369 return primarySwitchId;
372 private void installNaptPfibExternalOutputFlow(Routers routers, BigInteger dpnId) {
373 Long extVpnId = NatUtil.getVpnId(dataBroker, routers.getNetworkId().getValue());
375 String ip = getExternalIpFromRouter(routers);
376 Uuid subnetId = getSubnetIdOfIp(ip);
378 if (subnetId != null) {
379 FlowEntity postNaptFlowEntity = buildNaptFibExternalOutputFlowEntity(dpnId, extVpnId, subnetId, ip);
380 mdsalManager.installFlow(postNaptFlowEntity);
384 private Uuid getSubnetIdOfIp(String ip) {
386 IpAddress externalIpv4Address = new IpAddress(new Ipv4Address(ip));
387 Port port = NatUtil.getNeutronPortForRouterGetewayIp(dataBroker, externalIpv4Address);
388 Uuid subnetId = NatUtil.getSubnetIdForFloatingIp(port, externalIpv4Address);
394 private String getExternalIpFromRouter(Routers routers) {
395 List<String> extIps = routers.getExternalIps();
396 if (extIps != null && !extIps.isEmpty()) {
397 return extIps.get(0);
402 private void subnetRegisterMapping(Routers routerEntry,Long segmentId) {
403 List<Uuid> subnetList = null;
404 List<String> externalIps = null;
405 LOG.debug("NAT Service : Fetching values from extRouters model");
406 subnetList = routerEntry.getSubnetIds();
407 externalIps = routerEntry.getExternalIps();
409 int extIpCounter = externalIps.size();
410 LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
411 for(Uuid subnet : subnetList) {
412 LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
413 InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
414 .builder(Subnetmaps.class)
415 .child(Subnetmap.class, new SubnetmapKey(subnet))
417 Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
420 Subnetmap subnetmapEntry = sn.get();
421 String subnetString = subnetmapEntry.getSubnetIp();
422 String[] subnetSplit = subnetString.split("/");
423 String subnetIp = subnetSplit[0];
424 String subnetPrefix = "0";
425 if(subnetSplit.length == 2) {
426 subnetPrefix = subnetSplit[1];
428 IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
429 LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
431 LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
432 if(extIpCounter != 0) {
433 if(counter < extIpCounter) {
434 String[] IpSplit = externalIps.get(counter).split("/");
435 String externalIp = IpSplit[0];
436 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
437 if(IpSplit.length==2) {
438 extPrefix = IpSplit[1];
440 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
441 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
442 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
443 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
444 externalIp, extPrefix);
446 counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
447 LOG.debug("NAT Service : Counter on externalIps got reset");
448 String[] IpSplit = externalIps.get(counter).split("/");
449 String externalIp = IpSplit[0];
450 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
451 if(IpSplit.length==2) {
452 extPrefix = IpSplit[1];
454 IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
455 LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
456 naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
457 LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
458 externalIp, extPrefix);
462 LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
464 LOG.warn("NAT Service : No internal subnets present in extRouters Model");
469 private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
470 //Check if BGP VPN exists. If exists then invoke the new method.
471 long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
472 if(bgpVpnId != NatConstants.INVALID_ID) {
473 Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
474 if (bgpVpnUuid != null) {
475 String bgpVpnName = bgpVpnUuid.getValue();
476 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
477 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
478 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
480 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
484 //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
485 addOrDelDefaultFibRouteForSNAT(routerName, create);
488 private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
489 List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
490 if (switches == null || switches.isEmpty()) {
491 LOG.debug("No switches found for router {}",routerName);
494 long routerId = NatUtil.readVpnId(dataBroker, routerName);
495 if (routerId == NatConstants.INVALID_ID) {
496 LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
499 for (BigInteger dpnId : switches) {
501 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
502 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
504 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
505 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
510 private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
511 List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
512 if(dpnIds == null || dpnIds.isEmpty()) {
513 LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
516 long routerId = NatUtil.getVpnId(dataBroker, routerName);
517 for (BigInteger dpnId : dpnIds) {
519 if (bgpVpnId != NatConstants.INVALID_ID) {
520 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
521 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
523 LOG.debug("NAT Service : installing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
524 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
527 if (bgpVpnId != NatConstants.INVALID_ID) {
528 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the BGP vpnID {}",routerId,dpnId,bgpVpnId);
529 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
531 LOG.debug("NAT Service : removing default NAT route for router {} in dpn {} for the internal vpn",routerId,dpnId);
532 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
538 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
540 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
542 Optional<T> result = Optional.absent();
545 result = tx.read(datastoreType, path).get();
549 throw new RuntimeException(e);
556 public void close() throws Exception
558 if (listenerRegistration != null)
562 listenerRegistration.close();
564 catch (final Exception e)
566 LOG.error("Error when cleaning up ExternalRoutersListener.", e);
569 listenerRegistration = null;
571 LOG.debug("ExternalRoutersListener Closed");
574 protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
575 long routerId = NatUtil.getVpnId(dataBroker, routerName);
576 LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
577 if(routerId != NatConstants.INVALID_ID) {
578 LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
579 createOutboundTblEntry(primarySwitchId, routerId);
581 LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
585 public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
586 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
587 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
590 private String getFlowRefNaptFib(BigInteger dpnId, short tableId, long routerID, String externalIp) {
591 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
592 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).
593 append(NatConstants.FLOWID_SEPARATOR).append(externalIp).toString();
596 public BigInteger getCookieOutboundFlow(long routerId) {
597 return NwConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
598 BigInteger.valueOf(routerId));
601 protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
602 LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
603 List<MatchInfo> matches = new ArrayList<>();
604 matches.add(new MatchInfo(MatchFieldType.eth_type,
605 new long[] { 0x0800L }));
606 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
607 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
609 List<InstructionInfo> instructions = new ArrayList<>();
610 List<ActionInfo> actionsInfos = new ArrayList<>();
611 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
612 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
613 instructions.add(new InstructionInfo(InstructionType.write_metadata,
614 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
616 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
617 BigInteger cookie = getCookieOutboundFlow(routerId);
618 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef,
620 cookie, matches, instructions);
621 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
625 public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
626 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
627 FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
628 LOG.debug("NAT Service : Installing flow {}", flowEntity);
629 mdsalManager.installFlow(flowEntity);
632 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
633 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
634 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
636 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
637 .setSourceDpid(srcDpId)
638 .setDestinationDpid(dstDpId)
639 .setTunnelType(tunType)
641 rpcResult = result.get();
642 if(!rpcResult.isSuccessful()) {
643 tunType = TunnelTypeGre.class ;
644 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
645 .setSourceDpid(srcDpId)
646 .setDestinationDpid(dstDpId)
647 .setTunnelType(tunType)
649 rpcResult = result.get();
650 if(!rpcResult.isSuccessful()) {
651 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
653 return rpcResult.getResult().getInterfaceName();
655 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
657 return rpcResult.getResult().getInterfaceName();
659 } catch (InterruptedException | ExecutionException | NullPointerException e) {
660 LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
666 protected void installSnatMissEntryForPrimrySwch(BigInteger dpnId, String routerName) {
667 LOG.debug("NAT Service : installSnatMissEntry called for for the primary NAOT switch dpnId {} ", dpnId);
668 // Install miss entry pointing to group
669 FlowEntity flowEntity = buildSnatFlowEntityForPrmrySwtch(dpnId, routerName);
670 mdsalManager.installFlow(flowEntity);
673 protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
674 LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
675 // Install the select group
676 long groupId = createGroupId(getGroupIdKey(routerName));
677 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
678 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
679 mdsalManager.installGroup(groupEntity);
680 // Install miss entry pointing to group
681 FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
682 mdsalManager.installFlow(flowEntity);
685 long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
686 long groupId = createGroupId(getGroupIdKey(routerName));
687 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
688 LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
689 mdsalManager.installGroup(groupEntity);
693 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
695 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
696 long routerId = NatUtil.getVpnId(dataBroker, routerName);
697 List<MatchInfo> matches = new ArrayList<>();
698 matches.add(new MatchInfo(MatchFieldType.eth_type,
699 new long[] { 0x0800L }));
700 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
701 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
704 List<InstructionInfo> instructions = new ArrayList<>();
705 List<ActionInfo> actionsInfo = new ArrayList<>();
707 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
708 BigInteger.valueOf(routerId)}) ;
709 actionsInfo.add(actionSetField);
710 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
711 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
712 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
713 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
714 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
715 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
716 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
718 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
722 public FlowEntity buildSnatFlowEntityForPrmrySwtch(BigInteger dpId, String routerName) {
724 LOG.debug("NAT Service : buildSnatFlowEntity is called for primary NAPT switch dpId {}, routerName {}", dpId,
726 long routerId = NatUtil.getVpnId(dataBroker, routerName);
727 List<MatchInfo> matches = new ArrayList<MatchInfo>();
728 matches.add(new MatchInfo(MatchFieldType.eth_type,
729 new long[] { 0x0800L }));
730 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
731 MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
733 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
734 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
735 { NwConstants.OUTBOUND_NAPT_TABLE }));
737 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
738 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
739 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
740 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
742 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
746 // TODO : Replace this with ITM Rpc once its available with full functionality
747 protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
748 LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
749 FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
750 mdsalManager.installFlow(flowEntity);
754 private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
756 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
757 List<MatchInfo> matches = new ArrayList<>();
758 matches.add(new MatchInfo(MatchFieldType.eth_type,
759 new long[] { 0x0800L }));
760 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
762 List<InstructionInfo> instructions = new ArrayList<>();
763 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
764 { MetaDataUtil.getVpnIdMetadata(routerId.longValue()), MetaDataUtil.METADATA_MASK_VRFID }));
765 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
766 { NwConstants.OUTBOUND_NAPT_TABLE }));
767 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
768 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
769 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
770 NwConstants.COOKIE_TS_TABLE, matches, instructions);
774 public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
775 return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
776 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
779 public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
780 return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
781 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
784 private String getGroupIdKey(String routerName){
785 String groupIdKey = new String("snatmiss." + routerName);
789 protected long createGroupId(String groupIdKey) {
790 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
791 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
794 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
795 RpcResult<AllocateIdOutput> rpcResult = result.get();
796 return rpcResult.getResult().getIdValue();
797 } catch (NullPointerException | InterruptedException | ExecutionException e) {
803 protected void createGroupIdPool() {
804 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
805 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
806 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
807 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
810 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
811 if ((result != null) && (result.get().isSuccessful())) {
812 LOG.debug("NAT Service : Created GroupIdPool");
814 LOG.error("NAT Service : Unable to create GroupIdPool");
816 } catch (InterruptedException | ExecutionException e) {
817 LOG.error("Failed to create PortPool for NAPT Service",e);
821 protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
822 LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
823 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
824 String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
825 List<BucketInfo> listBucketInfo = new ArrayList<>();
826 long routerId = NatUtil.getVpnId(dataBroker, routerName);
828 if(ifNamePrimary != null) {
829 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
830 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
832 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
834 listBucketInfo.add(0, bucketPrimary);
835 installSnatMissEntry(dpnId, listBucketInfo, routerName);
838 List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
839 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
840 String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
841 List<BucketInfo> listBucketInfo = new ArrayList<>();
842 long routerId = NatUtil.getVpnId(dataBroker, routerName);
844 if (ifNamePrimary != null) {
845 LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
846 listActionInfoPrimary = NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
848 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
850 listBucketInfo.add(0, bucketPrimary);
851 return listBucketInfo;
853 protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName) {
856 * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
859 LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
862 List<BucketInfo> listBucketInfo = new ArrayList<>();
863 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
864 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
865 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
866 listBucketInfo.add(0, bucketPrimary);
869 long routerId = NatUtil.getVpnId(dataBroker, routerName);
871 installSnatMissEntryForPrimrySwch(dpnId, routerName);
872 installTerminatingServiceTblEntry(dpnId, routerName);
873 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
874 installNaptPfibEntry(dpnId, routerId);
875 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
876 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
877 if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
878 installNaptPfibEntry(dpnId, vpnId);
882 List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
883 List<BucketInfo> listBucketInfo = new ArrayList<>();
884 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
885 listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NwConstants.INTERNAL_TUNNEL_TABLE)}));
886 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
887 listBucketInfo.add(0, bucketPrimary);
888 return listBucketInfo;
891 public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
892 LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
893 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
894 mdsalManager.installFlow(naptPfibFlowEntity);
897 public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
899 LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
900 List<MatchInfo> matches = new ArrayList<>();
901 matches.add(new MatchInfo(MatchFieldType.eth_type,
902 new long[] { 0x0800L }));
903 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
904 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
906 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
907 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
908 listActionInfo.add(new ActionInfo(ActionType.nx_load_in_port, new BigInteger[]{BigInteger.ZERO}));
909 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
910 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
912 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
913 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
914 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
915 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
917 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
921 private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
922 LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
923 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
924 if(networkId == null) {
925 LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
928 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
929 if(vpnName == null) {
930 LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
931 networkId, externalIp, routerId);
934 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
935 LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
938 public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
939 VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
941 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
942 //Generate VPN label for the external IP
943 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
944 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
946 //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
947 ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
950 public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
951 if (result.isSuccessful()) {
952 LOG.debug("NAT Service : inside apply with result success");
953 GenerateVpnLabelOutput output = result.getResult();
954 final long label = output.getLabel();
956 int externalIpInDsFlag = 0;
957 //Get IPMaps from the DB for the router ID
958 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
959 if (dbIpMaps != null) {
960 for (IpMap dbIpMap : dbIpMaps) {
961 String dbExternalIp = dbIpMap.getExternalIp();
962 //Select the IPMap, whose external IP is the IP for which FIB is installed
963 if (externalIp.equals(dbExternalIp)) {
964 String dbInternalIp = dbIpMap.getInternalIp();
965 IpMapKey dbIpMapKey = dbIpMap.getKey();
966 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
967 IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
968 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
969 externalIpInDsFlag++;
972 if (externalIpInDsFlag <=0) {
973 LOG.debug("NAT Service : External Ip {} not found in DS,Failed to update label {} for routerId {} in DS", externalIp, label, routerId);
974 String errMsg = String.format("Failed to update label %s due to external Ip %s not found in DS for router %s", externalIp, label, routerId);
975 return Futures.immediateFailedFuture(new Exception(errMsg));
978 LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
983 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
984 String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
985 NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, rd, externalIp, nextHopIp, label, log, RouteOrigin.STATIC);
987 //Install custom FIB routes
988 List<Instruction> customInstructions = new ArrayList<>();
989 customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
990 makeTunnelTableEntry(dpnId, label, customInstructions);
991 makeLFibTableEntry(dpnId, label, tableId);
993 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
994 .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
995 Future<RpcResult<Void>> future = fibService.createFibEntry(input);
996 return JdkFutureAdapters.listenInPoolThread(future);
998 LOG.error("NAT Service : inside apply with result failed");
999 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
1000 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1005 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
1008 public void onFailure(Throwable error) {
1009 log.error("NAT Service : Error in generate label or fib install process", error);
1013 public void onSuccess(RpcResult<Void> result) {
1014 if (result.isSuccessful()) {
1015 log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
1017 log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
1023 private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
1024 List<MatchInfo> matches = new ArrayList<>();
1025 matches.add(new MatchInfo(MatchFieldType.eth_type,
1026 new long[]{0x8847L}));
1027 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1029 List<Instruction> instructions = new ArrayList<>();
1030 List<ActionInfo> actionsInfos = new ArrayList<>();
1031 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
1032 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
1033 instructions.add(writeInstruction);
1034 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
1036 // Install the flow entry in L3_LFIB_TABLE
1037 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
1039 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
1041 COOKIE_VM_LFIB_TABLE, matches, instructions);
1043 mdsalManager.installFlow(dpId, flowEntity);
1045 LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
1048 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
1049 List<MatchInfo> mkMatches = new ArrayList<>();
1051 LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
1053 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1055 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1056 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
1057 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
1059 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
1062 protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
1063 InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
1064 RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
1068 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
1069 return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
1070 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
1071 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
1075 protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
1076 String routerName = original.getRouterName();
1077 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1078 BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1079 Uuid networkId = original.getNetworkId();
1081 // Check if its update on SNAT flag
1082 boolean originalSNATEnabled = original.isEnableSnat();
1083 boolean updatedSNATEnabled = update.isEnableSnat();
1084 LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
1085 if(originalSNATEnabled != updatedSNATEnabled) {
1086 if(originalSNATEnabled) {
1087 //SNAT disabled for the router
1088 Uuid networkUuid = original.getNetworkId();
1089 LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
1090 if (routerId == NatConstants.INVALID_ID) {
1091 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1094 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
1095 handleDisableSnat(original, networkUuid, externalIps, false, null, dpnId);
1097 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1098 handleEnableSnat(original, routerId, dpnId);
1102 if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
1103 handleRouterGwFlows(original, dpnId, NwConstants.DEL_FLOW);
1104 handleRouterGwFlows(update, dpnId, NwConstants.ADD_FLOW);
1107 //Check if the Update is on External IPs
1108 LOG.debug("NAT Service : Checking if this is update on External IPs");
1109 List<String> originalExternalIpsList = original.getExternalIps();
1110 List<String> updatedExternalIpsList = update.getExternalIps();
1111 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1112 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1114 //Check if the External IPs are added during the update.
1115 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1116 if(addedExternalIps.size() != 0) {
1117 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1118 vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps, update.getExtGwMacAddress(), dpnId,
1119 update.getNetworkId(), null, NwConstants.ADD_FLOW);
1121 for (String addedExternalIp : addedExternalIps) {
1123 1) Do nothing in the IntExtIp model.
1124 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1126 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1127 String externalIp = externalIpParts[0];
1128 String externalIpPrefix = externalIpParts[1];
1129 String externalpStr = externalIp + "/" + externalIpPrefix;
1130 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1131 externalpStr, routerId);
1132 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1134 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1137 //Check if the External IPs are removed during the update.
1138 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1139 if(removedExternalIps.size() > 0) {
1140 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1141 vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerName, removedExternalIps, original.getExtGwMacAddress(),
1142 dpnId, networkId, null, NwConstants.DEL_FLOW);
1144 List<String> removedExternalIpsAsList = new ArrayList<>();
1145 for (String removedExternalIp : removedExternalIps) {
1147 1) Remove the mappings in the IntExt IP model which has external IP.
1148 2) Remove the external IP in the ExternalCounter model.
1149 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1150 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1151 4) Increase the count of the allocated external IP by one.
1152 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.
1153 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1154 7) Advertise to the BGP for removing the route for the removed external IPs.
1157 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1158 String externalIp = externalIpParts[0];
1159 String externalIpPrefix = externalIpParts[1];
1160 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1162 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1163 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1164 String vpnName = "";
1165 if(vpnUuId != null){
1166 vpnName = vpnUuId.getValue();
1168 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1170 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1171 //Get the internal IPs which are associated to the removed external IPs
1172 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1173 List<String> removedInternalIps = new ArrayList<>();
1174 for(IpMap ipMap : ipMaps){
1175 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1176 removedInternalIps.add(ipMap.getInternalIp());
1180 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1181 for(String removedInternalIp : removedInternalIps){
1182 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1183 removedInternalIp, routerId);
1184 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1187 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1188 externalIpAddrStr, routerId );
1189 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1190 removedExternalIpsAsList.add(externalIpAddrStr);
1192 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1193 for(String removedInternalIp : removedInternalIps) {
1194 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1197 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1198 //Get the internalIP and internal Port which were associated to the removed external IP.
1199 List<Integer> externalPorts = new ArrayList<>();
1200 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1201 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1202 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1203 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1204 if (ipPortMapping.isPresent()) {
1205 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1206 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1207 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1208 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1209 for(IpPortMap ipPortMap : ipPortMaps){
1210 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1211 if(ipPortExternal.getIpAddress().equals(externalIp)){
1212 externalPorts.add(ipPortExternal.getPortNum());
1213 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1214 if(removedInternalIpPorts != null){
1215 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1216 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1218 removedInternalIpPorts = new ArrayList<>();
1219 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1220 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1227 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1228 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1229 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1230 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1231 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1232 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1233 for(String removedInternalIpPort : removedInternalIpPorts){
1234 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1235 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1236 //Remove the IP port incomint packer map.
1237 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1238 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1239 if(removedInternalIpPortParts.length == 2){
1240 String removedInternalIp = removedInternalIpPortParts[0];
1241 String removedInternalPort = removedInternalIpPortParts[1];
1242 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1243 if (removedInternalPortsList != null){
1244 removedInternalPortsList.add(removedInternalPort);
1245 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1247 removedInternalPortsList = new ArrayList<>();
1248 removedInternalPortsList.add(removedInternalPort);
1249 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1255 // Delete the entry from SnatIntIpPortMap DS
1256 Set<String> internalIps = internalIpPortMap.keySet();
1257 for(String internalIp : internalIps){
1258 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1259 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1262 naptManager.removeNaptPortPool(externalIp);
1264 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1265 for(Integer externalPort : externalPorts) {
1266 //Remove the NAPT translation entries from Inbound NAPT table
1267 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1270 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1271 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1272 String internalIp = internalIpPort.getKey();
1273 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1274 List<String> internalPorts = internalIpPort.getValue();
1275 for(String internalPort : internalPorts){
1276 //Remove the NAPT translation entries from Outbound NAPT table
1277 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1281 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1284 //Check if its Update on subnets
1285 LOG.debug("NAT Service : Checking if this is update on subnets");
1286 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1287 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1288 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1289 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1290 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1292 //Check if the Subnet IDs are added during the update.
1293 if(addedSubnetIds.size() != 0){
1294 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1295 for(Uuid addedSubnetId : addedSubnetIds){
1297 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.
1298 2) Increase the count of the selected external IP by one.
1299 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.
1301 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1302 if(subnetIp != null) {
1303 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1306 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1309 //Check if the Subnet IDs are removed during the update.
1310 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1311 if(removedSubnetIds.size() != 0){
1312 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1313 for(Uuid removedSubnetId : removedSubnetIds){
1314 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1315 if(subnetAddr != null){
1317 1) Remove the subnet IP and the external IP in the IntExtIp map
1318 2) Decrease the count of the coresponding external IP by one.
1319 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1322 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1323 if (externalIp == null) {
1324 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1328 naptManager.updateCounter(routerId, externalIp, false);
1329 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1330 if (!isExternalIpAllocated(externalIp)) {
1331 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1332 List<String> externalIps = new ArrayList<>();
1333 externalIps.add(externalIp);
1334 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1335 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1336 dpnId,routerId,networkId,externalIps);
1339 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1340 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1343 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1347 private boolean isExternalIpAllocated(String externalIp) {
1348 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1349 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1350 if (externalCountersData.isPresent()) {
1351 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1352 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1353 for(ExternalCounters ext : externalCounters) {
1354 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1355 if (externalIpCount.getExternalIp().equals(externalIp)) {
1356 if (externalIpCount.getCounter() != 0) {
1367 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1368 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1369 if (leastLoadedExtIpAddr != null) {
1370 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1371 String leastLoadedExtIp = externalIpParts[0];
1372 String leastLoadedExtIpPrefix = externalIpParts[1];
1373 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1374 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1375 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1376 subnetIp = subnetIpParts[0];
1377 String subnetIpPrefix = subnetIpParts[1];
1378 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1379 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1380 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1381 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1384 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1385 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1386 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1389 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1390 IpMapKey ipMapKey = new IpMapKey(internalIp);
1391 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1392 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1393 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1397 //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.
1398 //Get the VPN Name using the network ID
1399 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1400 if (vpnName != null) {
1401 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1402 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1403 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1404 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1406 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1407 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1412 protected Long checkExternalIpLabel(long routerId, String externalIp){
1413 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1414 for(IpMap ipMap : ipMaps){
1415 if(ipMap.getExternalIp().equals(externalIp)){
1416 if (ipMap.getLabel() != null){
1417 return ipMap.getLabel();
1425 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1426 LOG.trace("NAT Service : Router delete method");
1429 ROUTER DELETE SCENARIO
1430 1) Get the router ID from the event.
1431 2) Build the cookie information from the router ID.
1432 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1433 4) Build the flow with the cookie value.
1434 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1435 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1436 7) Get the list of external IP address maintained for the router ID.
1437 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1438 9) Withdraw the corresponding routes from the BGP.
1441 if (identifier == null || router == null) {
1442 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1446 String routerName = router.getRouterName();
1447 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1448 addOrDelDefFibRouteToSNAT(routerName, false);
1449 Uuid networkUuid = router.getNetworkId();
1450 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1451 if (routerId == NatConstants.INVALID_ID) {
1452 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1456 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1457 handleRouterGwFlows(router, primarySwitchId, NwConstants.DEL_FLOW);
1458 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1459 handleDisableSnat(router, networkUuid, externalIps, true, null, primarySwitchId);
1463 private void handleRouterGwFlows(Routers router, BigInteger primarySwitchId, int addOrRemove) {
1464 WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
1465 vpnManager.setupRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
1466 router.getNetworkId(), writeTx, addOrRemove);
1467 vpnManager.setupArpResponderFlowsToExternalNetworkIps(router.getRouterName(), router.getExternalIps(),
1468 router.getExtGwMacAddress(), primarySwitchId, router.getNetworkId(), writeTx, addOrRemove);
1472 public void handleDisableSnat(Routers router, Uuid networkUuid, List<String> externalIps, boolean routerFlag,
1473 String vpnId, BigInteger naptSwitchDpnId) {
1474 LOG.info("NAT Service : handleDisableSnat() Entry");
1475 String routerName = router.getRouterName();
1477 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1479 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1480 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1481 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1484 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId, externalIps);
1485 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1487 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1488 } catch (Exception ex) {
1489 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1492 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1493 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1494 naptManager.removeMapping(routerId);
1497 removeNaptSwitch(routerName);
1499 updateNaptSwitch(routerName, BigInteger.ZERO);
1502 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1503 naptManager.removeExternalCounter(routerId);
1504 } catch (Exception ex) {
1505 LOG.error("Exception while handling disableSNAT : {}", ex);
1507 LOG.info("NAT Service : handleDisableSnat() Exit");
1510 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1511 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1513 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1514 BigInteger naptSwitchDpnId = null;
1515 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1516 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1517 if (rtrToNapt.isPresent()) {
1518 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1520 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1522 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1524 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1525 } catch (Exception ex) {
1526 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1528 } catch (Exception ex) {
1529 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1531 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1534 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1535 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1536 .setPrimarySwitchId(naptSwitchId).build();
1538 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1539 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1540 } catch (Exception ex) {
1541 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1542 naptSwitchId,routerName);
1544 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1545 naptSwitchId,routerName);
1548 protected void removeNaptSwitch(String routerName){
1549 // Remove router and switch from model
1550 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1551 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1552 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1555 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName, List<String> externalIps){
1557 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1558 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1560 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1561 // traffic which comes from the VMs of the NAPT switches)
1562 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1563 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1565 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);
1566 mdsalManager.removeFlow(pSNatFlowEntity);
1568 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1569 // traffic which comes from the VMs of the non NAPT switches)
1570 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1571 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1573 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);
1574 mdsalManager.removeFlow(tsNatFlowEntity);
1576 //Remove the Outbound flow entry which forwards the packet to FIB Table
1577 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1578 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1580 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);
1581 mdsalManager.removeFlow(outboundNatFlowEntity);
1583 removeNaptFibExternalOutputFlows(routerId, dpnId, externalIps);
1585 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1586 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1587 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1589 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);
1590 mdsalManager.removeFlow(natPfibFlowEntity);
1592 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1593 //Get the VPN ID from the ExternalNetworks model
1595 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1596 // ie called from router delete cases
1597 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1598 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1599 if(vpnUuid != null) {
1600 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1601 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1604 // ie called from disassociate vpn case
1605 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1606 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1607 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1610 if(vpnId != NatConstants.INVALID_ID){
1611 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1612 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1613 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1614 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);
1615 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1618 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1619 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1620 if(ipPortMapping == null){
1621 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1625 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1626 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1627 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1628 for(IpPortMap ipPortMap : ipPortMaps){
1629 String ipPortInternal = ipPortMap.getIpPortInternal();
1630 String[] ipPortParts = ipPortInternal.split(":");
1631 if(ipPortParts.length != 2) {
1632 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1635 String internalIp = ipPortParts[0];
1636 String internalPort = ipPortParts[1];
1638 //Build the flow for the outbound NAPT table
1639 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1640 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1642 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);
1643 mdsalManager.removeFlow(outboundNaptFlowEntity);
1645 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1646 String externalIp = ipPortExternal.getIpAddress();
1647 int externalPort = ipPortExternal.getPortNum();
1649 //Build the flow for the inbound NAPT table
1650 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1651 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1653 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);
1654 mdsalManager.removeFlow(inboundNaptFlowEntity);
1659 private void removeNaptFibExternalOutputFlows(long routerId, BigInteger dpnId, List<String> externalIps) {
1660 for (String ip : externalIps) {
1661 String extIp = removeMaskFromIp(ip);
1662 String postNaptFlowRef = getFlowRefNaptFib(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId, extIp);
1663 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);
1664 mdsalManager.removeFlow(NatUtil.buildFlowEntity(dpnId,NwConstants.NAPT_PFIB_TABLE, postNaptFlowRef));
1668 private String removeMaskFromIp(String ip) {
1669 if (ip != null && !ip.trim().isEmpty()) {
1670 return ip.split("/")[0];
1675 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1677 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1678 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1680 //Remove the NAPT PFIB TABLE entry
1682 if(vpnName != null) {
1683 // ie called from disassociate vpn case
1684 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1685 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1686 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1689 if(vpnId != NatConstants.INVALID_ID){
1690 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1691 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1692 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1693 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);
1694 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1696 // Remove IP-PORT active NAPT entries and release port from IdManager
1697 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1698 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1699 if(ipPortMapping == null){
1700 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1703 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1704 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1705 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1706 for(IpPortMap ipPortMap : ipPortMaps){
1707 String ipPortInternal = ipPortMap.getIpPortInternal();
1708 String[] ipPortParts = ipPortInternal.split(":");
1709 if(ipPortParts.length != 2) {
1710 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1713 String internalIp = ipPortParts[0];
1714 String internalPort = ipPortParts[1];
1716 //Build the flow for the outbound NAPT table
1717 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1718 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1720 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);
1721 mdsalManager.removeFlow(outboundNaptFlowEntity);
1723 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1724 String externalIp = ipPortExternal.getIpAddress();
1725 int externalPort = ipPortExternal.getPortNum();
1727 //Build the flow for the inbound NAPT table
1728 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1729 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1731 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);
1732 mdsalManager.removeFlow(inboundNaptFlowEntity);
1734 // Finally release port from idmanager
1735 String internalIpPort = internalIp +":"+internalPort;
1736 naptManager.removePortFromPool(internalIpPort, externalIp);
1738 //Remove sessions from models
1739 naptManager.removeIpPortMappingForRouterID(routerId);
1740 naptManager.removeIntIpPortMappingForRouterID(routerId);
1744 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1748 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1749 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1751 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1752 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1753 if(allSwitchList == null || allSwitchList.isEmpty()){
1754 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1757 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1758 for (BigInteger dpnId : allSwitchList) {
1759 if (!naptSwitchDpnId.equals(dpnId)) {
1760 LOG.info("NAT Service : Handle Ordinary switch");
1762 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1763 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1764 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1766 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1767 mdsalManager.removeFlow(pSNatFlowEntity);
1769 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1770 long groupId = createGroupId(getGroupIdKey(routerName));
1771 List<BucketInfo> listBucketInfo = new ArrayList<>();
1772 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1774 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1775 mdsalManager.removeGroup(pSNatGroupEntity);
1781 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1782 //Withdraw the corresponding routes from the BGP.
1783 //Get the network ID using the router ID.
1784 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1785 externalIps,routerId,networkUuid, vpnName);
1786 if(networkUuid == null ){
1787 LOG.error("NAT Service : networkId is null");
1791 if (externalIps == null || externalIps.isEmpty()) {
1792 LOG.debug("NAT Service : externalIps is null");
1796 if(vpnName ==null) {
1797 //Get the VPN Name using the network ID
1798 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1799 if (vpnName == null) {
1800 LOG.error("No VPN associated with ext nw {} for the router {}",
1801 networkUuid, routerId);
1805 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1807 //Remove custom FIB routes
1808 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1809 for (String extIp : externalIps) {
1810 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1814 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1815 clearBgpRoutes(extIp,vpnName);
1816 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1819 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1820 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1822 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1823 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1827 final long label = tempLabel;
1828 final String externalIp = extIp;
1830 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1831 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1833 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1836 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1838 if (result.isSuccessful()) {
1839 removeTunnelTableEntry(dpnId, label);
1840 removeLFibTableEntry(dpnId, label);
1841 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1842 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1843 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1845 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1847 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1853 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1856 public void onFailure(Throwable error) {
1857 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1861 public void onSuccess(RpcResult<Void> result) {
1862 if (result.isSuccessful()) {
1863 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1865 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1871 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1872 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1873 //Get IPMaps from the DB for the router ID
1874 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1875 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1876 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1880 long tempLabel = NatConstants.INVALID_ID;
1881 for (IpMap dbIpMap : dbIpMaps) {
1882 String dbExternalIp = dbIpMap.getExternalIp();
1883 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1884 //Select the IPMap, whose external IP is the IP for which FIB is installed
1885 if (extIp.equals(dbExternalIp)) {
1886 tempLabel = dbIpMap.getLabel();
1887 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1891 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1892 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1896 final long label = tempLabel;
1897 final String externalIp = extIp;
1899 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1900 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1902 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1905 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1907 if (result.isSuccessful()) {
1908 removeTunnelTableEntry(dpnId, label);
1909 removeLFibTableEntry(dpnId, label);
1910 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1911 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1912 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1914 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1916 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1922 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1925 public void onFailure(Throwable error) {
1926 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1930 public void onSuccess(RpcResult<Void> result) {
1931 if (result.isSuccessful()) {
1932 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1934 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1940 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1941 //Withdraw the corresponding routes from the BGP.
1942 //Get the network ID using the router ID.
1943 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1944 externalIps,routerId,networkUuid, vpnName);
1945 if (networkUuid == null) {
1946 LOG.error("NAT Service : networkId is null");
1950 if (externalIps == null || externalIps.isEmpty()) {
1951 LOG.debug("NAT Service : externalIps is null");
1955 if (vpnName == null) {
1956 //Get the VPN Name using the network ID
1957 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1958 if (vpnName == null) {
1959 LOG.error("No VPN associated with ext nw {} for the router {}",
1960 networkUuid, routerId);
1964 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1966 //Remove custom FIB routes
1967 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1968 for (String extIp : externalIps) {
1969 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1973 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1974 //Inform BGP about the route removal
1975 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1976 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1977 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
1980 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1981 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1982 List<MatchInfo> mkMatches = new ArrayList<>();
1983 // Matching metadata
1984 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1985 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1986 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1987 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1988 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1989 mdsalManager.removeFlow(dpnId, flowEntity);
1990 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1993 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
1994 List<MatchInfo> matches = new ArrayList<>();
1995 matches.add(new MatchInfo(MatchFieldType.eth_type,
1996 new long[] { 0x8847L }));
1997 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
1999 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
2001 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
2003 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
2005 COOKIE_VM_LFIB_TABLE, matches, null);
2007 mdsalManager.removeFlow(dpnId, flowEntity);
2009 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
2013 * router association to vpn
2014 *@param routerName - Name of router
2015 *@param bgpVpnName BGP VPN name
2017 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
2018 LOG.debug("NAT Service : Router associated to BGP VPN");
2019 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2020 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2022 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2024 if(bgpVpnId != NatConstants.INVALID_ID){
2025 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
2026 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
2027 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
2029 // Get the allocated Primary NAPT Switch for this router
2030 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2031 LOG.debug("Router ID value {} ", routerId);
2032 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2034 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
2035 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
2038 long groupId = createGroupId(getGroupIdKey(routerName));
2039 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2045 * router disassociation from vpn
2046 *@param routerName - Name of router
2047 *@param bgpVpnName BGP VPN name
2049 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2050 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2051 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2052 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2053 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2055 // Get the allocated Primary NAPT Switch for this router
2056 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2057 LOG.debug("Router ID value {} ", routerId);
2058 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2060 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2061 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2064 long groupId = createGroupId(getGroupIdKey(routerName));
2065 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2069 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2070 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2071 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2072 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2073 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2078 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2079 routerId, boolean isSnatCfgd){
2080 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, isSnatCfgd, null);
2083 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2084 routerId, boolean isSnatCfgd, Routers router){
2085 long changedVpnId = bgpVpnId;
2086 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2087 if (bgpVpnId == NatConstants.INVALID_ID){
2088 changedVpnId = routerId;
2089 logMsg = "NAT Service : Update the router ID {}";
2092 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2093 if (switches == null || switches.isEmpty()) {
2094 LOG.debug("No switches found for router {}",routerName);
2097 for(BigInteger dpnId : switches) {
2098 // Update the BGP VPN ID in the SNAT miss entry to group
2099 if( !dpnId.equals(primarySwitchId) ) {
2100 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2101 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2102 long groupId = createGroupId(getGroupIdKey(routerName));
2104 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2107 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2108 changedVpnId, groupId, dpnId);
2109 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2110 mdsalManager.installFlow(flowEntity);
2113 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2114 changedVpnId, primarySwitchId);
2115 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2116 mdsalManager.installFlow(flowEntity);
2118 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2119 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2120 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2122 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2123 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2124 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2126 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2127 changedVpnId, primarySwitchId);
2128 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2130 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2131 " in the Primary switch {}", changedVpnId, primarySwitchId);
2132 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2134 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2135 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2136 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2137 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2138 installNaptPfibEntry(primarySwitchId, vpnId);
2144 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2145 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2146 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2147 if(ipPortMapping == null){
2148 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2152 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2153 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2154 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2155 for(IpPortMap ipPortMap : ipPortMaps){
2156 String ipPortInternal = ipPortMap.getIpPortInternal();
2157 String[] ipPortParts = ipPortInternal.split(":");
2158 if(ipPortParts.length != 2) {
2159 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2162 String internalIp = ipPortParts[0];
2163 String internalPort = ipPortParts[1];
2165 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2166 NAPTEntryEvent.Protocol protocol;
2167 switch (protocolTypes){
2169 protocol = NAPTEntryEvent.Protocol.TCP;
2172 protocol = NAPTEntryEvent.Protocol.UDP;
2175 protocol = NAPTEntryEvent.Protocol.TCP;
2177 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2178 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2179 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2180 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2181 internalAddress, externalAddress, protocol);
2182 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2183 externalAddress, internalAddress, protocol);
2189 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2191 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2192 List<MatchInfo> matches = new ArrayList<>();
2193 matches.add(new MatchInfo(MatchFieldType.eth_type,
2194 new long[] { 0x0800L }));
2195 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2196 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2198 List<InstructionInfo> instructions = new ArrayList<>();
2199 List<ActionInfo> actionsInfo = new ArrayList<>();
2201 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2202 BigInteger.valueOf(changedVpnId)}) ;
2203 actionsInfo.add(actionSetField);
2204 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2205 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2206 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
2207 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2208 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2209 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2210 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2212 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2216 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2218 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2219 List<MatchInfo> matches = new ArrayList<>();
2220 matches.add(new MatchInfo(MatchFieldType.eth_type,
2221 new long[] { 0x0800L }));
2222 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2223 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2225 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2226 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2227 { NwConstants.OUTBOUND_NAPT_TABLE }));
2229 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2230 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2231 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2232 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2234 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2238 // TODO : Replace this with ITM Rpc once its available with full functionality
2239 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2240 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2241 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2242 mdsalManager.installFlow(flowEntity);
2246 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2247 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2248 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2249 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2250 List<MatchInfo> matches = new ArrayList<>();
2251 matches.add(new MatchInfo(MatchFieldType.eth_type,
2252 new long[] { 0x0800L }));
2253 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2255 List<InstructionInfo> instructions = new ArrayList<>();
2256 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2257 { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2258 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2259 { NwConstants.OUTBOUND_NAPT_TABLE }));
2260 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2261 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2262 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2263 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2267 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2268 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2269 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2270 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2271 mdsalManager.installFlow(flowEntity);
2274 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2275 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2276 List<MatchInfo> matches = new ArrayList<>();
2277 matches.add(new MatchInfo(MatchFieldType.eth_type,
2278 new long[]{0x0800L}));
2279 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2280 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2282 List<InstructionInfo> instructions = new ArrayList<>();
2283 List<ActionInfo> actionsInfos = new ArrayList<>();
2284 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2285 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2286 instructions.add(new InstructionInfo(InstructionType.write_metadata,
2287 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2289 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2290 BigInteger cookie = getCookieOutboundFlow(routerId);
2291 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2292 cookie, matches, instructions);
2293 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2297 protected FlowEntity buildNaptFibExternalOutputFlowEntity(BigInteger dpId, long extVpnId, Uuid subnetId, String externalIp) {
2298 LOG.debug("NAT Service : buildPostSnatFlowEntity called for dpId {}, routerId {}, srcIp {}", dpId, extVpnId,
2301 List<MatchInfo> matches = new ArrayList<>();
2302 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 }));
2303 matches.add(new MatchInfo(MatchFieldType.metadata,
2304 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(extVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2305 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] { externalIp , "32" }));
2307 List<InstructionInfo> instructions = new ArrayList<>();
2308 List<ActionInfo> actionsInfos = new ArrayList<>();
2309 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2310 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetId.getValue()), idManager);
2311 actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
2313 String flowRef = getFlowRefNaptFib(dpId, NwConstants.NAPT_PFIB_TABLE, extVpnId, externalIp);
2314 BigInteger cookie = getCookieOutboundFlow(extVpnId);
2315 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef, 6, flowRef, 0,
2316 0, cookie, matches, instructions);
2317 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2321 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2322 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2323 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2324 mdsalManager.installFlow(naptPfibFlowEntity);
2327 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2329 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2330 List<MatchInfo> matches = new ArrayList<>();
2331 matches.add(new MatchInfo(MatchFieldType.eth_type,
2332 new long[] { 0x0800L }));
2333 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2334 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2336 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2337 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2338 listActionInfo.add(new ActionInfo(ActionType.nx_load_in_port, new BigInteger[]{BigInteger.ZERO}));
2339 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
2340 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2342 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2343 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2344 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2345 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2347 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2352 protected ExternalRoutersListener getDataTreeChangeListener()
2354 return ExternalRoutersListener.this;