2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.natservice.internal;
10 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
11 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
12 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
15 import org.opendaylight.genius.mdsalutil.ActionInfo;
16 import org.opendaylight.genius.mdsalutil.ActionType;
17 import org.opendaylight.genius.mdsalutil.FlowEntity;
18 import org.opendaylight.genius.mdsalutil.InstructionInfo;
19 import org.opendaylight.genius.mdsalutil.InstructionType;
20 import org.opendaylight.genius.mdsalutil.MDSALUtil;
21 import org.opendaylight.genius.mdsalutil.MatchFieldType;
22 import org.opendaylight.genius.mdsalutil.MatchInfo;
23 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
24 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
37 import org.opendaylight.yangtools.concepts.ListenerRegistration;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
48 import java.util.concurrent.ExecutionException;
49 import java.util.concurrent.Future;
51 import com.google.common.base.Optional;
52 import com.google.common.base.Strings;
54 import java.math.BigInteger;
55 import java.net.InetAddress;
56 import java.net.UnknownHostException;
57 import java.util.ArrayList;
58 import java.util.List;
61 * Created by emhamla on 1/18/2016.
63 public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> implements AutoCloseable{
64 private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
65 private ListenerRegistration<DataChangeListener> listenerRegistration;
66 private final DataBroker broker;
67 private OdlInterfaceRpcService interfaceManager;
68 private IMdsalApiManager mdsalManager;
69 private FloatingIPHandler handler;
72 public FloatingIPListener (final DataBroker db) {
73 super(IpMapping.class);
78 void setFloatingIpHandler(FloatingIPHandler handler) {
79 this.handler = handler;
83 public void close() throws Exception {
84 if (listenerRegistration != null) {
86 listenerRegistration.close();
87 } catch (final Exception e) {
88 LOG.error("Error when cleaning up DataChangeListener.", e);
90 listenerRegistration = null;
92 LOG.info("FloatingIP Listener Closed");
95 private void registerListener(final DataBroker db) {
97 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
98 getWildCardPath(), FloatingIPListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
99 } catch (final Exception e) {
100 LOG.error("FloatingIP DataChange listener registration fail!", e);
101 throw new IllegalStateException("FloatingIP Listener registration Listener failed.", e);
105 private InstanceIdentifier<IpMapping> getWildCardPath() {
106 return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class).child(IpMapping.class);
109 public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
110 this.interfaceManager = interfaceManager;
113 public void setMdsalManager(IMdsalApiManager mdsalManager) {
114 this.mdsalManager = mdsalManager;
118 protected void add(final InstanceIdentifier<IpMapping> identifier,
119 final IpMapping mapping) {
120 LOG.trace("FloatingIPListener add ip mapping method - key: " + identifier + ", value=" + mapping );
121 processFloatingIPAdd(identifier, mapping);
125 protected void remove(InstanceIdentifier<IpMapping> identifier, IpMapping mapping) {
126 LOG.trace("FloatingIPListener remove ip mapping method - key: " + identifier + ", value=" + mapping );
127 processFloatingIPDel(identifier, mapping);
131 protected void update(InstanceIdentifier<IpMapping> identifier, IpMapping original, IpMapping update) {
132 LOG.trace("FloatingIPListener update ip mapping method - key: " + identifier + ", original=" + original + ", update=" + update );
135 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
136 BigInteger nodeId = BigInteger.ZERO;
138 GetDpidFromInterfaceInput
140 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
141 Future<RpcResult<GetDpidFromInterfaceOutput>>
143 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
144 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
145 if (dpIdResult.isSuccessful()) {
146 nodeId = dpIdResult.getResult().getDpid();
148 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
150 } catch (InterruptedException | ExecutionException e) {
151 LOG.error("Exception when getting dpn for interface {}", ifName, e);
156 private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId) {
157 return buildPreDNATFlowEntity(dpId, internalIp, externalIp, routerId, vpnId, NatConstants.INVALID_ID);
160 private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpn) {
161 LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
163 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
164 LOG.debug("Segment id {} in build preDNAT Flow", segmentId);
166 List<MatchInfo> matches = new ArrayList<>();
167 matches.add(new MatchInfo(MatchFieldType.eth_type,
168 new long[] { 0x0800L }));
170 matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
171 externalIp, "32" }));
173 // matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
174 // BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
176 List<ActionInfo> actionsInfos = new ArrayList<>();
177 actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
179 List<InstructionInfo> instructions = new ArrayList<>();
180 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
181 (segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
182 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
183 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.DNAT_TABLE }));
185 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, routerId, externalIp);
187 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
188 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
189 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
196 private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
197 return buildDNATFlowEntity(dpId, internalIp, externalIp, routerId, NatConstants.INVALID_ID);
200 private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long associatedVpn) {
202 LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
204 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
205 LOG.debug("Segment id {} in build DNAT", segmentId);
207 List<MatchInfo> matches = new ArrayList<>();
208 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
209 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
211 matches.add(new MatchInfo(MatchFieldType.eth_type,
212 new long[] { 0x0800L }));
214 matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
215 // externalIp, "32" }));
216 internalIp, "32" }));
218 List<ActionInfo> actionsInfos = new ArrayList<>();
219 // actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
221 List<InstructionInfo> instructions = new ArrayList<>();
222 // instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
223 // (routerId), MetaDataUtil.METADATA_MASK_VRFID }));
224 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
225 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
226 //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
228 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, routerId, externalIp);
230 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
231 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
232 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
238 private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId) {
239 return buildPreSNATFlowEntity(dpId, internalIp, externalIp, vpnId, routerId, NatConstants.INVALID_ID);
242 private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId, long associatedVpn) {
244 LOG.info("Building PSNAT Flow entity for ip {} ", internalIp);
246 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
248 LOG.debug("Segment id {} in build preSNAT flow", segmentId);
250 List<MatchInfo> matches = new ArrayList<>();
251 matches.add(new MatchInfo(MatchFieldType.eth_type,
252 new long[] { 0x0800L }));
254 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
255 internalIp, "32" }));
257 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
258 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
260 List<ActionInfo> actionsInfos = new ArrayList<>();
261 actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
263 List<InstructionInfo> instructions = new ArrayList<>();
264 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
265 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
266 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.SNAT_TABLE }));
268 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, routerId, internalIp);
270 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
271 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
272 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
277 private FlowEntity buildSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, String macAddress) {
279 LOG.info("Building SNAT Flow entity for ip {} ", internalIp);
281 List<MatchInfo> matches = new ArrayList<>();
282 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
283 BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
285 matches.add(new MatchInfo(MatchFieldType.eth_type,
286 new long[] { 0x0800L }));
288 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
289 // internalIp, "32" }));
290 externalIp, "32" }));
292 List<ActionInfo> actionsInfos = new ArrayList<>();
293 // actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
295 //TODO: Set external gateway mac address
296 if(!Strings.isNullOrEmpty(macAddress)) {
297 LOG.debug("Setting ext gw mac address {} in SNAT {} flow action", macAddress, internalIp);
298 actionsInfos.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{ macAddress }));
301 List<InstructionInfo> instructions = new ArrayList<>();
302 //instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
303 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
304 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
305 //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
307 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, vpnId, internalIp);
309 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
310 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
311 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
318 private void createDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpnId) {
319 FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
320 mdsalManager.installFlow(pFlowEntity);
322 FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
323 mdsalManager.installFlow(flowEntity);
326 private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId) {
327 FlowEntity pFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId );
328 mdsalManager.removeFlow(pFlowEntity);
330 FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId);
331 mdsalManager.removeFlow(flowEntity);
334 private void createSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long vpnId, long routerId, String macAddress, long associatedVpnId) {
335 FlowEntity pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
336 mdsalManager.installFlow(pFlowEntity);
338 FlowEntity flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddress);
339 mdsalManager.installFlow(flowEntity);
343 private void removeSNATTblEntry(BigInteger dpnId, String internalIp, long routerId, String externalIp, long vpnId) {
344 FlowEntity pFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId, externalIp);
345 mdsalManager.removeFlow(pFlowEntity);
347 FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, internalIp, vpnId, externalIp);
348 mdsalManager.removeFlow(flowEntity);
352 private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> pIdentifier, LogicalDatastoreType dataStoreType) {
353 Optional<RouterPorts> rtrPort = NatUtil.read(broker, dataStoreType, pIdentifier);
354 if(!rtrPort.isPresent()) {
355 LOG.error("Unable to read router port entry for {}", pIdentifier);
359 Uuid extNwId = rtrPort.get().getExternalNetworkId();
363 private long getVpnId(Uuid extNwId) {
364 InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class, new NetworksKey(extNwId)).build();
365 Optional<Networks> nw = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, nwId);
366 if(!nw.isPresent()) {
367 LOG.error("Unable to read external network for {}", extNwId);
368 return NatConstants.INVALID_ID;
371 Uuid vpnUuid = nw.get().getVpnid();
372 if(vpnUuid == null) {
373 return NatConstants.INVALID_ID;
376 //Get the id using the VPN UUID (also vpn instance name)
377 return NatUtil.readVpnId(broker, vpnUuid.getValue());
380 private void processFloatingIPAdd(final InstanceIdentifier<IpMapping> identifier,
381 final IpMapping mapping) {
382 LOG.trace("Add event - key: {}, value: {}", identifier, mapping);
384 final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
385 final PortsKey pKey = identifier.firstKeyOf(Ports.class);
386 String interfaceName = pKey.getPortName();
388 InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
389 createNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
392 private void processFloatingIPDel(final InstanceIdentifier<IpMapping> identifier,
393 final IpMapping mapping) {
394 LOG.trace("Del event - key: {}, value: {}", identifier, mapping);
396 final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
397 final PortsKey pKey = identifier.firstKeyOf(Ports.class);
398 String interfaceName = pKey.getPortName();
400 InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
401 removeNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
404 private InetAddress getInetAddress(String ipAddr) {
405 InetAddress ipAddress = null;
407 ipAddress = InetAddress.getByName(ipAddr);
408 } catch (UnknownHostException e) {
409 LOG.error("UnknowHostException for ip {}", ipAddr);
414 private boolean validateIpMapping(IpMapping mapping) {
415 return getInetAddress(mapping.getInternalIp()) != null &&
416 getInetAddress(mapping.getExternalIp()) != null;
419 void createNATFlowEntries(String interfaceName, final IpMapping mapping,
420 final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
421 if(!validateIpMapping(mapping)) {
422 LOG.warn("Not a valid ip addresses in the mapping {}", mapping);
426 //Get the DPN on which this interface resides
427 BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
429 if(dpnId.equals(BigInteger.ZERO)) {
430 LOG.error("No DPN for interface {}. NAT flow entries for ip mapping {} will not be installed",
431 interfaceName, mapping);
435 long routerId = NatUtil.getVpnId(broker, routerName);
436 if(routerId == NatConstants.INVALID_ID) {
437 LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
440 //Check if the router to vpn association is present
441 //long associatedVpnId = NatUtil.getAssociatedVpn(broker, routerName);
442 Uuid associatedVpn = NatUtil.getVpnForRouter(broker, routerName);
443 long associatedVpnId = NatConstants.INVALID_ID;
444 if(associatedVpn == null) {
445 LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
447 LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpn);
448 associatedVpnId = NatUtil.getVpnId(broker, associatedVpn.getValue());
449 LOG.debug("vpninstance Id is {} for VPN {}", associatedVpnId, associatedVpn);
450 //routerId = associatedVpnId;
453 Uuid extNwId = getExtNetworkId(pIdentifier, LogicalDatastoreType.CONFIGURATION);
454 if(extNwId == null) {
455 LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
456 LOG.error("NAT flow entries will not be installed {}", mapping);
459 long vpnId = getVpnId(extNwId);
461 LOG.error("No VPN associated with Ext nw {}. Unable to create SNAT table entry for fixed ip {}",
462 extNwId, mapping.getInternalIp());
466 //Create the DNAT and SNAT table entries
467 createDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId, vpnId, associatedVpnId);
470 String macAddr = getExternalGatewayMacAddress(routerName);
471 createSNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), vpnId, routerId, macAddr, associatedVpnId);
473 handler.onAddFloatingIp(dpnId, routerName, extNwId, interfaceName, mapping.getExternalIp(), mapping
477 void createNATFlowEntries(BigInteger dpnId, String interfaceName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
478 long routerId = NatUtil.getVpnId(broker, routerName);
479 if(routerId == NatConstants.INVALID_ID) {
480 LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
483 //Check if the router to vpn association is present
484 long associatedVpnId = NatUtil.getAssociatedVpn(broker, routerName);
485 if(associatedVpnId == NatConstants.INVALID_ID) {
486 LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
488 LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpnId);
489 //routerId = associatedVpnId;
492 long vpnId = getVpnId(externalNetworkId);
494 LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
497 //Create the DNAT and SNAT table entries
498 createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId);
500 String macAddr = getExternalGatewayMacAddress(routerName);
501 createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr, associatedVpnId);
503 handler.onAddFloatingIp(dpnId, routerName, externalNetworkId, interfaceName, externalIp, internalIp);
506 void createNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN, Uuid externalNetworkId, String internalIp, String externalIp) {
507 //String segmentId = associatedVPN == null ? routerName : associatedVPN;
508 LOG.debug("Retrieving vpn id for VPN {} to proceed with create NAT Flows", routerName);
509 long routerId = NatUtil.getVpnId(broker, routerName);
510 if(routerId == NatConstants.INVALID_ID) {
511 LOG.warn("Could not retrieve vpn id for {} to create NAT Flow entries", routerName);
514 long associatedVpnId = NatUtil.getVpnId(broker, associatedVPN);
515 LOG.debug("Associated VPN Id {} for router {}", associatedVpnId, routerName);
516 long vpnId = getVpnId(externalNetworkId);
518 LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
521 //Create the DNAT and SNAT table entries
522 //createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
523 FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
524 mdsalManager.installFlow(pFlowEntity);
526 FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
527 mdsalManager.installFlow(flowEntity);
529 String macAddr = getExternalGatewayMacAddress(routerName);
530 //createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr);
531 pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
532 mdsalManager.installFlow(pFlowEntity);
534 flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddr);
535 mdsalManager.installFlow(flowEntity);
539 private String getExternalGatewayMacAddress(String routerName) {
540 InstanceIdentifier<Routers> routersIdentifier = NatUtil.buildRouterIdentifier(routerName);
541 Optional<Routers> optRouters = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier);
542 if(optRouters.isPresent()) {
543 Routers routers = optRouters.get();
544 return routers.getExtGwMacAddress();
549 void removeNATFlowEntries(String interfaceName, final IpMapping mapping,
550 final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
552 //Get the DPN on which this interface resides
553 BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
554 if(dpnId.equals(BigInteger.ZERO)) {
555 LOG.info("Abort processing Floating ip configuration. No DPN for port : {}", interfaceName);
559 long routerId = NatUtil.getVpnId(broker, routerName);
560 if(routerId == NatConstants.INVALID_ID) {
561 LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
564 //if(routerId == NatConstants.INVALID_ID) {
565 //The router could be associated with BGP VPN
566 Uuid associatedVPN = NatUtil.getVpnForRouter(broker, routerName);
567 long associatedVpnId = NatConstants.INVALID_ID;
568 if(associatedVPN == null) {
569 LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
571 LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", associatedVPN.getValue());
572 associatedVpnId = NatUtil.getVpnId(broker, associatedVPN.getValue());
575 //Delete the DNAT and SNAT table entries
576 removeDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId);
578 Uuid extNwId = getExtNetworkId(pIdentifier, LogicalDatastoreType.OPERATIONAL);
579 if(extNwId == null) {
580 LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
583 long vpnId = getVpnId(extNwId);
585 LOG.error("No VPN associated with ext nw {}. Unable to delete SNAT table entry for fixed ip {}",
586 extNwId, mapping.getInternalIp());
589 removeSNATTblEntry(dpnId, mapping.getInternalIp(), routerId, mapping.getExternalIp(), vpnId);
591 long label = getOperationalIpMapping(routerName, interfaceName, mapping.getInternalIp());
593 LOG.error("Could not retrieve label for prefix {} in router {}", mapping.getInternalIp(), routerId);
596 //Uuid extNwId = getExtNetworkId(pIdentifier);
597 // Uuid extNwId = getExternalNetworkForRouter(routerName);
598 // if(extNwId == null) {
599 // LOG.error("External network associated with router {} could not be retrieved", routerName);
602 handler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping.getExternalIp(), mapping.getInternalIp(), (int) label);
603 removeOperationalDS(routerName, interfaceName, mapping.getInternalIp(), mapping.getExternalIp());
607 void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
608 long routerId = NatUtil.getVpnId(broker, routerName);
609 if(routerId == NatConstants.INVALID_ID) {
610 LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
614 long vpnId = NatUtil.getVpnId(broker, vpnName);
615 if(vpnId == NatConstants.INVALID_ID) {
616 LOG.warn("VPN Id not found for {} to remove NAT flow entries {}", vpnName, internalIp);
619 //Delete the DNAT and SNAT table entries
620 removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
622 removeSNATTblEntry(dpnId, internalIp, routerId, externalIp, vpnId);
624 long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
626 LOG.error("Could not retrieve label for prefix {} in router {}", internalIp, routerId);
629 //handler.onRemoveFloatingIp(dpnId, routerName, externalNetworkId, externalIp, internalIp, (int)label);
630 ((VpnFloatingIpHandler)handler).cleanupFibEntries(dpnId, vpnName, externalIp, label);
631 removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
634 void removeNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN,
635 String internalIp, String externalIp) {
636 String segmentId = associatedVPN == null ? routerName : associatedVPN;
637 LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", segmentId);
638 long routerId = NatUtil.getVpnId(broker, segmentId);
639 if(routerId == NatConstants.INVALID_ID) {
640 LOG.warn("Could not retrieve vpn id for {} to remove NAT Flow entries", segmentId);
643 //Delete the DNAT and SNAT table entries
644 removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
646 //removeSNATTblEntry(dpnId, internalIp, routerId, externalIp);
649 private long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
650 InstanceIdentifier<IpMapping> ipMappingIdentifier = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
651 Optional<IpMapping> ipMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, ipMappingIdentifier);
652 if(ipMapping.isPresent()) {
653 return ipMapping.get().getLabel();
655 return NatConstants.INVALID_ID;
658 private Uuid getExternalNetworkForRouter(String routerId) {
659 InstanceIdentifier<RouterPorts> identifier = NatUtil.getRouterPortsId(routerId);
660 Optional<RouterPorts> optRouterPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
661 if(optRouterPorts.isPresent()) {
662 RouterPorts routerPorts = optRouterPorts.get();
663 return routerPorts.getExternalNetworkId();
668 void updateOperationalDS(String routerId, String interfaceName, long label, String internalIp, String externalIp) {
670 LOG.info("Updating operational DS for floating ip config : {} with label {}", internalIp, label);
671 InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
672 Optional<Ports> optPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portsId);
673 IpMapping ipMapping = new IpMappingBuilder().setKey(new IpMappingKey(internalIp)).setInternalIp(internalIp)
674 .setExternalIp(externalIp).setLabel(label).build();
675 if(optPorts.isPresent()) {
676 LOG.debug("Ports {} entry already present. Updating ipmapping for internal ip {}", interfaceName, internalIp);
677 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId.child(IpMapping.class, new IpMappingKey(internalIp)), ipMapping);
679 LOG.debug("Adding Ports entry {} along with ipmapping {}", interfaceName, internalIp);
680 List<IpMapping> ipMappings = new ArrayList<>();
681 ipMappings.add(ipMapping);
682 Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName).setIpMapping(ipMappings).build();
683 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
687 void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
688 LOG.info("Remove operational DS for floating ip config: {}", internalIp);
689 InstanceIdentifier<IpMapping> ipMappingId = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
690 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, ipMappingId);
693 private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
695 LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
697 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, routerId, externalIp);
699 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
700 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
701 NatConstants.COOKIE_DNAT_TABLE, null, null);
708 private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
710 LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
712 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, routerId, externalIp);
714 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
715 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
716 NatConstants.COOKIE_DNAT_TABLE, null, null);
722 private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
724 LOG.info("Building Delete PSNAT Flow entity for ip {} ", internalIp);
726 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, routerId, internalIp);
728 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
729 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
730 NatConstants.COOKIE_DNAT_TABLE, null, null);
735 private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
737 LOG.info("Building Delete SNAT Flow entity for ip {} ", internalIp);
739 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, routerId, internalIp);
741 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
742 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
743 NatConstants.COOKIE_DNAT_TABLE, null, null);