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.Collection;
14 import java.util.HashSet;
15 import java.util.List;
17 import java.util.Map.Entry;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
28 import org.opendaylight.genius.infra.Datastore.Configuration;
29 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
30 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
31 import org.opendaylight.genius.mdsalutil.ActionInfo;
32 import org.opendaylight.genius.mdsalutil.BucketInfo;
33 import org.opendaylight.genius.mdsalutil.FlowEntity;
34 import org.opendaylight.genius.mdsalutil.GroupEntity;
35 import org.opendaylight.genius.mdsalutil.InstructionInfo;
36 import org.opendaylight.genius.mdsalutil.MDSALUtil;
37 import org.opendaylight.genius.mdsalutil.MatchInfo;
38 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
39 import org.opendaylight.genius.mdsalutil.NwConstants;
40 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
41 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
42 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
43 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
44 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
45 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
46 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
47 import org.opendaylight.netvirt.elanmanager.api.IElanService;
48 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
49 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
76 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;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
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 odlInterfaceRpcService;
92 private final IdManagerService idManager;
93 private final NAPTSwitchSelector naptSwitchSelector;
94 private final ExternalRoutersListener externalRouterListener;
95 private final NaptEventHandler naptEventHandler;
96 private final IFibManager fibManager;
97 private final IElanService elanManager;
98 private final EvpnNaptSwitchHA evpnNaptSwitchHA;
99 private final SnatServiceManager natServiceManager;
100 private final NatMode natMode;
101 private final IInterfaceManager interfaceManager;
102 private final NatOverVxlanUtil natOverVxlanUtil;
104 private volatile Collection<String> externalIpsCache;
107 public NaptSwitchHA(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
108 final ExternalRoutersListener externalRouterListener,
109 final ItmRpcService itmManager,
110 final OdlInterfaceRpcService odlInterfaceRpcService,
111 final IdManagerService idManager,
112 final NAPTSwitchSelector naptSwitchSelector,
113 final IFibManager fibManager,
114 final EvpnNaptSwitchHA evpnNaptSwitchHA,
115 final IElanService elanManager,
116 final SnatServiceManager natServiceManager,
117 final NatserviceConfig config,
118 final NaptEventHandler naptEventHandler,
119 final IInterfaceManager interfaceManager,
120 final NatOverVxlanUtil natOverVxlanUtil) {
121 this.dataBroker = dataBroker;
122 this.mdsalManager = mdsalManager;
123 this.externalRouterListener = externalRouterListener;
124 this.itmManager = itmManager;
125 this.odlInterfaceRpcService = odlInterfaceRpcService;
126 this.idManager = idManager;
127 this.naptSwitchSelector = naptSwitchSelector;
128 this.naptEventHandler = naptEventHandler;
129 this.fibManager = fibManager;
130 this.evpnNaptSwitchHA = evpnNaptSwitchHA;
131 this.elanManager = elanManager;
132 this.natServiceManager = natServiceManager;
133 this.interfaceManager = interfaceManager;
134 if (config != null) {
135 this.natMode = config.getNatMode();
137 this.natMode = NatMode.Controller;
139 this.natOverVxlanUtil = natOverVxlanUtil;
142 protected void removeSnatFlowsInOldNaptSwitch(String routerName, Long routerId, BigInteger naptSwitch,
143 @Nullable Map<String, Long> externalIpmap,
144 TypedReadWriteTransaction<Configuration> confTx)
145 throws ExecutionException, InterruptedException {
147 //remove SNAT flows in old NAPT SWITCH
148 Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
149 String vpnName = getExtNetworkVpnName(routerName, networkId);
150 if (vpnName == null) {
151 LOG.error("removeSnatFlowsInOldNaptSwitch : Vpn is not associated to externalN/w of router {}",
155 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, networkId);
156 if (extNwProvType == null) {
157 LOG.error("removeSnatFlowsInOldNaptSwitch : Unable to retrieve the External Network Provider Type "
158 + "for Router {}", routerName);
161 if (extNwProvType == ProviderTypes.VXLAN) {
162 evpnNaptSwitchHA.evpnRemoveSnatFlowsInOldNaptSwitch(routerName, routerId, vpnName, naptSwitch, confTx);
164 //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
165 long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager,
166 idManager, routerId, routerName);
167 String tsFlowRef = externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE,
169 FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.INTERNAL_TUNNEL_TABLE,
172 LOG.info("removeSnatFlowsInOldNaptSwitch : Remove the flow in table {} for the old napt switch "
173 + "with the DPN ID {} and router ID {}", NwConstants.INTERNAL_TUNNEL_TABLE, naptSwitch, routerId);
174 mdsalManager.removeFlow(confTx, tsNatFlowEntity);
176 if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanManager, extNwProvType)) {
177 //Remove the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
178 NatUtil.removePreDnatToSnatTableEntry(confTx, mdsalManager, naptSwitch);
180 //Remove the Outbound flow entry which forwards the packet to Outbound NAPT Table
181 LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
182 NwConstants.OUTBOUND_NAPT_TABLE, naptSwitch, routerId);
184 String outboundTcpNatFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch,
185 NwConstants.OUTBOUND_NAPT_TABLE, routerId, NwConstants.IP_PROT_TCP);
186 FlowEntity outboundTcpNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch,
187 NwConstants.OUTBOUND_NAPT_TABLE, outboundTcpNatFlowRef);
188 mdsalManager.removeFlow(confTx, outboundTcpNatFlowEntity);
190 String outboundUdpNatFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch,
191 NwConstants.OUTBOUND_NAPT_TABLE, routerId, NwConstants.IP_PROT_UDP);
192 FlowEntity outboundUdpNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch,
193 NwConstants.OUTBOUND_NAPT_TABLE, outboundUdpNatFlowRef);
194 mdsalManager.removeFlow(confTx, outboundUdpNatFlowEntity);
196 String icmpDropFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch,
197 NwConstants.OUTBOUND_NAPT_TABLE, routerId, NwConstants.IP_PROT_ICMP);
198 FlowEntity icmpDropFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
200 mdsalManager.removeFlow(confTx, icmpDropFlowEntity);
202 //Remove the NAPT PFIB TABLE (47->21) which forwards the incoming packet to FIB Table matching on the
203 // External Subnet Vpn Id.
204 Collection<Uuid> externalSubnetIdsForRouter = NatUtil.getExternalSubnetIdsForRouter(dataBroker,
206 for (Uuid externalSubnetId : externalSubnetIdsForRouter) {
207 long subnetVpnId = NatUtil.getVpnId(dataBroker, externalSubnetId.getValue());
208 if (subnetVpnId != -1 && !NatUtil.checkForRoutersWithSameExtSubnetAndNaptSwitch(
209 dataBroker, externalSubnetId, routerName, naptSwitch)) {
210 String natPfibSubnetFlowRef = externalRouterListener.getFlowRefTs(naptSwitch,
211 NwConstants.NAPT_PFIB_TABLE, subnetVpnId);
212 FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NwConstants.NAPT_PFIB_TABLE,
213 natPfibSubnetFlowRef);
214 mdsalManager.removeFlow(confTx, natPfibFlowEntity);
215 LOG.debug("removeSnatFlowsInOldNaptSwitch : Removed the flow in table {} with external subnet "
216 + "Vpn Id {} as metadata on Napt Switch {}", NwConstants.NAPT_PFIB_TABLE,
217 subnetVpnId, naptSwitch);
221 // Remove the NAPT_PFIB_TABLE(47) flow entry forwards the packet to Fib Table for inbound traffic
222 // matching on the router ID.
223 String naptPFibflowRef =
224 externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.NAPT_PFIB_TABLE, routerId);
225 FlowEntity naptPFibFlowEntity =
226 NatUtil.buildFlowEntity(naptSwitch, NwConstants.NAPT_PFIB_TABLE, naptPFibflowRef);
227 LOG.info("removeSnatFlowsInOldNaptSwitch : Remove the flow in table {} for the old napt switch "
228 + "with the DPN ID {} and router ID {}", NwConstants.NAPT_PFIB_TABLE, naptSwitch, routerId);
229 mdsalManager.removeFlow(confTx, naptPFibFlowEntity);
231 // Remove the NAPT_PFIB_TABLE(47) flow entry forwards the packet to Fib Table for outbound traffic
232 // matching on the vpn ID.
233 boolean switchSharedByRouters = false;
234 Uuid extNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
235 if (extNetworkId != null && !NatUtil.checkForRoutersWithSameExtNetAndNaptSwitch(
236 dataBroker, networkId, routerName, naptSwitch)) {
237 List<String> routerNamesAssociated = getRouterIdsForExtNetwork(extNetworkId);
238 for (String routerNameAssociated : routerNamesAssociated) {
239 if (!routerNameAssociated.equals(routerName)) {
240 Long routerIdAssociated = NatUtil.getVpnId(dataBroker, routerNameAssociated);
241 BigInteger naptDpn = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerNameAssociated);
242 if (naptDpn != null && naptDpn.equals(naptSwitch)) {
243 LOG.debug("removeSnatFlowsInOldNaptSwitch : Napt switch {} is also acting as primary "
244 + "for router {}", naptSwitch, routerIdAssociated);
245 switchSharedByRouters = true;
250 if (!switchSharedByRouters) {
251 Long vpnId = getVpnIdForRouter(routerId, extNetworkId);
252 if (vpnId != NatConstants.INVALID_ID) {
253 String naptFibflowRef =
254 externalRouterListener.getFlowRefTs(naptSwitch, NwConstants.NAPT_PFIB_TABLE, vpnId);
255 FlowEntity naptFibFlowEntity =
256 NatUtil.buildFlowEntity(naptSwitch, NwConstants.NAPT_PFIB_TABLE, naptFibflowRef);
257 LOG.info("removeSnatFlowsInOldNaptSwitch : Remove the flow in table {} for the old napt switch"
258 + " with the DPN ID {} and vpnId {}", NwConstants.NAPT_PFIB_TABLE, naptSwitch, vpnId);
259 mdsalManager.removeFlow(confTx, naptFibFlowEntity);
261 LOG.error("removeSnatFlowsInOldNaptSwitch : Invalid vpnId retrieved for routerId {}",
268 //Remove Fib entries,tables 20->44 ,36-> 44
269 String gwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
270 if (externalIpmap != null && !externalIpmap.isEmpty()) {
271 for (Entry<String, Long> entry : externalIpmap.entrySet()) {
272 String externalIp = entry.getKey();
273 Long label = entry.getValue();
274 externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerName, routerId, externalIp, vpnName,
275 extNetworkId, label, gwMacAddress, true, confTx);
276 LOG.debug("removeSnatFlowsInOldNaptSwitch : Successfully removed fib entries in old naptswitch {} "
277 + "for router {} and externalIps {} label {}", naptSwitch, routerId, externalIp, label);
280 List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerName);
281 if (networkId != null) {
282 externalRouterListener.clearFibTsAndReverseTraffic(naptSwitch, routerId, networkId,
283 externalIps, null, gwMacAddress, confTx);
285 "removeSnatFlowsInOldNaptSwitch : Successfully removed fib entries in old naptswitch {} for "
286 + "router {} with networkId {} and externalIps {}", naptSwitch, routerId, networkId,
289 LOG.debug("removeSnatFlowsInOldNaptSwitch : External network not associated to router {}",
292 externalRouterListener.removeNaptFibExternalOutputFlows(routerId, naptSwitch, extNetworkId,
293 externalIps, confTx);
296 //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
297 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
298 if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null
299 || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
300 LOG.warn("removeSnatFlowsInOldNaptSwitch : No Internal Ip Port mapping associated to router {}, "
301 + "no flows need to be removed in oldNaptSwitch {}", routerId, naptSwitch);
304 BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
305 List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
306 for (IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes) {
307 if (intextIpProtocolType.getIpPortMap() == null || intextIpProtocolType.getIpPortMap().isEmpty()) {
308 LOG.debug("removeSnatFlowsInOldNaptSwitch : No {} session associated to router {},"
309 + "no flows need to be removed in oldNaptSwitch {}",
310 intextIpProtocolType.getProtocol(), routerId, naptSwitch);
313 List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
314 for (IpPortMap ipPortMap : ipPortMaps) {
315 String ipPortInternal = ipPortMap.getIpPortInternal();
316 String[] ipPortParts = ipPortInternal.split(":");
317 if (ipPortParts.length != 2) {
318 LOG.error("removeSnatFlowsInOldNaptSwitch : Unable to retrieve the Internal IP and port");
321 String internalIp = ipPortParts[0];
322 String internalPort = ipPortParts[1];
324 //Build and remove flow in outbound NAPT table
325 String switchFlowRef =
326 NatUtil.getNaptFlowRef(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId),
327 internalIp, Integer.parseInt(internalPort));
328 FlowEntity outboundNaptFlowEntity =
329 NatUtil.buildFlowEntity(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
330 cookieSnatFlow, switchFlowRef);
332 LOG.info("removeSnatFlowsInOldNaptSwitch : Remove the flow in table {} for old napt switch "
333 + "with the DPN ID {} and router ID {}", NwConstants.OUTBOUND_NAPT_TABLE, naptSwitch, routerId);
334 mdsalManager.removeFlow(confTx, outboundNaptFlowEntity);
336 IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
337 if (ipPortExternal == null) {
339 "removeSnatFlowsInOldNaptSwitch : External Ipport mapping not found for internalIp {} "
340 + "with port {} for router {}", internalIp, internalPort, routerId);
343 String externalIp = ipPortExternal.getIpAddress();
344 int externalPort = ipPortExternal.getPortNum();
346 //Build and remove flow in inbound NAPT table
348 NatUtil.getNaptFlowRef(naptSwitch, NwConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId),
349 externalIp, externalPort);
350 FlowEntity inboundNaptFlowEntity =
351 NatUtil.buildFlowEntity(naptSwitch, NwConstants.INBOUND_NAPT_TABLE,
352 cookieSnatFlow, switchFlowRef);
355 "removeSnatFlowsInOldNaptSwitch : Remove the flow in table {} for old napt switch with the "
356 + "DPN ID {} and router ID {}", NwConstants.INBOUND_NAPT_TABLE, naptSwitch, routerId);
357 mdsalManager.removeFlow(confTx, inboundNaptFlowEntity);
363 private List<String> getRouterIdsForExtNetwork(Uuid extNetworkId) {
364 List<String> routerUuidsAsString = new ArrayList<>();
365 InstanceIdentifier<Networks> extNetwork = InstanceIdentifier.builder(ExternalNetworks.class)
366 .child(Networks.class, new NetworksKey(extNetworkId)).build();
367 Optional<Networks> extNetworkData =
368 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
369 LogicalDatastoreType.CONFIGURATION, extNetwork);
370 if (extNetworkData.isPresent()) {
371 List<Uuid> routerUuids = extNetworkData.get().getRouterIds();
372 if (routerUuids != null) {
373 for (Uuid routerUuid : routerUuids) {
374 routerUuidsAsString.add(routerUuid.getValue());
378 return routerUuidsAsString;
381 public boolean isNaptSwitchDown(String routerName, Long routerId, BigInteger dpnId, BigInteger naptSwitch,
382 Long routerVpnId, Collection<String> externalIpCache,
383 TypedReadWriteTransaction<Configuration> confTx)
384 throws ExecutionException, InterruptedException {
385 return isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId, externalIpCache, true,
389 // TODO Clean up the exception handling
390 @SuppressWarnings("checkstyle:IllegalCatch")
391 public boolean isNaptSwitchDown(String routerName, Long routerId, BigInteger dpnId, BigInteger naptSwitch,
392 Long routerVpnId, Collection<String> externalIpCache, boolean isClearBgpRts,
393 TypedReadWriteTransaction<Configuration> confTx)
394 throws ExecutionException, InterruptedException {
395 externalIpsCache = externalIpCache;
396 if (!naptSwitch.equals(dpnId)) {
397 LOG.debug("isNaptSwitchDown : DpnId {} is not a naptSwitch {} for Router {}",
398 dpnId, naptSwitch, routerName);
401 LOG.debug("NaptSwitch {} is down for Router {}", naptSwitch, routerName);
402 if (routerId == NatConstants.INVALID_ID) {
403 LOG.error("isNaptSwitchDown : Invalid routerId returned for routerName {}", routerName);
406 Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
407 String vpnName = getExtNetworkVpnName(routerName, networkId);
408 //elect a new NaptSwitch
409 naptSwitch = naptSwitchSelector.selectNewNAPTSwitch(routerName);
410 if (natMode == NatMode.Conntrack) {
411 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
412 natServiceManager.notify(confTx, extRouters, null, dpnId, dpnId,
413 SnatServiceManager.Action.CNT_ROUTER_ALL_SWITCH_DISBL);
414 if (extRouters.isEnableSnat()) {
415 natServiceManager.notify(confTx, extRouters, null, dpnId, dpnId,
416 SnatServiceManager.Action.SNAT_ALL_SWITCH_DISBL);
418 natServiceManager.notify(confTx, extRouters, null, naptSwitch, naptSwitch,
419 SnatServiceManager.Action.CNT_ROUTER_ALL_SWITCH_ENBL);
420 if (extRouters.isEnableSnat()) {
421 natServiceManager.notify(confTx, extRouters, null, naptSwitch, naptSwitch,
422 SnatServiceManager.Action.SNAT_ALL_SWITCH_ENBL);
425 if (naptSwitch.equals(BigInteger.ZERO)) {
426 LOG.warn("isNaptSwitchDown : No napt switch is elected since all the switches for router {}"
427 + " are down. SNAT IS NOT SUPPORTED FOR ROUTER {}", routerName, routerName);
428 boolean naptUpdatedStatus = updateNaptSwitch(routerName, naptSwitch);
429 if (!naptUpdatedStatus) {
430 LOG.debug("isNaptSwitchDown : Failed to update naptSwitch {} for router {} in ds",
431 naptSwitch, routerName);
434 if (externalIpsCache != null) {
435 if (vpnName != null) {
436 //List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
437 //if (externalIps != null) {
439 LOG.debug("isNaptSwitchDown : Clearing both FIB entries and the BGP routes");
440 for (String externalIp : externalIpsCache) {
441 externalRouterListener.clearBgpRoutes(externalIp, vpnName);
444 LOG.debug("isNaptSwitchDown : Clearing the FIB entries but not the BGP routes");
445 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
446 for (String externalIp : externalIpsCache) {
447 LOG.debug("isNaptSwitchDown : Removing Fib entry rd {} prefix {}", rd, externalIp);
448 fibManager.removeFibEntry(rd, externalIp, null);
452 LOG.debug("isNaptSwitchDown : vpn is not associated to extn/w for router {}", routerName);
455 LOG.debug("isNaptSwitchDown : No ExternalIps found for subnets under router {}, "
456 + "no bgp routes need to be cleared", routerName);
460 //checking elected switch health status
461 if (!NatUtil.getSwitchStatus(dataBroker, naptSwitch)) {
462 LOG.error("isNaptSwitchDown : Newly elected Napt switch {} for router {} is down",
463 naptSwitch, routerName);
466 LOG.debug("isNaptSwitchDown : New NaptSwitch {} is up for Router {} and can proceed for flow installation",
467 naptSwitch, routerName);
468 //update napt model for new napt switch
469 boolean naptUpdated = updateNaptSwitch(routerName, naptSwitch);
471 //update group of ordinary switch point to naptSwitch tunnel port
472 updateNaptSwitchBucketStatus(routerName, routerId, naptSwitch);
474 LOG.error("isNaptSwitchDown : Failed to update naptSwitch model for newNaptSwitch {} for router {}",
475 naptSwitch, routerName);
478 //update table26 forward packets to table46(outbound napt table)
479 FlowEntity flowEntity =
480 buildSnatFlowEntityForNaptSwitch(naptSwitch, routerName, routerVpnId, NatConstants.ADD_FLOW);
481 if (flowEntity == null) {
482 LOG.error("isNaptSwitchDown : Failed to populate flowentity for router {} in naptSwitch {}",
483 routerName, naptSwitch);
485 LOG.debug("isNaptSwitchDown : Successfully installed flow in naptSwitch {} for router {}",
486 naptSwitch, routerName);
487 mdsalManager.addFlow(confTx, flowEntity);
490 installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, confTx);
492 boolean flowInstalledStatus = handleNatFlowsInNewNaptSwitch(routerName, routerId, dpnId, naptSwitch,
493 routerVpnId, networkId);
494 if (flowInstalledStatus) {
495 LOG.debug("isNaptSwitchDown :Installed all active session flows in newNaptSwitch {} for routerName {}",
496 naptSwitch, routerName);
498 LOG.error("isNaptSwitchDown : Failed to install flows in newNaptSwitch {} for routerId {}",
499 naptSwitch, routerId);
502 //remove group in new naptswitch, coz this switch acted previously as ordinary switch
503 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
505 LOG.info("isNaptSwitchDown : Removing NAPT Group in new naptSwitch {}", naptSwitch);
506 mdsalManager.removeGroup(confTx, naptSwitch, groupId);
507 } catch (Exception ex) {
508 LOG.error("isNaptSwitchDown : Failed to remove group in new naptSwitch {}", naptSwitch, ex);
515 private String getExtNetworkVpnName(String routerName, Uuid networkId) {
516 if (networkId == null) {
517 LOG.error("getExtNetworkVpnName : networkId is null for the router ID {}", routerName);
519 final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
520 if (vpnName != null) {
521 LOG.debug("getExtNetworkVpnName : retrieved vpn name {} associated with ext nw {} in router {}",
522 vpnName, networkId, routerName);
525 LOG.error("getExtNetworkVpnName : No VPN associated with ext nw {} belonging to routerId {}",
526 networkId, routerName);
529 LOG.error("getExtNetworkVpnName : External Network VPN not found for router : {}", routerName);
533 public void updateNaptSwitchBucketStatus(String routerName, long routerId, BigInteger naptSwitch) {
534 LOG.debug("updateNaptSwitchBucketStatus : called");
536 List<BigInteger> dpnList = naptSwitchSelector.getDpnsForVpn(routerName);
537 //List<BigInteger> dpnList = getDpnListForRouter(routerName);
538 if (dpnList.isEmpty()) {
539 LOG.warn("updateNaptSwitchBucketStatus : No switches found for router {}", routerName);
542 for (BigInteger dpn : dpnList) {
543 if (!dpn.equals(naptSwitch)) {
544 LOG.debug("updateNaptSwitchBucketStatus : Updating SNAT_TABLE missentry for DpnId {} "
545 + "which is not naptSwitch for router {}", dpn, routerName);
546 List<BucketInfo> bucketInfoList = handleGroupInNeighborSwitches(dpn, routerName, routerId, naptSwitch);
547 modifySnatGroupEntry(dpn, bucketInfoList, routerName);
552 // TODO Clean up the exception handling
553 @SuppressWarnings("checkstyle:IllegalCatch")
554 private boolean handleNatFlowsInNewNaptSwitch(String routerName, Long routerId, BigInteger oldNaptSwitch,
555 BigInteger newNaptSwitch, Long routerVpnId, Uuid networkId) {
556 LOG.debug("handleNatFlowsInNewNaptSwitch : Proceeding to install flows in newNaptSwitch {} for routerId {}",
557 newNaptSwitch, routerId);
558 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
559 if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null
560 || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
561 LOG.debug("handleNatFlowsInNewNaptSwitch : No Internal Ip Port mapping associated to router {},"
562 + "no flows need to be installed in newNaptSwitch {}", routerId, newNaptSwitch);
566 Long vpnId = getVpnIdForRouter(routerId, networkId);
567 if (vpnId == NatConstants.INVALID_ID) {
568 LOG.error("handleNatFlowsInNewNaptSwitch : Invalid vpnId for routerId {}", routerId);
572 if (routerId.equals(routerVpnId)) {
573 bgpVpnId = NatConstants.INVALID_ID;
575 bgpVpnId = routerVpnId;
577 LOG.debug("handleNatFlowsInNewNaptSwitch : retrieved bgpVpnId {} for router {}", bgpVpnId, routerId);
578 // Get the External Gateway MAC Address
579 String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
580 if (extGwMacAddress != null) {
581 LOG.debug("handleNatFlowsInNewNaptSwitch :External Gateway MAC address {} found for External Router ID {}",
582 extGwMacAddress, routerId);
584 LOG.error("handleNatFlowsInNewNaptSwitch : No External Gateway MAC address found for External Router ID {}",
588 for (IntextIpProtocolType protocolType : ipPortMapping.getIntextIpProtocolType()) {
589 if (protocolType.getIpPortMap() == null || protocolType.getIpPortMap().isEmpty()) {
590 LOG.debug("handleNatFlowsInNewNaptSwitch : No {} session associated to router {}",
591 protocolType.getProtocol(), routerId);
594 for (IpPortMap intIpPortMap : protocolType.getIpPortMap()) {
595 String internalIpAddress = intIpPortMap.getIpPortInternal().split(":")[0];
596 String intportnum = intIpPortMap.getIpPortInternal().split(":")[1];
597 LOG.debug("handleNatFlowsInNewNaptSwitch : Found Internal IP Address {} and Port Number {}",
598 internalIpAddress, intportnum);
599 //Get the external IP address and the port from the model
600 NAPTEntryEvent.Protocol proto =
601 protocolType.getProtocol().toString().equals(ProtocolTypes.TCP.toString())
602 ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
603 IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
604 internalIpAddress, intportnum, proto);
605 if (ipPortExternal == null) {
606 LOG.debug("handleNatFlowsInNewNaptSwitch : External Ipport mapping is not found for internalIp {} "
607 + "with port {}", internalIpAddress, intportnum);
610 String externalIpAddress = ipPortExternal.getIpAddress();
611 Integer extportNumber = ipPortExternal.getPortNum();
612 LOG.debug("handleNatFlowsInNewNaptSwitch : ExternalIPport {}:{} mapping for internal ipport {}:{}",
613 externalIpAddress, extportNumber, internalIpAddress, intportnum);
615 SessionAddress sourceAddress = new SessionAddress(internalIpAddress, Integer.parseInt(intportnum));
616 SessionAddress externalAddress = new SessionAddress(externalIpAddress, extportNumber);
618 //checking naptSwitch status before installing flows
619 if (NatUtil.getSwitchStatus(dataBroker, newNaptSwitch)) {
620 //Install the flow in newNaptSwitch Inbound NAPT table.
622 naptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NwConstants.INBOUND_NAPT_TABLE,
623 vpnId, routerId, bgpVpnId, externalAddress, sourceAddress, proto, extGwMacAddress);
624 } catch (RuntimeException ex) {
625 LOG.error("handleNatFlowsInNewNaptSwitch : Failed to add flow in INBOUND_NAPT_TABLE for "
626 + "routerid {} dpnId {} extIpport{}:{} proto {} ipport {}:{} BgpVpnId {}",
627 routerId, newNaptSwitch, externalAddress, extportNumber, proto,
628 internalIpAddress, intportnum, bgpVpnId);
631 LOG.debug("handleNatFlowsInNewNaptSwitch : Successfully installed a flow in Primary switch {} "
632 + "Inbound NAPT table for router {} ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
633 newNaptSwitch, routerId, internalIpAddress,
634 intportnum, proto, externalAddress, extportNumber, bgpVpnId);
635 //Install the flow in newNaptSwitch Outbound NAPT table.
637 naptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
638 vpnId, routerId, bgpVpnId, sourceAddress, externalAddress, proto, extGwMacAddress);
639 } catch (RuntimeException ex) {
640 LOG.error("handleNatFlowsInNewNaptSwitch : Failed to add flow in OUTBOUND_NAPT_TABLE for "
641 + "routerid {} dpnId {} ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
642 routerId, newNaptSwitch, internalIpAddress,
643 intportnum, proto, externalAddress, extportNumber, bgpVpnId, ex);
646 LOG.debug("handleNatFlowsInNewNaptSwitch : Successfully installed a flow in Primary switch {} "
647 + "Outbound NAPT table for router {} ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}",
648 newNaptSwitch, routerId, internalIpAddress,
649 intportnum, proto, externalAddress, extportNumber, bgpVpnId);
651 LOG.error("handleNatFlowsInNewNaptSwitch : NewNaptSwitch {} gone down while installing flows "
652 + "from oldNaptswitch {}", newNaptSwitch, oldNaptSwitch);
660 // TODO Clean up the exception handling
661 @SuppressWarnings("checkstyle:IllegalCatch")
662 private Long getVpnIdForRouter(Long routerId, Uuid networkId) {
665 if (networkId == null) {
666 LOG.debug("getVpnIdForRouter : network is not associated to router {}", routerId);
668 Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
669 if (vpnUuid == null) {
670 LOG.debug("getVpnIdForRouter : vpn is not associated for network {} in router {}",
671 networkId, routerId);
673 Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
675 LOG.debug("getVpnIdForRouter : retrieved vpnId {} for router {}", vpnId, routerId);
678 LOG.debug("getVpnIdForRouter : retrieved invalid vpn Id");
682 } catch (Exception ex) {
683 LOG.error("getVpnIdForRouter : Exception while retrieving vpnId for router {}", routerId, ex);
685 return NatConstants.INVALID_ID;
689 public List<BucketInfo> handleGroupInNeighborSwitches(BigInteger dpnId, String routerName, long routerId,
690 BigInteger naptSwitch) {
691 List<BucketInfo> listBucketInfo = new ArrayList<>();
692 String ifNamePrimary;
693 if (routerId == NatConstants.INVALID_ID) {
694 LOG.error("handleGroupInNeighborSwitches : Invalid routerId returned for routerName {}", routerName);
695 return listBucketInfo;
697 ifNamePrimary = getTunnelInterfaceName(dpnId, naptSwitch);
698 if (ifNamePrimary != null) {
699 LOG.debug("handleGroupInNeighborSwitches : TunnelInterface {} between ordinary switch {} and naptSwitch {}",
700 ifNamePrimary, dpnId, naptSwitch);
701 List<ActionInfo> listActionInfoPrimary =
702 NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmManager, interfaceManager,
703 ifNamePrimary, routerId, true);
704 BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
705 listBucketInfo.add(bucketPrimary);
707 LOG.debug("handleGroupInNeighborSwitches : No TunnelInterface between ordinary switch {} and naptSwitch {}",
710 return listBucketInfo;
713 // TODO Clean up the exception handling
714 @SuppressWarnings("checkstyle:IllegalCatch")
715 protected void installSnatGroupEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
716 GroupEntity groupEntity = null;
718 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
719 LOG.debug("installSnatGroupEntry : install SnatMissEntry for groupId {} for dpnId {} for router {}",
720 groupId, dpnId, routerName);
721 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
722 GroupTypes.GroupAll, bucketInfo);
723 mdsalManager.syncInstallGroup(groupEntity);
724 LOG.debug("installSnatGroupEntry : installed the SNAT to NAPT GroupEntity:{}", groupEntity);
725 } catch (Exception ex) {
726 LOG.error("installSnatGroupEntry : Failed to install group for groupEntity {}", groupEntity, ex);
730 private void modifySnatGroupEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
731 installSnatGroupEntry(dpnId, bucketInfo, routerName);
732 LOG.debug("modifySnatGroupEntry : modified SnatMissEntry for dpnId {} of router {}", dpnId, routerName);
736 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
737 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
738 RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
741 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(
742 new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId).setDestinationDpid(dstDpId)
743 .setTunnelType(tunType).build());
744 rpcResult = result.get();
745 if (!rpcResult.isSuccessful()) {
746 tunType = TunnelTypeGre.class;
747 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
748 .setSourceDpid(srcDpId)
749 .setDestinationDpid(dstDpId)
750 .setTunnelType(tunType)
752 rpcResult = result.get();
753 if (!rpcResult.isSuccessful()) {
754 LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
755 rpcResult.getErrors());
757 return rpcResult.getResult().getInterfaceName();
759 LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
760 rpcResult.getErrors());
762 return rpcResult.getResult().getInterfaceName();
764 } catch (InterruptedException | ExecutionException e) {
765 LOG.error("getTunnelInterfaceName :Exception when getting tunnel interface Id for tunnel between {} and {}",
766 srcDpId, dstDpId, e);
768 LOG.error("getTunnelInterfaceName : Tunnel missing between dpn {}:{}", srcDpId, dstDpId);
772 // TODO Clean up the exception handling
773 @SuppressWarnings("checkstyle:IllegalCatch")
774 public boolean updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
775 RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().withKey(new RouterToNaptSwitchKey(routerName))
776 .setPrimarySwitchId(naptSwitchId).build();
778 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
779 NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
780 } catch (Exception ex) {
781 LOG.error("updateNaptSwitch : Failed to write naptSwitch {} for router {} in ds",
782 naptSwitchId, routerName);
785 LOG.debug("updateNaptSwitch : Successfully updated naptSwitch {} for router {} in ds",
786 naptSwitchId, routerName);
790 public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId,
791 long routerVpnId, int addordel) {
792 FlowEntity flowEntity;
793 List<MatchInfo> matches = new ArrayList<>();
794 matches.add(MatchEthernetType.IPV4);
795 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerVpnId), MetaDataUtil.METADATA_MASK_VRFID));
797 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
799 if (addordel == NatConstants.ADD_FLOW) {
800 List<ActionInfo> actionsInfo = new ArrayList<>();
801 long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, natOverVxlanUtil, elanManager,
802 idManager, routerVpnId, routerName);
803 actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
804 LOG.debug("buildSnatFlowEntity : Setting the tunnel to the list of action infos {}", actionsInfo);
805 actionsInfo.add(new ActionGroup(groupId));
806 List<InstructionInfo> instructions = new ArrayList<>();
807 instructions.add(new InstructionApplyActions(actionsInfo));
809 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
810 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
811 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
813 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
814 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
815 NwConstants.COOKIE_SNAT_TABLE, matches, null);
820 public FlowEntity buildSnatFlowEntityForNaptSwitch(BigInteger dpId, String routerName,
821 long routerVpnId, int addordel) {
822 FlowEntity flowEntity;
823 List<MatchInfo> matches = new ArrayList<>();
824 matches.add(MatchEthernetType.IPV4);
825 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerVpnId), MetaDataUtil.METADATA_MASK_VRFID));
827 String flowRef = getFlowRefSnat(dpId, NwConstants.PSNAT_TABLE, routerName);
829 if (addordel == NatConstants.ADD_FLOW) {
830 List<InstructionInfo> instructions = new ArrayList<>();
832 instructions.add(new InstructionGotoTable(NwConstants.OUTBOUND_NAPT_TABLE));
834 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
835 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
836 NwConstants.COOKIE_SNAT_TABLE, matches, instructions);
838 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
839 NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
840 NwConstants.COOKIE_SNAT_TABLE, matches, null);
845 private String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
846 return NatConstants.SNAT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
847 .FLOWID_SEPARATOR + routerID;
850 protected void installSnatFlows(String routerName, Long routerId, BigInteger naptSwitch, Long routerVpnId,
851 TypedReadWriteTransaction<Configuration> confTx) {
853 if (routerId.equals(routerVpnId)) {
854 LOG.debug("installSnatFlows : Installing flows for router with internalvpnId");
855 //36 -> 46 ..Install flow forwarding packet to table46 from table36
856 LOG.debug("installSnatFlows : installTerminatingServiceTblEntry in naptswitch with dpnId {} for "
857 + "routerName {} with routerId {}", naptSwitch, routerName, routerId);
858 externalRouterListener.installTerminatingServiceTblEntry(naptSwitch, routerName, routerId, confTx);
860 //Install default flows punting to controller in table 46(OutBoundNapt table)
861 LOG.debug("installSnatFlows : installOutboundMissEntry in naptswitch with dpnId {} for "
862 + "routerName {} with routerId {}", naptSwitch, routerName, routerId);
863 externalRouterListener.createOutboundTblEntry(naptSwitch, routerId, confTx);
865 //Table 47 point to table 21 for inbound traffic
866 LOG.debug("installSnatFlows : installNaptPfibEntry in naptswitch with dpnId {} for router {}",
867 naptSwitch, routerId);
868 externalRouterListener.installNaptPfibEntry(naptSwitch, routerId, confTx);
870 //Table 47 point to group
871 LOG.debug("installSnatFlows : installNaptPfibExternalOutputFlow in naptswitch with dpnId {} for router {}",
872 naptSwitch, routerId);
873 externalRouterListener.installNaptPfibExternalOutputFlow(routerName, routerId, naptSwitch, confTx);
875 Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
876 if (extNetworkUuid == null) {
877 LOG.error("onRouterAssociatedToVpn : Unable to retrieve external network Uuid for router {}",
881 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName,
883 if (extNwProvType == null) {
884 LOG.error("onRouterAssociatedToVpn : External Network Provider Type missing");
887 //36 -> 46 ..Install flow forwarding packet to table46 from table36
888 LOG.debug("installSnatFlows : installTerminatingServiceTblEntry in naptswitch with dpnId {} for "
889 + "routerName {} with BgpVpnId {}", naptSwitch, routerName, routerVpnId);
890 externalRouterListener
891 .installTerminatingServiceTblEntryWithUpdatedVpnId(naptSwitch, routerName, routerId,
892 routerVpnId, confTx, extNwProvType);
894 //Install default flows punting to controller in table 46(OutBoundNapt table)
895 LOG.debug("installSnatFlows : installOutboundMissEntry in naptswitch with dpnId {} for "
896 + "routerName {} with BgpVpnId {}", naptSwitch, routerName, routerVpnId);
897 externalRouterListener.createOutboundTblEntryWithBgpVpn(naptSwitch, routerId, routerVpnId, confTx);
899 //Table 47 point to table 21 for inbound traffic
900 LOG.debug("installSnatFlows : installNaptPfibEntry in naptswitch with dpnId {} for router {} "
901 + "with BgpVpnId {}", naptSwitch, routerId, routerVpnId);
902 externalRouterListener.installNaptPfibEntryWithBgpVpn(naptSwitch, routerId, routerVpnId, confTx);
905 Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
906 String vpnName = getExtNetworkVpnName(routerName, networkId);
907 if (vpnName != null) {
908 //NAPT PFIB point to FIB table for outbound traffic
909 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
910 boolean shouldInstallNaptPfibWithExtNetworkVpnId = true;
911 Collection<Uuid> externalSubnetIds = NatUtil.getExternalSubnetIdsForRouter(dataBroker, routerName);
912 if (!externalSubnetIds.isEmpty()) {
913 //NAPT PFIB point to FIB table for outbound traffic - using external subnetID as vpnID.
914 for (Uuid externalSubnetId : externalSubnetIds) {
915 long externalSubnetVpnId = NatUtil.getExternalSubnetVpnId(dataBroker, externalSubnetId);
916 if (externalSubnetVpnId != NatConstants.INVALID_ID) {
917 shouldInstallNaptPfibWithExtNetworkVpnId = false;
918 LOG.debug("installSnatFlows : installNaptPfibEntry fin naptswitch with dpnId {} for "
919 + "BgpVpnId {}", naptSwitch, externalSubnetVpnId);
920 externalRouterListener.installNaptPfibEntry(naptSwitch, externalSubnetVpnId, confTx);
924 if (vpnId != NatConstants.INVALID_ID && shouldInstallNaptPfibWithExtNetworkVpnId) {
925 //NAPT PFIB table point to FIB table for outbound traffic - using external networkID as vpnID.
926 LOG.debug("installSnatFlows : installNaptPfibEntry fin naptswitch with dpnId {} for "
927 + "BgpVpnId {}", naptSwitch, vpnId);
928 externalRouterListener.installNaptPfibEntry(naptSwitch, vpnId, confTx);
929 } else if (vpnId != NatConstants.INVALID_ID) {
930 LOG.debug("installSnatFlows : Associated BgpvpnId not found for router {}", routerId);
933 //Install Fib entries for ExternalIps & program 36 -> 44
934 Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
935 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
936 for (String externalIp : externalIps) {
937 removeFibEntry(rd, externalIp);
938 LOG.debug("installSnatFlows : advToBgpAndInstallFibAndTsFlows in naptswitch id {} "
939 + "with vpnName {} and externalIp {}", naptSwitch, vpnName, externalIp);
940 externalRouterListener.advToBgpAndInstallFibAndTsFlows(naptSwitch, NwConstants.INBOUND_NAPT_TABLE,
941 vpnName, routerId, routerName, externalIp, networkId, null /* external-router */, confTx);
942 LOG.debug("installSnatFlows : Successfully added fib entries in naptswitch {} for "
943 + "router {} with external IP {}", naptSwitch, routerId, externalIp);
946 LOG.debug("installSnatFlows : Associated vpnName not found for router {}", routerId);
950 protected void bestEffortDeletion(long routerId, String routerName, Map<String, Long> externalIpLabel,
951 TypedReadWriteTransaction<Configuration> confTx)
952 throws ExecutionException, InterruptedException {
953 Collection<String> newExternalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
954 if (externalIpsCache != null) {
955 Set<String> removedExternalIps = new HashSet<>(externalIpsCache);
956 removedExternalIps.removeAll(newExternalIps);
957 if (removedExternalIps.isEmpty()) {
958 LOG.info("bestEffortDeletion : No external Ip needed to be removed in bestEffortDeletion "
959 + "method for router {}", routerName);
962 Uuid networkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
963 String vpnName = getExtNetworkVpnName(routerName, networkId);
964 if (vpnName == null) {
965 LOG.error("bestEffortDeletion : Vpn is not associated to externalN/w of router {}", routerName);
968 BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
969 if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
970 LOG.error("bestEffortDeletion : No naptSwitch is selected for router {}", routerName);
973 ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName, networkId);
974 if (extNwProvType == null) {
977 String gwMacAddress = NatUtil.getExtGwMacAddFromRouterName(dataBroker, routerName);
978 if (gwMacAddress != null) {
979 LOG.debug("bestEffortDeletion : External Gateway MAC address {} found for External Router ID {}",
980 gwMacAddress, routerId);
982 LOG.error("bestEffortDeletion : No External Gateway MAC address found for External Router ID {}",
986 if (extNwProvType == ProviderTypes.VXLAN) {
987 for (String externalIp : removedExternalIps) {
988 externalRouterListener.clearBgpRoutes(externalIp, vpnName);
989 externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerName, routerId, externalIp,
990 vpnName, networkId, NatConstants.DEFAULT_LABEL_VALUE, gwMacAddress, true, confTx);
991 LOG.debug("bestEffortDeletion : Successfully removed fib entry for externalIp {} for routerId {} "
992 + "on NAPT switch {} ", externalIp, routerId, naptSwitch);
995 if (externalIpLabel == null || externalIpLabel.isEmpty()) {
996 LOG.error("bestEffortDeletion : ExternalIpLabel map is empty for router {}", routerName);
1000 for (String externalIp : removedExternalIps) {
1001 if (externalIpLabel.containsKey(externalIp)) {
1002 label = externalIpLabel.get(externalIp);
1003 LOG.debug("bestEffortDeletion : Label {} for ExternalIp {} for router {}",
1004 label, externalIp, routerName);
1006 LOG.debug("bestEffortDeletion : Label for ExternalIp {} is not found for router {}",
1007 externalIp, routerName);
1010 externalRouterListener.clearBgpRoutes(externalIp, vpnName);
1011 externalRouterListener.delFibTsAndReverseTraffic(naptSwitch, routerName, routerId, externalIp,
1012 vpnName, networkId, label, gwMacAddress, true, confTx);
1013 LOG.debug("bestEffortDeletion : Successfully removed fib entries in switch {} for router {} "
1014 + "and externalIps {}", naptSwitch, routerId, externalIp);
1018 LOG.debug("bestEffortDeletion : No external IP found for router {}", routerId);
1022 private void removeFibEntry(String rd, String prefix) {
1023 InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
1024 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
1025 .child(VrfEntry.class, new VrfEntryKey(prefix));
1026 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
1027 Optional<VrfEntry> ent = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
1028 if (ent.isPresent()) {
1029 LOG.debug("removeFibEntry : Removing Fib entry rd {} prefix {}", rd, prefix);
1030 fibManager.removeFibEntry(rd, prefix, null);
1034 protected void subnetRegisterMapping(Routers routerEntry, Long segmentId) {
1035 externalRouterListener.subnetRegisterMapping(routerEntry, segmentId);