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 // Allocate Primary Napt Switch for existing router
1098 BigInteger primarySwitchId = getPrimaryNaptSwitch(routerName, routerId);
1099 if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
1100 LOG.error("NAT Service: Failed to get or allocated NAPT switch in ExternalRouterListener.Update()");
1103 LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
1104 handleEnableSnat(original, routerId, primarySwitchId);
1108 if (!Objects.equals(original.getExtGwMacAddress(), update.getExtGwMacAddress())) {
1109 handleRouterGwFlows(original, dpnId, NwConstants.DEL_FLOW);
1110 handleRouterGwFlows(update, dpnId, NwConstants.ADD_FLOW);
1113 //Check if the Update is on External IPs
1114 LOG.debug("NAT Service : Checking if this is update on External IPs");
1115 List<String> originalExternalIpsList = original.getExternalIps();
1116 List<String> updatedExternalIpsList = update.getExternalIps();
1117 Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
1118 Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
1120 //Check if the External IPs are added during the update.
1121 SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
1122 if(addedExternalIps.size() != 0) {
1123 LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
1124 vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerName, addedExternalIps, update.getExtGwMacAddress(), dpnId,
1125 update.getNetworkId(), null, NwConstants.ADD_FLOW);
1127 for (String addedExternalIp : addedExternalIps) {
1129 1) Do nothing in the IntExtIp model.
1130 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
1132 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
1133 String externalIp = externalIpParts[0];
1134 String externalIpPrefix = externalIpParts[1];
1135 String externalpStr = externalIp + "/" + externalIpPrefix;
1136 LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
1137 externalpStr, routerId);
1138 naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
1140 LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
1143 //Check if the External IPs are removed during the update.
1144 SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
1145 if(removedExternalIps.size() > 0) {
1146 LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
1147 vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerName, removedExternalIps, original.getExtGwMacAddress(),
1148 dpnId, networkId, null, NwConstants.DEL_FLOW);
1150 List<String> removedExternalIpsAsList = new ArrayList<>();
1151 for (String removedExternalIp : removedExternalIps) {
1153 1) Remove the mappings in the IntExt IP model which has external IP.
1154 2) Remove the external IP in the ExternalCounter model.
1155 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
1156 Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
1157 4) Increase the count of the allocated external IP by one.
1158 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.
1159 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
1160 7) Advertise to the BGP for removing the route for the removed external IPs.
1163 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
1164 String externalIp = externalIpParts[0];
1165 String externalIpPrefix = externalIpParts[1];
1166 String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
1168 LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
1169 Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1170 String vpnName = "";
1171 if(vpnUuId != null){
1172 vpnName = vpnUuId.getValue();
1174 clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
1176 LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
1177 //Get the internal IPs which are associated to the removed external IPs
1178 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1179 List<String> removedInternalIps = new ArrayList<>();
1180 for(IpMap ipMap : ipMaps){
1181 if(ipMap.getExternalIp().equals(externalIpAddrStr)){
1182 removedInternalIps.add(ipMap.getInternalIp());
1186 LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
1187 for(String removedInternalIp : removedInternalIps){
1188 LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
1189 removedInternalIp, routerId);
1190 naptManager.removeFromIpMapDS(routerId, removedInternalIp);
1193 LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
1194 externalIpAddrStr, routerId );
1195 naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
1196 removedExternalIpsAsList.add(externalIpAddrStr);
1198 LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
1199 for(String removedInternalIp : removedInternalIps) {
1200 allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
1203 LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
1204 //Get the internalIP and internal Port which were associated to the removed external IP.
1205 List<Integer> externalPorts = new ArrayList<>();
1206 Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
1207 InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
1208 .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1209 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
1210 if (ipPortMapping.isPresent()) {
1211 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
1212 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1213 ProtocolTypes protoType = intextIpProtocolType.getProtocol();
1214 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1215 for(IpPortMap ipPortMap : ipPortMaps){
1216 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1217 if(ipPortExternal.getIpAddress().equals(externalIp)){
1218 externalPorts.add(ipPortExternal.getPortNum());
1219 List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
1220 if(removedInternalIpPorts != null){
1221 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1222 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1224 removedInternalIpPorts = new ArrayList<>();
1225 removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
1226 protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
1233 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
1234 Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
1235 Map<String, List<String>> internalIpPortMap = new HashMap<>();
1236 for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
1237 ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
1238 List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
1239 for(String removedInternalIpPort : removedInternalIpPorts){
1240 //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
1241 naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
1242 //Remove the IP port incomint packer map.
1243 naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
1244 String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
1245 if(removedInternalIpPortParts.length == 2){
1246 String removedInternalIp = removedInternalIpPortParts[0];
1247 String removedInternalPort = removedInternalIpPortParts[1];
1248 List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
1249 if (removedInternalPortsList != null){
1250 removedInternalPortsList.add(removedInternalPort);
1251 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1253 removedInternalPortsList = new ArrayList<>();
1254 removedInternalPortsList.add(removedInternalPort);
1255 internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
1261 // Delete the entry from SnatIntIpPortMap DS
1262 Set<String> internalIps = internalIpPortMap.keySet();
1263 for(String internalIp : internalIps){
1264 LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
1265 naptManager.removeFromSnatIpPortDS(routerId, internalIp);
1268 naptManager.removeNaptPortPool(externalIp);
1270 LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
1271 for(Integer externalPort : externalPorts) {
1272 //Remove the NAPT translation entries from Inbound NAPT table
1273 naptEventHandler.removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
1276 Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
1277 for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
1278 String internalIp = internalIpPort.getKey();
1279 LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
1280 List<String> internalPorts = internalIpPort.getValue();
1281 for(String internalPort : internalPorts){
1282 //Remove the NAPT translation entries from Outbound NAPT table
1283 naptEventHandler.removeNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
1287 LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
1290 //Check if its Update on subnets
1291 LOG.debug("NAT Service : Checking if this is update on subnets");
1292 List<Uuid> originalSubnetIdsList = original.getSubnetIds();
1293 List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
1294 Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
1295 Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
1296 SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
1298 //Check if the Subnet IDs are added during the update.
1299 if(addedSubnetIds.size() != 0){
1300 LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
1301 for(Uuid addedSubnetId : addedSubnetIds){
1303 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.
1304 2) Increase the count of the selected external IP by one.
1305 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.
1307 String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
1308 if(subnetIp != null) {
1309 allocateExternalIp(dpnId, routerId, networkId, subnetIp);
1312 LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
1315 //Check if the Subnet IDs are removed during the update.
1316 SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
1317 if(removedSubnetIds.size() != 0){
1318 LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
1319 for(Uuid removedSubnetId : removedSubnetIds){
1320 String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
1321 if(subnetAddr != null){
1323 1) Remove the subnet IP and the external IP in the IntExtIp map
1324 2) Decrease the count of the coresponding external IP by one.
1325 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
1328 String externalIp = naptManager.getExternalIpAllocatedForSubnet(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1329 if (externalIp == null) {
1330 LOG.debug("No mapping found for router ID {} and internal IP {}", routerId, subnetAddr[0]);
1334 naptManager.updateCounter(routerId, externalIp, false);
1335 //Traverse entire model of external-ip counter whether external ip is not used by any other internal ip in any router
1336 if (!isExternalIpAllocated(externalIp)) {
1337 LOG.debug("NAT Service : external ip is not allocated to any other internal IP so proceeding to remove routes");
1338 List<String> externalIps = new ArrayList<>();
1339 externalIps.add(externalIp);
1340 clrRtsFromBgpAndDelFibTs(dpnId, routerId, networkId, externalIps, null);
1341 LOG.debug("Successfully removed fib entries in switch {} for router {} with networkId {} and externalIps {}",
1342 dpnId,routerId,networkId,externalIps);
1345 LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {} external IP {}", routerId, subnetAddr[0],externalIp);
1346 naptManager.removeIntExtIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
1349 LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
1353 private boolean isExternalIpAllocated(String externalIp) {
1354 InstanceIdentifier<ExternalIpsCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).build();
1355 Optional <ExternalIpsCounter> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1356 if (externalCountersData.isPresent()) {
1357 ExternalIpsCounter externalIpsCounters = externalCountersData.get();
1358 List<ExternalCounters> externalCounters = externalIpsCounters.getExternalCounters();
1359 for(ExternalCounters ext : externalCounters) {
1360 for (ExternalIpCounter externalIpCount : ext.getExternalIpCounter()) {
1361 if (externalIpCount.getExternalIp().equals(externalIp)) {
1362 if (externalIpCount.getCounter() != 0) {
1373 private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
1374 String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
1375 if (leastLoadedExtIpAddr != null) {
1376 String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
1377 String leastLoadedExtIp = externalIpParts[0];
1378 String leastLoadedExtIpPrefix = externalIpParts[1];
1379 String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
1380 IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
1381 String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
1382 subnetIp = subnetIpParts[0];
1383 String subnetIpPrefix = subnetIpParts[1];
1384 IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
1385 LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
1386 routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
1387 naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
1390 //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
1391 //If external IP is already assigned a route, (, do not re-advertise to the BGP
1392 Long label = checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr);
1395 String internalIp = subnetIpParts[0] + "/" + subnetIpParts[1];
1396 IpMapKey ipMapKey = new IpMapKey(internalIp);
1397 LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, internalIp, leastLoadedExtIpAddrStr);
1398 IpMap newIpm = new IpMapBuilder().setKey(ipMapKey).setInternalIp(internalIp).setExternalIp(leastLoadedExtIpAddrStr).setLabel(label).build();
1399 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, internalIp), newIpm);
1403 //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.
1404 //Get the VPN Name using the network ID
1405 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
1406 if (vpnName != null) {
1407 LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
1408 if (dpnId == null || dpnId.equals(BigInteger.ZERO)) {
1409 LOG.debug("Best effort for getting primary napt switch when router i/f are added after gateway-set");
1410 dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker,routerId);
1412 advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
1413 leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
1418 protected Long checkExternalIpLabel(long routerId, String externalIp){
1419 List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
1420 for(IpMap ipMap : ipMaps){
1421 if(ipMap.getExternalIp().equals(externalIp)){
1422 if (ipMap.getLabel() != null){
1423 return ipMap.getLabel();
1431 protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
1432 LOG.trace("NAT Service : Router delete method");
1435 ROUTER DELETE SCENARIO
1436 1) Get the router ID from the event.
1437 2) Build the cookie information from the router ID.
1438 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
1439 4) Build the flow with the cookie value.
1440 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
1441 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1442 7) Get the list of external IP address maintained for the router ID.
1443 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
1444 9) Withdraw the corresponding routes from the BGP.
1447 if (identifier == null || router == null) {
1448 LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
1452 String routerName = router.getRouterName();
1453 LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
1454 addOrDelDefFibRouteToSNAT(routerName, false);
1455 Uuid networkUuid = router.getNetworkId();
1456 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1457 if (routerId == NatConstants.INVALID_ID) {
1458 LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
1462 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
1463 handleRouterGwFlows(router, primarySwitchId, NwConstants.DEL_FLOW);
1464 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
1465 handleDisableSnat(router, networkUuid, externalIps, true, null, primarySwitchId);
1469 private void handleRouterGwFlows(Routers router, BigInteger primarySwitchId, int addOrRemove) {
1470 WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
1471 vpnManager.setupRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
1472 router.getNetworkId(), writeTx, addOrRemove);
1473 vpnManager.setupArpResponderFlowsToExternalNetworkIps(router.getRouterName(), router.getExternalIps(),
1474 router.getExtGwMacAddress(), primarySwitchId, router.getNetworkId(), writeTx, addOrRemove);
1478 public void handleDisableSnat(Routers router, Uuid networkUuid, List<String> externalIps, boolean routerFlag,
1479 String vpnId, BigInteger naptSwitchDpnId) {
1480 LOG.info("NAT Service : handleDisableSnat() Entry");
1481 String routerName = router.getRouterName();
1483 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1485 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1486 if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
1487 LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
1490 removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId, externalIps);
1491 removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
1493 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1494 } catch (Exception ex) {
1495 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1498 //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
1499 LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
1500 naptManager.removeMapping(routerId);
1503 removeNaptSwitch(routerName);
1505 updateNaptSwitch(routerName, BigInteger.ZERO);
1508 LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
1509 naptManager.removeExternalCounter(routerId);
1510 } catch (Exception ex) {
1511 LOG.error("Exception while handling disableSNAT : {}", ex);
1513 LOG.info("NAT Service : handleDisableSnat() Exit");
1516 public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
1517 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
1519 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1520 BigInteger naptSwitchDpnId = null;
1521 InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
1522 Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch);
1523 if (rtrToNapt.isPresent()) {
1524 naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
1526 LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
1528 removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
1530 clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
1531 } catch (Exception ex) {
1532 LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
1534 } catch (Exception ex) {
1535 LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
1537 LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
1540 public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
1541 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
1542 .setPrimarySwitchId(naptSwitchId).build();
1544 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1545 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
1546 } catch (Exception ex) {
1547 LOG.error("Failed to write naptSwitch {} for router {} in ds",
1548 naptSwitchId,routerName);
1550 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
1551 naptSwitchId,routerName);
1554 protected void removeNaptSwitch(String routerName){
1555 // Remove router and switch from model
1556 InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1557 LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
1558 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1561 public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName, List<String> externalIps){
1563 LOG.debug("NAT Service : Remove NAPT flows from Active switch");
1564 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1566 //Remove the PSNAT entry which forwards the packet to Outbound NAPT Table (For the
1567 // traffic which comes from the VMs of the NAPT switches)
1568 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, routerName);
1569 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1571 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);
1572 mdsalManager.removeFlow(pSNatFlowEntity);
1574 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table (For the
1575 // traffic which comes from the VMs of the non NAPT switches)
1576 String tsFlowRef = getFlowRefTs(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId);
1577 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, tsFlowRef);
1579 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);
1580 mdsalManager.removeFlow(tsNatFlowEntity);
1582 //Remove the Outbound flow entry which forwards the packet to FIB Table
1583 String outboundNatFlowRef = getFlowRefOutbound(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
1584 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
1586 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);
1587 mdsalManager.removeFlow(outboundNatFlowEntity);
1589 removeNaptFibExternalOutputFlows(routerId, dpnId, externalIps);
1591 //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
1592 String natPfibFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId);
1593 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
1595 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);
1596 mdsalManager.removeFlow(natPfibFlowEntity);
1598 //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
1599 //Get the VPN ID from the ExternalNetworks model
1601 if( (vpnName == null) || (vpnName.isEmpty()) ) {
1602 // ie called from router delete cases
1603 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
1604 LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
1605 if(vpnUuid != null) {
1606 vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
1607 LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
1610 // ie called from disassociate vpn case
1611 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1612 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1613 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1616 if(vpnId != NatConstants.INVALID_ID){
1617 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1618 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1619 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1620 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);
1621 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1624 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1625 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1626 if(ipPortMapping == null){
1627 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1631 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1632 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1633 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1634 for(IpPortMap ipPortMap : ipPortMaps){
1635 String ipPortInternal = ipPortMap.getIpPortInternal();
1636 String[] ipPortParts = ipPortInternal.split(":");
1637 if(ipPortParts.length != 2) {
1638 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1641 String internalIp = ipPortParts[0];
1642 String internalPort = ipPortParts[1];
1644 //Build the flow for the outbound NAPT table
1645 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1646 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1648 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);
1649 mdsalManager.removeFlow(outboundNaptFlowEntity);
1651 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1652 String externalIp = ipPortExternal.getIpAddress();
1653 int externalPort = ipPortExternal.getPortNum();
1655 //Build the flow for the inbound NAPT table
1656 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1657 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1659 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);
1660 mdsalManager.removeFlow(inboundNaptFlowEntity);
1665 private void removeNaptFibExternalOutputFlows(long routerId, BigInteger dpnId, List<String> externalIps) {
1666 for (String ip : externalIps) {
1667 String extIp = removeMaskFromIp(ip);
1668 String postNaptFlowRef = getFlowRefNaptFib(dpnId, NwConstants.NAPT_PFIB_TABLE, routerId, extIp);
1669 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);
1670 mdsalManager.removeFlow(NatUtil.buildFlowEntity(dpnId,NwConstants.NAPT_PFIB_TABLE, postNaptFlowRef));
1674 private String removeMaskFromIp(String ip) {
1675 if (ip != null && !ip.trim().isEmpty()) {
1676 return ip.split("/")[0];
1681 public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
1683 LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
1684 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
1686 //Remove the NAPT PFIB TABLE entry
1688 if(vpnName != null) {
1689 // ie called from disassociate vpn case
1690 LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
1691 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
1692 LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
1695 if(vpnId != NatConstants.INVALID_ID){
1696 //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
1697 String natPfibVpnFlowRef = getFlowRefTs(dpnId, NwConstants.NAPT_PFIB_TABLE, vpnId);
1698 FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
1699 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);
1700 mdsalManager.removeFlow(natPfibVpnFlowEntity);
1702 // Remove IP-PORT active NAPT entries and release port from IdManager
1703 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
1704 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
1705 if(ipPortMapping == null){
1706 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
1709 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
1710 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
1711 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
1712 for(IpPortMap ipPortMap : ipPortMaps){
1713 String ipPortInternal = ipPortMap.getIpPortInternal();
1714 String[] ipPortParts = ipPortInternal.split(":");
1715 if(ipPortParts.length != 2) {
1716 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
1719 String internalIp = ipPortParts[0];
1720 String internalPort = ipPortParts[1];
1722 //Build the flow for the outbound NAPT table
1723 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
1724 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1726 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);
1727 mdsalManager.removeFlow(outboundNaptFlowEntity);
1729 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
1730 String externalIp = ipPortExternal.getIpAddress();
1731 int externalPort = ipPortExternal.getPortNum();
1733 //Build the flow for the inbound NAPT table
1734 switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
1735 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
1737 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);
1738 mdsalManager.removeFlow(inboundNaptFlowEntity);
1740 // Finally release port from idmanager
1741 String internalIpPort = internalIp +":"+internalPort;
1742 naptManager.removePortFromPool(internalIpPort, externalIp);
1744 //Remove sessions from models
1745 naptManager.removeIpPortMappingForRouterID(routerId);
1746 naptManager.removeIntIpPortMappingForRouterID(routerId);
1750 LOG.error("NAT Service : Invalid vpnId {}", vpnId);
1754 public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
1755 LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
1757 //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
1758 List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
1759 if(allSwitchList == null || allSwitchList.isEmpty()){
1760 LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
1763 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
1764 for (BigInteger dpnId : allSwitchList) {
1765 if (!naptSwitchDpnId.equals(dpnId)) {
1766 LOG.info("NAT Service : Handle Ordinary switch");
1768 //Remove the PSNAT entry which forwards the packet to Terminating Service table
1769 String pSNatFlowRef = getFlowRefSnat(dpnId, NwConstants.PSNAT_TABLE, String.valueOf(routerName));
1770 FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NwConstants.PSNAT_TABLE, pSNatFlowRef);
1772 LOG.info("Remove the flow in the " + NwConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
1773 mdsalManager.removeFlow(pSNatFlowEntity);
1775 //Remove the group entry which forwards the traffic to the out port (VXLAN tunnel).
1776 long groupId = createGroupId(getGroupIdKey(routerName));
1777 List<BucketInfo> listBucketInfo = new ArrayList<>();
1778 GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
1780 LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
1781 mdsalManager.removeGroup(pSNatGroupEntity);
1787 public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1788 //Withdraw the corresponding routes from the BGP.
1789 //Get the network ID using the router ID.
1790 LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
1791 externalIps,routerId,networkUuid, vpnName);
1792 if(networkUuid == null ){
1793 LOG.error("NAT Service : networkId is null");
1797 if (externalIps == null || externalIps.isEmpty()) {
1798 LOG.debug("NAT Service : externalIps is null");
1802 if(vpnName ==null) {
1803 //Get the VPN Name using the network ID
1804 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1805 if (vpnName == null) {
1806 LOG.error("No VPN associated with ext nw {} for the router {}",
1807 networkUuid, routerId);
1811 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1813 //Remove custom FIB routes
1814 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1815 for (String extIp : externalIps) {
1816 clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
1820 protected void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1821 clearBgpRoutes(extIp,vpnName);
1822 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1825 protected void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName,long tempLabel) {
1826 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1828 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1829 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1833 final long label = tempLabel;
1834 final String externalIp = extIp;
1836 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1837 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1839 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1842 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1844 if (result.isSuccessful()) {
1845 removeTunnelTableEntry(dpnId, label);
1846 removeLFibTableEntry(dpnId, label);
1847 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1848 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1849 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1851 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1853 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1859 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1862 public void onFailure(Throwable error) {
1863 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1867 public void onSuccess(RpcResult<Void> result) {
1868 if (result.isSuccessful()) {
1869 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1871 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1877 private void delFibTsAndReverseTraffic(final BigInteger dpnId, long routerId, String extIp, final String vpnName) {
1878 LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
1879 //Get IPMaps from the DB for the router ID
1880 List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
1881 if (dbIpMaps == null || dbIpMaps.isEmpty()) {
1882 LOG.error("NAT Service : IPMaps not found for router {}",routerId);
1886 long tempLabel = NatConstants.INVALID_ID;
1887 for (IpMap dbIpMap : dbIpMaps) {
1888 String dbExternalIp = dbIpMap.getExternalIp();
1889 LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
1890 //Select the IPMap, whose external IP is the IP for which FIB is installed
1891 if (extIp.equals(dbExternalIp)) {
1892 tempLabel = dbIpMap.getLabel();
1893 LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
1897 if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
1898 LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
1902 final long label = tempLabel;
1903 final String externalIp = extIp;
1905 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
1906 Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
1908 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
1911 public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
1913 if (result.isSuccessful()) {
1914 removeTunnelTableEntry(dpnId, label);
1915 removeLFibTableEntry(dpnId, label);
1916 RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
1917 Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
1918 return JdkFutureAdapters.listenInPoolThread(labelFuture);
1920 String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
1922 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
1928 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
1931 public void onFailure(Throwable error) {
1932 LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
1936 public void onSuccess(RpcResult<Void> result) {
1937 if (result.isSuccessful()) {
1938 LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
1940 LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
1946 protected void clearFibTsAndReverseTraffic(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
1947 //Withdraw the corresponding routes from the BGP.
1948 //Get the network ID using the router ID.
1949 LOG.debug("NAT Service : clearFibTsAndReverseTraffic for externalIps {} with routerId {}, network Id {} and vpnName {}",
1950 externalIps,routerId,networkUuid, vpnName);
1951 if (networkUuid == null) {
1952 LOG.error("NAT Service : networkId is null");
1956 if (externalIps == null || externalIps.isEmpty()) {
1957 LOG.debug("NAT Service : externalIps is null");
1961 if (vpnName == null) {
1962 //Get the VPN Name using the network ID
1963 vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
1964 if (vpnName == null) {
1965 LOG.error("No VPN associated with ext nw {} for the router {}",
1966 networkUuid, routerId);
1970 LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
1972 //Remove custom FIB routes
1973 //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
1974 for (String extIp : externalIps) {
1975 delFibTsAndReverseTraffic(dpnId,routerId,extIp,vpnName);
1979 protected void clearBgpRoutes(String externalIp, final String vpnName) {
1980 //Inform BGP about the route removal
1981 LOG.info("Informing BGP to remove route for externalIP {} of vpn {}",externalIp,vpnName);
1982 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
1983 NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, LOG);
1986 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
1987 LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
1988 List<MatchInfo> mkMatches = new ArrayList<>();
1989 // Matching metadata
1990 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
1991 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1992 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
1993 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
1994 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
1995 mdsalManager.removeFlow(dpnId, flowEntity);
1996 LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
1999 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
2000 List<MatchInfo> matches = new ArrayList<>();
2001 matches.add(new MatchInfo(MatchFieldType.eth_type,
2002 new long[] { 0x8847L }));
2003 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
2005 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
2007 LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
2009 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
2011 COOKIE_VM_LFIB_TABLE, matches, null);
2013 mdsalManager.removeFlow(dpnId, flowEntity);
2015 LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
2019 * router association to vpn
2020 *@param routerName - Name of router
2021 *@param bgpVpnName BGP VPN name
2023 public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
2024 LOG.debug("NAT Service : Router associated to BGP VPN");
2025 if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2026 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2028 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2030 if(bgpVpnId != NatConstants.INVALID_ID){
2031 LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
2032 RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
2033 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
2035 // Get the allocated Primary NAPT Switch for this router
2036 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2037 LOG.debug("Router ID value {} ", routerId);
2038 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2040 LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
2041 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
2044 long groupId = createGroupId(getGroupIdKey(routerName));
2045 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, true);
2051 * router disassociation from vpn
2052 *@param routerName - Name of router
2053 *@param bgpVpnName BGP VPN name
2055 public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
2056 LOG.debug("NAT Service : Router dissociated from BGP VPN");
2057 if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
2058 long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
2059 LOG.debug("BGP VPN ID value {} ", bgpVpnId);
2061 // Get the allocated Primary NAPT Switch for this router
2062 long routerId = NatUtil.getVpnId(dataBroker, routerName);
2063 LOG.debug("Router ID value {} ", routerId);
2064 BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
2066 LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
2067 addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
2070 long groupId = createGroupId(getGroupIdKey(routerName));
2071 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, NatConstants.INVALID_ID, routerId, true);
2075 boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
2076 InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
2077 (Routers.class, new RoutersKey(routerUuid.getValue())).build();
2078 Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
2079 if (routerData.isPresent() && routerData.get().isEnableSnat()) {
2084 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2085 routerId, boolean isSnatCfgd){
2086 installFlowsWithUpdatedVpnId(primarySwitchId, routerName, bgpVpnId, routerId, isSnatCfgd, null);
2089 public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long bgpVpnId, long
2090 routerId, boolean isSnatCfgd, Routers router){
2091 long changedVpnId = bgpVpnId;
2092 String logMsg = "NAT Service : Update the BGP VPN ID {}";
2093 if (bgpVpnId == NatConstants.INVALID_ID){
2094 changedVpnId = routerId;
2095 logMsg = "NAT Service : Update the router ID {}";
2098 List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
2099 if (switches == null || switches.isEmpty()) {
2100 LOG.debug("No switches found for router {}",routerName);
2103 for(BigInteger dpnId : switches) {
2104 // Update the BGP VPN ID in the SNAT miss entry to group
2105 if( !dpnId.equals(primarySwitchId) ) {
2106 LOG.debug("NAT Service : Install group in non NAPT switch {}", dpnId);
2107 List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
2108 long groupId = createGroupId(getGroupIdKey(routerName));
2110 groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
2113 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
2114 changedVpnId, groupId, dpnId);
2115 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
2116 mdsalManager.installFlow(flowEntity);
2119 LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
2120 changedVpnId, primarySwitchId);
2121 FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(primarySwitchId, routerName, changedVpnId);
2122 mdsalManager.installFlow(flowEntity);
2124 LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
2125 " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
2126 installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
2128 LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
2129 " controller in the Primary switch {}", changedVpnId, primarySwitchId);
2130 createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2132 LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
2133 changedVpnId, primarySwitchId);
2134 installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
2136 LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
2137 " in the Primary switch {}", changedVpnId, primarySwitchId);
2138 updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
2140 LOG.debug("NAT Service : Installing SNAT PFIB flow in the primary switch {}", primarySwitchId);
2141 Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
2142 //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
2143 if (vpnId != null && vpnId != NatConstants.INVALID_ID) {
2144 installNaptPfibEntry(primarySwitchId, vpnId);
2150 public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
2151 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
2152 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
2153 if(ipPortMapping == null){
2154 LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
2158 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
2159 for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
2160 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
2161 for(IpPortMap ipPortMap : ipPortMaps){
2162 String ipPortInternal = ipPortMap.getIpPortInternal();
2163 String[] ipPortParts = ipPortInternal.split(":");
2164 if(ipPortParts.length != 2) {
2165 LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
2168 String internalIp = ipPortParts[0];
2169 String internalPort = ipPortParts[1];
2171 ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
2172 NAPTEntryEvent.Protocol protocol;
2173 switch (protocolTypes){
2175 protocol = NAPTEntryEvent.Protocol.TCP;
2178 protocol = NAPTEntryEvent.Protocol.UDP;
2181 protocol = NAPTEntryEvent.Protocol.TCP;
2183 SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
2184 SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
2185 long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
2186 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2187 internalAddress, externalAddress, protocol);
2188 NaptEventHandler.buildAndInstallNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
2189 externalAddress, internalAddress, protocol);
2195 public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
2197 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
2198 List<MatchInfo> matches = new ArrayList<>();
2199 matches.add(new MatchInfo(MatchFieldType.eth_type,
2200 new long[] { 0x0800L }));
2201 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2202 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2204 List<InstructionInfo> instructions = new ArrayList<>();
2205 List<ActionInfo> actionsInfo = new ArrayList<>();
2207 ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
2208 BigInteger.valueOf(changedVpnId)}) ;
2209 actionsInfo.add(actionSetField);
2210 LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
2211 actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
2212 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
2213 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2214 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2215 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2216 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2218 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2222 public FlowEntity buildSnatFlowEntityWithUpdatedVpnIdForPrimrySwtch(BigInteger dpId, String routerName, long changedVpnId) {
2224 LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} changed VPN ID {}", dpId, routerName, changedVpnId );
2225 List<MatchInfo> matches = new ArrayList<>();
2226 matches.add(new MatchInfo(MatchFieldType.eth_type,
2227 new long[] { 0x0800L }));
2228 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2229 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2231 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
2232 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2233 { NwConstants.OUTBOUND_NAPT_TABLE }));
2235 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
2236 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
2237 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2238 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
2240 LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
2244 // TODO : Replace this with ITM Rpc once its available with full functionality
2245 protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
2246 LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
2247 FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
2248 mdsalManager.installFlow(flowEntity);
2252 private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
2253 LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
2254 BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
2255 BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
2256 List<MatchInfo> matches = new ArrayList<>();
2257 matches.add(new MatchInfo(MatchFieldType.eth_type,
2258 new long[] { 0x0800L }));
2259 matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
2261 List<InstructionInfo> instructions = new ArrayList<>();
2262 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
2263 { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2264 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
2265 { NwConstants.OUTBOUND_NAPT_TABLE }));
2266 String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, routerId.longValue());
2267 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, flowRef,
2268 NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
2269 NwConstants.COOKIE_TS_TABLE, matches, instructions);
2273 public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
2274 LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
2275 FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
2276 LOG.debug("NAT Service : Installing flow {}", flowEntity);
2277 mdsalManager.installFlow(flowEntity);
2280 protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
2281 LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
2282 List<MatchInfo> matches = new ArrayList<>();
2283 matches.add(new MatchInfo(MatchFieldType.eth_type,
2284 new long[]{0x0800L}));
2285 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
2286 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
2288 List<InstructionInfo> instructions = new ArrayList<>();
2289 List<ActionInfo> actionsInfos = new ArrayList<>();
2290 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
2291 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2292 instructions.add(new InstructionInfo(InstructionType.write_metadata,
2293 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2295 String flowRef = getFlowRefOutbound(dpId, NwConstants.OUTBOUND_NAPT_TABLE, routerId);
2296 BigInteger cookie = getCookieOutboundFlow(routerId);
2297 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.OUTBOUND_NAPT_TABLE, flowRef, 5, flowRef, 0, 0,
2298 cookie, matches, instructions);
2299 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2303 protected FlowEntity buildNaptFibExternalOutputFlowEntity(BigInteger dpId, long extVpnId, Uuid subnetId, String externalIp) {
2304 LOG.debug("NAT Service : buildPostSnatFlowEntity called for dpId {}, routerId {}, srcIp {}", dpId, extVpnId,
2307 List<MatchInfo> matches = new ArrayList<>();
2308 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 }));
2309 matches.add(new MatchInfo(MatchFieldType.metadata,
2310 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(extVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2311 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] { externalIp , "32" }));
2313 List<InstructionInfo> instructions = new ArrayList<>();
2314 List<ActionInfo> actionsInfos = new ArrayList<>();
2315 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
2316 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetId.getValue()), idManager);
2317 actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
2319 String flowRef = getFlowRefNaptFib(dpId, NwConstants.NAPT_PFIB_TABLE, extVpnId, externalIp);
2320 BigInteger cookie = getCookieOutboundFlow(extVpnId);
2321 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef, 6, flowRef, 0,
2322 0, cookie, matches, instructions);
2323 LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
2327 public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
2328 LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
2329 FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
2330 mdsalManager.installFlow(naptPfibFlowEntity);
2333 public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
2335 LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
2336 List<MatchInfo> matches = new ArrayList<>();
2337 matches.add(new MatchInfo(MatchFieldType.eth_type,
2338 new long[] { 0x0800L }));
2339 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
2340 MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
2342 ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
2343 ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
2344 listActionInfo.add(new ActionInfo(ActionType.nx_load_in_port, new BigInteger[]{BigInteger.ZERO}));
2345 listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
2346 instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
2348 String flowRef = getFlowRefTs(dpId, NwConstants.NAPT_PFIB_TABLE, segmentId);
2349 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.NAPT_PFIB_TABLE, flowRef,
2350 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
2351 NwConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
2353 LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
2358 protected ExternalRoutersListener getDataTreeChangeListener()
2360 return ExternalRoutersListener.this;