Switch to JDT annotations for Nullable and NonNull
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatSouthboundEventHandlers.java
1 /*
2  * Copyright (c) 2016 - 2018 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 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import com.google.common.base.Optional;
14 import com.google.common.collect.HashBasedTable;
15 import com.google.common.collect.Table;
16 import com.google.common.util.concurrent.FluentFuture;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import java.math.BigInteger;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.concurrent.Callable;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.Future;
26 import java.util.concurrent.locks.ReentrantLock;
27 import javax.inject.Inject;
28 import javax.inject.Singleton;
29 import org.eclipse.jdt.annotation.NonNull;
30 import org.eclipse.jdt.annotation.Nullable;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
34 import org.opendaylight.genius.infra.Datastore.Operational;
35 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
36 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
37 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
38 import org.opendaylight.genius.mdsalutil.FlowEntity;
39 import org.opendaylight.genius.mdsalutil.NwConstants;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
51 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;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.neutron.vip.states.VipState;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.opendaylight.yangtools.yang.common.RpcResult;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @Singleton
66 public class NatSouthboundEventHandlers {
67
68     private static final Logger LOG = LoggerFactory.getLogger(NatSouthboundEventHandlers.class);
69     private static final String NAT_DS = "NATDS";
70     private final DataBroker dataBroker;
71     private final ManagedNewTransactionRunner txRunner;
72     private final OdlInterfaceRpcService odlInterfaceRpcService;
73     private final JobCoordinator coordinator;
74     private final FloatingIPListener floatingIPListener;
75     private final NeutronvpnService neutronVpnService;
76     private final IMdsalApiManager mdsalManager;
77     private final NaptManager naptManager;
78     private final VipStateTracker vipStateTracker;
79     Table<Interface.OperStatus, Interface.OperStatus, IntfTransitionState> stateTable = HashBasedTable.create();
80
81     enum IntfTransitionState {
82         STATE_UP,
83         STATE_DOWN,
84         STATE_IGNORE
85     }
86
87     private void initialize() {
88         stateTable.put(Interface.OperStatus.Up, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
89         stateTable.put(Interface.OperStatus.Down, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
90         stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
91         stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
92         stateTable.put(Interface.OperStatus.Up, Interface.OperStatus.Unknown, IntfTransitionState.STATE_DOWN);
93     }
94
95     @Inject
96     public NatSouthboundEventHandlers(final DataBroker dataBroker,
97             final OdlInterfaceRpcService odlInterfaceRpcService, final JobCoordinator coordinator,
98             final FloatingIPListener floatingIPListener,final NeutronvpnService neutronvpnService,
99             final IMdsalApiManager mdsalManager, final NaptManager naptManager, final VipStateTracker vipStateTracker) {
100         this.dataBroker = dataBroker;
101         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
102         this.odlInterfaceRpcService = odlInterfaceRpcService;
103         this.coordinator = coordinator;
104         this.floatingIPListener = floatingIPListener;
105         this.neutronVpnService = neutronvpnService;
106         this.mdsalManager = mdsalManager;
107         this.naptManager = naptManager;
108         this.vipStateTracker = vipStateTracker;
109         initialize();
110     }
111
112     public void handleAdd(String interfaceName, BigInteger intfDpnId, RouterInterface routerInterface) {
113         handleAdd(interfaceName, intfDpnId, routerInterface, null);
114     }
115
116     public void handleAdd(String interfaceName, BigInteger intfDpnId,
117                           RouterInterface routerInterface, @Nullable VipState vipState) {
118         String routerName = routerInterface.getRouterName();
119         NatInterfaceStateAddWorker natIfaceStateAddWorker = new NatInterfaceStateAddWorker(interfaceName,
120                 intfDpnId, routerName);
121         coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natIfaceStateAddWorker);
122
123         NatFlowAddWorker natFlowAddWorker = new NatFlowAddWorker(interfaceName, routerName, intfDpnId, vipState);
124         coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natFlowAddWorker, NatConstants.NAT_DJC_MAX_RETRIES);
125     }
126
127     public void handleRemove(String interfaceName, BigInteger intfDpnId, RouterInterface routerInterface) {
128         String routerName = routerInterface.getRouterName();
129         NatInterfaceStateRemoveWorker natIfaceStateRemoveWorker = new NatInterfaceStateRemoveWorker(interfaceName,
130                 intfDpnId, routerName);
131         coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natIfaceStateRemoveWorker);
132
133         NatFlowRemoveWorker natFlowRemoveWorker = new NatFlowRemoveWorker(interfaceName, intfDpnId, routerName);
134         coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natFlowRemoveWorker,
135                 NatConstants.NAT_DJC_MAX_RETRIES);
136     }
137
138     public void handleUpdate(Interface original, Interface update,
139                              BigInteger intfDpnId, RouterInterface routerInterface) {
140         String routerName = routerInterface.getRouterName();
141         NatInterfaceStateUpdateWorker natIfaceStateupdateWorker = new NatInterfaceStateUpdateWorker(original,
142                 update, intfDpnId, routerName);
143         coordinator.enqueueJob(NAT_DS + "-" + update.getName(), natIfaceStateupdateWorker);
144         NatFlowUpdateWorker natFlowUpdateWorker = new NatFlowUpdateWorker(original, update, routerName);
145         coordinator.enqueueJob(NAT_DS + "-" + update.getName(), natFlowUpdateWorker,
146                 NatConstants.NAT_DJC_MAX_RETRIES);
147     }
148
149     void handleRouterInterfacesUpEvent(String routerName, String interfaceName, BigInteger dpId,
150             TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
151         LOG.debug("handleRouterInterfacesUpEvent : Handling UP event for router interface {} in Router {} on Dpn {}",
152                 interfaceName, routerName, dpId);
153         NatUtil.addToNeutronRouterDpnsMap(routerName, interfaceName, dpId, operTx);
154         NatUtil.addToDpnRoutersMap(routerName, interfaceName, dpId, operTx);
155     }
156
157     void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId,
158                                          TypedReadWriteTransaction<Operational> operTx)
159         throws ExecutionException, InterruptedException {
160         LOG.debug("handleRouterInterfacesDownEvent : Handling DOWN event for router Interface {} in Router {}",
161                 interfaceName, routerName);
162         NatUtil.removeFromNeutronRouterDpnsMap(routerName, dpnId, operTx);
163         NatUtil.removeFromDpnRoutersMap(dataBroker, routerName, interfaceName, dpnId, odlInterfaceRpcService,
164                 operTx);
165     }
166
167     private IntfTransitionState getTransitionState(Interface.OperStatus original , Interface.OperStatus updated) {
168         IntfTransitionState transitionState = stateTable.get(original, updated);
169
170         if (transitionState == null) {
171             return IntfTransitionState.STATE_IGNORE;
172         }
173         return transitionState;
174     }
175
176     private class NatInterfaceStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
177         private final String interfaceName;
178         private final String routerName;
179         private final BigInteger intfDpnId;
180
181         NatInterfaceStateAddWorker(String interfaceName, BigInteger intfDpnId, String routerName) {
182             this.interfaceName = interfaceName;
183             this.routerName = routerName;
184             this.intfDpnId = intfDpnId;
185         }
186
187         @Override
188         @SuppressWarnings("checkstyle:IllegalCatch")
189         public List<ListenableFuture<Void>> call() {
190             LOG.trace("call : Received interface {} PORT UP OR ADD event ", interfaceName);
191             List<ListenableFuture<Void>> futures = new ArrayList<>();
192             final ReentrantLock lock = NatUtil.lockForNat(intfDpnId);
193             lock.lock();
194             try {
195                 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx ->
196                     handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, tx)));
197             } catch (Exception e) {
198                 LOG.error("call : Exception caught in Interface {} Operational State Up event",
199                     interfaceName, e);
200             } finally {
201                 lock.unlock();
202             }
203             return futures;
204         }
205     }
206
207     private class NatInterfaceStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
208         private final String interfaceName;
209         private final String routerName;
210         private final BigInteger intfDpnId;
211
212         NatInterfaceStateRemoveWorker(String interfaceName, BigInteger intfDpnId, String routerName) {
213             this.interfaceName = interfaceName;
214             this.routerName = routerName;
215             this.intfDpnId = intfDpnId;
216         }
217
218         @Override
219         @SuppressWarnings("checkstyle:IllegalCatch")
220         public List<ListenableFuture<Void>> call() {
221             LOG.trace("call : Received interface {} PORT DOWN or REMOVE event", interfaceName);
222             List<ListenableFuture<Void>> futures = new ArrayList<>();
223             final ReentrantLock lock = NatUtil.lockForNat(intfDpnId);
224             lock.lock();
225             try {
226                 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx ->
227                     handleRouterInterfacesDownEvent(routerName, interfaceName, intfDpnId, tx)));
228             } catch (Exception e) {
229                 LOG.error("call : Exception observed in handling deletion of VPN Interface {}.", interfaceName, e);
230             } finally {
231                 lock.unlock();
232             }
233             return futures;
234         }
235     }
236
237     private class NatInterfaceStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
238         private final Interface original;
239         private final Interface update;
240         private final BigInteger intfDpnId;
241         private final String routerName;
242
243         NatInterfaceStateUpdateWorker(Interface original, Interface update, BigInteger intfDpnId, String routerName) {
244             this.original = original;
245             this.update = update;
246             this.intfDpnId = intfDpnId;
247             this.routerName = routerName;
248         }
249
250         @Override
251         @SuppressWarnings("checkstyle:IllegalCatch")
252         public List<ListenableFuture<Void>> call() {
253             final String interfaceName = update.getName();
254             LOG.trace("call : Received interface {} state change event", interfaceName);
255             LOG.debug("call : DPN ID {} for the interface {} ", intfDpnId, interfaceName);
256
257             List<ListenableFuture<Void>> futures = new ArrayList<>();
258             final ReentrantLock lock = NatUtil.lockForNat(intfDpnId);
259             lock.lock();
260             try {
261                 IntfTransitionState state = getTransitionState(original.getOperStatus(), update.getOperStatus());
262                 if (state.equals(IntfTransitionState.STATE_IGNORE)) {
263                     LOG.info("NAT Service: Interface {} state original {} updated {} not handled",
264                         interfaceName, original.getOperStatus(), update.getOperStatus());
265                     return futures;
266                 }
267                 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> {
268                     if (state.equals(IntfTransitionState.STATE_DOWN)) {
269                         LOG.debug("call : DPN {} connnected to the interface {} has gone down."
270                                 + "Hence clearing the dpn-vpninterfaces-list entry from the"
271                                 + " neutron-router-dpns model in the ODL:L3VPN", intfDpnId, interfaceName);
272                         // If the interface state is unknown, it means that the corresponding DPN has gone down.
273                         // So remove the dpn-vpninterfaces-list from the neutron-router-dpns model.
274                         NatUtil.removeFromNeutronRouterDpnsMap(routerName, interfaceName,
275                             intfDpnId, tx);
276                     } else if (state.equals(IntfTransitionState.STATE_UP)) {
277                         LOG.debug("call : DPN {} connnected to the interface {} has come up. Hence adding"
278                                 + " the dpn-vpninterfaces-list entry from the neutron-router-dpns model"
279                                 + " in the ODL:L3VPN", intfDpnId, interfaceName);
280                         handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, tx);
281                     }
282                 }));
283             } catch (Exception e) {
284                 LOG.error("call : Exception observed in handling updation of VPN Interface {}.", update.getName(), e);
285             } finally {
286                 lock.unlock();
287             }
288             return futures;
289         }
290     }
291
292     private void processInterfaceAdded(String portName, String routerId, BigInteger dpnId, VipState vipState) {
293         LOG.trace("processInterfaceAdded : Processing Interface Add Event for interface {}", portName);
294         List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
295         if (intExtPortMapList.isEmpty()) {
296             LOG.debug("processInterfaceAdded : Ip Mapping list is empty/null for portname {}", portName);
297             return;
298         }
299         InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
300         FluentFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
301             for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
302                 floatingIPListener.createNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, tx);
303             }
304         });
305         future.transform((ignored) -> {
306             if (vipState != null) {
307                 return this.vipStateTracker.writeVipState(vipState);
308             }
309             return null;
310         }, MoreExecutors.directExecutor());
311     }
312
313     @NonNull
314     private List<InternalToExternalPortMap> getIntExtPortMapListForPortName(String portName, String routerId) {
315         InstanceIdentifier<Ports> portToIpMapIdentifier = NatUtil.buildPortToIpMapIdentifier(routerId, portName);
316         Optional<Ports> port =
317                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
318                         LogicalDatastoreType.CONFIGURATION, portToIpMapIdentifier);
319         if (!port.isPresent()) {
320             LOG.info("getIntExtPortMapListForPortName : Unable to read router port entry for router ID {} "
321                     + "and port name {}", routerId, portName);
322             return Collections.emptyList();
323         }
324         return port.get().nonnullInternalToExternalPortMap();
325     }
326
327     @Nullable
328     private BigInteger getNaptSwitchforRouter(DataBroker broker, String routerName) {
329         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
330             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
331         Optional<RouterToNaptSwitch> routerToNaptSwitchData =
332                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
333                         LogicalDatastoreType.CONFIGURATION, rtrNaptSw);
334         if (routerToNaptSwitchData.isPresent()) {
335             RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
336             return routerToNaptSwitchInstance.getPrimarySwitchId();
337         }
338         return null;
339     }
340
341     private void removeNatFlow(BigInteger dpnId, short tableId, Long routerId, String ipAddress, int ipPort) {
342
343         String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), ipAddress, ipPort);
344         FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
345
346         mdsalManager.removeFlow(snatFlowEntity);
347         LOG.debug("removeNatFlow : Removed the flow in table {} for the switch with the DPN ID {} for "
348             + "router {} ip {} port {}", tableId, dpnId, routerId, ipAddress, ipPort);
349     }
350
351     @Nullable
352     private List<String> getFixedIpsForPort(String interfname) {
353         LOG.debug("getFixedIpsForPort : getFixedIpsForPort method is called for interface {}", interfname);
354         try {
355             Future<RpcResult<GetFixedIPsForNeutronPortOutput>> result =
356                 neutronVpnService.getFixedIPsForNeutronPort(new GetFixedIPsForNeutronPortInputBuilder()
357                     .setPortId(new Uuid(interfname)).build());
358
359             RpcResult<GetFixedIPsForNeutronPortOutput> rpcResult = result.get();
360             if (!rpcResult.isSuccessful()) {
361                 LOG.error("getFixedIpsForPort : RPC Call to GetFixedIPsForNeutronPortOutput returned with Errors {}",
362                     rpcResult.getErrors());
363             } else {
364                 return rpcResult.getResult().getFixedIPs();
365             }
366         } catch (InterruptedException | ExecutionException | NullPointerException ex) {
367             LOG.error("getFixedIpsForPort : Exception while receiving fixedIps for port {}", interfname, ex);
368         }
369         return null;
370     }
371
372     private void processInterfaceRemoved(String portName, BigInteger dpnId, String routerId,
373             List<ListenableFuture<Void>> futures) {
374         LOG.trace("processInterfaceRemoved : Processing Interface Removed Event for interface {} on DPN ID {}",
375                 portName, dpnId);
376         List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
377         if (intExtPortMapList.isEmpty()) {
378             LOG.debug("processInterfaceRemoved : Ip Mapping list is empty/null for portName {}", portName);
379             return;
380         }
381         InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
382         ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
383             for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
384                 LOG.trace("processInterfaceRemoved : Removing DNAT Flow entries for dpnId {} ", dpnId);
385                 floatingIPListener.removeNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, tx);
386             }
387         });
388         futures.add(future);
389         try {
390             future.get();
391         } catch (InterruptedException | ExecutionException e) {
392             LOG.error("Error processing interface removal", e);
393         }
394     }
395
396     // TODO Clean up the exception handling
397     @SuppressWarnings("checkstyle:IllegalCatch")
398     private void removeSnatEntriesForPort(String interfaceName, String routerName) {
399         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
400         if (routerId == NatConstants.INVALID_ID) {
401             LOG.error("removeSnatEntriesForPort : routerId not found for routername {}", routerName);
402             return;
403         }
404         BigInteger naptSwitch = getNaptSwitchforRouter(dataBroker, routerName);
405         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
406             LOG.error("removeSnatEntriesForPort : NaptSwitch is not elected for router {} with Id {}",
407                     routerName, routerId);
408             return;
409         }
410         //getInternalIp for port
411         List<String> fixedIps = getFixedIpsForPort(interfaceName);
412         if (fixedIps == null) {
413             LOG.warn("removeSnatEntriesForPort : Internal Ips not found for InterfaceName {} in router {} with id {}",
414                 interfaceName, routerName, routerId);
415             return;
416         }
417
418         for (String internalIp : fixedIps) {
419             LOG.debug("removeSnatEntriesForPort : Internal Ip retrieved for interface {} is {} in router with Id {}",
420                 interfaceName, internalIp, routerId);
421             IpPort ipPort = NatUtil.getInternalIpPortInfo(dataBroker, routerId, internalIp);
422             if (ipPort == null) {
423                 LOG.debug("removeSnatEntriesForPort : no snatint-ip-port-map found for ip:{}", internalIp);
424                 continue;
425             }
426
427             for (IntIpProtoType protoType : ipPort.nonnullIntIpProtoType()) {
428                 ProtocolTypes protocol = protoType.getProtocol();
429                 @Nullable List<Integer> ports = protoType.getPorts();
430                 for (Integer portnum : (ports != null ? ports : Collections.<Integer>emptyList())) {
431                     //build and remove the flow in outbound table
432                     try {
433                         removeNatFlow(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, portnum);
434                     } catch (Exception ex) {
435                         LOG.error("removeSnatEntriesForPort : Failed to remove snat flow for internalIP {} with "
436                                 + "Port {} protocol {} for routerId {} in OUTBOUNDTABLE of NaptSwitch {}",
437                             internalIp, portnum, protocol, routerId, naptSwitch, ex);
438                     }
439                     //Get the external IP address and the port from the model
440                     NAPTEntryEvent.Protocol proto = protocol.toString().equals(ProtocolTypes.TCP.toString())
441                         ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
442                     IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
443                         internalIp, String.valueOf(portnum), proto);
444                     if (ipPortExternal == null) {
445                         LOG.error("removeSnatEntriesForPort : Mapping for internalIp {} with port {} is not found in "
446                             + "router with Id {}", internalIp, portnum, routerId);
447                         return;
448                     }
449                     String externalIpAddress = ipPortExternal.getIpAddress();
450                     Integer portNumber = ipPortExternal.getPortNum();
451
452                     //build and remove the flow in inboundtable
453                     try {
454                         removeNatFlow(naptSwitch, NwConstants.INBOUND_NAPT_TABLE, routerId,
455                             externalIpAddress, portNumber);
456                     } catch (Exception ex) {
457                         LOG.error("removeSnatEntriesForPort : Failed to remove snat flow internalIP {} with "
458                                 + "Port {} protocol {} for routerId {} in INBOUNDTABLE of naptSwitch {}",
459                             externalIpAddress, portNumber, protocol, routerId, naptSwitch, ex);
460                     }
461
462                     String internalIpPort = internalIp + ":" + portnum;
463                     // delete the entry from IntExtIpPortMap DS
464                     try {
465                         naptManager.removeFromIpPortMapDS(routerId, internalIpPort, proto);
466                         naptManager.removePortFromPool(internalIpPort, externalIpAddress);
467                     } catch (Exception ex) {
468                         LOG.error("removeSnatEntriesForPort : releaseIpExtPortMapping failed, Removal of "
469                             + "ipportmap {} for router {} failed", internalIpPort, routerId, ex);
470                     }
471                 }
472             }
473             // delete the entry from SnatIntIpPortMap DS
474             LOG.debug("removeSnatEntriesForPort : Removing InternalIp:{} on router {}", internalIp, routerId);
475             naptManager.removeFromSnatIpPortDS(routerId, internalIp);
476         }
477     }
478
479     private class NatFlowAddWorker implements Callable<List<ListenableFuture<Void>>> {
480         private final String interfaceName;
481         private final String routerName;
482         private final BigInteger dpnId;
483         private final VipState vipState;
484
485         NatFlowAddWorker(String interfaceName,String routerName, BigInteger dpnId, VipState vipState) {
486             this.interfaceName = interfaceName;
487             this.routerName = routerName;
488             this.dpnId = dpnId;
489             this.vipState = vipState;
490         }
491
492         @Override
493         @SuppressWarnings("checkstyle:IllegalCatch")
494         public List<ListenableFuture<Void>> call() {
495             final List<ListenableFuture<Void>> futures = new ArrayList<>();
496             LOG.trace("call : Interface {} up event received", interfaceName);
497             try {
498                 LOG.trace("call : Port added event received for interface {} ", interfaceName);
499                 processInterfaceAdded(interfaceName, routerName, dpnId, vipState);
500             } catch (Exception ex) {
501                 LOG.error("call : Exception caught in Interface {} Operational State Up event",
502                         interfaceName, ex);
503             }
504             return futures;
505         }
506     }
507
508     private class NatFlowUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
509         private final Interface original;
510         private final Interface update;
511         private final String routerName;
512
513         NatFlowUpdateWorker(Interface original, Interface update, String routerName) {
514             this.original = original;
515             this.update = update;
516             this.routerName = routerName;
517         }
518
519         @Override
520         @SuppressWarnings("checkstyle:IllegalCatch")
521         public List<ListenableFuture<Void>> call() {
522             final List<ListenableFuture<Void>> futures = new ArrayList<>();
523             String interfaceName = update.getName();
524             IntfTransitionState state = getTransitionState(original.getOperStatus(), update.getOperStatus());
525             if (state.equals(IntfTransitionState.STATE_IGNORE)) {
526                 LOG.info("NAT Service: Interface {} state original {} updated {} not handled",
527                         interfaceName, original.getOperStatus(), update.getOperStatus());
528                 return futures;
529             }
530             if (state.equals(IntfTransitionState.STATE_UP)) {
531                 LOG.debug("call : Port UP event received for interface {} ", interfaceName);
532             } else if (state.equals(IntfTransitionState.STATE_DOWN)) {
533                 LOG.debug("call : Port DOWN event received for interface {} ", interfaceName);
534                 try {
535                     removeSnatEntriesForPort(interfaceName, routerName);
536                 } catch (Exception ex) {
537                     LOG.error("call : Exception caught in Interface {} OperationalStateDown", interfaceName, ex);
538                 }
539             }
540             return futures;
541         }
542     }
543
544     private class NatFlowRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
545         private final String interfaceName;
546         private final String routerName;
547         private final BigInteger intfDpnId;
548
549         NatFlowRemoveWorker(String interfaceName, BigInteger intfDpnId, String routerName) {
550             this.interfaceName = interfaceName;
551             this.routerName = routerName;
552             this.intfDpnId = intfDpnId;
553         }
554
555         @Override
556         @SuppressWarnings("checkstyle:IllegalCatch")
557         public List<ListenableFuture<Void>> call() {
558             final List<ListenableFuture<Void>> futures = new ArrayList<>();
559             LOG.trace("call : Interface {} removed event received", interfaceName);
560             try {
561                 LOG.trace("call : Port removed event received for interface {} ", interfaceName);
562                 processInterfaceRemoved(interfaceName, intfDpnId, routerName, futures);
563                 removeSnatEntriesForPort(interfaceName, routerName);
564             } catch (Exception e) {
565                 LOG.error("call : Exception caught in Interface {} OperationalStateRemove", interfaceName, e);
566             }
567             return futures;
568         }
569     }
570 }