Merge "Bug 5267 - Setting vlan id for termination end point not working"
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / servicebindings / flowbased / confighelpers / FlowBasedServicesConfigUnbindHelper.java
index cc57ff0e24bfe263d28dbcc4834585ce2050fb6a..25b93c24f5b3228871983f665d0b4c2ce993e5c0 100644 (file)
@@ -7,7 +7,12 @@
  */
 package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers;
 
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
@@ -15,6 +20,7 @@ import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.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;
@@ -23,16 +29,11 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
 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;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class FlowBasedServicesConfigUnbindHelper {
     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigUnbindHelper.class);
@@ -40,10 +41,18 @@ public class FlowBasedServicesConfigUnbindHelper {
     public static List<ListenableFuture<Void>> unbindService(InstanceIdentifier<BoundServices> instanceIdentifier,
                                                              BoundServices boundServiceOld, DataBroker dataBroker) {
         List<ListenableFuture<Void>> futures = new ArrayList<>();
-        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-
         String interfaceName =
                 InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+
+        // Get the Parent ServiceInfo
+        ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
+        if (servicesInfo == null) {
+            LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+            return futures;
+        }
+
+        InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+        Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
         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) {
@@ -51,31 +60,81 @@ public class FlowBasedServicesConfigUnbindHelper {
                     ifState.getOperStatus(), interfaceName);
             return futures;
         }
+        List<BoundServices> boundServices = servicesInfo.getBoundServices();
 
-        // Get the Parent ServiceInfo
-        ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
-        if (servicesInfo == null) {
-            LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+        // Split based on type of interface....
+        if (iface.getType().isAssignableFrom(L2vlan.class)) {
+            return unbindServiceOnVlan(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+        } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+           return unbindServiceOnTunnel(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+        }
+        return futures;
+    }
+
+    private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+            BoundServices boundServiceOld,
+            List<BoundServices> boundServices, Interface iface, int ifIndex,
+            DataBroker dataBroker) {
+
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+        NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+        BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+        if (boundServices.isEmpty()) {
+            // Remove default entry from Lport Dispatcher Table.
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+            if (t != null) {
+                futures.add(t.submit());
+            }
             return futures;
         }
+        BoundServices[] highLow = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, boundServiceOld);
+        BoundServices low = highLow[0];
+        BoundServices high = highLow[1];
+        // This means the one removed was the highest priority service
+        if (high == null) {
+            LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, IfmConstants.DEFAULT_SERVICE_INDEX);
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+            if (low != null) {
+                //delete the lower services flow entry.
+                LOG.trace("Deleting table entry for lower service {}, match service index {}", low, low.getServicePriority());
+                FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), low, t, low.getServicePriority());
+                BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, low)[0];
+                short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+                LOG.trace("Installing new entry for lower service {}, match service index {}, update service index {}", low, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, low, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+            }
+        } else {
+            LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, boundServiceOld.getServicePriority());
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, boundServiceOld.getServicePriority());
+            short lowerServiceIndex = (short) ((low!=null) ? low.getServicePriority() : boundServiceOld.getServicePriority() + 1);
+            BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(boundServices);
+            if (high.equals(highest)) {
+                LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+            } else {
+                LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, high.getServicePriority(), lowerServiceIndex);
+                FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, high.getServicePriority(), lowerServiceIndex);
+            }
+        }
+        futures.add(t.submit());
+        return futures;
+    }
 
-        InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
-        Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+    private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+            BoundServices boundServiceOld,
+            List<BoundServices> boundServices, Interface iface, int ifIndex,
+            DataBroker dataBroker) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
         NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
         long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
         BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
 
-        int vlanId = 0;
-        if (iface.getType().isAssignableFrom(L2vlan.class)) {
-            IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
-            if(l2vlan != null) {
-                vlanId = iface.getAugmentation(IfL2vlan.class).getVlanId().getValue();
-            }
-        }
-        List<BoundServices> boundServices = servicesInfo.getBoundServices();
         if (boundServices.isEmpty()) {
             // Remove entry from Ingress Table.
-            FlowBasedServicesUtils.removeIngressFlow(iface, boundServiceOld, dpId, t);
+            FlowBasedServicesUtils.removeIngressFlow(iface.getName(), boundServiceOld, dpId, t);
             if (t != null) {
                 futures.add(t.submit());
             }
@@ -92,7 +151,7 @@ public class FlowBasedServicesConfigUnbindHelper {
         }
 
         if (highestPriority < boundServiceOld.getServicePriority()) {
-            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t);
+            FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, boundServiceOld.getServicePriority());
             if (t != null) {
                 futures.add(t.submit());
             }
@@ -100,21 +159,18 @@ public class FlowBasedServicesConfigUnbindHelper {
         }
 
         List<MatchInfo> matches = null;
-        if (iface.getType().isAssignableFrom(L2vlan.class)) {
-            matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, vlanId);
-        } else if (iface.getType().isAssignableFrom(Tunnel.class)){
-            matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
-        }
+        matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
 
         BoundServices toBeMoved = tmpServicesMap.get(highestPriority);
-        FlowBasedServicesUtils.removeIngressFlow(iface, boundServiceOld, dpId, t);
-        FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface.getName(), vlanId, toBeMoved, dataBroker, t,
-                matches, ifState.getIfIndex(), IfmConstants.VLAN_INTERFACE_INGRESS_TABLE);
-        FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, toBeMoved, t);
+        FlowBasedServicesUtils.removeIngressFlow(iface.getName(), boundServiceOld, dpId, t);
+        FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, toBeMoved, t,
+                matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+        FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), toBeMoved, t, toBeMoved.getServicePriority());
 
         if (t != null) {
             futures.add(t.submit());
         }
         return futures;
     }
+
 }
\ No newline at end of file