Merge "LLDP monitor interval update fixes"
[vpnservice.git] / natservice / natservice-impl / src / main / java / org / opendaylight / vpnservice / natservice / internal / FloatingIPListener.java
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.vpnservice.natservice.internal;
9
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;
46
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.Future;
49
50 import com.google.common.base.Optional;
51 import com.google.common.base.Strings;
52
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;
58
59 /**
60  * Created by emhamla on 1/18/2016.
61  */
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;
69
70
71     public FloatingIPListener (final DataBroker db) {
72         super(IpMapping.class);
73         broker = db;
74         registerListener(db);
75     }
76
77     void setFloatingIpHandler(FloatingIPHandler handler) {
78         this.handler = handler;
79     }
80
81     @Override
82     public void close() throws Exception {
83         if (listenerRegistration != null) {
84             try {
85                 listenerRegistration.close();
86             } catch (final Exception e) {
87                 LOG.error("Error when cleaning up DataChangeListener.", e);
88             }
89             listenerRegistration = null;
90         }
91         LOG.info("FloatingIP Listener Closed");
92     }
93
94     private void registerListener(final DataBroker db) {
95         try {
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);
101         }
102     }
103
104     private InstanceIdentifier<IpMapping> getWildCardPath() {
105         return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class).child(IpMapping.class);
106     }
107
108     public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
109         this.interfaceManager = interfaceManager;
110     }
111
112     public void setMdsalManager(IMdsalApiManager mdsalManager) {
113         this.mdsalManager = mdsalManager;
114     }
115
116     @Override
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);
121     }
122
123     @Override
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);
127     }
128
129     @Override
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 );
132     }
133
134     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
135         BigInteger nodeId = BigInteger.ZERO;
136         try {
137             GetDpidFromInterfaceInput
138                     dpIdInput =
139                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
140             Future<RpcResult<GetDpidFromInterfaceOutput>>
141                     dpIdOutput =
142                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
143             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
144             if (dpIdResult.isSuccessful()) {
145                 nodeId = dpIdResult.getResult().getDpid();
146             } else {
147                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
148             }
149         } catch (InterruptedException | ExecutionException e) {
150             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
151         }
152         return nodeId;
153     }
154
155     private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId) {
156
157         LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
158
159         List<MatchInfo> matches = new ArrayList<MatchInfo>();
160         matches.add(new MatchInfo(MatchFieldType.eth_type,
161                 new long[] { 0x0800L }));
162
163         matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
164                 externalIp, "32" }));
165
166 //        matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
167 //                BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
168
169         List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
170         actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
171
172         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
173         instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
174                 (routerId), MetaDataUtil.METADATA_MASK_VRFID }));
175         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
176         instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.DNAT_TABLE }));
177
178         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, externalIp);
179
180         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
181                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
182                 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
183
184         return flowEntity;
185     }
186
187
188
189     private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
190
191         LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
192
193         List<MatchInfo> matches = new ArrayList<MatchInfo>();
194         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
195                 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
196
197         matches.add(new MatchInfo(MatchFieldType.eth_type,
198                 new long[] { 0x0800L }));
199
200         matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
201         //        externalIp, "32" }));
202                   internalIp, "32" }));
203
204         List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
205 //        actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
206
207         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
208 //        instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
209 //                (routerId), MetaDataUtil.METADATA_MASK_VRFID }));
210         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
211         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
212         //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
213
214         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, externalIp);
215
216         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
217                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
218                 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
219
220         return flowEntity;
221
222     }
223
224     private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId) {
225
226         LOG.info("Building PSNAT Flow entity for ip {} ", internalIp);
227
228         List<MatchInfo> matches = new ArrayList<MatchInfo>();
229         matches.add(new MatchInfo(MatchFieldType.eth_type,
230                 new long[] { 0x0800L }));
231
232         matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
233                 internalIp, "32" }));
234
235         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
236                 BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
237
238         List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
239         actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
240
241         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
242         instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
243         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
244         instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.SNAT_TABLE }));
245
246         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, internalIp);
247
248         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
249                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
250                 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
251
252         return flowEntity;
253     }
254
255     private FlowEntity buildSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, String macAddress) {
256
257         LOG.info("Building SNAT Flow entity for ip {} ", internalIp);
258
259         List<MatchInfo> matches = new ArrayList<MatchInfo>();
260         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
261                 BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
262
263         matches.add(new MatchInfo(MatchFieldType.eth_type,
264                 new long[] { 0x0800L }));
265
266         matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
267         //        internalIp, "32" }));
268                   externalIp, "32" }));
269
270         List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
271 //        actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
272
273         //TODO: Set external gateway mac address
274         if(!Strings.isNullOrEmpty(macAddress)) {
275             LOG.debug("Setting ext gw mac address {} in SNAT {} flow action", macAddress, internalIp);
276             actionsInfos.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{ macAddress }));
277         }
278
279         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
280         //instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
281         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
282         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
283         //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
284
285         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, internalIp);
286
287         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
288                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
289                 NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
290
291         return flowEntity;
292
293
294     }
295
296     private void createDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId) {
297         FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId );
298         mdsalManager.installFlow(pFlowEntity);
299
300         FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId);
301         mdsalManager.installFlow(flowEntity);
302     }
303
304     private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId) {
305         FlowEntity pFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId );
306         mdsalManager.removeFlow(pFlowEntity);
307
308         FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId);
309         mdsalManager.removeFlow(flowEntity);
310     }
311
312     private void createSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long vpnId, long routerId, String macAddress) {
313         FlowEntity pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId);
314         mdsalManager.installFlow(pFlowEntity);
315
316         FlowEntity flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddress);
317         mdsalManager.installFlow(flowEntity);
318
319     }
320
321     private void removeSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp) {
322         FlowEntity pFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, externalIp);
323         mdsalManager.removeFlow(pFlowEntity);
324
325         FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, internalIp, externalIp);
326         mdsalManager.removeFlow(flowEntity);
327
328     }
329
330     private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> pIdentifier) {
331         Optional<RouterPorts> rtrPort = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, pIdentifier);
332         if(!rtrPort.isPresent()) {
333             LOG.error("Unable to read router port entry for {}", pIdentifier);
334             return null;
335         }
336
337         Uuid extNwId = rtrPort.get().getExternalNetworkId();
338         return extNwId;
339     }
340
341     private long getVpnId(Uuid extNwId) {
342         InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class, new NetworksKey(extNwId)).build();
343         Optional<Networks> nw = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, nwId);
344         if(!nw.isPresent()) {
345             LOG.error("Unable to read external network for {}", extNwId);
346             return NatConstants.INVALID_ID;
347         }
348
349         Uuid vpnUuid = nw.get().getVpnid();
350         if(vpnUuid == null) {
351             return NatConstants.INVALID_ID;
352         }
353
354         //Get the id using the VPN UUID (also vpn instance name)
355         return NatUtil.readVpnId(broker, vpnUuid.getValue());
356
357     }
358
359     private void processFloatingIPAdd(final InstanceIdentifier<IpMapping> identifier,
360                                       final IpMapping mapping) {
361         LOG.trace("Add event - key: {}, value: {}", identifier, mapping);
362
363         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
364         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
365         String interfaceName = pKey.getPortName();
366
367         InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
368         createNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
369     }
370
371     private void processFloatingIPDel(final InstanceIdentifier<IpMapping> identifier,
372                                       final IpMapping mapping) {
373         LOG.trace("Del event - key: {}, value: {}", identifier, mapping);
374
375         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
376         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
377         String interfaceName = pKey.getPortName();
378
379         InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
380         removeNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
381     }
382
383     private InetAddress getInetAddress(String ipAddr) {
384         InetAddress ipAddress = null;
385         try {
386             ipAddress = InetAddress.getByName(ipAddr);
387         } catch (UnknownHostException e) {
388             LOG.error("UnknowHostException for ip {}", ipAddr);
389         }
390         return ipAddress;
391     }
392
393     private boolean validateIpMapping(IpMapping mapping) {
394         return getInetAddress(mapping.getInternalIp()) != null &&
395                     getInetAddress(mapping.getExternalIp()) != null;
396     }
397
398     void createNATFlowEntries(String interfaceName, final IpMapping mapping,
399                               final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
400         if(!validateIpMapping(mapping)) {
401             LOG.warn("Not a valid ip addresses in the mapping {}", mapping);
402             return;
403         }
404
405         //Get the DPN on which this interface resides
406         BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
407
408         if(dpnId.equals(BigInteger.ZERO)) {
409              LOG.error("No DPN for interface {}. NAT flow entries for ip mapping {} will not be installed", 
410                      interfaceName, mapping);
411              return;
412         }
413
414         long routerId = NatUtil.getVpnId(broker, routerName);
415         if(routerId == NatConstants.INVALID_ID) {
416             LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
417             return;
418         }
419
420         Uuid extNwId = getExtNetworkId(pIdentifier);
421         if(extNwId == null) {
422             LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
423             LOG.error("NAT flow entries will not be installed {}", mapping);
424             return;
425         }
426         long vpnId = getVpnId(extNwId);
427         if(vpnId < 0) {
428             LOG.error("No VPN associated with Ext nw {}. Unable to create SNAT table entry for fixed ip {}", 
429                     extNwId, mapping.getInternalIp());
430             return;
431         }
432
433         //Create the DNAT and SNAT table entries
434         createDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId, vpnId);
435
436
437         String macAddr = getExternalGatewayMacAddress(routerName);
438         createSNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), vpnId, routerId, macAddr);
439
440         handler.onAddFloatingIp(dpnId, routerName, extNwId, interfaceName, mapping.getExternalIp(), mapping
441                 .getInternalIp());
442     }
443
444     void createNATFlowEntries(BigInteger dpnId,  String interfaceName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
445         long routerId = NatUtil.getVpnId(broker, routerName);
446         if(routerId == NatConstants.INVALID_ID) {
447             LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
448             return;
449         }
450         long vpnId = getVpnId(externalNetworkId);
451         if(vpnId < 0) {
452             LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
453             return;
454         }
455         //Create the DNAT and SNAT table entries
456         createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
457
458         String macAddr = getExternalGatewayMacAddress(routerName);
459         createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr);
460
461         handler.onAddFloatingIp(dpnId, routerName, externalNetworkId, interfaceName, externalIp, internalIp);
462     }
463
464     private String getExternalGatewayMacAddress(String routerName) {
465         InstanceIdentifier<Routers> routersIdentifier = NatUtil.buildRouterIdentifier(routerName);
466         Optional<Routers> optRouters = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier);
467         if(optRouters.isPresent()) {
468             Routers routers = optRouters.get();
469             return routers.getExtGwMacAddress();
470         }
471         return "";
472     }
473
474     void removeNATFlowEntries(String interfaceName, final IpMapping mapping,
475                               final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
476
477         //Get the DPN on which this interface resides
478         BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
479         if(dpnId.equals(BigInteger.ZERO)) {
480             LOG.info("Abort processing Floating ip configuration. No DPN for port : {}", interfaceName);
481             return;
482         }
483
484         long routerId = NatUtil.getVpnId(broker, routerName);
485         if(routerId == NatConstants.INVALID_ID) {
486             LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
487             return;
488         }
489
490         //Delete the DNAT and SNAT table entries
491         removeDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId);
492
493 //        Uuid extNwId = getExtNetworkId(pIdentifier);
494 //        if(extNwId == null) {
495 //            LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
496 //            return;
497 //        }
498 //        long vpnId = getVpnId(extNwId);
499 //        if(vpnId < 0) {
500 //            LOG.error("No VPN associated with ext nw {}. Unable to delete SNAT table entry for fixed ip {}", 
501 //                    extNwId, mapping.getInternalIp());
502 //            return;
503 //        }
504         removeSNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp());
505
506         long label = getOperationalIpMapping(routerName, interfaceName, mapping.getInternalIp());
507         if(label < 0) {
508             LOG.error("Could not retrieve label for prefix {} in router {}", mapping.getInternalIp(), routerId);
509             return;
510         }
511         //Uuid extNwId = getExtNetworkId(pIdentifier);
512         Uuid extNwId = getExternalNetworkForRouter(routerName);
513         if(extNwId == null) {
514             LOG.error("External network associated with router {} could not be retrieved", routerName);
515             return;
516         }
517         handler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping.getExternalIp(), mapping.getInternalIp(), (int) label);
518         removeOperationalDS(routerName, interfaceName, mapping.getInternalIp(), mapping.getExternalIp());
519
520     }
521
522     void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
523         long routerId = NatUtil.getVpnId(broker, routerName);
524         if(routerId == NatConstants.INVALID_ID) {
525             LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
526             return;
527         }
528         //Delete the DNAT and SNAT table entries
529         removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
530
531 //        long vpnId = getVpnId(externalNetworkId);
532 //        if(vpnId < 0) {
533 //            LOG.error("Unable to delete SNAT table entry for fixed ip {}", internalIp);
534 //            return;
535 //        }
536         removeSNATTblEntry(dpnId, internalIp, externalIp);
537
538         long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
539         if(label < 0) {
540             LOG.error("Could not retrieve label for prefix {} in router {}", internalIp, routerId);
541             return;
542         }
543         //handler.onRemoveFloatingIp(dpnId, routerName, externalNetworkId, externalIp, internalIp, (int)label);
544         ((VpnFloatingIpHandler)handler).cleanupFibEntries(dpnId, vpnName, externalIp, label);
545         removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
546     }
547
548     private long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
549         InstanceIdentifier<IpMapping> ipMappingIdentifier = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
550         Optional<IpMapping> ipMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, ipMappingIdentifier);
551         if(ipMapping.isPresent()) {
552             return ipMapping.get().getLabel();
553         }
554         return NatConstants.INVALID_ID;
555     }
556
557     private Uuid getExternalNetworkForRouter(String routerId) {
558         InstanceIdentifier<RouterPorts> identifier = NatUtil.getRouterPortsId(routerId);
559         Optional<RouterPorts> optRouterPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
560         if(optRouterPorts.isPresent()) {
561             RouterPorts routerPorts = optRouterPorts.get();
562             return routerPorts.getExternalNetworkId();
563         }
564         return null;
565     }
566
567     void updateOperationalDS(String routerId, String interfaceName, int label, String internalIp, String externalIp) {
568
569         LOG.info("Updating operational DS for floating ip config : {} with label {}", internalIp, label);
570         InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
571         Optional<Ports> optPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portsId);
572         IpMapping ipMapping = new IpMappingBuilder().setKey(new IpMappingKey(internalIp)).setInternalIp(internalIp)
573                 .setExternalIp(externalIp).setLabel(label).build();
574         if(optPorts.isPresent()) {
575             LOG.debug("Ports {} entry already present. Updating ipmapping for internal ip {}", interfaceName, internalIp);
576             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId.child(IpMapping.class, new IpMappingKey(internalIp)), ipMapping);
577         } else {
578             LOG.debug("Adding Ports entry {} along with ipmapping {}", interfaceName, internalIp);
579             List<IpMapping> ipMappings = new ArrayList<>();
580             ipMappings.add(ipMapping);
581             Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName).setIpMapping(ipMappings).build();
582             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
583         }
584     }
585
586     void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
587         LOG.info("Remove operational DS for floating ip config: {}", internalIp);
588         InstanceIdentifier<IpMapping> ipMappingId = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
589         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, ipMappingId);
590     }
591
592     private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
593
594         LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
595
596         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, externalIp);
597
598         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
599                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
600                 NatConstants.COOKIE_DNAT_TABLE, null, null);
601
602         return flowEntity;
603     }
604
605
606
607     private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
608
609         LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
610
611         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, externalIp);
612
613         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
614                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
615                 NatConstants.COOKIE_DNAT_TABLE, null, null);
616
617         return flowEntity;
618
619     }
620
621     private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp) {
622
623         LOG.info("Building Delete PSNAT Flow entity for ip {} ", internalIp);
624
625         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, internalIp);
626
627         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
628                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
629                 NatConstants.COOKIE_DNAT_TABLE, null, null);
630
631         return flowEntity;
632     }
633
634     private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp) {
635
636         LOG.info("Building Delete SNAT Flow entity for ip {} ", internalIp);
637
638         String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, internalIp);
639
640         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
641                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
642                 NatConstants.COOKIE_DNAT_TABLE, null, null);
643
644         return flowEntity;
645
646
647     }
648 }
649