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