2 * Copyright © 2016, 2017 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 java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.Future;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.genius.mdsalutil.ActionInfo;
24 import org.opendaylight.genius.mdsalutil.BucketInfo;
25 import org.opendaylight.genius.mdsalutil.FlowEntity;
26 import org.opendaylight.genius.mdsalutil.GroupEntity;
27 import org.opendaylight.genius.mdsalutil.InstructionInfo;
28 import org.opendaylight.genius.mdsalutil.MDSALUtil;
29 import org.opendaylight.genius.mdsalutil.MatchInfo;
30 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
31 import org.opendaylight.genius.mdsalutil.NwConstants;
32 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
33 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
34 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
35 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
36 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
39 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
40 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
41 import org.opendaylight.netvirt.elanmanager.api.IElanService;
42 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
43 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
75 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;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
80 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
81 import org.opendaylight.yangtools.yang.common.RpcResult;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
86 public class NaptSwitchHA {
87 private static final Logger LOG = LoggerFactory.getLogger(NaptSwitchHA.class);
88 private final DataBroker dataBroker;
89 private final IMdsalApiManager mdsalManager;
90 private final ItmRpcService itmManager;
91 private final OdlInterfaceRpcService interfaceManager;
92 private final IdManagerService idManager;
93 private final NAPTSwitchSelector naptSwitchSelector;
94 private final ExternalRoutersListener externalRouterListener;
95 private final IBgpManager bgpManager;
96 private final VpnRpcService vpnService;
97 private final FibRpcService fibService;
98 private final IFibManager fibManager;
99 private final IElanService elanManager;
100 private List<String> externalIpsCache;
101 private HashMap<String, Long> externalIpsLabel;
102 private final EvpnNaptSwitchHA evpnNaptSwitchHA;
103 private SnatServiceManager natServiceManager;
104 private NatMode natMode = NatMode.Controller;
107 public NaptSwitchHA(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
108 final ExternalRoutersListener externalRouterListener,
109 final ItmRpcService itmManager,
110 final OdlInterfaceRpcService interfaceManager,
111 final IdManagerService idManager,
112 final NAPTSwitchSelector naptSwitchSelector,
113 final IBgpManager bgpManager,
114 final VpnRpcService vpnService,
115 final FibRpcService fibService,
116 final IFibManager fibManager,
117 final EvpnNaptSwitchHA evpnNaptSwitchHA,
118 final IElanService elanManager,
119 final SnatServiceManager natServiceManager,
120 final NatserviceConfig config) {
121 this.dataBroker = dataBroker;
122 this.mdsalManager = mdsalManager;
123 this.externalRouterListener = externalRouterListener;
124 this.itmManager = itmManager;
125 this.interfaceManager = interfaceManager;
126 this.idManager = idManager;
127 this.naptSwitchSelector = naptSwitchSelector;
128 this.bgpManager = bgpManager;
129 this.vpnService = vpnService;
130 this.fibService = fibService;
131 this.fibManager = fibManager;
132 this.evpnNaptSwitchHA = evpnNaptSwitchHA;
133 this.elanManager = elanManager;
134 this.natServiceManager = natServiceManager;
135 if (config != null) {
136 this.natMode = config.getNatMode();
140 /* This method checks the switch that gone down is a NaptSwitch for a router.
141 If it is a NaptSwitch
142 1) selects new NAPT switch
143 2) installs nat flows in new NAPT switch
144 table 21(FIB)->26(PSNAT)->group(resubmit/napttunnel)->36(Terminating)->46(outbound)->47(resubmit)->21
145 3) modify the group and miss entry flow in other vSwitches pointing to newNaptSwitch
146 4) Remove nat flows in oldNaptSwitch
148 /*public void handleNaptSwitchDown(BigInteger dpnId){
150 LOG.debug("handleNaptSwitchDown method is called with dpnId {}",dpnId);
151 BigInteger naptSwitch;
153 NaptSwitches naptSwitches = NatUtil.getNaptSwitch(dataBroker);
154 if (naptSwitches == null || naptSwitches.getRouterToNaptSwitch() == null
155 || naptSwitches.getRouterToNaptSwitch().isEmpty()) {
156 LOG.debug("NaptSwitchDown: NaptSwitch is not allocated for none of the routers");
159 for (RouterToNaptSwitch routerToNaptSwitch : naptSwitches.getRouterToNaptSwitch()) {
160 String routerName = routerToNaptSwitch.getRouterName();
161 naptSwitch = routerToNaptSwitch.getPrimarySwitchId();
162 boolean naptStatus = isNaptSwitchDown(routerName,dpnId,naptSwitch);
164 LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
167 removeSnatFlowsInOldNaptSwitch(routerName,naptSwitch);
171 } catch (Exception ex) {
172 LOG.error("Exception in handleNaptSwitchDown method {}",ex);
176 protected void removeSnatFlowsInOldNaptSwitch(String routerName, BigInteger naptSwitch,
177 HashMap<String, Long> externalIpmap) {
178 externalIpsLabel = externalIpmap;
179 //remove SNAT flows in old NAPT SWITCH
180 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
181 if (routerId == NatConstants.INVALID_ID) {
182 LOG.error("Invalid routerId returned for routerName {}", routerName);
185 String vpnName = getExtNetworkVpnName(routerName);
186 if (vpnName == null) {
187 LOG.error("Vpn is not associated to externalN/w of router {}", routerName);
190 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
191 if (extNwProvType == null) {
192 LOG.error("NAT Service : Unable to retrieve the External Network Provider Type for Router {}",
196 if (extNwProvType == ProviderTypes.VXLAN) {
197 evpnNaptSwitchHA.evpnRemoveSnatFlowsInOldNaptSwitch(routerName, routerId, vpnName, naptSwitch);
199 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
200 String tsFlowRef = externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE,
202 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE,
205 LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
206 NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
207 mdsalManager.removeFlow(tsNatFlowEntity);
209 //Remove the Outbound flow entry which forwards the packet to Outbound NAPT Table
210 String outboundNatFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch,
211 NwConstants.OUTBOUND_NAPT_TABLE, routerId);
212 FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch,
213 NwConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
214 LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
215 NwConstants.OUTBOUND_NAPT_TABLE, naptSwitch, routerId);
216 mdsalManager.removeFlow(outboundNatFlowEntity);
218 // Remove the NAPT_PFIB_TABLE(47) flow entry forwards the packet to Fib Table for inbound traffic
219 // matching on the router ID.
220 String naptPFibflowRef = externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.NAPT_PFIB_TABLE, routerId);
221 FlowEntity naptPFibFlowEntity =
222 NatUtil.buildFlowEntity(naptSwitch, NwConstants.NAPT_PFIB_TABLE, naptPFibflowRef);
223 LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
224 NwConstants.NAPT_PFIB_TABLE, naptSwitch, routerId);
225 NatUtil.djcFlow(naptPFibFlowEntity, NwConstants.DEL_FLOW, mdsalManager);
227 // Remove the NAPT_PFIB_TABLE(47) flow entry forwards the packet to Fib Table for outbound traffic
228 // matching on the vpn ID.
229 boolean switchSharedByRouters = false;
230 Uuid extNetworkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
231 if (extNetworkId != null) {
232 List<String> routerNamesAssociated = getRouterIdsForExtNetwork(extNetworkId);
233 if (routerNamesAssociated != null) {
234 for (String routerNameAssociated : routerNamesAssociated) {
235 if (!routerNameAssociated.equals(routerName)) {
236 Long routerIdAssociated = NatUtil.getVpnId(dataBroker, routerNameAssociated);
237 BigInteger naptDpn = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerNameAssociated);
238 if (naptDpn != null && naptDpn.equals(naptSwitch)) {
239 LOG.debug("Napt switch {} is also acting as primary for router {}", routerIdAssociated);
240 switchSharedByRouters = true;
245 if (!switchSharedByRouters) {
246 Long vpnId = getVpnIdForRouter(routerId);
247 if (vpnId != NatConstants.INVALID_ID) {
248 String naptFibflowRef =
249 externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.NAPT_PFIB_TABLE, vpnId);
250 FlowEntity naptFibFlowEntity =
251 NatUtil.buildFlowEntity(naptSwitch, NwConstants.NAPT_PFIB_TABLE, naptFibflowRef);
252 LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and vpnId {}",
253 NwConstants.NAPT_PFIB_TABLE, naptSwitch, vpnId);
254 NatUtil.djcFlow(naptFibFlowEntity, NwConstants.DEL_FLOW, mdsalManager);
256 LOG.error("Invalid vpnId retrieved for routerId {}", routerId);
263 //Remove Fib entries,tables 20->44 ,36-> 44
264 String gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
265 if (externalIpsLabel != null && !externalIpsLabel.isEmpty()) {
266 for (String externalIp : externalIpsLabel.keySet()) {
267 Long label = externalIpsLabel.get(externalIp);
268 externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName, label,
270 LOG.debug("Successfully removed fib entries in old naptswitch {} for router {} and "
271 + "externalIps {} label {}", naptSwitch, routerId, externalIp, label);
274 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerName);
275 if (externalIps != null) {
276 Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
277 if (networkId != null) {
278 externalRouterListener.clearFibTsAndReverseTraffic(naptSwitch, routerId, networkId,
279 externalIps, null, gwMacAddress);
280 LOG.debug("Successfully removed fib entries in old naptswitch {} for "
281 + "router {} with networkId {} and externalIps {}", naptSwitch, routerId, networkId,
284 LOG.debug("External network not associated to router {}", routerId);
286 externalRouterListener.removeNaptFibExternalOutputFlows(routerId, naptSwitch, extNetworkId,
289 LOG.debug("ExternalIps not found for router {}", routerName);
293 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
294 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
295 if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null
296 || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
297 LOG.debug("No Internal Ip Port mapping associated to router {}, no flows need to be removed in"
298 + "oldNaptSwitch {}", routerId, naptSwitch);
301 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
302 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
303 for (IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes) {
304 if (intextIpProtocolType.getIpPortMap() == null || intextIpProtocolType.getIpPortMap().isEmpty()) {
305 LOG.debug("No {} session associated to router {},no flows need to be removed in oldNaptSwitch {}",
306 intextIpProtocolType.getProtocol(), routerId, naptSwitch);
309 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
310 for (IpPortMap ipPortMap : ipPortMaps) {
311 String ipPortInternal = ipPortMap.getIpPortInternal();
312 String[] ipPortParts = ipPortInternal.split(":");
313 if (ipPortParts.length != 2) {
314 LOG.error("Unable to retrieve the Internal IP and port");
317 String internalIp = ipPortParts[0];
318 String internalPort = ipPortParts[1];
320 //Build and remove flow in outbound NAPT table
321 String switchFlowRef =
322 NatUtil.getNaptFlowRef(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId),
323 internalIp, Integer.valueOf(internalPort));
324 FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
325 cookieSnatFlow, switchFlowRef);
327 LOG.info("Remove the flow in table {} for old napt switch with the DPN ID {} and router ID {}",
328 NwConstants.OUTBOUND_NAPT_TABLE, naptSwitch, routerId);
329 mdsalManager.removeFlow(outboundNaptFlowEntity);
331 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
332 if (ipPortExternal == null) {
333 LOG.debug("External Ipport mapping not found for internalIp {} with port {} for router", internalIp,
334 internalPort, routerId);
337 String externalIp = ipPortExternal.getIpAddress();
338 int externalPort = ipPortExternal.getPortNum();
340 //Build and remove flow in inbound NAPT table
342 NatUtil.getNaptFlowRef(naptSwitch, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId),
343 externalIp, externalPort);
344 FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INBOUND_NAPT_TABLE,
345 cookieSnatFlow, switchFlowRef);
347 LOG.info("Remove the flow in table {} for old napt switch with the DPN ID {} and router ID {}",
348 NwConstants.INBOUND_NAPT_TABLE, naptSwitch, routerId);
349 mdsalManager.removeFlow(inboundNaptFlowEntity);
355 private List<String> getRouterIdsForExtNetwork(Uuid extNetworkId) {
356 List<String> routerUuidsAsString = new ArrayList<>();
357 InstanceIdentifier<Networks> extNetwork = InstanceIdentifier.builder(ExternalNetworks.class)
358 .child(Networks.class, new NetworksKey(extNetworkId)).build();
359 Optional<Networks> extNetworkData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetwork);
360 if (extNetworkData.isPresent()) {
361 List<Uuid> routerUuids = extNetworkData.get().getRouterIds();
362 if (routerUuids != null) {
363 for (Uuid routerUuid : routerUuids) {
364 routerUuidsAsString.add(routerUuid.getValue());
368 return routerUuidsAsString;
371 public boolean isNaptSwitchDown(String routerName, BigInteger dpnId, BigInteger naptSwitch,
372 Long routerVpnId, List<String> externalIpCache) {
373 return isNaptSwitchDown(routerName, dpnId, naptSwitch, routerVpnId, externalIpCache, true);
376 // TODO Clean up the exception handling
377 @SuppressWarnings("checkstyle:IllegalCatch")
378 public boolean isNaptSwitchDown(String routerName, BigInteger dpnId, BigInteger naptSwitch,
379 Long routerVpnId, List<String> externalIpCache, boolean isClearBgpRts) {
380 externalIpsCache = externalIpCache;
381 if (!naptSwitch.equals(dpnId)) {
382 LOG.debug("DpnId {} is not a naptSwitch {} for Router {}", dpnId, naptSwitch, routerName);
385 LOG.debug("NaptSwitch {} is down for Router {}", naptSwitch, routerName);
386 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
387 if (routerId == NatConstants.INVALID_ID) {
388 LOG.error("Invalid routerId returned for routerName {}", routerName);
391 //elect a new NaptSwitch
392 naptSwitch = naptSwitchSelector.selectNewNAPTSwitch(routerName);
393 if (natMode == NatMode.Conntrack) {
394 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
395 natServiceManager.notify(extRouters, dpnId, dpnId, SnatServiceManager.Action.SNAT_ALL_SWITCH_DISBL);
396 natServiceManager.notify(extRouters, naptSwitch, naptSwitch,
397 SnatServiceManager.Action.SNAT_ALL_SWITCH_ENBL);
399 if (naptSwitch.equals(BigInteger.ZERO)) {
400 LOG.error("NAT Service : No napt switch is elected since all the switches for router {}"
401 + " are down. SNAT IS NOT SUPPORTED FOR ROUTER {}", routerName);
402 boolean naptUpdatedStatus = updateNaptSwitch(routerName, naptSwitch);
403 if (!naptUpdatedStatus) {
404 LOG.debug("Failed to update naptSwitch {} for router {} in ds", naptSwitch, routerName);
407 if (externalIpsCache != null) {
408 String vpnName = getExtNetworkVpnName(routerName);
409 if (vpnName != null) {
410 //List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
411 //if (externalIps != null) {
413 LOG.debug("NAT Service : Clearing both FIB entries and the BGP routes");
414 for (String externalIp : externalIpsCache) {
415 externalRouterListener.clearBgpRoutes(externalIp, vpnName);
418 LOG.debug("NAT Service : Clearing the FIB entries but not the BGP routes");
419 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
420 for (String externalIp : externalIpsCache) {
421 LOG.debug("NAT Service : Removing Fib entry rd {} prefix {}", rd, externalIp);
422 fibManager.removeFibEntry(dataBroker, rd, externalIp, null);
426 LOG.debug("vpn is not associated to extn/w for router {}", routerName);
429 LOG.debug("No ExternalIps found for subnets under router {}, no bgp routes need to be cleared",
434 //checking elected switch health status
435 if (!getSwitchStatus(naptSwitch)) {
436 LOG.error("Newly elected Napt switch {} for router {} is down", naptSwitch, routerName);
439 LOG.debug("New NaptSwitch {} is up for Router {} and can proceed for flow installation",
440 naptSwitch, routerName);
441 //update napt model for new napt switch
442 boolean naptUpdated = updateNaptSwitch(routerName, naptSwitch);
444 //update group of ordinary switch point to naptSwitch tunnel port
445 updateNaptSwitchBucketStatus(routerName, naptSwitch);
447 LOG.error("Failed to update naptSwitch model for newNaptSwitch {} for router {}",
448 naptSwitch, routerName);
451 //update table26 forward packets to table46(outbound napt table)
452 FlowEntity flowEntity =
453 buildSnatFlowEntityForNaptSwitch(naptSwitch, routerName, routerVpnId, NatConstants.ADD_FLOW);
454 if (flowEntity == null) {
455 LOG.debug("Failed to populate flowentity for router {} in naptSwitch {}", routerName, naptSwitch);
457 LOG.debug("Successfully installed flow in naptSwitch {} for router {}", naptSwitch, routerName);
458 mdsalManager.installFlow(flowEntity);
461 installSnatFlows(routerName, routerId, naptSwitch, routerVpnId);
463 boolean flowInstalledStatus = handleNatFlowsInNewNaptSwitch(routerId, dpnId, naptSwitch, routerVpnId);
464 if (flowInstalledStatus) {
465 LOG.debug("Installed all active session flows in newNaptSwitch {} for routerName {}",
466 naptSwitch, routerName);
468 LOG.error("Failed to install flows in newNaptSwitch {} for routerId {}", naptSwitch, routerId);
471 //remove group in new naptswitch, coz this switch acted previously as ordinary switch
472 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
473 GroupEntity groupEntity = null;
475 groupEntity = MDSALUtil.buildGroupEntity(naptSwitch, groupId, routerName,
476 GroupTypes.GroupAll, null);
477 LOG.info("NAT Service : Removing NAPT Group in new naptSwitch {}", naptSwitch);
478 mdsalManager.removeGroup(groupEntity);
479 } catch (Exception ex) {
480 LOG.debug("NAT Service : Failed to remove group in new naptSwitch {} : {}", groupEntity, ex);
486 private String getExtNetworkVpnName(String routerName) {
487 Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
488 if (networkId == null) {
489 LOG.error("networkId is null for the router ID {}", routerName);
491 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
492 if (vpnName != null) {
493 LOG.debug("retrieved vpn name {} associated with ext nw {} in router {}",
494 vpnName, networkId, routerName);
497 LOG.error("No VPN associated with ext nw {} belonging to routerId {}",
498 networkId, routerName);
504 public void updateNaptSwitchBucketStatus(String routerName, BigInteger naptSwitch) {
505 LOG.debug("updateNaptSwitchBucketStatus method is called");
507 List<BigInteger> dpnList = naptSwitchSelector.getDpnsForVpn(routerName);
508 //List<BigInteger> dpnList = getDpnListForRouter(routerName);
509 if (dpnList == null || dpnList.isEmpty()) {
510 LOG.debug("No switches found for router {}", routerName);
513 for (BigInteger dpn : dpnList) {
514 if (!dpn.equals(naptSwitch)) {
515 LOG.debug("Updating SNAT_TABLE missentry for DpnId {} which is not naptSwitch for router {}",
517 List<BucketInfo> bucketInfoList = handleGroupInNeighborSwitches(dpn, routerName, naptSwitch);
518 if (bucketInfoList == null) {
519 LOG.debug("Failed to populate bucketInfo for orinaryswitch {} whose naptSwitch {} for router {} ",
520 dpn, naptSwitch, routerName);
523 modifySnatGroupEntry(dpn, bucketInfoList, routerName);
528 // TODO Clean up the exception handling
529 @SuppressWarnings("checkstyle:IllegalCatch")
530 private boolean handleNatFlowsInNewNaptSwitch(Long routerId, BigInteger oldNaptSwitch, BigInteger newNaptSwitch,
532 LOG.debug("Proceeding to install flows in newNaptSwitch {} for routerId {}", newNaptSwitch, routerId);
533 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
534 if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null
535 || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
536 LOG.debug("No Internal Ip Port mapping associated to router {}, no flows need to be installed in"
537 + "newNaptSwitch {}", routerId, newNaptSwitch);
541 Long vpnId = getVpnIdForRouter(routerId);
542 if (vpnId == NatConstants.INVALID_ID) {
543 LOG.error("Invalid vpnId for routerId {}", routerId);
547 if (routerId.equals(routerVpnId)) {
548 bgpVpnId = NatConstants.INVALID_ID;
550 bgpVpnId = routerVpnId;
552 LOG.debug("retrieved bgpVpnId {} for router {}", bgpVpnId, routerId);
553 // Get the External Gateway MAC Address
554 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
555 if (extGwMacAddress != null) {
556 LOG.debug("External Gateway MAC address {} found for External Router ID {}", extGwMacAddress, routerId);
558 LOG.error("No External Gateway MAC address found for External Router ID {}", routerId);
561 for (IntextIpProtocolType protocolType : ipPortMapping.getIntextIpProtocolType()) {
562 if (protocolType.getIpPortMap() == null || protocolType.getIpPortMap().isEmpty()) {
563 LOG.debug("No {} session associated to router {}", protocolType.getProtocol(), routerId);
566 for (IpPortMap intIpPortMap : protocolType.getIpPortMap()) {
567 String internalIpAddress = intIpPortMap.getIpPortInternal().split(":")[0];
568 String intportnum = intIpPortMap.getIpPortInternal().split(":")[1];
569 LOG.debug("NAT Service: Found Internal IP Address {} and Port Number {}",
570 internalIpAddress, intportnum);
571 //Get the external IP address and the port from the model
572 NAPTEntryEvent.Protocol proto =
573 protocolType.getProtocol().toString().equals(ProtocolTypes.TCP.toString())
574 ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
575 IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
576 internalIpAddress, intportnum, proto);
577 if (ipPortExternal == null) {
578 LOG.debug("External Ipport mapping is not found for internalIp {} with port {}",
579 internalIpAddress, intportnum);
582 String externalIpAddress = ipPortExternal.getIpAddress();
583 Integer extportNumber = ipPortExternal.getPortNum();
584 LOG.debug("ExternalIPport {}:{} mapping for internal ipport {}:{}", externalIpAddress, extportNumber,
585 internalIpAddress, intportnum);
587 SessionAddress sourceAddress = new SessionAddress(internalIpAddress, Integer.valueOf(intportnum));
588 SessionAddress externalAddress = new SessionAddress(externalIpAddress, extportNumber);
590 //checking naptSwitch status before installing flows
591 if (getSwitchStatus(newNaptSwitch)) {
592 //Install the flow in newNaptSwitch Inbound NAPT table.
594 NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NwConstants.INBOUND_NAPT_TABLE,
595 vpnId, routerId, bgpVpnId, externalAddress, sourceAddress, proto, extGwMacAddress);
596 } catch (Exception ex) {
597 LOG.error("Failed to add flow in INBOUND_NAPT_TABLE for routerid {} dpnId {} "
598 + "extIpport{}:{} proto {} ipport {}:{} BgpVpnId {}",
599 routerId, newNaptSwitch, externalAddress, extportNumber, proto,
600 internalIpAddress, intportnum, bgpVpnId);
603 LOG.debug("Successfully installed a flow in Primary switch {} Inbound NAPT table for router {} "
604 + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
605 newNaptSwitch, routerId, internalIpAddress,
606 intportnum, proto, externalAddress, extportNumber, bgpVpnId);
607 //Install the flow in newNaptSwitch Outbound NAPT table.
609 NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
610 vpnId, routerId, bgpVpnId, sourceAddress, externalAddress, proto, extGwMacAddress);
611 } catch (Exception ex) {
612 LOG.error("Failed to add flow in OUTBOUND_NAPT_TABLE for routerid {} dpnId {} "
613 + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {} - {}",
614 routerId, newNaptSwitch, internalIpAddress,
615 intportnum, proto, externalAddress, extportNumber, bgpVpnId, ex);
618 LOG.debug("Successfully installed a flow in Primary switch {} Outbound NAPT table for router {} "
619 + "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
620 newNaptSwitch, routerId, internalIpAddress,
621 intportnum, proto, externalAddress, extportNumber, bgpVpnId);
623 LOG.error("NewNaptSwitch {} gone down while installing flows from oldNaptswitch {}",
624 newNaptSwitch, oldNaptSwitch);
632 // TODO Clean up the exception handling
633 @SuppressWarnings("checkstyle:IllegalCatch")
634 private Long getVpnIdForRouter(Long routerId) {
637 Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
638 if (networkId == null) {
639 LOG.debug("network is not associated to router {}", routerId);
641 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
642 if (vpnUuid == null) {
643 LOG.debug("vpn is not associated for network {} in router {}", networkId, routerId);
645 Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
647 LOG.debug("retrieved vpnId {} for router {}", vpnId, routerId);
650 LOG.debug("retrieved invalid vpn Id");
654 } catch (Exception ex) {
655 LOG.debug("Exception while retrieving vpnId for router {} - {}", routerId, ex);
657 return NatConstants.INVALID_ID;
660 public boolean getSwitchStatus(BigInteger switchId) {
661 NodeId nodeId = new NodeId("openflow:" + switchId);
662 LOG.debug("Querying switch with dpnId {} is up/down", nodeId);
663 InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
664 .child(Node.class, new NodeKey(nodeId)).build();
665 Optional<Node> nodeOptional = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
666 if (nodeOptional.isPresent()) {
667 LOG.debug("Switch {} is up", nodeId);
670 LOG.debug("Switch {} is down", nodeId);
674 public List<BucketInfo> handleGroupInPrimarySwitch() {
675 List<BucketInfo> listBucketInfo = new ArrayList<>();
676 List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
677 listActionInfoPrimary.add(new ActionNxResubmit(NwConstants.INTERNAL_TUNNEL_TABLE));
678 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
679 listBucketInfo.add(bucketPrimary);
680 return listBucketInfo;
683 public List<BucketInfo> handleGroupInNeighborSwitches(BigInteger dpnId, String routerName, BigInteger naptSwitch) {
684 List<BucketInfo> listBucketInfo = new ArrayList<>();
685 String ifNamePrimary;
686 Long routerId = NatUtil.getVpnId(dataBroker, routerName);
687 if (routerId == NatConstants.INVALID_ID) {
688 LOG.error("Invalid routerId returned for routerName {}", routerName);
689 return listBucketInfo;
691 ifNamePrimary = getTunnelInterfaceName(dpnId, naptSwitch);
692 if (ifNamePrimary != null) {
693 LOG.debug("TunnelInterface {} between ordinary switch {} and naptSwitch {}",
694 ifNamePrimary, dpnId, naptSwitch);
695 List<ActionInfo> listActionInfoPrimary =
696 NatUtil.getEgressActionsForInterface(interfaceManager, ifNamePrimary, routerId);
697 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
698 listBucketInfo.add(bucketPrimary);
700 LOG.debug("No TunnelInterface between ordinary switch {} and naptSwitch {}", dpnId, naptSwitch);
702 return listBucketInfo;
705 // TODO Clean up the exception handling
706 @SuppressWarnings("checkstyle:IllegalCatch")
707 protected void installSnatGroupEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
708 GroupEntity groupEntity = null;
710 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
711 LOG.debug("install SnatMissEntry for groupId {} for dpnId {} for router {}", groupId, dpnId, routerName);
712 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
713 GroupTypes.GroupAll, bucketInfo);
714 mdsalManager.syncInstallGroup(groupEntity, 0);
715 LOG.debug("installed the SNAT to NAPT GroupEntity:{}", groupEntity);
716 } catch (Exception ex) {
717 LOG.error("Failed to install group for groupEntity {} : {}", groupEntity, ex);
721 private void modifySnatGroupEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
722 installSnatGroupEntry(dpnId, bucketInfo, routerName);
723 LOG.debug("modified SnatMissEntry for dpnId {} of router {}", dpnId, routerName);
726 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
727 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
728 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
731 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(
732 new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId).setDestinationDpid(dstDpId)
733 .setTunnelType(tunType).build());
734 rpcResult = result.get();
735 if (!rpcResult.isSuccessful()) {
736 tunType = TunnelTypeGre.class;
737 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
738 .setSourceDpid(srcDpId)
739 .setDestinationDpid(dstDpId)
740 .setTunnelType(tunType)
742 rpcResult = result.get();
743 if (!rpcResult.isSuccessful()) {
744 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
746 return rpcResult.getResult().getInterfaceName();
748 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
750 return rpcResult.getResult().getInterfaceName();
752 } catch (InterruptedException | ExecutionException e) {
753 LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {} :",
754 srcDpId, dstDpId, e);
760 // TODO Clean up the exception handling
761 @SuppressWarnings("checkstyle:IllegalCatch")
762 public boolean updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
763 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
764 .setPrimarySwitchId(naptSwitchId).build();
766 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
767 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
768 } catch (Exception ex) {
769 LOG.error("Failed to write naptSwitch {} for router {} in ds",
770 naptSwitchId, routerName);
773 LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
774 naptSwitchId, routerName);
778 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId,
779 long routerVpnId, int addordel) {
780 FlowEntity flowEntity;
781 List<MatchInfo> matches = new ArrayList<>();
782 matches.add(MatchEthernetType.IPV4);
783 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerVpnId), MetaDataUtil.METADATA_MASK_VRFID));
785 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
787 if (addordel == NatConstants.ADD_FLOW) {
788 List<ActionInfo> actionsInfo = new ArrayList<>();
789 long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerVpnId,
791 actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
792 LOG.debug("Setting the tunnel to the list of action infos {}", actionsInfo);
793 actionsInfo.add(new ActionGroup(groupId));
794 List<InstructionInfo> instructions = new ArrayList<>();
795 instructions.add(new InstructionApplyActions(actionsInfo));
797 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
798 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
799 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
801 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
802 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
803 NwConstants.COOKIE_SNAT_TABLE, matches, null);
808 public FlowEntity buildSnatFlowEntityForNaptSwitch(BigInteger dpId, String routerName,
809 long routerVpnId, int addordel) {
810 FlowEntity flowEntity;
811 List<MatchInfo> matches = new ArrayList<>();
812 matches.add(MatchEthernetType.IPV4);
813 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerVpnId), MetaDataUtil.METADATA_MASK_VRFID));
815 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
817 if (addordel == NatConstants.ADD_FLOW) {
818 List<InstructionInfo> instructions = new ArrayList<>();
820 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
822 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
823 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
824 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
826 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
827 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
828 NwConstants.COOKIE_SNAT_TABLE, matches, null);
833 private String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
834 return NatConstants.SNAT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
835 .FLOWID_SEPARATOR + routerID;
838 protected void installSnatFlows(String routerName, Long routerId, BigInteger naptSwitch, Long routerVpnId) {
840 if (routerId.equals(routerVpnId)) {
841 LOG.debug("NAT Service : Installing flows for router with internalvpnId");
842 //36 -> 46 ..Install flow forwarding packet to table46 from table36
843 LOG.debug("NAT Service : installTerminatingServiceTblEntry in naptswitch with dpnId {} for "
844 + "routerName {} with routerId {}",
845 naptSwitch, routerName, routerId);
846 externalRouterListener.installTerminatingServiceTblEntry(naptSwitch, routerName);
848 //Install default flows punting to controller in table 46(OutBoundNapt table)
849 LOG.debug("NAT Service : installOutboundMissEntry in naptswitch with dpnId {} for "
850 + "routerName {} with routerId {}",
851 naptSwitch, routerName, routerId);
852 externalRouterListener.createOutboundTblEntry(naptSwitch, routerId);
854 //Table 47 point to table 21 for inbound traffic
855 LOG.debug("NAT Service : installNaptPfibEntry in naptswitch with dpnId {} for router {}",
856 naptSwitch, routerId);
857 externalRouterListener.installNaptPfibEntry(naptSwitch, routerId);
859 //Table 47 point to group
860 LOG.debug("NAT Service : installNaptPfibExternalOutputFlow in naptswitch with dpnId {} for router {}",
861 naptSwitch, routerId);
862 externalRouterListener.installNaptPfibExternalOutputFlow(routerName, routerId, naptSwitch);
864 //36 -> 46 ..Install flow forwarding packet to table46 from table36
865 LOG.debug("NAT Service : installTerminatingServiceTblEntry in naptswitch with dpnId {} for "
866 + "routerName {} with BgpVpnId {}",
867 naptSwitch, routerName, routerVpnId);
868 externalRouterListener
869 .installTerminatingServiceTblEntryWithUpdatedVpnId(naptSwitch, routerName, routerVpnId);
871 //Install default flows punting to controller in table 46(OutBoundNapt table)
872 LOG.debug("NAT Service : installOutboundMissEntry in naptswitch with dpnId {} for "
873 + "routerName {} with BgpVpnId {}",
874 naptSwitch, routerName, routerVpnId);
875 externalRouterListener.createOutboundTblEntryWithBgpVpn(naptSwitch, routerId, routerVpnId);
877 //Table 47 point to table 21 for inbound traffic
878 LOG.debug("NAT Service : installNaptPfibEntry in naptswitch with dpnId {} for router {} with BgpVpnId {}",
879 naptSwitch, routerId, routerVpnId);
880 externalRouterListener.installNaptPfibEntryWithBgpVpn(naptSwitch, routerId, routerVpnId);
883 String vpnName = getExtNetworkVpnName(routerName);
884 if (vpnName != null) {
885 //NAPT PFIB point to FIB table for outbound traffic
886 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
887 boolean shouldInstallNaptPfibWithExtNetworkVpnId = true;
888 List<Uuid> externalSubnetIds = NatUtil.getExternalSubnetIdsForRouter(dataBroker, routerName);
889 if (externalSubnetIds != null && !externalSubnetIds.isEmpty()) {
890 //NAPT PFIB point to FIB table for outbound traffic - using external subnetID as vpnID.
891 for (Uuid externalSubnetId : externalSubnetIds) {
892 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnId(dataBroker, externalSubnetId);
893 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
894 shouldInstallNaptPfibWithExtNetworkVpnId = false;
895 LOG.debug("NAT Service : installNaptPfibEntry fin naptswitch with dpnId {} for "
896 + "BgpVpnId {}", naptSwitch, externalSubnetVpnId);
897 externalRouterListener.installNaptPfibEntry(naptSwitch, externalSubnetVpnId);
901 if (vpnId != NatConstants.INVALID_ID && shouldInstallNaptPfibWithExtNetworkVpnId) {
902 //NAPT PFIB table point to FIB table for outbound traffic - using external networkID as vpnID.
903 LOG.debug("NAT Service : installNaptPfibEntry fin naptswitch with dpnId {} for "
904 + "BgpVpnId {}", naptSwitch, vpnId);
905 externalRouterListener.installNaptPfibEntry(naptSwitch, vpnId);
906 } else if (vpnId != NatConstants.INVALID_ID) {
907 LOG.debug("NAT Service : Associated BgpvpnId not found for router {}", routerId);
910 //Install Fib entries for ExternalIps & program 36 -> 44
911 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
912 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
913 if (externalIps != null) {
914 for (String externalIp : externalIps) {
915 removeFibEntry(rd, externalIp);
916 LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows in naptswitch id {} "
917 + "with vpnName {} and externalIp {}",
918 naptSwitch, vpnName, externalIp);
919 externalRouterListener.advToBgpAndInstallFibAndTsFlows(naptSwitch, NwConstants.INBOUND_NAPT_TABLE,
920 vpnName, routerId, routerName, externalIp, null /* external-router */, vpnService, fibService,
921 bgpManager, dataBroker, LOG);
922 LOG.debug("NAT Service : Successfully added fib entries in naptswitch {} for "
923 + "router {} with external IP {}", naptSwitch,
924 routerId, externalIp);
927 LOG.debug("NAT Service : External Ip not found for routerId {}", routerId);
930 LOG.debug("NAT Service : Associated vpnName not found for router {}", routerId);
934 protected void bestEffortDeletion(long routerId, String routerName, HashMap<String, Long> externalIpLabel) {
935 List<String> newExternalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
936 if (newExternalIps != null && externalIpsCache != null) {
937 Set<String> removedExternalIps = new HashSet<>(externalIpsCache);
938 removedExternalIps.removeAll(newExternalIps);
939 if (removedExternalIps.isEmpty()) {
940 LOG.debug("No external Ip needed to be removed in bestEffortDeletion method for router {}", routerName);
943 String vpnName = getExtNetworkVpnName(routerName);
944 if (vpnName == null) {
945 LOG.debug("Vpn is not associated to externalN/w of router {}", routerName);
948 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
949 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
950 LOG.debug("No naptSwitch is selected for router {}", routerName);
953 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
954 if (extNwProvType == null) {
957 String gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
958 if (extNwProvType == ProviderTypes.VXLAN) {
959 for (String externalIp : removedExternalIps) {
960 externalRouterListener.clearBgpRoutes(externalIp, vpnName);
961 externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName,
962 NatConstants.DEFAULT_LABEL_VALUE, gwMacAddress);
963 LOG.debug("NAT Service: Successfully removed fib entry for externalIp {} for routerId {} "
964 + "on NAPT switch {} ", externalIp, routerId, naptSwitch);
967 if (externalIpLabel == null || externalIpLabel.size() == 0) {
968 LOG.debug("ExternalIpLabel map is empty for router {}", routerName);
972 for (String externalIp : removedExternalIps) {
973 if (externalIpLabel.containsKey(externalIp)) {
974 label = externalIpLabel.get(externalIp);
975 LOG.debug("Label {} for ExternalIp {} for router {}", label, externalIp, routerName);
977 LOG.debug("Label for ExternalIp {} is not found for router {}", externalIp, routerName);
980 externalRouterListener.clearBgpRoutes(externalIp, vpnName);
981 externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerId, externalIp, vpnName, label,
983 LOG.debug("Successfully removed fib entries in switch {} for router {} and externalIps {}",
984 naptSwitch, routerId, externalIp);
988 LOG.debug("No external IP found for router {}", routerId);
992 private void removeFibEntry(String rd, String prefix) {
993 InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
994 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
995 .child(VrfEntry.class, new VrfEntryKey(prefix));
996 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
997 Optional<VrfEntry> ent = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
998 if (ent.isPresent()) {
999 LOG.debug("NAT Service : Removing Fib entry rd {} prefix {}", rd, prefix);
1000 fibManager.removeFibEntry(dataBroker, rd, prefix, null);
1004 protected void subnetRegisterMapping(Routers routerEntry, Long segmentId) {
1005 externalRouterListener.subnetRegisterMapping(routerEntry, segmentId);