a3fc74b667415ed36dd8b8ef1369ecbd40446b9e
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / InterfaceStateEventListener.java
1 /*
2  * Copyright (c) 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 com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.concurrent.Callable;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import javax.annotation.PostConstruct;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
25 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
26 import org.opendaylight.genius.mdsalutil.FlowEntity;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
29 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.opendaylight.yangtools.yang.common.RpcResult;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 @Singleton
56 public class InterfaceStateEventListener
57     extends AsyncDataTreeChangeListenerBase<Interface, InterfaceStateEventListener> {
58
59     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateEventListener.class);
60
61     private static final String NAT_FLOW = "NATFLOW";
62
63     private final DataBroker dataBroker;
64     private final IMdsalApiManager mdsalManager;
65     private final FloatingIPListener floatingIPListener;
66     private final NaptManager naptManager;
67     private final NeutronvpnService neutronVpnService;
68     private final JobCoordinator coordinator;
69
70     @Inject
71     public InterfaceStateEventListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
72                                        final FloatingIPListener floatingIPListener,
73                                        final NaptManager naptManager,
74                                        final NeutronvpnService neutronvpnService,
75                                        final JobCoordinator coordinator) {
76         super(Interface.class, InterfaceStateEventListener.class);
77         this.dataBroker = dataBroker;
78         this.mdsalManager = mdsalManager;
79         this.floatingIPListener = floatingIPListener;
80         this.naptManager = naptManager;
81         this.neutronVpnService = neutronvpnService;
82         this.coordinator = coordinator;
83     }
84
85     @Override
86     @PostConstruct
87     public void init() {
88         LOG.info("{} init", getClass().getSimpleName());
89         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
90     }
91
92     @Override
93     protected InstanceIdentifier<Interface> getWildCardPath() {
94         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
95     }
96
97     @Override
98     protected InterfaceStateEventListener getDataTreeChangeListener() {
99         return InterfaceStateEventListener.this;
100     }
101
102     @Override
103     // TODO Clean up the exception handling
104     @SuppressWarnings("checkstyle:IllegalCatch")
105     protected void remove(InstanceIdentifier<Interface> identifier, Interface delintrf) {
106         LOG.trace("remove : Interface {} removed event received", delintrf);
107         if (!L2vlan.class.equals(delintrf.getType())) {
108             LOG.debug("remove : Interface {} is a not type Vlan.Ignoring", delintrf.getName());
109             return;
110         }
111
112         NatFlowRemoveWorker natFlowRemoveWorker =
113                 new NatFlowRemoveWorker(delintrf);
114         coordinator.enqueueJob(NAT_FLOW + "-" + delintrf.getName(), natFlowRemoveWorker,
115                 NatConstants.NAT_DJC_MAX_RETRIES);
116     }
117
118     @Override
119     // TODO Clean up the exception handling
120     @SuppressWarnings("checkstyle:IllegalCatch")
121     protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
122         LOG.trace("update : Operation Interface update event - Old: {}, New: {}", original, update);
123         if (!L2vlan.class.equals(update.getType())) {
124             LOG.debug("update : Interface {} is not type Vlan.Ignoring", update.getName());
125             return;
126         }
127
128         NatFlowUpdateWorker natFlowUpdateWorker =
129                 new NatFlowUpdateWorker(update);
130         coordinator.enqueueJob(NAT_FLOW + "-" + update.getName(), natFlowUpdateWorker,
131                 NatConstants.NAT_DJC_MAX_RETRIES);
132
133     }
134
135     @Override
136     // TODO Clean up the exception handling
137     @SuppressWarnings("checkstyle:IllegalCatch")
138     protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
139         LOG.trace("add : Interface {} up event received", intrf);
140         if (!L2vlan.class.equals(intrf.getType())) {
141             LOG.debug("add : Interface {} is not type vlan.Ignoring", intrf.getName());
142             return;
143         }
144
145         NatFlowAddWorker natFlowAddWorker =
146                 new NatFlowAddWorker(intrf);
147         coordinator.enqueueJob(NAT_FLOW + "-" + intrf.getName(), natFlowAddWorker,
148                 NatConstants.NAT_DJC_MAX_RETRIES);
149     }
150
151     // TODO Clean up the exception handling
152     @SuppressWarnings("checkstyle:IllegalCatch")
153     private void removeSnatEntriesForPort(String interfaceName, String routerName) {
154         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
155         if (routerId == NatConstants.INVALID_ID) {
156             LOG.error("removeSnatEntriesForPort : routerId not found for routername {}", routerName);
157             return;
158         }
159         BigInteger naptSwitch = getNaptSwitchforRouter(dataBroker, routerName);
160         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
161             LOG.error("removeSnatEntriesForPort : NaptSwitch is not elected for router {} with Id {}",
162                     routerName, routerId);
163             return;
164         }
165         //getInternalIp for port
166         List<String> fixedIps = getFixedIpsForPort(interfaceName);
167         if (fixedIps == null) {
168             LOG.warn("removeSnatEntriesForPort : Internal Ips not found for InterfaceName {} in router {} with id {}",
169                 interfaceName, routerName, routerId);
170             return;
171         }
172
173         for (String internalIp : fixedIps) {
174             LOG.debug("removeSnatEntriesForPort : Internal Ip retrieved for interface {} is {} in router with Id {}",
175                 interfaceName, internalIp, routerId);
176             IpPort ipPort = NatUtil.getInternalIpPortInfo(dataBroker, routerId, internalIp);
177             if (ipPort == null) {
178                 LOG.debug("removeSnatEntriesForPort : no snatint-ip-port-map found for ip:{}", internalIp);
179                 continue;
180             }
181
182             for (IntIpProtoType protoType: ipPort.getIntIpProtoType()) {
183                 ProtocolTypes protocol = protoType.getProtocol();
184                 for (Integer portnum : protoType.getPorts()) {
185                     //build and remove the flow in outbound table
186                     try {
187                         removeNatFlow(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, portnum);
188                     } catch (Exception ex) {
189                         LOG.error("removeSnatEntriesForPort : Failed to remove snat flow for internalIP {} with "
190                                 + "Port {} protocol {} for routerId {} in OUTBOUNDTABLE of NaptSwitch {}: {}",
191                             internalIp, portnum, protocol, routerId, naptSwitch, ex);
192                     }
193                     //Get the external IP address and the port from the model
194                     NAPTEntryEvent.Protocol proto = protocol.toString().equals(ProtocolTypes.TCP.toString())
195                         ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
196                     IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
197                         internalIp, String.valueOf(portnum), proto);
198                     if (ipPortExternal == null) {
199                         LOG.error("removeSnatEntriesForPort : Mapping for internalIp {} with port {} is not found in "
200                             + "router with Id {}", internalIp, portnum, routerId);
201                         return;
202                     }
203                     String externalIpAddress = ipPortExternal.getIpAddress();
204                     Integer portNumber = ipPortExternal.getPortNum();
205
206                     //build and remove the flow in inboundtable
207                     try {
208                         removeNatFlow(naptSwitch, NwConstants.INBOUND_NAPT_TABLE, routerId,
209                             externalIpAddress, portNumber);
210                     } catch (Exception ex) {
211                         LOG.error("removeSnatEntriesForPort : Failed to remove snat flow internalIP {} with "
212                                 + "Port {} protocol {} for routerId {} in INBOUNDTABLE of naptSwitch {}",
213                             externalIpAddress, portNumber, protocol, routerId, naptSwitch, ex);
214                     }
215
216                     String internalIpPort = internalIp + ":" + portnum;
217                     // delete the entry from IntExtIpPortMap DS
218                     try {
219                         naptManager.removeFromIpPortMapDS(routerId, internalIpPort, proto);
220                         naptManager.removePortFromPool(internalIpPort, externalIpAddress);
221                     } catch (Exception ex) {
222                         LOG.error("removeSnatEntriesForPort : releaseIpExtPortMapping failed, Removal of "
223                             + "ipportmap {} for router {} failed {}", internalIpPort, routerId, ex);
224                     }
225                 }
226             }
227             // delete the entry from SnatIntIpPortMap DS
228             LOG.debug("removeSnatEntriesForPort : Removing InternalIp:{} on router {}", internalIp, routerId);
229             naptManager.removeFromSnatIpPortDS(routerId, internalIp);
230         }
231     }
232
233     // TODO Clean up the exception handling
234     @SuppressWarnings("checkstyle:IllegalCatch")
235     private String getRouterIdForPort(String interfaceName) {
236         String routerName = null;
237         VpnInterface vpnInterface = null;
238         try {
239             vpnInterface = NatUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
240         } catch (Exception ex) {
241             LOG.error("getRouterIdForPort : Unable to process for interface {} as it is not configured",
242                     interfaceName, ex);
243         }
244         if (vpnInterface != null) {
245             //getVpnName
246             if (vpnInterface.getVpnInstanceNames() == null) {
247                 LOG.debug("getRouterIdForPort : vpnName not found for vpnInterface {} of port {}",
248                     vpnInterface, interfaceName);
249             } else {
250                 for (VpnInstanceNames vpnInstance : vpnInterface.getVpnInstanceNames()) {
251                     String vpnName  = vpnInstance.getVpnName();
252                     try {
253                         routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
254                     } catch (Exception e) {
255                         LOG.error("getRouterIdForPort : Unable to get routerId for vpnName {}", vpnName, e);
256                     }
257                     if (routerName != null) {
258                         //check router is associated to external network
259                         if (NatUtil.isSnatEnabledForRouterId(dataBroker, routerName)) {
260                             LOG.debug("getRouterIdForPort : Retreived Router Id {} for vpnname {} "
261                                     + "associated to interface {}", routerName, vpnName, interfaceName);
262                             return routerName;
263                         } else {
264                             LOG.warn("getRouterIdForPort : Interface {} associated to routerId {} is not "
265                                 + "associated to external network", interfaceName, routerName);
266                         }
267                     } else {
268                         LOG.warn("getRouterIdForPort : Router is not associated to vpnname {} for interface {}",
269                                 vpnName, interfaceName);
270                     }
271                 }
272             }
273         } else {
274             LOG.debug("getRouterIdForPort : Interface {} is not a vpninterface", interfaceName);
275         }
276         return null;
277     }
278
279     private BigInteger getNaptSwitchforRouter(DataBroker broker, String routerName) {
280         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
281             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
282         Optional<RouterToNaptSwitch> routerToNaptSwitchData =
283                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
284                         LogicalDatastoreType.CONFIGURATION, rtrNaptSw);
285         if (routerToNaptSwitchData.isPresent()) {
286             RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
287             return routerToNaptSwitchInstance.getPrimarySwitchId();
288         }
289         return null;
290     }
291
292     private void removeNatFlow(BigInteger dpnId, short tableId, Long routerId, String ipAddress, int ipPort) {
293
294         String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), ipAddress, ipPort);
295         FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
296
297         mdsalManager.removeFlow(snatFlowEntity);
298         LOG.debug("removeNatFlow : Removed the flow in table {} for the switch with the DPN ID {} for "
299             + "router {} ip {} port {}", tableId, dpnId, routerId, ipAddress, ipPort);
300     }
301
302     private void processInterfaceAdded(String portName, String routerId, List<ListenableFuture<Void>> futures) {
303         LOG.trace("processInterfaceAdded : Processing Interface Add Event for interface {}", portName);
304         List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
305         if (intExtPortMapList == null || intExtPortMapList.isEmpty()) {
306             LOG.debug("processInterfaceAdded : Ip Mapping list is empty/null for portname {}", portName);
307             return;
308         }
309         InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
310         WriteTransaction installFlowInvTx = dataBroker.newWriteOnlyTransaction();
311         for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
312             floatingIPListener.createNATFlowEntries(portName, intExtPortMap, portIid, routerId, installFlowInvTx);
313         }
314         //final submit call for installFlowInvTx
315         futures.add(NatUtil.waitForTransactionToComplete(installFlowInvTx));
316     }
317
318     private void processInterfaceRemoved(String portName, BigInteger dpnId, String routerId,
319                                          List<ListenableFuture<Void>> futures) {
320         LOG.trace("processInterfaceRemoved : Processing Interface Removed Event for interface {} on DPN ID {}",
321                 portName, dpnId);
322         List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
323         if (intExtPortMapList == null || intExtPortMapList.isEmpty()) {
324             LOG.debug("processInterfaceRemoved : Ip Mapping list is empty/null for portName {}", portName);
325             return;
326         }
327         InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
328         WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
329         for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
330             LOG.trace("processInterfaceRemoved : Removing DNAT Flow entries for dpnId {} ", dpnId);
331             floatingIPListener.removeNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, removeFlowInvTx);
332         }
333         //final submit call for removeFlowInvTx
334         futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
335     }
336
337     private List<InternalToExternalPortMap> getIntExtPortMapListForPortName(String portName, String routerId) {
338         InstanceIdentifier<Ports> portToIpMapIdentifier = NatUtil.buildPortToIpMapIdentifier(routerId, portName);
339         Optional<Ports> port =
340                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
341                         LogicalDatastoreType.CONFIGURATION, portToIpMapIdentifier);
342         if (!port.isPresent()) {
343             LOG.info("getIntExtPortMapListForPortName : Unable to read router port entry for router ID {} "
344                     + "and port name {}", routerId, portName);
345             return null;
346         }
347         return port.get().getInternalToExternalPortMap();
348     }
349
350     private List<String> getFixedIpsForPort(String interfname) {
351         LOG.debug("getFixedIpsForPort : getFixedIpsForPort method is called for interface {}", interfname);
352         try {
353             Future<RpcResult<GetFixedIPsForNeutronPortOutput>> result =
354                 neutronVpnService.getFixedIPsForNeutronPort(new GetFixedIPsForNeutronPortInputBuilder()
355                     .setPortId(new Uuid(interfname)).build());
356
357             RpcResult<GetFixedIPsForNeutronPortOutput> rpcResult = result.get();
358             if (!rpcResult.isSuccessful()) {
359                 LOG.error("getFixedIpsForPort : RPC Call to GetFixedIPsForNeutronPortOutput returned with Errors {}",
360                     rpcResult.getErrors());
361             } else {
362                 return rpcResult.getResult().getFixedIPs();
363             }
364         } catch (InterruptedException | ExecutionException | NullPointerException ex) {
365             LOG.error("getFixedIpsForPort : Exception while receiving fixedIps for port {}", interfname, ex);
366         }
367         return null;
368     }
369
370     private class NatFlowAddWorker implements Callable<List<ListenableFuture<Void>>> {
371         Interface iface;
372
373         NatFlowAddWorker(Interface iface) {
374             this.iface = iface;
375         }
376
377         @Override
378         @SuppressWarnings("checkstyle:IllegalCatch")
379         public List<ListenableFuture<Void>> call() {
380             final List<ListenableFuture<Void>> futures = new ArrayList<>();
381             LOG.trace("call : Interface {} up event received", iface);
382             String interfaceName = iface.getName();
383             try {
384                 LOG.trace("call : Port added event received for interface {} ", interfaceName);
385                 String routerId = getRouterIdForPort(interfaceName);
386                 if (routerId != null) {
387                     processInterfaceAdded(interfaceName, routerId, futures);
388                 }
389             } catch (Exception ex) {
390                 LOG.error("call : Exception caught in Interface {} Operational State Up event",
391                         interfaceName, ex);
392             }
393             return futures;
394         }
395     }
396
397     private class NatFlowRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
398         Interface delintrf;
399
400         NatFlowRemoveWorker(Interface delintrf) {
401             this.delintrf = delintrf;
402         }
403
404         @Override
405         @SuppressWarnings("checkstyle:IllegalCatch")
406         public List<ListenableFuture<Void>> call() {
407             final List<ListenableFuture<Void>> futures = new ArrayList<>();
408             final String interfaceName = delintrf.getName();
409             LOG.trace("call : Interface {} removed event received", delintrf);
410             try {
411                 String routerName = getRouterIdForPort(interfaceName);
412                 if (routerName != null) {
413                     LOG.trace("call : Port removed event received for interface {} ", interfaceName);
414
415                     BigInteger dpId = null;
416                     try {
417                         dpId = NatUtil.getDpIdFromInterface(delintrf);
418                     } catch (Exception e) {
419                         LOG.warn(
420                                 "call: Unable to retrieve DPNID from Interface operational data store for"
421                                         + " Interface {}. Fetching from VPN Interface op data store. ",
422                                 interfaceName, e);
423                         InstanceIdentifier<VpnInterface> id = NatUtil.getVpnInterfaceIdentifier(interfaceName);
424                         Optional<VpnInterface> cfgVpnInterface =
425                                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
426                                         dataBroker, LogicalDatastoreType.CONFIGURATION, id);
427                         if (!cfgVpnInterface.isPresent()) {
428                             LOG.debug("call : Interface {} is not a VPN Interface, ignoring.", interfaceName);
429                             return futures;
430                         }
431                         for (VpnInstanceNames vpnInstance : cfgVpnInterface.get().getVpnInstanceNames()) {
432                             String vpnName  = vpnInstance.getVpnName();
433                             InstanceIdentifier<VpnInterfaceOpDataEntry> idOper = NatUtil
434                                   .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
435                             Optional<VpnInterfaceOpDataEntry> optVpnInterface =
436                                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
437                                        dataBroker, LogicalDatastoreType.OPERATIONAL, idOper);
438                             if (optVpnInterface.isPresent()) {
439                                 dpId = optVpnInterface.get().getDpnId();
440                                 break;
441                             }
442                         }
443                     }
444                     if (dpId == null || dpId.equals(BigInteger.ZERO)) {
445                         LOG.error("call : Unable to get DPN ID for the Interface {}", interfaceName);
446                         return futures;
447                     }
448                     processInterfaceRemoved(interfaceName, dpId, routerName, futures);
449                     removeSnatEntriesForPort(interfaceName, routerName);
450                 } else {
451                     LOG.debug("call : PORT_REMOVE: Router Id is null either Interface {} is not associated "
452                             + "to router or failed to retrieve routerId due to exception", interfaceName);
453                 }
454             } catch (Exception e) {
455                 LOG.error("call : Exception caught in Interface {} OperationalStateRemove", interfaceName, e);
456             }
457             return futures;
458         }
459     }
460
461     private class NatFlowUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
462         Interface update;
463
464         NatFlowUpdateWorker(Interface update) {
465             this.update = update;
466         }
467
468         @Override
469         @SuppressWarnings("checkstyle:IllegalCatch")
470         public List<ListenableFuture<Void>> call() {
471             final List<ListenableFuture<Void>> futures = new ArrayList<>();
472             String interfaceName = update.getName();
473             if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
474                 LOG.debug("call : Port UP event received for interface {} ", interfaceName);
475             } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
476                 LOG.debug("call : Port DOWN event received for interface {} ", interfaceName);
477                 try {
478                     String routerName = getRouterIdForPort(interfaceName);
479                     if (routerName != null) {
480                         removeSnatEntriesForPort(interfaceName, routerName);
481                     } else {
482                         LOG.debug(
483                                 "call : PORT_DOWN: Router Id is null, either Interface {} is not associated "
484                                         + "to a router or failed to retrieve routerId due to exception", interfaceName);
485                     }
486                 } catch (Exception ex) {
487                     LOG.error("call : Exception caught in Interface {} OperationalStateDown", interfaceName, ex);
488                 }
489             }
490             return futures;
491         }
492     }
493 }