Migrate ListenableFutures.addErrorLogging() users
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / FloatingIPListener.java
1 /*
2  * Copyright © 2016, 2017 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 static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Optional;
19 import java.util.concurrent.ExecutionException;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
25 import org.opendaylight.genius.infra.Datastore.Configuration;
26 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
28 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
29 import org.opendaylight.genius.mdsalutil.ActionInfo;
30 import org.opendaylight.genius.mdsalutil.FlowEntity;
31 import org.opendaylight.genius.mdsalutil.InstructionInfo;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchInfo;
34 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
35 import org.opendaylight.genius.mdsalutil.NwConstants;
36 import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
37 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
38 import org.opendaylight.genius.mdsalutil.actions.ActionSetDestinationIp;
39 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
40 import org.opendaylight.genius.mdsalutil.actions.ActionSetSourceIp;
41 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
42 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
43 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
44 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
45 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
46 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
47 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
48 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
49 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
50 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
51 import org.opendaylight.infrautils.utils.concurrent.Executors;
52 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
53 import org.opendaylight.mdsal.binding.api.DataBroker;
54 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
55 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
56 import org.opendaylight.netvirt.natservice.api.NatSwitchCache;
57 import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.common.Uint32;
76 import org.opendaylight.yangtools.yang.common.Uint64;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
79
80 @Singleton
81 public class FloatingIPListener extends AbstractAsyncDataTreeChangeListener<InternalToExternalPortMap> {
82     private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
83     private final DataBroker dataBroker;
84     private final ManagedNewTransactionRunner txRunner;
85     private final IMdsalApiManager mdsalManager;
86     private final OdlInterfaceRpcService interfaceManager;
87     private final FloatingIPHandler floatingIPHandler;
88     private final SNATDefaultRouteProgrammer defaultRouteProgrammer;
89     private final JobCoordinator coordinator;
90     private final CentralizedSwitchScheduler centralizedSwitchScheduler;
91     private final NatSwitchCache natSwitchCache;
92
93     @Inject
94     public FloatingIPListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
95                               final OdlInterfaceRpcService interfaceManager,
96                               final FloatingIPHandler floatingIPHandler,
97                               final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
98                               final JobCoordinator coordinator,
99                               final CentralizedSwitchScheduler centralizedSwitchScheduler,
100                               final NatSwitchCache natSwitchCache) {
101         super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(FloatingIpInfo.class)
102                 .child(RouterPorts.class).child(Ports.class).child(InternalToExternalPortMap.class),
103                 Executors.newListeningSingleThreadExecutor("FloatingIPListener", LOG));
104         this.dataBroker = dataBroker;
105         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
106         this.mdsalManager = mdsalManager;
107         this.interfaceManager = interfaceManager;
108         this.floatingIPHandler = floatingIPHandler;
109         this.defaultRouteProgrammer = snatDefaultRouteProgrammer;
110         this.coordinator = coordinator;
111         this.centralizedSwitchScheduler = centralizedSwitchScheduler;
112         this.natSwitchCache = natSwitchCache;
113     }
114
115     public void init() {
116         LOG.info("{} init", getClass().getSimpleName());
117     }
118
119     @Override
120     @PreDestroy
121     public void close() {
122         super.close();
123         Executors.shutdownAndAwaitTermination(getExecutorService());
124     }
125
126     @Override
127     public void add(final InstanceIdentifier<InternalToExternalPortMap> identifier,
128                        final InternalToExternalPortMap mapping) {
129         LOG.trace("FloatingIPListener add ip mapping method - key: {} value: {}",mapping.key(), mapping);
130         processFloatingIPAdd(identifier, mapping);
131     }
132
133     @Override
134     public void remove(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap mapping) {
135         LOG.trace("FloatingIPListener remove ip mapping method - kkey: {} value: {}",mapping.key(), mapping);
136         processFloatingIPDel(identifier, mapping);
137     }
138
139     @Override
140     public void update(InstanceIdentifier<InternalToExternalPortMap> identifier, InternalToExternalPortMap
141             original, InternalToExternalPortMap update) {
142         LOG.trace("FloatingIPListener update ip mapping method - key: {}, original: {}, update: {}",
143                 update.key(), original, update);
144     }
145
146     @Nullable
147     private FlowEntity buildPreDNATFlowEntity(Uint64 dpId, InternalToExternalPortMap mapping, Uint32 routerId,
148                                               Uint32 associatedVpn) {
149         String externalIp = mapping.getExternalIp();
150         Uuid floatingIpId = mapping.getExternalId();
151         //Get the FIP MAC address for DNAT
152         String floatingIpPortMacAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
153         if (floatingIpPortMacAddress == null) {
154             LOG.error("buildPreDNATFlowEntity : Unable to retrieve floatingIpPortMacAddress from floating IP UUID {} "
155                     + "for floating IP {}", floatingIpId, externalIp);
156             return null;
157         }
158         LOG.debug("buildPreDNATFlowEntity : Bulding DNAT Flow entity for ip {} ", externalIp);
159         Uint32 segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
160         LOG.debug("buildPreDNATFlowEntity : Segment id {} in build preDNAT Flow", segmentId);
161
162         List<MatchInfo> matches = new ArrayList<>();
163         matches.add(MatchEthernetType.IPV4);
164
165         matches.add(new MatchIpv4Destination(externalIp, "32"));
166         //Match Destination Floating IP MAC Address on table = 25 (PDNAT_TABLE)
167         matches.add(new MatchEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
168
169 //        matches.add(new MatchMetadata(
170 //                BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
171         List<ActionInfo> actionsInfos = new ArrayList<>();
172         String internalIp = mapping.getInternalIp();
173         actionsInfos.add(new ActionSetDestinationIp(internalIp, "32"));
174
175         List<InstructionInfo> instructions = new ArrayList<>();
176         instructions.add(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
177                 MetaDataUtil.METADATA_MASK_VRFID));
178         instructions.add(new InstructionApplyActions(actionsInfos));
179         instructions.add(new InstructionGotoTable(NwConstants.DNAT_TABLE));
180
181         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PDNAT_TABLE, routerId, externalIp);
182
183         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PDNAT_TABLE, flowRef,
184                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
185                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
186
187         return flowEntity;
188     }
189
190     private FlowEntity buildDNATFlowEntity(Uint64 dpId, InternalToExternalPortMap mapping, Uint32 routerId, Uint32
191             associatedVpn) {
192         String externalIp = mapping.getExternalIp();
193         LOG.info("buildDNATFlowEntity : Bulding DNAT Flow entity for ip {} ", externalIp);
194
195         Uint32 segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
196         LOG.debug("buildDNATFlowEntity : Segment id {} in build DNAT", segmentId);
197
198         List<MatchInfo> matches = new ArrayList<>();
199         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
200                 MetaDataUtil.METADATA_MASK_VRFID));
201
202         matches.add(MatchEthernetType.IPV4);
203         String internalIp = mapping.getInternalIp();
204         matches.add(new MatchIpv4Destination(internalIp, "32"));
205
206         List<ActionInfo> actionsInfos = new ArrayList<>();
207 //        actionsInfos.add(new ActionSetDestinationIp(internalIp, "32"));
208
209         List<InstructionInfo> instructions = new ArrayList<>();
210 //        instructions.add(new InstructionWriteMetadata(Uint64.valueOf
211 //                (routerId), MetaDataUtil.METADATA_MASK_VRFID));
212         actionsInfos.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
213         actionsInfos.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
214         instructions.add(new InstructionApplyActions(actionsInfos));
215         //instructions.add(new InstructionGotoTable(NatConstants.L3_FIB_TABLE));
216
217         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.DNAT_TABLE, routerId, internalIp);
218
219         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DNAT_TABLE, flowRef,
220                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
221                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
222
223         return flowEntity;
224
225     }
226
227     private FlowEntity buildPreSNATFlowEntity(Uint64 dpId, String internalIp, String externalIp, Uint32 vpnId, Uint32
228             routerId, Uint32 associatedVpn) {
229
230         LOG.debug("buildPreSNATFlowEntity : Building PSNAT Flow entity for ip {} ", internalIp);
231
232         Uint32 segmentId = associatedVpn == NatConstants.INVALID_ID ? routerId : associatedVpn;
233
234         LOG.debug("buildPreSNATFlowEntity : Segment id {} in build preSNAT flow", segmentId);
235
236         List<MatchInfo> matches = new ArrayList<>();
237         matches.add(MatchEthernetType.IPV4);
238
239         matches.add(new MatchIpv4Source(internalIp, "32"));
240
241         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(segmentId.longValue()),
242                 MetaDataUtil.METADATA_MASK_VRFID));
243
244         List<ActionInfo> actionsInfos = new ArrayList<>();
245         actionsInfos.add(new ActionSetSourceIp(externalIp, "32"));
246
247         List<InstructionInfo> instructions = new ArrayList<>();
248         instructions.add(
249                 new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
250                         MetaDataUtil.METADATA_MASK_VRFID));
251         instructions.add(new InstructionApplyActions(actionsInfos));
252         instructions.add(new InstructionGotoTable(NwConstants.SNAT_TABLE));
253
254         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PSNAT_TABLE, routerId, internalIp);
255
256         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
257                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
258                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
259
260         return flowEntity;
261     }
262
263     @Nullable
264     private FlowEntity buildSNATFlowEntity(Uint64 dpId, InternalToExternalPortMap mapping, Uint32 vpnId, Uuid
265             externalNetworkId) {
266         String internalIp = mapping.getInternalIp();
267         LOG.debug("buildSNATFlowEntity : Building SNAT Flow entity for ip {} ", internalIp);
268
269         ProviderTypes provType = NatUtil.getProviderTypefromNetworkId(dataBroker, externalNetworkId);
270         if (provType == null) {
271             LOG.error("buildSNATFlowEntity : Unable to get Network Provider Type for network {}", externalNetworkId);
272             return null;
273         }
274
275         List<MatchInfo> matches = new ArrayList<>();
276         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
277                 MetaDataUtil.METADATA_MASK_VRFID));
278         matches.add(MatchEthernetType.IPV4);
279         String externalIp = mapping.getExternalIp();
280         matches.add(new MatchIpv4Source(externalIp, "32"));
281
282         List<ActionInfo> actionsInfo = new ArrayList<>();
283         actionsInfo.add(new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)));
284         Uuid floatingIpId = mapping.getExternalId();
285         String macAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
286         if (macAddress != null) {
287             actionsInfo.add(new ActionSetFieldEthernetSource(new MacAddress(macAddress)));
288         } else {
289             LOG.warn("buildSNATFlowEntity : No MAC address found for floating IP {}", externalIp);
290         }
291
292         LOG.trace("buildSNATFlowEntity : External Network Provider Type is {}, resubmit to FIB", provType.toString());
293         actionsInfo.add(new ActionNxResubmit(NwConstants.L3_FIB_TABLE));
294         List<InstructionInfo> instructions = new ArrayList<>();
295         instructions.add(new InstructionApplyActions(actionsInfo));
296         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, vpnId, externalIp);
297
298         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.SNAT_TABLE, flowRef,
299                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
300                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
301
302         return flowEntity;
303
304     }
305
306     private void createDNATTblEntry(Uint64 dpnId, InternalToExternalPortMap mapping, Uint32 routerId,
307                                     Uint32 associatedVpnId, TypedReadWriteTransaction<Configuration> confTx) {
308         FlowEntity preFlowEntity = buildPreDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
309         if (preFlowEntity == null) {
310             LOG.error("createDNATTblEntry : Flow entity received as NULL. "
311                     + "Cannot proceed with installation of Pre-DNAT flow table {} --> table {} on DpnId {}",
312                     NwConstants.PDNAT_TABLE, NwConstants.DNAT_TABLE, dpnId);
313         } else {
314             mdsalManager.addFlow(confTx, preFlowEntity);
315             FlowEntity flowEntity = buildDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
316             if (flowEntity != null) {
317                 mdsalManager.addFlow(confTx, flowEntity);
318             }
319         }
320     }
321
322     private void removeDNATTblEntry(Uint64 dpnId, String internalIp, String externalIp, Uint32 routerId,
323             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
324         FlowEntity preFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, externalIp, routerId);
325         mdsalManager.removeFlow(confTx, preFlowEntity);
326
327         FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, routerId);
328         if (flowEntity != null) {
329             mdsalManager.removeFlow(confTx, flowEntity);
330         }
331     }
332
333     private void createSNATTblEntry(Uint64 dpnId, InternalToExternalPortMap mapping, Uint32 vpnId, Uint32 routerId,
334                                     Uint32 associatedVpnId, Uuid externalNetworkId,
335                                     TypedReadWriteTransaction<Configuration> confTx) {
336         FlowEntity preFlowEntity = buildPreSNATFlowEntity(dpnId, mapping.getInternalIp(), mapping.getExternalIp(),
337             vpnId, routerId, associatedVpnId);
338         mdsalManager.addFlow(confTx, preFlowEntity);
339
340         FlowEntity flowEntity = buildSNATFlowEntity(dpnId, mapping, vpnId, externalNetworkId);
341         if (flowEntity != null) {
342             mdsalManager.addFlow(confTx, flowEntity);
343         }
344     }
345
346     private void removeSNATTblEntry(Uint64 dpnId, String internalIp, String externalIp, Uint32 routerId, Uint32 vpnId,
347                                     TypedReadWriteTransaction<Configuration> removeFlowInvTx)
348             throws ExecutionException, InterruptedException {
349         FlowEntity preFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId);
350         mdsalManager.removeFlow(removeFlowInvTx, preFlowEntity);
351
352         FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, externalIp, vpnId);
353         if (flowEntity != null) {
354             mdsalManager.removeFlow(removeFlowInvTx, flowEntity);
355         }
356     }
357
358     @Nullable
359     private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> portIid,
360                                  LogicalDatastoreType dataStoreType) {
361         Optional<RouterPorts> rtrPort =
362                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
363                         dataStoreType, portIid);
364         if (!rtrPort.isPresent()) {
365             LOG.error("getExtNetworkId : Unable to read router port entry for {}", portIid);
366             return null;
367         }
368
369         return rtrPort.get().getExternalNetworkId();
370     }
371
372     private Uuid getVpnUuid(Uuid extNwId, Uuid floatingIpExternalId) {
373
374         InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class,
375                 new NetworksKey(extNwId)).build();
376         Optional<Networks> nw =
377                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
378                         LogicalDatastoreType.CONFIGURATION, nwId);
379         if (!nw.isPresent()) {
380             LOG.error("getVpnId : Unable to read external network for {}", extNwId);
381             return null;
382         }
383
384         ProviderTypes providerType = nw.get().getProviderNetworkType();
385         if (providerType == ProviderTypes.FLAT || providerType == ProviderTypes.VLAN) {
386             Uuid subnetId = NatUtil
387                 .getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpExternalId);
388             if (subnetId != null) {
389                 return subnetId;
390             }
391         }
392
393         Uuid vpnUuid = nw.get().getVpnid();
394         if (vpnUuid == null) {
395             LOG.error("getVpnId : Unable to read vpn from External network: {}", extNwId);
396             return null;
397         }
398         return vpnUuid;
399     }
400
401     private Uint32 getVpnId(Uuid extNwId, Uuid floatingIpExternalId) {
402         Uuid vpnUuid = getVpnUuid(extNwId, floatingIpExternalId);
403         //Get the id using the VPN UUID (also vpn instance name)
404         return vpnUuid != null ? NatUtil.getVpnId(dataBroker, vpnUuid.getValue()) : NatConstants.INVALID_ID;
405     }
406
407     private void processFloatingIPAdd(final InstanceIdentifier<InternalToExternalPortMap> identifier,
408                                       final InternalToExternalPortMap mapping) {
409         LOG.trace("processFloatingIPAdd key: {}, value: {}", mapping.key(), mapping);
410
411         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
412         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
413         String interfaceName = pKey.getPortName();
414
415         InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
416         coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.key(), () -> Collections.singletonList(
417                 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
418                     tx -> createNATFlowEntries(interfaceName, mapping, portIid, routerId, null, tx))),
419                 NatConstants.NAT_DJC_MAX_RETRIES);
420     }
421
422     private void processFloatingIPDel(final InstanceIdentifier<InternalToExternalPortMap> identifier,
423                                       final InternalToExternalPortMap mapping) {
424         LOG.trace("processFloatingIPDel : key: {}, value: {}", mapping.key(), mapping);
425
426         final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
427         final PortsKey pKey = identifier.firstKeyOf(Ports.class);
428         String interfaceName = pKey.getPortName();
429
430         InstanceIdentifier<RouterPorts> portIid = identifier.firstIdentifierOf(RouterPorts.class);
431         coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + mapping.key(), () -> Collections.singletonList(
432                 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
433                     tx -> removeNATFlowEntries(interfaceName, mapping, portIid, routerId, null, tx))),
434                 NatConstants.NAT_DJC_MAX_RETRIES);
435     }
436
437     private InetAddress getInetAddress(String ipAddr) {
438         InetAddress ipAddress = null;
439         try {
440             ipAddress = InetAddress.getByName(ipAddr);
441         } catch (UnknownHostException e) {
442             LOG.error("getInetAddress : UnknowHostException for ip {}", ipAddr, e);
443         }
444         return ipAddress;
445     }
446
447     private boolean validateIpMapping(InternalToExternalPortMap mapping) {
448         return getInetAddress(mapping.getInternalIp()) != null && getInetAddress(mapping.getExternalIp()) != null;
449     }
450
451     private Uint64 getAssociatedDpnWithExternalInterface(final String routerName, Uuid extNwId, Uint64 dpnId,
452             String interfaceName) {
453         //Get the DPN on which this interface resides
454         if (dpnId == null) {
455             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
456                 .state.Interface interfaceState = NatUtil.getInterfaceStateFromOperDS(dataBroker, interfaceName);
457             if (interfaceState != null) {
458                 dpnId = NatUtil.getDpIdFromInterface(interfaceState);
459             }
460         }
461         Uint64 updatedDpnId = dpnId;
462         if (updatedDpnId != null && updatedDpnId.equals(Uint64.ZERO)) {
463             LOG.debug("getAssociatedDpnWithExternalInterface : The interface {} is not associated with any dpn",
464                     interfaceName);
465             return updatedDpnId;
466         }
467         ProviderTypes providerType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNwId);
468         if (providerType == null) {
469             LOG.warn("getAssociatedDpnWithExternalInterface : Provider Network Type for router {} and"
470                     + " externalNetwork {} is missing.", routerName, extNwId);
471             return updatedDpnId;
472         }
473
474         // For FLAT and VLAN provider networks, we have to ensure that dpn hosting the VM has connectivity
475         // to External Network via provider_mappings. In case the dpn does not have the provider mappings,
476         // traffic from the VM has to be forwarded to the NAPT Switch (which is scheduled based on the provider
477         // mappings) and then sent out on the external Network.
478         if (providerType == ProviderTypes.FLAT || providerType == ProviderTypes.VLAN) {
479             String providerNet = NatUtil.getElanInstancePhysicalNetwok(extNwId.getValue(), dataBroker);
480             boolean isDpnConnected = natSwitchCache.isSwitchConnectedToExternal(updatedDpnId, providerNet);
481             if (!isDpnConnected) {
482                 updatedDpnId = centralizedSwitchScheduler.getCentralizedSwitch(routerName);
483             }
484         }
485         return updatedDpnId;
486     }
487
488     void createNATFlowEntries(String interfaceName, final InternalToExternalPortMap mapping,
489             final InstanceIdentifier<RouterPorts> portIid, final String routerName, @Nullable Uint64 dpnId,
490             TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
491         if (!validateIpMapping(mapping)) {
492             LOG.error("createNATFlowEntries : Not a valid ip addresses in the mapping {}", mapping);
493             return;
494         }
495
496         Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.CONFIGURATION);
497         if (extNwId == null) {
498             LOG.error("createNATFlowEntries : External network associated with interface {} could not be retrieved",
499                     interfaceName);
500             return;
501         }
502
503         // For Overlay Networks, get the DPN on which this interface resides.
504         // For FLAT/VLAN Networks, get the DPN with provider_mappings for external network.
505         dpnId = getAssociatedDpnWithExternalInterface(routerName, extNwId, dpnId, interfaceName);
506         if (dpnId == null || dpnId.equals(Uint64.ZERO)) {
507             LOG.warn("createNATFlowEntries : No DPN for interface {}. NAT flow entries for ip mapping {} will "
508                     + "not be installed", interfaceName, mapping);
509             return;
510         }
511
512         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
513         if (routerId == NatConstants.INVALID_ID) {
514             LOG.error("createNATFlowEntries : Could not retrieve router id for {} to create NAT Flow entries",
515                     routerName);
516             return;
517         }
518         //Check if the router to vpn association is present
519         //long associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
520         Uuid associatedVpn = NatUtil.getVpnForRouter(dataBroker, routerName);
521         Uint32 associatedVpnId = NatConstants.INVALID_ID;
522         if (associatedVpn == null) {
523             LOG.debug("createNATFlowEntries : Router {} is not assicated with any BGP VPN instance", routerName);
524         } else {
525             LOG.debug("createNATFlowEntries : Router {} is associated with VPN Instance with Id {}",
526                     routerName, associatedVpn);
527             associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVpn.getValue());
528             LOG.debug("createNATFlowEntries : vpninstance Id is {} for VPN {}", associatedVpnId, associatedVpn);
529             //routerId = associatedVpnId;
530         }
531
532         Uuid vpnUuid = getVpnUuid(extNwId, mapping.getExternalId());
533
534         LOG.trace("createNATFlowEntries : vpnUuid {} for External Network {}", vpnUuid, extNwId);
535         if (vpnUuid == null) {
536             LOG.error("createNATFlowEntries : No VPN associated with Ext nw {}. Unable to create SNAT table entry "
537                     + "for fixed ip {}", extNwId, mapping.getInternalIp());
538             return;
539         }
540         VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnUuid.getValue());
541         if (vpnInstance == null || vpnInstance.getVpnId() == null) {
542             LOG.error("createNATFlowEntries : No VPN associated with Ext nw {}. Unable to create SNAT table entry "
543                     + "for fixed ip {}", extNwId, mapping.getInternalIp());
544             return;
545         }
546         //Install the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
547         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
548         if (!isSnatEnabled) {
549             addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, true);
550         }
551         //Create the DNAT and SNAT table entries
552         Uint32 vpnId = vpnInstance.getVpnId();
553         String vrfId = vpnInstance.getVrfId();
554         createDNATTblEntry(dpnId, mapping, routerId, associatedVpnId, confTx);
555         createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, extNwId, confTx);
556         floatingIPHandler.onAddFloatingIp(dpnId, routerName, routerId, extNwId, interfaceName, mapping,
557             vrfId, confTx);
558     }
559
560     void createNATFlowEntries(Uint64 dpnId,  String interfaceName, String routerName, Uuid externalNetworkId,
561                               InternalToExternalPortMap mapping, TypedReadWriteTransaction<Configuration> confTx)
562             throws ExecutionException, InterruptedException {
563         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
564         if (routerId == NatConstants.INVALID_ID) {
565             LOG.error("createNATFlowEntries : Could not retrieve router id for {} to create NAT Flow entries",
566                     routerName);
567             return;
568         }
569         //Check if the router to vpn association is present
570         Uint32 associatedVpnId = NatUtil.getAssociatedVpn(dataBroker, routerName);
571         if (associatedVpnId == NatConstants.INVALID_ID) {
572             LOG.debug("createNATFlowEntries : Router {} is not assicated with any BGP VPN instance", routerName);
573         } else {
574             LOG.debug("createNATFlowEntries : Router {} is associated with VPN Instance with Id {}",
575                 routerName, associatedVpnId);
576             //routerId = associatedVpnId;
577         }
578
579         Uuid vpnUuid = getVpnUuid(externalNetworkId, mapping.getExternalId());
580         LOG.trace("createNATFlowEntries : vpnUuid {} for External Network {}", vpnUuid, externalNetworkId);
581         if (vpnUuid == null) {
582             LOG.error("createNATFlowEntries : No vpnUuid associated with Ext nw {}. Unable to create SNAT table entry"
583                     + " for fixed ip {}", externalNetworkId, mapping.getInternalIp());
584             return;
585         }
586         VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnUuid.getValue());
587         if (vpnInstance == null || vpnInstance.getVpnId() == null) {
588             LOG.error("createNATFlowEntries: VpnInstance associated with Ext nw {}. Unable to create SNAT table entry"
589                     + " for fixed ip {}",externalNetworkId, mapping.getInternalIp());
590             return;
591         }
592         //Install the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
593         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
594         if (!isSnatEnabled) {
595             addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, true);
596         }
597         //Create the DNAT and SNAT table entries
598         Uint32 vpnId = vpnInstance.getVpnId();
599         String vrfId = vpnInstance.getVrfId();
600         createDNATTblEntry(dpnId, mapping, routerId, associatedVpnId, confTx);
601         createSNATTblEntry(dpnId, mapping, vpnId, routerId, associatedVpnId, externalNetworkId, confTx);
602         floatingIPHandler.onAddFloatingIp(dpnId, routerName, routerId, externalNetworkId, interfaceName, mapping,
603             vrfId, confTx);
604     }
605
606     void createNATOnlyFlowEntries(Uint64 dpnId, String routerName, @Nullable String associatedVPN,
607                                   Uuid externalNetworkId, InternalToExternalPortMap mapping)
608             throws ExecutionException, InterruptedException {
609         //String segmentId = associatedVPN == null ? routerName : associatedVPN;
610         LOG.debug("createNATOnlyFlowEntries : Retrieving vpn id for VPN {} to proceed with create NAT Flows",
611                 routerName);
612         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
613         if (routerId == NatConstants.INVALID_ID) {
614             LOG.error("createNATOnlyFlowEntries : Could not retrieve vpn id for {} to create NAT Flow entries",
615                     routerName);
616             return;
617         }
618         Uint32 associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVPN);
619         LOG.debug("createNATOnlyFlowEntries : Associated VPN Id {} for router {}", associatedVpnId, routerName);
620         Uint32 vpnId = getVpnId(externalNetworkId, mapping.getExternalId());
621         if (vpnId.longValue() < 0) {
622             LOG.error("createNATOnlyFlowEntries : Unable to create SNAT table entry for fixed ip {}",
623                     mapping.getInternalIp());
624             return;
625         }
626         //Install the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
627         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
628         if (!isSnatEnabled) {
629             addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, null, true);
630         }
631         //Create the DNAT and SNAT table entries
632         FlowEntity preFlowEntity = buildPreDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
633         mdsalManager.installFlow(preFlowEntity);
634
635         FlowEntity flowEntity = buildDNATFlowEntity(dpnId, mapping, routerId, associatedVpnId);
636         mdsalManager.installFlow(flowEntity);
637
638         String externalIp = mapping.getExternalIp();
639         preFlowEntity = buildPreSNATFlowEntity(dpnId, mapping.getInternalIp(), externalIp, vpnId,
640                 routerId, associatedVpnId);
641         mdsalManager.installFlow(preFlowEntity);
642
643         flowEntity = buildSNATFlowEntity(dpnId, mapping, vpnId, externalNetworkId);
644         if (flowEntity != null) {
645             mdsalManager.installFlow(flowEntity);
646         }
647
648     }
649
650     void removeNATFlowEntries(String interfaceName, final InternalToExternalPortMap mapping,
651             InstanceIdentifier<RouterPorts> portIid, final String routerName, @Nullable Uint64 dpnId,
652             TypedReadWriteTransaction<Configuration> removeFlowInvTx) throws ExecutionException, InterruptedException {
653         Uuid extNwId = getExtNetworkId(portIid, LogicalDatastoreType.OPERATIONAL);
654         if (extNwId == null) {
655             LOG.error("removeNATFlowEntries : External network associated with interface {} could not be retrieved",
656                     interfaceName);
657             return;
658         }
659
660         // For Overlay Networks, get the DPN on which this interface resides.
661         // For FLAT/VLAN Networks, get the DPN with provider_mappings for external network.
662         if (dpnId == null) {
663             dpnId = getAssociatedDpnWithExternalInterface(routerName, extNwId,
664                     NatUtil.getDpnForInterface(interfaceManager, interfaceName), interfaceName);
665             if (dpnId == null || dpnId.equals(Uint64.ZERO)) {
666                 LOG.warn("removeNATFlowEntries: Abort processing Floating ip configuration. No DPN for port: {}",
667                         interfaceName);
668                 return;
669             }
670         }
671
672         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
673         if (routerId == NatConstants.INVALID_ID) {
674             LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries",
675                     routerName);
676             return;
677         }
678
679         String internalIp = mapping.getInternalIp();
680         String externalIp = mapping.getExternalIp();
681
682         //Delete the DNAT and SNAT table entries
683         removeDNATTblEntry(dpnId, internalIp, externalIp, routerId, removeFlowInvTx);
684         Uuid vpnUuid = getVpnUuid(extNwId, mapping.getExternalId());
685         if (vpnUuid == null) {
686             LOG.error("removeNATFlowEntries : No VPN associated with Ext nw {}. Unable to remove SNAT table entry "
687                     + "for fixed ip {}", extNwId, mapping.getInternalIp());
688             return;
689         }
690         VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnUuid.getValue());
691         if (vpnInstance == null || vpnInstance.getVpnId() == null) {
692             LOG.error("removeNATFlowEntries: No VPN associated with Ext nw {}. Unable to create SNAT table entry "
693                 + "for fixed ip {}", extNwId, mapping.getInternalIp());
694             return;
695         }
696         Uint32 vpnId = vpnInstance.getVpnId();
697         String vrfId = vpnInstance.getVrfId();
698         removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, removeFlowInvTx);
699         //Remove the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
700         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
701         if (!isSnatEnabled) {
702             addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, removeFlowInvTx, false);
703         }
704         ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNwId);
705         if (provType == null) {
706             LOG.error("removeNATFlowEntries : External Network Provider Type missing");
707             return;
708         }
709         if (provType == ProviderTypes.VXLAN) {
710             floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, routerId, extNwId, mapping,
711                     NatConstants.DEFAULT_L3VNI_VALUE, vrfId, removeFlowInvTx);
712             removeOperationalDS(routerName, interfaceName, internalIp);
713             return;
714         }
715         Uint32 label = getOperationalIpMapping(routerName, interfaceName, internalIp);
716         if (label.longValue() < 0) {
717             LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}",
718                     internalIp, routerId);
719             return;
720         }
721         floatingIPHandler.onRemoveFloatingIp(dpnId, routerName, routerId, extNwId, mapping, label, vrfId,
722                 removeFlowInvTx);
723         removeOperationalDS(routerName, interfaceName, internalIp);
724     }
725
726     void removeNATFlowEntries(Uint64 dpnId, String interfaceName, String vpnName, String routerName,
727                               InternalToExternalPortMap mapping, TypedReadWriteTransaction<Configuration> confTx)
728             throws ExecutionException, InterruptedException {
729         String internalIp = mapping.getInternalIp();
730         String externalIp = mapping.getExternalIp();
731         Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
732         if (routerId == NatConstants.INVALID_ID) {
733             LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries",
734                     routerName);
735             return;
736         }
737
738         VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnName);
739         if (vpnInstance == null || vpnInstance.getVpnId() == null) {
740             LOG.warn("removeNATFlowEntries: VPN Id not found for {} to remove NAT flow entries {}",
741                 vpnName, internalIp);
742             return;
743         }
744         Uint32 vpnId = vpnInstance.getVpnId();
745         String vrfId = vpnInstance.getVrfId();
746
747         //Delete the DNAT and SNAT table entries
748         removeDNATTblEntry(dpnId, internalIp, externalIp, routerId, confTx);
749         removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, confTx);
750         //Remove the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
751         boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
752         if (!isSnatEnabled) {
753             addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, false);
754         }
755         Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker,routerName);
756         ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, externalNetworkId);
757         if (provType == null) {
758             LOG.error("removeNATFlowEntries : External Network Provider Type Missing");
759             return;
760         }
761         if (provType == ProviderTypes.VXLAN) {
762             floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE, vrfId,
763                     confTx, provType);
764             removeOperationalDS(routerName, interfaceName, internalIp);
765             return;
766         }
767         Uint32 label = getOperationalIpMapping(routerName, interfaceName, internalIp);
768         if (label != null && label.longValue() < 0) {
769             LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}",
770                     internalIp, routerId);
771             return;
772         }
773         if (provType == ProviderTypes.VXLAN) {
774             floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE, vrfId,
775                 confTx, provType);
776             removeOperationalDS(routerName, interfaceName, internalIp);
777             return;
778         }
779         floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, label, vrfId, confTx, provType);
780         removeOperationalDS(routerName, interfaceName, internalIp);
781     }
782
783     protected Uint32 getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
784         InstanceIdentifier<InternalToExternalPortMap> intExtPortMapIdentifier =
785             NatUtil.getIntExtPortMapIdentifier(routerId, interfaceName, internalIp);
786         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
787                 LogicalDatastoreType.OPERATIONAL, intExtPortMapIdentifier).map(
788                 InternalToExternalPortMap::getLabel).orElse(NatConstants.INVALID_ID);
789     }
790
791     static void updateOperationalDS(DataBroker dataBroker, String routerId, String interfaceName, Uint32 label,
792                                     String internalIp, String externalIp) {
793
794         LOG.info("updateOperationalDS : Updating operational DS for floating ip config : {} with label {}",
795                 internalIp, label);
796         InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
797         Optional<Ports> optPorts =
798                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
799                         LogicalDatastoreType.OPERATIONAL, portsId);
800         InternalToExternalPortMap intExtPortMap = new InternalToExternalPortMapBuilder().withKey(new
801                 InternalToExternalPortMapKey(internalIp)).setInternalIp(internalIp).setExternalIp(externalIp)
802                 .setLabel(label).build();
803         if (optPorts.isPresent()) {
804             LOG.debug("updateOperationalDS : Ports {} entry already present. Updating intExtPortMap for internal ip {}",
805                     interfaceName, internalIp);
806             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId.child(InternalToExternalPortMap
807                     .class, new InternalToExternalPortMapKey(internalIp)), intExtPortMap);
808         } else {
809             LOG.debug("updateOperationalDS : Adding Ports entry {} along with intExtPortMap {}",
810                     interfaceName, internalIp);
811             List<InternalToExternalPortMap> intExtPortMapList = new ArrayList<>();
812             intExtPortMapList.add(intExtPortMap);
813             Ports ports = new PortsBuilder().withKey(new PortsKey(interfaceName)).setPortName(interfaceName)
814                     .setInternalToExternalPortMap(intExtPortMapList).build();
815             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
816         }
817     }
818
819     void removeOperationalDS(String routerId, String interfaceName, String internalIp) {
820         LOG.info("removeOperationalDS : Remove operational DS for floating ip config: {}", internalIp);
821         InstanceIdentifier<InternalToExternalPortMap> intExtPortMapId = NatUtil.getIntExtPortMapIdentifier(routerId,
822                 interfaceName, internalIp);
823         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, intExtPortMapId);
824     }
825
826     private FlowEntity buildPreDNATDeleteFlowEntity(Uint64 dpId, String externalIp, Uint32 routerId) {
827
828         LOG.info("buildPreDNATDeleteFlowEntity : Bulding Delete DNAT Flow entity for ip {} ", externalIp);
829
830         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PDNAT_TABLE, routerId, externalIp);
831
832         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PDNAT_TABLE, flowRef,
833                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
834                 NwConstants.COOKIE_DNAT_TABLE, null, null);
835
836         return flowEntity;
837     }
838
839
840
841     private FlowEntity buildDNATDeleteFlowEntity(Uint64 dpId, String internalIp, Uint32 routerId) {
842
843         LOG.info("buildDNATDeleteFlowEntity : Bulding Delete DNAT Flow entity for ip {} ", internalIp);
844
845         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.DNAT_TABLE, routerId, internalIp);
846
847         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DNAT_TABLE, flowRef,
848                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
849                 NwConstants.COOKIE_DNAT_TABLE, null, null);
850
851         return flowEntity;
852
853     }
854
855     private FlowEntity buildPreSNATDeleteFlowEntity(Uint64 dpId, String internalIp, Uint32 routerId) {
856
857         LOG.info("buildPreSNATDeleteFlowEntity : Building Delete PSNAT Flow entity for ip {} ", internalIp);
858
859         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.PSNAT_TABLE, routerId, internalIp);
860
861         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.PSNAT_TABLE, flowRef,
862                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
863                 NwConstants.COOKIE_DNAT_TABLE, null, null);
864         return flowEntity;
865     }
866
867     private FlowEntity buildSNATDeleteFlowEntity(Uint64 dpId, String externalIp, Uint32 routerId) {
868
869         LOG.info("buildSNATDeleteFlowEntity : Building Delete SNAT Flow entity for ip {} ", externalIp);
870
871         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, routerId, externalIp);
872
873         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.SNAT_TABLE, flowRef,
874                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
875                 NwConstants.COOKIE_DNAT_TABLE, null, null);
876
877         return flowEntity;
878     }
879
880     private void addOrDelDefaultFibRouteForDnat(Uint64 dpnId, String routerName, Uint32 routerId,
881             @Nullable TypedReadWriteTransaction<Configuration> confTx, boolean create)
882             throws ExecutionException, InterruptedException {
883         if (confTx == null) {
884             LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
885                 newTx -> addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, newTx, create)), LOG,
886                 "Error handling default FIB route for DNAT");
887             return;
888         }
889         //Check if the router to bgp-vpn association is present
890         Uint32 associatedVpnId = NatConstants.INVALID_ID;
891         Uuid associatedVpn = NatUtil.getVpnForRouter(dataBroker, routerName);
892         if (associatedVpn != null) {
893             associatedVpnId = NatUtil.getVpnId(dataBroker, associatedVpn.getValue());
894         }
895         if (create) {
896             if (associatedVpnId != NatConstants.INVALID_ID) {
897                 LOG.debug("addOrDelDefaultFibRouteForDnat: Install NAT default route on DPN {} for the router {} with "
898                         + "vpn-id {}", dpnId, routerName, associatedVpnId);
899                 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, associatedVpnId, routerId, confTx);
900             } else {
901                 LOG.debug("addOrDelDefaultFibRouteForDnat: Install NAT default route on DPN {} for the router {} with "
902                         + "vpn-id {}", dpnId, routerName, routerId);
903                 defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId, confTx);
904             }
905         } else {
906             if (associatedVpnId != NatConstants.INVALID_ID) {
907                 LOG.debug("addOrDelDefaultFibRouteForDnat: Remove NAT default route on DPN {} for the router {} "
908                         + "with vpn-id {}", dpnId, routerName, associatedVpnId);
909                 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, associatedVpnId, routerId, confTx);
910             } else {
911                 LOG.debug("addOrDelDefaultFibRouteForDnat: Remove NAT default route on DPN {} for the router {} "
912                         + "with vpn-id {}", dpnId, routerName, routerId);
913                 defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId, confTx);
914             }
915         }
916     }
917 }