a527c34d94b60a62707d7cedcc4bf73ddf811fd9
[netvirt.git] /
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.natservice.internal;
9
10 import io.netty.util.concurrent.GlobalEventExecutor;
11
12 import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
18 import org.opendaylight.genius.mdsalutil.ActionInfo;
19 import org.opendaylight.genius.mdsalutil.ActionType;
20 import org.opendaylight.genius.mdsalutil.FlowEntity;
21 import org.opendaylight.genius.mdsalutil.InstructionInfo;
22 import org.opendaylight.genius.mdsalutil.InstructionType;
23 import org.opendaylight.genius.mdsalutil.MatchFieldType;
24 import org.opendaylight.genius.mdsalutil.MatchInfo;
25 import org.opendaylight.genius.mdsalutil.MDSALUtil;
26 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.osgi.framework.BundleContext;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
51
52 import com.google.common.base.Optional;
53
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;
59
60 public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> implements AutoCloseable{
61     private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
62     private ListenerRegistration<DataChangeListener> listenerRegistration;
63     private final DataBroker dataBroker;
64     private final IMdsalApiManager mdsalManager;
65     private final OdlInterfaceRpcService interfaceManager;
66     private final IdManagerService idManager;
67     private FloatingIPHandler floatingIPHandler;
68
69
70     public FloatingIPListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
71                               final OdlInterfaceRpcService interfaceManager,
72                               final IdManagerService idManager,
73                               final BundleContext bundleContext) {
74         super(IpMapping.class);
75         this.dataBroker = dataBroker;
76         this.mdsalManager = mdsalManager;
77         this.interfaceManager = interfaceManager;
78         this.idManager = idManager;
79
80         GlobalEventExecutor.INSTANCE.execute(new Runnable() {
81             @Override
82             public void run() {
83                 final WaitingServiceTracker<FloatingIPHandler> tracker = WaitingServiceTracker.create(
84                         FloatingIPHandler.class, bundleContext);
85                 floatingIPHandler = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
86                 LOG.info("FloatingIPListener initialized. FloatingIPHandler={}", floatingIPHandler);
87             }
88         });
89     }
90
91     public void init() {
92         LOG.info("{} init", getClass().getSimpleName());
93         listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
94                 getWildCardPath(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
95     }
96
97     private InstanceIdentifier<IpMapping> getWildCardPath() {
98         return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class)
99                 .child(IpMapping.class);
100     }
101
102     @Override
103     public void close() throws Exception {
104         if (listenerRegistration != null) {
105             listenerRegistration.close();
106             listenerRegistration = null;
107         }
108         LOG.info("{} close", getClass().getSimpleName());
109     }
110
111     @Override
112     protected void add(final InstanceIdentifier<IpMapping> identifier,
113                        final IpMapping mapping) {
114         LOG.trace("FloatingIPListener add ip mapping method - key: " + identifier + ", value=" + mapping );
115         processFloatingIPAdd(identifier, mapping);
116     }
117
118     @Override
119     protected void remove(InstanceIdentifier<IpMapping> identifier, IpMapping mapping) {
120         LOG.trace("FloatingIPListener remove ip mapping method - key: " + identifier + ", value=" + mapping );
121         processFloatingIPDel(identifier, mapping);
122     }
123
124     @Override
125     protected void update(InstanceIdentifier<IpMapping> identifier, IpMapping original, IpMapping update) {
126         LOG.trace("FloatingIPListener update ip mapping method - key: " + identifier + ", original=" + original + ", update=" + update );
127     }
128
129     private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpn) {
130         LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
131
132         long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
133         LOG.debug("Segment id {} in build preDNAT Flow", segmentId);
134
135         List<MatchInfo> matches = new ArrayList<>();
136         matches.add(new MatchInfo(MatchFieldType.eth_type,
137                 new long[] { 0x0800L }));
138
139         matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
140                 externalIp, "32" }));
141
142 //        matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
143 //                BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
144
145         List<ActionInfo> actionsInfos = new ArrayList<>();
146         actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
147
148         List<InstructionInfo> instructions = new ArrayList<>();
149         instructions.add(new InstructionInfo(InstructionType.write_metadata,
150                 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
151         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
152         instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.DNAT_TABLE }));
153
154         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PDNAT_TABLE, routerId, externalIp);
155
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);
159
160         return flowEntity;
161     }
162
163     private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long associatedVpn) {
164
165         LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
166
167         long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
168         LOG.debug("Segment id {} in build DNAT", segmentId);
169
170         List<MatchInfo> matches = new ArrayList<>();
171         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
172                 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
173
174         matches.add(new MatchInfo(MatchFieldType.eth_type,
175                 new long[] { 0x0800L }));
176
177         matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
178         //        externalIp, "32" }));
179                   internalIp, "32" }));
180
181         List<ActionInfo> actionsInfos = new ArrayList<>();
182 //        actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
183
184         List<InstructionInfo> instructions = new ArrayList<>();
185 //        instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
186 //                (routerId), MetaDataUtil.METADATA_MASK_VRFID }));
187         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NwConstants.L3_FIB_TABLE) }));
188         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
189         //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
190
191         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.DNAT_TABLE, routerId, externalIp);
192
193         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DNAT_TABLE, flowRef,
194                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
195                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
196
197         return flowEntity;
198
199     }
200
201     private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId, long associatedVpn) {
202
203         LOG.info("Building PSNAT Flow entity for ip {} ", internalIp);
204
205         long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
206
207         LOG.debug("Segment id {} in build preSNAT flow", segmentId);
208
209         List<MatchInfo> matches = new ArrayList<>();
210         matches.add(new MatchInfo(MatchFieldType.eth_type,
211                 new long[] { 0x0800L }));
212
213         matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
214                 internalIp, "32" }));
215
216         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
217                 MetaDataUtil.getVpnIdMetadata(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
218
219         List<ActionInfo> actionsInfos = new ArrayList<>();
220         actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
221
222         List<InstructionInfo> instructions = new ArrayList<>();
223         instructions.add(new InstructionInfo(InstructionType.write_metadata,
224                 new BigInteger[] { MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
225         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
226         instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.SNAT_TABLE }));
227
228         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PSNAT_TABLE, routerId, internalIp);
229
230         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
231                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
232                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
233
234         return flowEntity;
235     }
236
237     private FlowEntity buildSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId) {
238         LOG.info("Building SNAT Flow entity for ip {} ", internalIp);
239
240         List<MatchInfo> matches = new ArrayList<>();
241         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
242                 MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
243
244         matches.add(new MatchInfo(MatchFieldType.eth_type,
245                 new long[] { 0x0800L }));
246
247         matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
248                   externalIp, "32" }));
249
250         List<ActionInfo> actionsInfo = new ArrayList<>();
251         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
252
253         IpAddress externalIpv4Address = new IpAddress(new Ipv4Address(externalIp));
254         Port port = NatUtil.getNeutronPortForFloatingIp(dataBroker, externalIpv4Address);
255         if (port != null && port.getMacAddress() != null) {
256             actionsInfo.add(new ActionInfo(ActionType.set_field_eth_src, new String[] { port.getMacAddress().getValue() }));
257         } else {
258             LOG.warn("No MAC address found for floating IP {}", externalIp);
259         }
260
261         Uuid subnetId = NatUtil.getSubnetIdForFloatingIp(port, externalIpv4Address);
262         if (subnetId != null) {
263             long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetId.getValue()), idManager);
264             actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
265         } else {
266             LOG.warn("No neutron Subnet found for floating IP {}", externalIp);
267         }
268
269         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
270         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, vpnId, internalIp);
271
272         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.SNAT_TABLE, flowRef,
273                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
274                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
275
276         return flowEntity;
277     }
278
279     private void createDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpnId) {
280         FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
281         mdsalManager.installFlow(pFlowEntity);
282
283         FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
284         mdsalManager.installFlow(flowEntity);
285     }
286
287     private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId) {
288         FlowEntity pFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId );
289         mdsalManager.removeFlow(pFlowEntity);
290
291         FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId);
292         mdsalManager.removeFlow(flowEntity);
293     }
294
295     private void createSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long vpnId, long routerId, long associatedVpnId) {
296         FlowEntity pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
297         mdsalManager.installFlow(pFlowEntity);
298
299         FlowEntity flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId);
300         mdsalManager.installFlow(flowEntity);
301
302     }
303
304     private void removeSNATTblEntry(BigInteger dpnId, String internalIp, long routerId, String externalIp, long vpnId) {
305         FlowEntity pFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId, externalIp);
306         mdsalManager.removeFlow(pFlowEntity);
307
308         FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, internalIp, vpnId, externalIp);
309         mdsalManager.removeFlow(flowEntity);
310
311     }
312
313     private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> pIdentifier, LogicalDatastoreType dataStoreType) {
314         Optional<RouterPorts> rtrPort = NatUtil.read(dataBroker, dataStoreType, pIdentifier);
315         if(!rtrPort.isPresent()) {
316             LOG.error("Unable to read router port entry for {}", pIdentifier);
317             return null;
318         }
319
320         Uuid extNwId = rtrPort.get().getExternalNetworkId();
321         return extNwId;
322     }
323
324     private long getVpnId(Uuid extNwId) {
325         InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class, new NetworksKey(extNwId)).build();
326         Optional<Networks> nw = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, nwId);
327         if(!nw.isPresent()) {
328             LOG.error("Unable to read external network for {}", extNwId);
329             return NatConstants.INVALID_ID;
330         }
331
332         Uuid vpnUuid = nw.get().getVpnid();
333         if(vpnUuid == null) {
334             return NatConstants.INVALID_ID;
335         }
336
337         //Get the id using the VPN UUID (also vpn instance name)
338         return NatUtil.readVpnId(dataBroker, vpnUuid.getValue());
339     }
340
341     private void processFloatingIPAdd(final InstanceIdentifier<IpMapping> identifier,
342                                       final IpMapping mapping) {
343         LOG.trace("Add event - key: {}, value: {}", identifier, mapping);
344
345         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
346         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
347         String interfaceName = pKey.getPortName();
348
349         InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
350         createNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
351     }
352
353     private void processFloatingIPDel(final InstanceIdentifier<IpMapping> identifier,
354                                       final IpMapping mapping) {
355         LOG.trace("Del event - key: {}, value: {}", identifier, mapping);
356
357         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
358         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
359         String interfaceName = pKey.getPortName();
360
361         InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
362         removeNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
363     }
364
365     private InetAddress getInetAddress(String ipAddr) {
366         InetAddress ipAddress = null;
367         try {
368             ipAddress = InetAddress.getByName(ipAddr);
369         } catch (UnknownHostException e) {
370             LOG.error("UnknowHostException for ip {}", ipAddr);
371         }
372         return ipAddress;
373     }
374
375     private boolean validateIpMapping(IpMapping mapping) {
376         return getInetAddress(mapping.getInternalIp()) != null &&
377                     getInetAddress(mapping.getExternalIp()) != null;
378     }
379
380     void createNATFlowEntries(String interfaceName, final IpMapping mapping,
381                               final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
382         if(!validateIpMapping(mapping)) {
383             LOG.warn("Not a valid ip addresses in the mapping {}", mapping);
384             return;
385         }
386
387         //Get the DPN on which this interface resides
388         BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
389
390         if(dpnId.equals(BigInteger.ZERO)) {
391              LOG.error("No DPN for interface {}. NAT flow entries for ip mapping {} will not be installed",
392                      interfaceName, mapping);
393              return;
394         }
395
396         long routerId = NatUtil.getVpnId(dataBroker, routerName);
397         if(routerId == NatConstants.INVALID_ID) {
398             LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
399             return;
400         }
401         //Check if the router to vpn association is present
402         //long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
403         Uuid associatedVpn = NatUtil.getVpnForRouter(dataBroker, routerName);
404         long associatedVpnId = NatConstants.INVALID_ID;
405         if(associatedVpn == null) {
406             LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
407         } else {
408             LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpn);
409             associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVpn.getValue());
410             LOG.debug("vpninstance Id is {} for VPN {}", associatedVpnId, associatedVpn);
411             //routerId = associatedVpnId;
412         }
413
414         Uuid extNwId = getExtNetworkId(pIdentifier, LogicalDatastoreType.CONFIGURATION);
415         if(extNwId == null) {
416             LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
417             LOG.error("NAT flow entries will not be installed {}", mapping);
418             return;
419         }
420         long vpnId = getVpnId(extNwId);
421         if(vpnId < 0) {
422             LOG.error("No VPN associated with Ext nw {}. Unable to create SNAT table entry for fixed ip {}",
423                     extNwId, mapping.getInternalIp());
424             return;
425         }
426
427         //Create the DNAT and SNAT table entries
428         createDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId, vpnId, associatedVpnId);
429
430
431         createSNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), vpnId, routerId, associatedVpnId);
432
433         floatingIPHandler.onAddFloatingIp(dpnId, routerName, extNwId, interfaceName, mapping.getExternalIp(), mapping
434                 .getInternalIp());
435     }
436
437     void createNATFlowEntries(BigInteger dpnId,  String interfaceName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
438         long routerId = NatUtil.getVpnId(dataBroker, routerName);
439         if(routerId == NatConstants.INVALID_ID) {
440             LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
441             return;
442         }
443         //Check if the router to vpn association is present
444         long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
445         if(associatedVpnId == NatConstants.INVALID_ID) {
446             LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
447         } else {
448             LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpnId);
449             //routerId = associatedVpnId;
450         }
451
452         long vpnId = getVpnId(externalNetworkId);
453         if(vpnId < 0) {
454             LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
455             return;
456         }
457         //Create the DNAT and SNAT table entries
458         createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId);
459
460         createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, associatedVpnId);
461
462         floatingIPHandler.onAddFloatingIp(dpnId, routerName, externalNetworkId, interfaceName, externalIp, internalIp);
463     }
464
465     void createNATOnlyFlowEntries(BigInteger dpnId,  String interfaceName, String routerName, String associatedVPN, Uuid externalNetworkId, String internalIp, String externalIp) {
466         //String segmentId = associatedVPN == null ? routerName : associatedVPN;
467         LOG.debug("Retrieving vpn id for VPN {} to proceed with create NAT Flows", routerName);
468         long routerId = NatUtil.getVpnId(dataBroker, routerName);
469         if(routerId == NatConstants.INVALID_ID) {
470             LOG.warn("Could not retrieve vpn id for {} to create NAT Flow entries", routerName);
471             return;
472         }
473         long associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVPN);
474         LOG.debug("Associated VPN Id {} for router {}", associatedVpnId, routerName);
475         long vpnId = getVpnId(externalNetworkId);
476         if(vpnId < 0) {
477             LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
478             return;
479         }
480         //Create the DNAT and SNAT table entries
481         //createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
482         FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
483         mdsalManager.installFlow(pFlowEntity);
484
485         FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
486         mdsalManager.installFlow(flowEntity);
487
488         //createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr);
489         pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
490         mdsalManager.installFlow(pFlowEntity);
491
492         flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId);
493         mdsalManager.installFlow(flowEntity);
494
495     }
496
497     void removeNATFlowEntries(String interfaceName, final IpMapping mapping,
498                               final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
499
500         //Get the DPN on which this interface resides
501         BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, interfaceName);
502         if(dpnId.equals(BigInteger.ZERO)) {
503             LOG.info("Abort processing Floating ip configuration. No DPN for port : {}", interfaceName);
504             return;
505         }
506
507         long routerId = NatUtil.getVpnId(dataBroker, routerName);
508         if(routerId == NatConstants.INVALID_ID) {
509             LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
510             return;
511         }
512         //if(routerId == NatConstants.INVALID_ID) {
513         //The router could be associated with BGP VPN
514         Uuid associatedVPN = NatUtil.getVpnForRouter(dataBroker, routerName);
515         long associatedVpnId = NatConstants.INVALID_ID;
516         if(associatedVPN == null) {
517             LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
518         } else {
519             LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", associatedVPN.getValue());
520             associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVPN.getValue());
521         }
522
523         //Delete the DNAT and SNAT table entries
524         removeDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId);
525
526         Uuid extNwId = getExtNetworkId(pIdentifier, LogicalDatastoreType.OPERATIONAL);
527         if(extNwId == null) {
528             LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
529             return;
530         }
531         long vpnId = getVpnId(extNwId);
532         if(vpnId < 0) {
533             LOG.error("No VPN associated with ext nw {}. Unable to delete SNAT table entry for fixed ip {}",
534                     extNwId, mapping.getInternalIp());
535             return;
536         }
537         removeSNATTblEntry(dpnId, mapping.getInternalIp(), routerId, mapping.getExternalIp(), vpnId);
538
539         long label = getOperationalIpMapping(routerName, interfaceName, mapping.getInternalIp());
540         if(label < 0) {
541             LOG.error("Could not retrieve label for prefix {} in router {}", mapping.getInternalIp(), routerId);
542             return;
543         }
544         //Uuid extNwId = getExtNetworkId(pIdentifier);
545 //        Uuid extNwId = getExternalNetworkForRouter(routerName);
546 //        if(extNwId == null) {
547 //            LOG.error("External network associated with router {} could not be retrieved", routerName);
548 //            return;
549 //        }
550         floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping.getExternalIp(), mapping.getInternalIp(), (int) label);
551         removeOperationalDS(routerName, interfaceName, mapping.getInternalIp(), mapping.getExternalIp());
552
553     }
554
555     void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
556         long routerId = NatUtil.getVpnId(dataBroker, routerName);
557         if(routerId == NatConstants.INVALID_ID) {
558             LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
559             return;
560         }
561
562         long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
563         if(vpnId == NatConstants.INVALID_ID) {
564             LOG.warn("VPN Id not found for {} to remove NAT flow entries {}", vpnName, internalIp);
565         }
566
567         //Delete the DNAT and SNAT table entries
568         removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
569
570         removeSNATTblEntry(dpnId, internalIp, routerId, externalIp, vpnId);
571
572         long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
573         if(label < 0) {
574             LOG.error("Could not retrieve label for prefix {} in router {}", internalIp, routerId);
575             return;
576         }
577         //floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, externalNetworkId, externalIp, internalIp, (int)label);
578         ((VpnFloatingIpHandler) floatingIPHandler).cleanupFibEntries(dpnId, vpnName, externalIp, label);
579         removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
580     }
581
582     void removeNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN,
583                                                                           String internalIp, String externalIp) {
584         String segmentId = associatedVPN == null ? routerName : associatedVPN;
585         LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", segmentId);
586         long routerId = NatUtil.getVpnId(dataBroker, segmentId);
587         if(routerId == NatConstants.INVALID_ID) {
588             LOG.warn("Could not retrieve vpn id for {} to remove NAT Flow entries", segmentId);
589             return;
590         }
591         //Delete the DNAT and SNAT table entries
592         removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
593
594         //removeSNATTblEntry(dpnId, internalIp, routerId, externalIp);
595     }
596
597     private long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
598         InstanceIdentifier<IpMapping> ipMappingIdentifier = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
599         Optional<IpMapping> ipMapping = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ipMappingIdentifier);
600         if(ipMapping.isPresent()) {
601             return ipMapping.get().getLabel();
602         }
603         return NatConstants.INVALID_ID;
604     }
605
606     void updateOperationalDS(String routerId, String interfaceName, long label, String internalIp, String externalIp) {
607
608         LOG.info("Updating operational DS for floating ip config : {} with label {}", internalIp, label);
609         InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
610         Optional<Ports> optPorts = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId);
611         IpMapping ipMapping = new IpMappingBuilder().setKey(new IpMappingKey(internalIp)).setInternalIp(internalIp)
612                 .setExternalIp(externalIp).setLabel(label).build();
613         if(optPorts.isPresent()) {
614             LOG.debug("Ports {} entry already present. Updating ipmapping for internal ip {}", interfaceName, internalIp);
615             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId.child(IpMapping.class, new IpMappingKey(internalIp)), ipMapping);
616         } else {
617             LOG.debug("Adding Ports entry {} along with ipmapping {}", interfaceName, internalIp);
618             List<IpMapping> ipMappings = new ArrayList<>();
619             ipMappings.add(ipMapping);
620             Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName).setIpMapping(ipMappings).build();
621             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
622         }
623     }
624
625     void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
626         LOG.info("Remove operational DS for floating ip config: {}", internalIp);
627         InstanceIdentifier<IpMapping> ipMappingId = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
628         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, ipMappingId);
629     }
630
631     private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
632
633         LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
634
635         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PDNAT_TABLE, routerId, externalIp);
636
637         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PDNAT_TABLE, flowRef,
638                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
639                 NwConstants.COOKIE_DNAT_TABLE, null, null);
640
641         return flowEntity;
642     }
643
644
645
646     private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
647
648         LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
649
650         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.DNAT_TABLE, routerId, externalIp);
651
652         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DNAT_TABLE, flowRef,
653                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
654                 NwConstants.COOKIE_DNAT_TABLE, null, null);
655
656         return flowEntity;
657
658     }
659
660     private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
661
662         LOG.info("Building Delete PSNAT Flow entity for ip {} ", internalIp);
663
664         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PSNAT_TABLE, routerId, internalIp);
665
666         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
667                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
668                 NwConstants.COOKIE_DNAT_TABLE, null, null);
669
670         return flowEntity;
671     }
672
673     private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
674
675         LOG.info("Building Delete SNAT Flow entity for ip {} ", internalIp);
676
677         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, routerId, internalIp);
678
679         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.SNAT_TABLE, flowRef,
680                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
681                 NwConstants.COOKIE_DNAT_TABLE, null, null);
682
683         return flowEntity;
684
685
686     }
687
688 }
689