Bug 7451 - Leftovers in dispatcher table when unbind and ietf-state
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / servicebindings / flowbased / config / helpers / FlowBasedEgressServicesConfigUnbindHelper.java
index c716bab97b8e851d6c1269b9f43543b2edc9ef23..57d2925a8fa2a78e3b23cb03c35ae1e3b683797e 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.genius.interfacemanager.servicebindings.flowbased.config.helpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.genius.interfacemanager.IfmConstants;
 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.config.factory.FlowBasedServicesConfigRemovable;
@@ -19,22 +21,14 @@ import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-
 public class FlowBasedEgressServicesConfigUnbindHelper implements FlowBasedServicesConfigRemovable {
     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedEgressServicesConfigUnbindHelper.class);
 
-    private InterfacemgrProvider interfaceMgrProvider;
+    private final InterfacemgrProvider interfaceMgrProvider;
     private static volatile FlowBasedServicesConfigRemovable flowBasedEgressServicesRemovable;
 
     private FlowBasedEgressServicesConfigUnbindHelper(InterfacemgrProvider interfaceMgrProvider) {
@@ -45,7 +39,8 @@ public class FlowBasedEgressServicesConfigUnbindHelper implements FlowBasedServi
         if (flowBasedEgressServicesRemovable == null) {
             synchronized (FlowBasedEgressServicesConfigUnbindHelper.class) {
                 if (flowBasedEgressServicesRemovable == null) {
-                    flowBasedEgressServicesRemovable = new FlowBasedEgressServicesConfigUnbindHelper(interfaceMgrProvider);
+                    flowBasedEgressServicesRemovable = new FlowBasedEgressServicesConfigUnbindHelper(
+                            interfaceMgrProvider);
                 }
             }
         }
@@ -58,52 +53,42 @@ public class FlowBasedEgressServicesConfigUnbindHelper implements FlowBasedServi
         return flowBasedEgressServicesRemovable;
     }
 
-    public List<ListenableFuture<Void>> unbindService(InstanceIdentifier<BoundServices> instanceIdentifier,
-                                                             BoundServices boundServiceOld) {
+    @Override
+    public List<ListenableFuture<Void>> unbindService(String interfaceName, BoundServices boundServiceOld,
+                                                      List<BoundServices> boundServices) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
         DataBroker dataBroker = interfaceMgrProvider.getDataBroker();
-        String interfaceName =
-                InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
-        Class<? extends ServiceModeBase> serviceMode = InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getServiceMode();
 
-        // Get the Parent ServiceInfo
-        ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, serviceMode, dataBroker);
-        if (servicesInfo == null) {
-            LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
+            ifState = InterfaceManagerCommonUtils.getInterfaceState(interfaceName, dataBroker);
+        if (ifState == null) {
+            LOG.info("Interface not operational, not unbinding Service for Interface: {}", interfaceName);
             return futures;
         }
 
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
-                InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
-        if (ifState == null || ifState.getOperStatus() == OperStatus.Down) {
-            LOG.info("Not unbinding Service since operstatus is DOWN for Interface: {}", interfaceName);
-            return futures;
-        }
-        List<BoundServices> boundServices = servicesInfo.getBoundServices();
-
-        // Split based on type of interface....
-        if (ifState.getType().isAssignableFrom(L2vlan.class)) {
-            return unbindServiceOnVlan(boundServiceOld, boundServices, ifState, dataBroker);
-        } else if (ifState.getType().isAssignableFrom(Tunnel.class)) {
-            return unbindServiceOnTunnel(boundServiceOld, boundServices, ifState, dataBroker);
+        if (L2vlan.class.equals(ifState.getType())
+            || Tunnel.class.equals(ifState.getType())) {
+            unbindService(boundServiceOld, boundServices, ifState, dataBroker);
         }
         return futures;
     }
 
-    private static List<ListenableFuture<Void>> unbindServiceOnVlan(
-            BoundServices boundServiceOld,
-            List<BoundServices> boundServices, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifaceState,
-            DataBroker dataBroker) {
-
+    private static List<ListenableFuture<Void>> unbindService(BoundServices boundServiceOld,
+            List<BoundServices> boundServices,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
+            .Interface ifaceState, DataBroker dataBroker) {
+        LOG.info("unbinding egress service {} for interface: {}", boundServiceOld.getServiceName(), ifaceState
+            .getName());
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
         Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(ifaceState.getName(), dataBroker);
         BigInteger dpId = FlowBasedServicesUtils.getDpnIdFromInterface(ifaceState);
         if (boundServices.isEmpty()) {
             // Remove default entry from Lport Dispatcher Table.
-            FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), boundServiceOld, t, NwConstants.DEFAULT_SERVICE_INDEX);
-            if (t != null) {
-                futures.add(t.submit());
+            FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), boundServiceOld, tx,
+                    NwConstants.DEFAULT_SERVICE_INDEX);
+            if (tx != null) {
+                futures.add(tx.submit());
             }
             return futures;
         }
