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