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.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.List;
16 import javax.annotation.PostConstruct;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
22 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
23 import org.opendaylight.genius.mdsalutil.ActionInfo;
24 import org.opendaylight.genius.mdsalutil.FlowEntity;
25 import org.opendaylight.genius.mdsalutil.InstructionInfo;
26 import org.opendaylight.genius.mdsalutil.MDSALUtil;
27 import org.opendaylight.genius.mdsalutil.MatchInfo;
28 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
29 import org.opendaylight.genius.mdsalutil.NwConstants;
30 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
31 import org.opendaylight.genius.mdsalutil.actions.ActionSetDestinationIp;
32 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
33 import org.opendaylight.genius.mdsalutil.actions.ActionSetSourceIp;
34 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
35 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
36 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
39 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
40 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
41 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
42 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
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.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
63 public class FloatingIPListener extends AsyncDataTreeChangeListenerBase<InternalToExternalPortMap, FloatingIPListener>
64 implements AutoCloseable {
65 private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
66 private final DataBroker dataBroker;
67 private final IMdsalApiManager mdsalManager;
68 private final OdlInterfaceRpcService interfaceManager;
69 private final FloatingIPHandler floatingIPHandler;
72 public FloatingIPListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
73 final OdlInterfaceRpcService interfaceManager,
74 final FloatingIPHandler floatingIPHandler) {
75 super(InternalToExternalPortMap.class, FloatingIPListener.class);
76 this.dataBroker = dataBroker;
77 this.mdsalManager = mdsalManager;
78 this.interfaceManager = interfaceManager;
79 this.floatingIPHandler = floatingIPHandler;
85 LOG.info("{} init", getClass().getSimpleName());
86 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
90 protected InstanceIdentifier<InternalToExternalPortMap> getWildCardPath() {
91 return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class)
92 .child(InternalToExternalPortMap.class);
96 protected FloatingIPListener getDataTreeChangeListener() {
97 return FloatingIPListener.this;
101 protected void add(final InstanceIdentifier<InternalToExternalPortMap> identifier,
102 final InternalToExternalPortMap mapping) {
103 LOG.trace("FloatingIPListener add ip mapping method - key: {} value: {}",mapping.getKey(), mapping);
104 processFloatingIPAdd(identifier, mapping);
108 protected void remove(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap mapping) {
109 LOG.trace("FloatingIPListener remove ip mapping method - kkey: {} value: {}",mapping.getKey(), mapping);
110 processFloatingIPDel(identifier, mapping);
114 protected void update(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap
115 original, InternalToExternalPortMap update) {
116 LOG.trace("FloatingIPListener update ip mapping method - key: {}, original: {}, update: {}",
117 update.getKey(), original, update);
120 private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, InternalToExternalPortMap mapping, long routerId, long
122 String externalIp = mapping.getExternalIp();
123 Uuid floatingIpId = mapping.getExternalId();
124 //Get the FIP MAC address for DNAT
125 String floatingIpPortMacAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
126 if (floatingIpPortMacAddress == null) {
127 LOG.error("buildPreDNATFlowEntity : Unable to retrieve floatingIpPortMacAddress from floating IP UUID {} "
128 + "for floating IP {}", floatingIpId, externalIp);
131 LOG.debug("buildPreDNATFlowEntity : Bulding DNAT Flow entity for ip {} ", externalIp);
132 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
133 LOG.debug("buildPreDNATFlowEntity : Segment id {} in build preDNAT Flow", segmentId);
135 List<MatchInfo> matches = new ArrayList<>();
136 matches.add(MatchEthernetType.IPV4);
138 matches.add(new MatchIpv4Destination(externalIp, "32"));
139 //Match Destination Floating IP MAC Address on table = 25 (PDNAT_TABLE)
140 matches.add(new MatchEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
142 // matches.add(new MatchMetadata(
143 // BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
144 List<ActionInfo> actionsInfos = new ArrayList<>();
145 String internalIp = mapping.getInternalIp();
146 actionsInfos.add(new ActionSetDestinationIp(internalIp, "32"));
148 List<InstructionInfo> instructions = new ArrayList<>();
149 instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(segmentId),
150 MetaDataUtil.METADATA_MASK_VRFID));
151 instructions.add(new InstructionApplyActions(actionsInfos));
152 instructions.add(new InstructionGotoTable(NwConstants.DNAT_TABLE));
154 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PDNAT_TABLE, routerId, externalIp);
156 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PDNAT_TABLE, flowRef,
157 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
158 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
163 private FlowEntity buildDNATFlowEntity(BigInteger dpId, InternalToExternalPortMap mapping, long routerId, long
165 String externalIp = mapping.getExternalIp();
166 LOG.info("buildDNATFlowEntity : Bulding DNAT Flow entity for ip {} ", externalIp);
168 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
169 LOG.debug("buildDNATFlowEntity : Segment id {} in build DNAT", segmentId);
171 List<MatchInfo> matches = new ArrayList<>();
172 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
174 matches.add(MatchEthernetType.IPV4);
175 String internalIp = mapping.getInternalIp();
176 matches.add(new MatchIpv4Destination(internalIp, "32"));
178 List<ActionInfo> actionsInfos = new ArrayList<>();
179 // actionsInfos.add(new ActionSetDestinationIp(internalIp, "32"));
181 List<InstructionInfo> instructions = new ArrayList<>();
182 // instructions.add(new InstructionWriteMetadata(BigInteger.valueOf
183 // (routerId), MetaDataUtil.METADATA_MASK_VRFID));
184 actionsInfos.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
185 instructions.add(new InstructionApplyActions(actionsInfos));
186 //instructions.add(new InstructionGotoTable(NatConstants.L3_FIB_TABLE));
188 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.DNAT_TABLE, routerId, internalIp);
190 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DNAT_TABLE, flowRef,
191 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
192 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
198 private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long
199 routerId, long associatedVpn) {
201 LOG.debug("buildPreSNATFlowEntity : Building PSNAT Flow entity for ip {} ", internalIp);
203 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
205 LOG.debug("buildPreSNATFlowEntity : Segment id {} in build preSNAT flow", segmentId);
207 List<MatchInfo> matches = new ArrayList<>();
208 matches.add(MatchEthernetType.IPV4);
210 matches.add(new MatchIpv4Source(internalIp, "32"));
212 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID));
214 List<ActionInfo> actionsInfos = new ArrayList<>();
215 actionsInfos.add(new ActionSetSourceIp(externalIp, "32"));
217 List<InstructionInfo> instructions = new ArrayList<>();
219 new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
220 instructions.add(new InstructionApplyActions(actionsInfos));
221 instructions.add(new InstructionGotoTable(NwConstants.SNAT_TABLE));
223 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PSNAT_TABLE, routerId, internalIp);
225 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
226 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
227 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
232 private FlowEntity buildSNATFlowEntity(BigInteger dpId, InternalToExternalPortMap mapping, long vpnId, Uuid
234 String internalIp = mapping.getInternalIp();
235 LOG.debug("buildSNATFlowEntity : Building SNAT Flow entity for ip {} ", internalIp);
237 ProviderTypes provType = NatUtil.getProviderTypefromNetworkId(dataBroker, externalNetworkId);
238 if (provType == null) {
239 LOG.error("buildSNATFlowEntity : Unable to get Network Provider Type for network {}", externalNetworkId);
243 List<MatchInfo> matches = new ArrayList<>();
244 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
245 matches.add(MatchEthernetType.IPV4);
246 String externalIp = mapping.getExternalIp();
247 matches.add(new MatchIpv4Source(externalIp, "32"));
249 List<ActionInfo> actionsInfo = new ArrayList<>();
250 Uuid floatingIpId = mapping.getExternalId();
251 String macAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
252 if (macAddress != null) {
253 actionsInfo.add(new ActionSetFieldEthernetSource(new MacAddress(macAddress)));
255 LOG.warn("buildSNATFlowEntity : No MAC address found for floating IP {}", externalIp);
258 LOG.trace("buildSNATFlowEntity : External Network Provider Type is {}, resubmit to FIB", provType.toString());
259 actionsInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
260 List<InstructionInfo> instructions = new ArrayList<>();
261 instructions.add(new InstructionApplyActions(actionsInfo));
262 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, vpnId, externalIp);
264 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.SNAT_TABLE, flowRef,
265 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
266 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
272 private void createDNATTblEntry(BigInteger dpnId, InternalToExternalPortMap mapping, long routerId, long vpnId,
273 long associatedVpnId) {
274 FlowEntity preFlowEntity = buildPreDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
275 if (preFlowEntity == null) {
276 LOG.error("createDNATTblEntry : Flow entity received as NULL. "
277 + "Cannot proceed with installation of Pre-DNAT flow table {} --> table {} on DpnId {}",
278 NwConstants.PDNAT_TABLE, NwConstants.DNAT_TABLE, dpnId);
280 mdsalManager.installFlow(preFlowEntity);
281 FlowEntity flowEntity = buildDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
282 mdsalManager.installFlow(flowEntity);
286 private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId) {
287 FlowEntity preFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, externalIp, routerId);
288 mdsalManager.removeFlow(preFlowEntity);
290 FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, routerId);
291 mdsalManager.removeFlow(flowEntity);
294 private void createSNATTblEntry(BigInteger dpnId, InternalToExternalPortMap mapping, long vpnId, long routerId,
295 long associatedVpnId, Uuid externalNetworkId) {
296 FlowEntity preFlowEntity = buildPreSNATFlowEntity(dpnId, mapping.getInternalIp(), mapping.getExternalIp(),
297 vpnId, routerId, associatedVpnId);
298 mdsalManager.installFlow(preFlowEntity);
300 FlowEntity flowEntity = buildSNATFlowEntity(dpnId, mapping, vpnId, externalNetworkId);
301 mdsalManager.installFlow(flowEntity);
304 private void removeSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId) {
305 FlowEntity preFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId);
306 mdsalManager.removeFlow(preFlowEntity);
308 FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, externalIp, vpnId);
309 mdsalManager.removeFlow(flowEntity);
312 private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> portIid,
313 LogicalDatastoreType dataStoreType) {
314 Optional<RouterPorts> rtrPort =
315 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
316 dataStoreType, portIid);
317 if (!rtrPort.isPresent()) {
318 LOG.error("getExtNetworkId : Unable to read router port entry for {}", portIid);
322 Uuid extNwId = rtrPort.get().getExternalNetworkId();
326 private long getVpnId(Uuid extNwId, Uuid floatingIpExternalId) {
327 Uuid subnetId = NatUtil.getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpExternalId);
328 if (subnetId != null) {
329 long vpnId = NatUtil.getVpnId(dataBroker, subnetId.getValue());
330 if (vpnId != NatConstants.INVALID_ID) {
331 LOG.debug("getVpnId : Got vpnId {} for floatingIpExternalId {}", vpnId, floatingIpExternalId);
336 InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class,
337 new NetworksKey(extNwId)).build();
338 Optional<Networks> nw =
339 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
340 LogicalDatastoreType.CONFIGURATION, nwId);
341 if (!nw.isPresent()) {
342 LOG.error("getVpnId : Unable to read external network for {}", extNwId);
343 return NatConstants.INVALID_ID;
346 Uuid vpnUuid = nw.get().getVpnid();
347 if (vpnUuid == null) {
348 LOG.error("getVpnId : Unable to read vpn from External network: {}", extNwId);
349 return NatConstants.INVALID_ID;
352 //Get the id using the VPN UUID (also vpn instance name)
353 return NatUtil.readVpnId(dataBroker, vpnUuid.getValue());
356 private void processFloatingIPAdd(final InstanceIdentifier<InternalToExternalPortMap> identifier,
357 final InternalToExternalPortMap mapping) {
358 LOG.trace("processFloatingIPAdd key: {}, value: {}", mapping.getKey(), mapping);
360 final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
361 final PortsKey pKey = identifier.firstKeyOf(Ports.class);
362 String interfaceName = pKey.getPortName();
364 InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
365 createNATFlowEntries(interfaceName, mapping, portIid, routerId);
368 private void processFloatingIPDel(final InstanceIdentifier<InternalToExternalPortMap> identifier,
369 final InternalToExternalPortMap mapping) {
370 LOG.trace("processFloatingIPDel : key: {}, value: {}", mapping.getKey(), mapping);
372 final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
373 final PortsKey pKey = identifier.firstKeyOf(Ports.class);
374 String interfaceName = pKey.getPortName();
376 InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
377 removeNATFlowEntries(interfaceName, mapping, portIid, routerId, null);
380 private InetAddress getInetAddress(String ipAddr) {
381 InetAddress ipAddress = null;
383 ipAddress = InetAddress.getByName(ipAddr);
384 } catch (UnknownHostException e) {
385 LOG.error("getInetAddress : UnknowHostException for ip {}", ipAddr, e);
390 private boolean validateIpMapping(InternalToExternalPortMap mapping) {
391 return getInetAddress(mapping.getInternalIp()) != null && getInetAddress(mapping.getExternalIp()) != null;
394 void createNATFlowEntries(String interfaceName, final InternalToExternalPortMap mapping,
395 final InstanceIdentifier<RouterPorts> portIid, final String routerName) {
396 if (!validateIpMapping(mapping)) {
397 LOG.error("createNATFlowEntries : Not a valid ip addresses in the mapping {}", mapping);
401 //Get the DPN on which this interface resides
402 BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
404 if (dpnId.equals(BigInteger.ZERO)) {
405 LOG.error("createNATFlowEntries : No DPN for interface {}. NAT flow entries for ip mapping {} will "
406 + "not be installed", interfaceName, mapping);
410 long routerId = NatUtil.getVpnId(dataBroker, routerName);
411 if (routerId == NatConstants.INVALID_ID) {
412 LOG.error("createNATFlowEntries : Could not retrieve router id for {} to create NAT Flow entries",
416 //Check if the router to vpn association is present
417 //long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
418 Uuid associatedVpn = NatUtil.getVpnForRouter(dataBroker, routerName);
419 long associatedVpnId = NatConstants.INVALID_ID;
420 if (associatedVpn == null) {
421 LOG.debug("createNATFlowEntries : Router {} is not assicated with any BGP VPN instance", routerName);
423 LOG.debug("createNATFlowEntries : Router {} is associated with VPN Instance with Id {}",
424 routerName, associatedVpn);
425 associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVpn.getValue());
426 LOG.debug("createNATFlowEntries : vpninstance Id is {} for VPN {}", associatedVpnId, associatedVpn);
427 //routerId = associatedVpnId;
430 Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.CONFIGURATION);
431 if (extNwId == null) {
432 LOG.error("createNATFlowEntries : External network associated with interface {} could not be retrieved",
436 long vpnId = getVpnId(extNwId, mapping.getExternalId());
438 LOG.error("createNATFlowEntries : No VPN associated with Ext nw {}. Unable to create SNAT table entry "
439 + "for fixed ip {}", extNwId, mapping.getInternalIp());
443 //Create the DNAT and SNAT table entries
444 createDNATTblEntry(dpnId, mapping, routerId, vpnId, associatedVpnId);
445 createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, extNwId);
446 floatingIPHandler.onAddFloatingIp(dpnId, routerName, extNwId, interfaceName, mapping);
449 void createNATFlowEntries(BigInteger dpnId, String interfaceName, String routerName, Uuid externalNetworkId,
450 InternalToExternalPortMap mapping) {
451 String internalIp = mapping.getInternalIp();
452 long routerId = NatUtil.getVpnId(dataBroker, routerName);
453 if (routerId == NatConstants.INVALID_ID) {
454 LOG.error("createNATFlowEntries : Could not retrieve router id for {} to create NAT Flow entries",
458 //Check if the router to vpn association is present
459 long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
460 if (associatedVpnId == NatConstants.INVALID_ID) {
461 LOG.debug("createNATFlowEntries : Router {} is not assicated with any BGP VPN instance", routerName);
463 LOG.debug("createNATFlowEntries : Router {} is associated with VPN Instance with Id {}",
464 routerName, associatedVpnId);
465 //routerId = associatedVpnId;
468 long vpnId = getVpnId(externalNetworkId, mapping.getExternalId());
470 LOG.error("createNATFlowEntries : Unable to create SNAT table entry for fixed ip {}", internalIp);
473 //Create the DNAT and SNAT table entries
474 createDNATTblEntry(dpnId, mapping, routerId, vpnId, associatedVpnId);
475 createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, externalNetworkId);
476 floatingIPHandler.onAddFloatingIp(dpnId, routerName, externalNetworkId, interfaceName, mapping);
479 void createNATOnlyFlowEntries(BigInteger dpnId, String routerName, String associatedVPN,
480 Uuid externalNetworkId, InternalToExternalPortMap mapping) {
481 String internalIp = mapping.getInternalIp();
482 //String segmentId = associatedVPN == null ? routerName : associatedVPN;
483 LOG.debug("createNATOnlyFlowEntries : Retrieving vpn id for VPN {} to proceed with create NAT Flows",
485 long routerId = NatUtil.getVpnId(dataBroker, routerName);
486 if (routerId == NatConstants.INVALID_ID) {
487 LOG.error("createNATOnlyFlowEntries : Could not retrieve vpn id for {} to create NAT Flow entries",
491 long associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVPN);
492 LOG.debug("createNATOnlyFlowEntries : Associated VPN Id {} for router {}", associatedVpnId, routerName);
493 long vpnId = getVpnId(externalNetworkId, mapping.getExternalId());
495 LOG.error("createNATOnlyFlowEntries : Unable to create SNAT table entry for fixed ip {}", internalIp);
498 //Create the DNAT and SNAT table entries
499 FlowEntity preFlowEntity = buildPreDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
500 mdsalManager.installFlow(preFlowEntity);
502 FlowEntity flowEntity = buildDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
503 mdsalManager.installFlow(flowEntity);
505 String externalIp = mapping.getExternalIp();
506 preFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
507 mdsalManager.installFlow(preFlowEntity);
509 flowEntity = buildSNATFlowEntity(dpnId, mapping, vpnId, externalNetworkId);
510 mdsalManager.installFlow(flowEntity);
514 void removeNATFlowEntries(String interfaceName, final InternalToExternalPortMap mapping,
515 InstanceIdentifier<RouterPorts> portIid, final String routerName, BigInteger dpnId) {
516 String internalIp = mapping.getInternalIp();
517 String externalIp = mapping.getExternalIp();
518 //Get the DPN on which this interface resides
520 dpnId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
521 if (dpnId.equals(BigInteger.ZERO)) {
522 LOG.error("removeNATFlowEntries: Abort processing Floating ip configuration. No DPN for port: {}",
528 long routerId = NatUtil.getVpnId(dataBroker, routerName);
529 if (routerId == NatConstants.INVALID_ID) {
530 LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries",
535 //Delete the DNAT and SNAT table entries
536 removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
538 Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.OPERATIONAL);
539 if (extNwId == null) {
540 LOG.error("removeNATFlowEntries : External network associated with interface {} could not be retrieved",
544 long vpnId = getVpnId(extNwId, mapping.getExternalId());
546 LOG.error("removeNATFlowEntries : No VPN associated with ext nw {}. Unable to delete SNAT table "
547 + "entry for fixed ip {}", extNwId, internalIp);
550 removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
551 ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
552 if (provType == null) {
553 LOG.error("removeNATFlowEntries : External Network Provider Type missing");
556 if (provType == ProviderTypes.VXLAN) {
557 floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping, NatConstants.DEFAULT_L3VNI_VALUE);
558 removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
561 long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
563 LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}",
564 internalIp, routerId);
567 floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping, (int) label);
568 removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
571 void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName,
572 InternalToExternalPortMap mapping) {
573 String internalIp = mapping.getInternalIp();
574 String externalIp = mapping.getExternalIp();
575 long routerId = NatUtil.getVpnId(dataBroker, routerName);
576 if (routerId == NatConstants.INVALID_ID) {
577 LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries",
582 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
583 if (vpnId == NatConstants.INVALID_ID) {
584 LOG.warn("removeNATFlowEntries : VPN Id not found for {} to remove NAT flow entries {}",
585 vpnName, internalIp);
588 //Delete the DNAT and SNAT table entries
589 removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
591 removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
592 ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
593 if (provType == null) {
594 LOG.error("removeNATFlowEntries : External Network Provider Type Missing");
597 if (provType == ProviderTypes.VXLAN) {
598 floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE);
599 removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
602 long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
604 LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}",
605 internalIp, routerId);
608 floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, label);
609 removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
612 protected long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
613 InstanceIdentifier<InternalToExternalPortMap> intExtPortMapIdentifier =
614 NatUtil.getIntExtPortMapIdentifier(routerId, interfaceName, internalIp);
615 return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
616 LogicalDatastoreType.OPERATIONAL, intExtPortMapIdentifier).toJavaUtil().map(
617 InternalToExternalPortMap::getLabel).orElse(NatConstants.INVALID_ID);
620 static void updateOperationalDS(DataBroker dataBroker, String routerId, String interfaceName, long label,
621 String internalIp, String externalIp) {
623 LOG.info("updateOperationalDS : Updating operational DS for floating ip config : {} with label {}",
625 InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
626 Optional<Ports> optPorts =
627 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
628 LogicalDatastoreType.OPERATIONAL, portsId);
629 InternalToExternalPortMap intExtPortMap = new InternalToExternalPortMapBuilder().setKey(new
630 InternalToExternalPortMapKey(internalIp)).setInternalIp(internalIp).setExternalIp(externalIp)
631 .setLabel(label).build();
632 if (optPorts.isPresent()) {
633 LOG.debug("updateOperationalDS : Ports {} entry already present. Updating intExtPortMap for internal ip {}",
634 interfaceName, internalIp);
635 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId.child(InternalToExternalPortMap
636 .class, new InternalToExternalPortMapKey(internalIp)), intExtPortMap);
638 LOG.debug("updateOperationalDS : Adding Ports entry {} along with intExtPortMap {}",
639 interfaceName, internalIp);
640 List<InternalToExternalPortMap> intExtPortMapList = new ArrayList<>();
641 intExtPortMapList.add(intExtPortMap);
642 Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName)
643 .setInternalToExternalPortMap(intExtPortMapList).build();
644 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
648 void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
649 LOG.info("removeOperationalDS : Remove operational DS for floating ip config: {}", internalIp);
650 InstanceIdentifier<InternalToExternalPortMap> intExtPortMapId = NatUtil.getIntExtPortMapIdentifier(routerId,
651 interfaceName, internalIp);
652 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, intExtPortMapId);
655 private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String externalIp, long routerId) {
657 LOG.info("buildPreDNATDeleteFlowEntity : Bulding Delete DNAT Flow entity for ip {} ", externalIp);
659 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PDNAT_TABLE, routerId, externalIp);
661 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PDNAT_TABLE, flowRef,
662 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
663 NwConstants.COOKIE_DNAT_TABLE, null, null);
670 private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId) {
672 LOG.info("buildDNATDeleteFlowEntity : Bulding Delete DNAT Flow entity for ip {} ", internalIp);
674 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.DNAT_TABLE, routerId, internalIp);
676 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DNAT_TABLE, flowRef,
677 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
678 NwConstants.COOKIE_DNAT_TABLE, null, null);
684 private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId) {
686 LOG.info("buildPreSNATDeleteFlowEntity : Building Delete PSNAT Flow entity for ip {} ", internalIp);
688 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PSNAT_TABLE, routerId, internalIp);
690 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
691 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
692 NwConstants.COOKIE_DNAT_TABLE, null, null);
696 private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String externalIp, long routerId) {
698 LOG.info("buildSNATDeleteFlowEntity : Building Delete SNAT Flow entity for ip {} ", externalIp);
700 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, routerId, externalIp);
702 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.SNAT_TABLE, flowRef,
703 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
704 NwConstants.COOKIE_DNAT_TABLE, null, null);