@@ -112,35 +97,57 @@ public class FlowBasedEgressServicesConfigUnbindHelper implements FlowBasedServi
         BoundServices high = highLow[1];
         // This means the one removed was the highest priority service
         if (high == null) {
-            FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), boundServiceOld, t, NwConstants.DEFAULT_SERVICE_INDEX);
+            LOG.trace("Deleting egress dispatcher table entry for service {}, match service index {}", boundServiceOld,
+                NwConstants.DEFAULT_SERVICE_INDEX);
+            FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), boundServiceOld, tx,
+                    NwConstants.DEFAULT_SERVICE_INDEX);
             if (low != null) {
                 //delete the lower services flow entry.
-                FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), low, t, low.getServicePriority());
+                LOG.trace("Deleting egress dispatcher table entry for lower service {}, match service index {}", low,
+                    low.getServicePriority());
+                FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), low, tx,
+                        low.getServicePriority());
                 BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, low)[0];
-                short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
-                FlowBasedServicesUtils.installEgressDispatcherFlows(dpId, low, ifaceState.getName(), t, ifaceState.getIfIndex(), NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex, iface);
+                short lowerServiceIndex = (short) (lower != null ? lower.getServicePriority()
+                        : low.getServicePriority() + 1);
+                LOG.trace(
+                        "Installing new egress dispatcher table entry for lower service {}, match service index {},"
+                                + " update service index {}",
+                        low, NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+                FlowBasedServicesUtils.installEgressDispatcherFlows(dpId, low, ifaceState.getName(), tx,
+                        ifaceState.getIfIndex(), NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex, iface);
             }
         } else {
-            FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), boundServiceOld, t, boundServiceOld.getServicePriority());
-            short lowerServiceIndex = (short) ((low!=null) ? low.getServicePriority() : boundServiceOld.getServicePriority() + 1);
+            LOG.trace("Deleting egress dispatcher table entry for service {}, match service index {}", boundServiceOld,
+                boundServiceOld.getServicePriority());
+            FlowBasedServicesUtils.removeEgressDispatcherFlows(dpId, ifaceState.getName(), boundServiceOld, tx,
+                    boundServiceOld.getServicePriority());
+            short lowerServiceIndex = (short) (low != null ? low.getServicePriority()
+                    : boundServiceOld.getServicePriority() + 1);
             BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(boundServices);
             if (high.equals(highest)) {
-                FlowBasedServicesUtils.installEgressDispatcherFlows(dpId, high, ifaceState.getName(),t, ifaceState.getIfIndex(), NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex, iface);
+                LOG.trace("Update the existing higher service {}, match service index {}, update service index {}",
+                    high, NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+                FlowBasedServicesUtils.installEgressDispatcherFlows(dpId, high, ifaceState.getName(), tx,
+                        ifaceState.getIfIndex(), NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex, iface);
             } else {
-                FlowBasedServicesUtils.installEgressDispatcherFlows(dpId, high, ifaceState.getName(),t, ifaceState.getIfIndex(), high.getServicePriority(), lowerServiceIndex, iface);
+                LOG.trace("Update the existing higher service {}, match service index {}, update service index {}",
+                    high, high.getServicePriority(), lowerServiceIndex);
+                FlowBasedServicesUtils.installEgressDispatcherFlows(dpId, high, ifaceState.getName(), tx,
+                        ifaceState.getIfIndex(), high.getServicePriority(), lowerServiceIndex, iface);
             }
         }
-        futures.add(t.submit());
+        futures.add(tx.submit());
         return futures;
     }
 
-    private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
-            BoundServices boundServiceOld,
-            List<BoundServices> boundServices, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState,
-            DataBroker dataBroker) {
+    private static List<ListenableFuture<Void>> unbindServiceOnTunnel(BoundServices boundServiceOld,
+            List<BoundServices> boundServices,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
+            .Interface ifState, DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
 
         // FIXME : not yet supported
         return futures;
     }
-}
\ No newline at end of file
+}