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.vpnservice.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.vpnservice.mdsalutil.ActionInfo;
15 import org.opendaylight.vpnservice.mdsalutil.ActionType;
16 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
17 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
18 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
19 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
20 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
21 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
22 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
23 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.FloatingIpInfo;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.NetworksKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
36 import org.opendaylight.yangtools.concepts.ListenerRegistration;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.Future;
50 import com.google.common.base.Optional;
51 import com.google.common.base.Strings;
53 import java.math.BigInteger;
54 import java.net.InetAddress;
55 import java.net.UnknownHostException;
56 import java.util.ArrayList;
57 import java.util.List;
60 * Created by emhamla on 1/18/2016.
62 public class FloatingIPListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<IpMapping> implements AutoCloseable{
63 private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
64 private ListenerRegistration<DataChangeListener> listenerRegistration;
65 private final DataBroker broker;
66 private OdlInterfaceRpcService interfaceManager;
67 private IMdsalApiManager mdsalManager;
68 private FloatingIPHandler handler;
71 public FloatingIPListener (final DataBroker db) {
72 super(IpMapping.class);
77 void setFloatingIpHandler(FloatingIPHandler handler) {
78 this.handler = handler;
82 public void close() throws Exception {
83 if (listenerRegistration != null) {
85 listenerRegistration.close();
86 } catch (final Exception e) {
87 LOG.error("Error when cleaning up DataChangeListener.", e);
89 listenerRegistration = null;
91 LOG.info("FloatingIP Listener Closed");
94 private void registerListener(final DataBroker db) {
96 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
97 getWildCardPath(), FloatingIPListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
98 } catch (final Exception e) {
99 LOG.error("FloatingIP DataChange listener registration fail!", e);
100 throw new IllegalStateException("FloatingIP Listener registration Listener failed.", e);
104 private InstanceIdentifier<IpMapping> getWildCardPath() {
105 return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class).child(IpMapping.class);
108 public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
109 this.interfaceManager = interfaceManager;
112 public void setMdsalManager(IMdsalApiManager mdsalManager) {
113 this.mdsalManager = mdsalManager;
117 protected void add(final InstanceIdentifier<IpMapping> identifier,
118 final IpMapping mapping) {
119 LOG.trace("FloatingIPListener add ip mapping method - key: " + identifier + ", value=" + mapping );
120 processFloatingIPAdd(identifier, mapping);
124 protected void remove(InstanceIdentifier<IpMapping> identifier, IpMapping mapping) {
125 LOG.trace("FloatingIPListener remove ip mapping method - key: " + identifier + ", value=" + mapping );
126 processFloatingIPDel(identifier, mapping);
130 protected void update(InstanceIdentifier<IpMapping> identifier, IpMapping original, IpMapping update) {
131 LOG.trace("FloatingIPListener update ip mapping method - key: " + identifier + ", original=" + original + ", update=" + update );
134 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
135 BigInteger nodeId = BigInteger.ZERO;
137 GetDpidFromInterfaceInput
139 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
140 Future<RpcResult<GetDpidFromInterfaceOutput>>
142 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
143 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
144 if (dpIdResult.isSuccessful()) {
145 nodeId = dpIdResult.getResult().getDpid();
147 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
149 } catch (InterruptedException | ExecutionException e) {
150 LOG.error("Exception when getting dpn for interface {}", ifName, e);
155 private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId) {
156 return buildPreDNATFlowEntity(dpId, internalIp, externalIp, routerId, vpnId, NatConstants.INVALID_ID);
159 private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpn) {
160 LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
162 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
163 LOG.debug("Segment id {} in build preDNAT Flow", segmentId);
165 List<MatchInfo> matches = new ArrayList<MatchInfo>();
166 matches.add(new MatchInfo(MatchFieldType.eth_type,
167 new long[] { 0x0800L }));
169 matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
170 externalIp, "32" }));
172 // matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
173 // BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
175 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
176 actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
178 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
179 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
180 (segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
181 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
182 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.DNAT_TABLE }));
184 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, routerId, externalIp);
186 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
187 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
188 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
195 private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
196 return buildDNATFlowEntity(dpId, internalIp, externalIp, routerId, NatConstants.INVALID_ID);
199 private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long associatedVpn) {
201 LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
203 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
204 LOG.debug("Segment id {} in build DNAT", segmentId);
206 List<MatchInfo> matches = new ArrayList<MatchInfo>();
207 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
208 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
210 matches.add(new MatchInfo(MatchFieldType.eth_type,
211 new long[] { 0x0800L }));
213 matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
214 // externalIp, "32" }));
215 internalIp, "32" }));
217 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
218 // actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
220 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
221 // instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
222 // (routerId), MetaDataUtil.METADATA_MASK_VRFID }));
223 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
224 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
225 //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
227 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, routerId, externalIp);
229 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
230 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
231 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
237 private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId) {
238 return buildPreSNATFlowEntity(dpId, internalIp, externalIp, vpnId, routerId, NatConstants.INVALID_ID);
241 private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId, long associatedVpn) {
243 LOG.info("Building PSNAT Flow entity for ip {} ", internalIp);
245 long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
247 LOG.debug("Segment id {} in build preSNAT flow", segmentId);
249 List<MatchInfo> matches = new ArrayList<MatchInfo>();
250 matches.add(new MatchInfo(MatchFieldType.eth_type,
251 new long[] { 0x0800L }));
253 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
254 internalIp, "32" }));
256 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
257 BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
259 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
260 actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
262 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
263 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
264 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
265 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.SNAT_TABLE }));
267 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, routerId, internalIp);
269 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
270 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
271 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
276 private FlowEntity buildSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, String macAddress) {
278 LOG.info("Building SNAT Flow entity for ip {} ", internalIp);
280 List<MatchInfo> matches = new ArrayList<MatchInfo>();
281 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
282 BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
284 matches.add(new MatchInfo(MatchFieldType.eth_type,
285 new long[] { 0x0800L }));
287 matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
288 // internalIp, "32" }));
289 externalIp, "32" }));
291 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
292 // actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
294 //TODO: Set external gateway mac address
295 if(!Strings.isNullOrEmpty(macAddress)) {
296 LOG.debug("Setting ext gw mac address {} in SNAT {} flow action", macAddress, internalIp);
297 actionsInfos.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{ macAddress }));
300 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
301 //instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
302 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
303 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
304 //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
306 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, vpnId, internalIp);
308 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
309 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
310 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
317 private void createDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpnId) {
318 FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
319 mdsalManager.installFlow(pFlowEntity);
321 FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
322 mdsalManager.installFlow(flowEntity);
325 private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId) {
326 FlowEntity pFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId );
327 mdsalManager.removeFlow(pFlowEntity);
329 FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId);
330 mdsalManager.removeFlow(flowEntity);
333 private void createSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long vpnId, long routerId, String macAddress, long associatedVpnId) {
334 FlowEntity pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
335 mdsalManager.installFlow(pFlowEntity);
337 FlowEntity flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddress);
338 mdsalManager.installFlow(flowEntity);
342 private void removeSNATTblEntry(BigInteger dpnId, String internalIp, long routerId, String externalIp, long vpnId) {
343 FlowEntity pFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId, externalIp);
344 mdsalManager.removeFlow(pFlowEntity);
346 FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, internalIp, vpnId, externalIp);
347 mdsalManager.removeFlow(flowEntity);
351 private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> pIdentifier) {
352 Optional<RouterPorts> rtrPort = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, pIdentifier);
353 if(!rtrPort.isPresent()) {
354 LOG.error("Unable to read router port entry for {}", pIdentifier);
358 Uuid extNwId = rtrPort.get().getExternalNetworkId();
362 private long getVpnId(Uuid extNwId) {
363 InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class, new NetworksKey(extNwId)).build();
364 Optional<Networks> nw = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, nwId);
365 if(!nw.isPresent()) {
366 LOG.error("Unable to read external network for {}", extNwId);
367 return NatConstants.INVALID_ID;
370 Uuid vpnUuid = nw.get().getVpnid();
371 if(vpnUuid == null) {
372 return NatConstants.INVALID_ID;
375 //Get the id using the VPN UUID (also vpn instance name)
376 return NatUtil.readVpnId(broker, vpnUuid.getValue());
379 private void processFloatingIPAdd(final InstanceIdentifier<IpMapping> identifier,
380 final IpMapping mapping) {
381 LOG.trace("Add event - key: {}, value: {}", identifier, mapping);
383 final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
384 final PortsKey pKey = identifier.firstKeyOf(Ports.class);
385 String interfaceName = pKey.getPortName();
387 InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
388 createNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
391 private void processFloatingIPDel(final InstanceIdentifier<IpMapping> identifier,
392 final IpMapping mapping) {
393 LOG.trace("Del event - key: {}, value: {}", identifier, mapping);
395 final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
396 final PortsKey pKey = identifier.firstKeyOf(Ports.class);
397 String interfaceName = pKey.getPortName();
399 InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
400 removeNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
403 private InetAddress getInetAddress(String ipAddr) {
404 InetAddress ipAddress = null;
406 ipAddress = InetAddress.getByName(ipAddr);
407 } catch (UnknownHostException e) {
408 LOG.error("UnknowHostException for ip {}", ipAddr);
413 private boolean validateIpMapping(IpMapping mapping) {
414 return getInetAddress(mapping.getInternalIp()) != null &&
415 getInetAddress(mapping.getExternalIp()) != null;
418 void createNATFlowEntries(String interfaceName, final IpMapping mapping,
419 final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
420 if(!validateIpMapping(mapping)) {
421 LOG.warn("Not a valid ip addresses in the mapping {}", mapping);
425 //Get the DPN on which this interface resides
426 BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
428 if(dpnId.equals(BigInteger.ZERO)) {
429 LOG.error("No DPN for interface {}. NAT flow entries for ip mapping {} will not be installed",
430 interfaceName, mapping);
434 long routerId = NatUtil.getVpnId(broker, routerName);
435 if(routerId == NatConstants.INVALID_ID) {
436 LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
439 //Check if the router to vpn association is present
440 //long associatedVpnId = NatUtil.getAssociatedVpn(broker, routerName);
441 Uuid associatedVpn = NatUtil.getVpnForRouter(broker, routerName);
442 long associatedVpnId = NatConstants.INVALID_ID;
443 if(associatedVpn == null) {
444 LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
446 LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpn);
447 associatedVpnId = NatUtil.getVpnId(broker, associatedVpn.getValue());
448 LOG.debug("vpninstance Id is {} for VPN {}", associatedVpnId, associatedVpn);
449 //routerId = associatedVpnId;
452 Uuid extNwId = getExtNetworkId(pIdentifier);
453 if(extNwId == null) {
454 LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
455 LOG.error("NAT flow entries will not be installed {}", mapping);
458 long vpnId = getVpnId(extNwId);
460 LOG.error("No VPN associated with Ext nw {}. Unable to create SNAT table entry for fixed ip {}",
461 extNwId, mapping.getInternalIp());
465 //Create the DNAT and SNAT table entries
466 createDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId, vpnId, associatedVpnId);
469 String macAddr = getExternalGatewayMacAddress(routerName);
470 createSNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), vpnId, routerId, macAddr, associatedVpnId);
472 handler.onAddFloatingIp(dpnId, routerName, extNwId, interfaceName, mapping.getExternalIp(), mapping
476 void createNATFlowEntries(BigInteger dpnId, String interfaceName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
477 long routerId = NatUtil.getVpnId(broker, routerName);
478 if(routerId == NatConstants.INVALID_ID) {
479 LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
482 //Check if the router to vpn association is present
483 long associatedVpnId = NatUtil.getAssociatedVpn(broker, routerName);
484 if(associatedVpnId == NatConstants.INVALID_ID) {
485 LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
487 LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpnId);
488 //routerId = associatedVpnId;
491 long vpnId = getVpnId(externalNetworkId);
493 LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
496 //Create the DNAT and SNAT table entries
497 createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId);
499 String macAddr = getExternalGatewayMacAddress(routerName);
500 createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr, associatedVpnId);
502 handler.onAddFloatingIp(dpnId, routerName, externalNetworkId, interfaceName, externalIp, internalIp);
505 void createNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN, Uuid externalNetworkId, String internalIp, String externalIp) {
506 //String segmentId = associatedVPN == null ? routerName : associatedVPN;
507 LOG.debug("Retrieving vpn id for VPN {} to proceed with create NAT Flows", routerName);
508 long routerId = NatUtil.getVpnId(broker, routerName);
509 if(routerId == NatConstants.INVALID_ID) {
510 LOG.warn("Could not retrieve vpn id for {} to create NAT Flow entries", routerName);
513 long associatedVpnId = NatUtil.getVpnId(broker, associatedVPN);
514 LOG.debug("Associated VPN Id {} for router {}", associatedVpnId, routerName);
515 long vpnId = getVpnId(externalNetworkId);
517 LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
520 //Create the DNAT and SNAT table entries
521 //createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
522 FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
523 mdsalManager.installFlow(pFlowEntity);
525 FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
526 mdsalManager.installFlow(flowEntity);
528 String macAddr = getExternalGatewayMacAddress(routerName);
529 //createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr);
530 pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
531 mdsalManager.installFlow(pFlowEntity);
533 flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddr);
534 mdsalManager.installFlow(flowEntity);
538 private String getExternalGatewayMacAddress(String routerName) {
539 InstanceIdentifier<Routers> routersIdentifier = NatUtil.buildRouterIdentifier(routerName);
540 Optional<Routers> optRouters = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier);
541 if(optRouters.isPresent()) {
542 Routers routers = optRouters.get();
543 return routers.getExtGwMacAddress();
548 void removeNATFlowEntries(String interfaceName, final IpMapping mapping,
549 final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
551 //Get the DPN on which this interface resides
552 BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
553 if(dpnId.equals(BigInteger.ZERO)) {
554 LOG.info("Abort processing Floating ip configuration. No DPN for port : {}", interfaceName);
558 long routerId = NatUtil.getVpnId(broker, routerName);
559 if(routerId == NatConstants.INVALID_ID) {
560 LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
563 //if(routerId == NatConstants.INVALID_ID) {
564 //The router could be associated with BGP VPN
565 Uuid associatedVPN = NatUtil.getVpnForRouter(broker, routerName);
566 long associatedVpnId = NatConstants.INVALID_ID;
567 if(associatedVPN == null) {
568 LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
570 LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", associatedVPN.getValue());
571 associatedVpnId = NatUtil.getVpnId(broker, associatedVPN.getValue());
574 //Delete the DNAT and SNAT table entries
575 removeDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId);
577 Uuid extNwId = getExtNetworkId(pIdentifier);
578 if(extNwId == null) {
579 LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
582 long vpnId = getVpnId(extNwId);
584 LOG.error("No VPN associated with ext nw {}. Unable to delete SNAT table entry for fixed ip {}",
585 extNwId, mapping.getInternalIp());
588 removeSNATTblEntry(dpnId, mapping.getInternalIp(), routerId, mapping.getExternalIp(), vpnId);
590 long label = getOperationalIpMapping(routerName, interfaceName, mapping.getInternalIp());
592 LOG.error("Could not retrieve label for prefix {} in router {}", mapping.getInternalIp(), routerId);
595 //Uuid extNwId = getExtNetworkId(pIdentifier);
596 // Uuid extNwId = getExternalNetworkForRouter(routerName);
597 // if(extNwId == null) {
598 // LOG.error("External network associated with router {} could not be retrieved", routerName);
601 handler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping.getExternalIp(), mapping.getInternalIp(), (int) label);
602 removeOperationalDS(routerName, interfaceName, mapping.getInternalIp(), mapping.getExternalIp());
606 void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
607 long routerId = NatUtil.getVpnId(broker, routerName);
608 if(routerId == NatConstants.INVALID_ID) {
609 LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
613 long vpnId = NatUtil.getVpnId(broker, vpnName);
614 if(vpnId == NatConstants.INVALID_ID) {
615 LOG.warn("VPN Id not found for {} to remove NAT flow entries {}", vpnName, internalIp);
618 //Delete the DNAT and SNAT table entries
619 removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
621 removeSNATTblEntry(dpnId, internalIp, routerId, externalIp, vpnId);
623 long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
625 LOG.error("Could not retrieve label for prefix {} in router {}", internalIp, routerId);
628 //handler.onRemoveFloatingIp(dpnId, routerName, externalNetworkId, externalIp, internalIp, (int)label);
629 ((VpnFloatingIpHandler)handler).cleanupFibEntries(dpnId, vpnName, externalIp, label);
630 removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
633 void removeNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN,
634 String internalIp, String externalIp) {
635 String segmentId = associatedVPN == null ? routerName : associatedVPN;
636 LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", segmentId);
637 long routerId = NatUtil.getVpnId(broker, segmentId);
638 if(routerId == NatConstants.INVALID_ID) {
639 LOG.warn("Could not retrieve vpn id for {} to remove NAT Flow entries", segmentId);
642 //Delete the DNAT and SNAT table entries
643 removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
645 //removeSNATTblEntry(dpnId, internalIp, routerId, externalIp);
648 private long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
649 InstanceIdentifier<IpMapping> ipMappingIdentifier = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
650 Optional<IpMapping> ipMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, ipMappingIdentifier);
651 if(ipMapping.isPresent()) {
652 return ipMapping.get().getLabel();
654 return NatConstants.INVALID_ID;
657 private Uuid getExternalNetworkForRouter(String routerId) {
658 InstanceIdentifier<RouterPorts> identifier = NatUtil.getRouterPortsId(routerId);
659 Optional<RouterPorts> optRouterPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
660 if(optRouterPorts.isPresent()) {
661 RouterPorts routerPorts = optRouterPorts.get();
662 return routerPorts.getExternalNetworkId();
667 void updateOperationalDS(String routerId, String interfaceName, int label, String internalIp, String externalIp) {
669 LOG.info("Updating operational DS for floating ip config : {} with label {}", internalIp, label);
670 InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
671 Optional<Ports> optPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portsId);
672 IpMapping ipMapping = new IpMappingBuilder().setKey(new IpMappingKey(internalIp)).setInternalIp(internalIp)
673 .setExternalIp(externalIp).setLabel(label).build();
674 if(optPorts.isPresent()) {
675 LOG.debug("Ports {} entry already present. Updating ipmapping for internal ip {}", interfaceName, internalIp);
676 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId.child(IpMapping.class, new IpMappingKey(internalIp)), ipMapping);
678 LOG.debug("Adding Ports entry {} along with ipmapping {}", interfaceName, internalIp);
679 List<IpMapping> ipMappings = new ArrayList<>();
680 ipMappings.add(ipMapping);
681 Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName).setIpMapping(ipMappings).build();
682 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
686 void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
687 LOG.info("Remove operational DS for floating ip config: {}", internalIp);
688 InstanceIdentifier<IpMapping> ipMappingId = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
689 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, ipMappingId);
692 private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
694 LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
696 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, routerId, externalIp);
698 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
699 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
700 NatConstants.COOKIE_DNAT_TABLE, null, null);
707 private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
709 LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
711 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, routerId, externalIp);
713 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
714 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
715 NatConstants.COOKIE_DNAT_TABLE, null, null);
721 private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
723 LOG.info("Building Delete PSNAT Flow entity for ip {} ", internalIp);
725 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, routerId, internalIp);
727 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
728 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
729 NatConstants.COOKIE_DNAT_TABLE, null, null);
734 private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
736 LOG.info("Building Delete SNAT Flow entity for ip {} ", internalIp);
738 String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, routerId, internalIp);
740 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
741 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
742 NatConstants.COOKIE_DNAT_TABLE, null, null);