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