stale entry in flow rules, after deleting port associated to qos policy with dscp 99/54599/9
authorNaveen Kumar Verma <naveen.kumar.verma@ericsson.com>
Mon, 10 Apr 2017 13:30:22 +0000 (19:00 +0530)
committerSam Hague <shague@redhat.com>
Fri, 28 Apr 2017 14:00:17 +0000 (14:00 +0000)
When we are delete the VM which has an associated qos policy with it,
the stale entry of DSCP marking use to persist for the table number 90.

The reason for this was that when QosNeutronPortChangeListner is called
rpc called to fetch DPN id use to fail. By moving the code to
QosInterfaceStateChangeLister we can use Interface to find out DPN id.

Change-Id: I485d84806eae2bcc8341518f8186973efb171658
Signed-off-by: Naveen Kumar Verma <naveen.kumar.verma@ericsson.com>
vpnservice/qosservice/impl/src/main/java/org/opendaylight/netvirt/qosservice/QosInterfaceStateChangeListener.java
vpnservice/qosservice/impl/src/main/java/org/opendaylight/netvirt/qosservice/QosNeutronPortChangeListener.java
vpnservice/qosservice/impl/src/main/java/org/opendaylight/netvirt/qosservice/QosNeutronUtils.java

index d8fde9eb8f81271cd7a05722a4bdaab43edbc336..aed211a47323cc7d7efa5a81d4e375f3d6750173 100644 (file)
@@ -34,7 +34,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 @Singleton
 public class QosInterfaceStateChangeListener extends AsyncDataTreeChangeListenerBase<Interface,
         QosInterfaceStateChangeListener> implements
@@ -121,13 +120,47 @@ public class QosInterfaceStateChangeListener extends AsyncDataTreeChangeListener
                 .transform(uuid -> neutronVpnManager.getNeutronPort(uuid));
     }
 
+    private Optional<Port> getNeutronPortForRemove(Interface intrf) {
+        final String portName = intrf.getName();
+        Optional<Uuid> uuid = uuidUtil.newUuidIfValidPattern(portName);
+        if (uuid.isPresent()) {
+            Port port = neutronVpnManager.getNeutronPort(portName);
+            if (port != null) {
+                return uuid.transform(uuid1 -> neutronVpnManager.getNeutronPort(uuid1));
+            }
+            LOG.trace("Qos Service : interface {} clearing stale flow entries if any", portName);
+            QosNeutronUtils.removeStaleFlowEntry(dataBroker,mdsalUtils,odlInterfaceRpcService,intrf);
+        }
+        return Optional.absent();
+    }
+
     @Override
     protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
         if (!Tunnel.class.equals(intrf.getType())) {
-            LOG.trace("Qos Service : Received interface {} PORT DOWN event ", intrf.getName());
-            String lowerLayerIf = intrf.getLowerLayerIf().get(0);
-            LOG.trace("lowerLayerIf {}", lowerLayerIf);
-            QosAlertManager.removeFromQosAlertCache(new NodeConnectorId(lowerLayerIf));
+            final String interfaceName = intrf.getName();
+            // Guava Optional asSet().forEach() emulates Java 8 Optional ifPresent()
+            getNeutronPortForRemove(intrf).asSet().forEach(port -> {
+                LOG.trace("Qos Service : Received interface {} PORT DOWN event ", interfaceName);
+
+                String lowerLayerIf = intrf.getLowerLayerIf().get(0);
+                LOG.trace("lowerLayerIf {}", lowerLayerIf);
+                QosAlertManager.removeFromQosAlertCache(new NodeConnectorId(lowerLayerIf));
+                QosPortExtension removeQos = port.getAugmentation(QosPortExtension.class);
+                if (removeQos != null) {
+                    QosNeutronUtils.handleNeutronPortRemove(dataBroker, odlInterfaceRpcService,
+                            mdsalUtils, port, removeQos.getQosPolicyId(), intrf);
+                    QosNeutronUtils.removeFromQosPortsCache(removeQos.getQosPolicyId(), port);
+                } else {
+                    Network network = neutronVpnManager.getNeutronNetwork(port.getNetworkId());
+                    if (network != null && network.getAugmentation(QosNetworkExtension.class) != null) {
+                        Uuid networkQosUuid = network.getAugmentation(QosNetworkExtension.class).getQosPolicyId();
+                        if (networkQosUuid != null) {
+                            QosNeutronUtils.handleNeutronPortRemove(dataBroker, odlInterfaceRpcService,
+                                    mdsalUtils, port, networkQosUuid, intrf);
+                        }
+                    }
+                }
+            });
         }
     }
 
index 2156e677e5c06fbe9509f2dc84550cc3a90c0796..7464a493c00b435dd62f1450677138d4ad970980 100644 (file)
@@ -16,12 +16,9 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosNetworkExtension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosPortExtension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -79,23 +76,6 @@ public class QosNeutronPortChangeListener extends AsyncDataTreeChangeListenerBas
         if (QosNeutronUtils.hasBandwidthLimitRule(neutronVpnManager, port)) {
             QosAlertManager.removeFromQosAlertCache(port);
         }
-        //Remove DSCP Flow when the port is removed
-        //Qos Policy Deletion
-        QosPortExtension removeQos = port.getAugmentation(QosPortExtension.class);
-        if (removeQos != null) {
-            QosNeutronUtils.handleNeutronPortRemove(dataBroker, odlInterfaceRpcService,
-                    mdsalUtils, port, removeQos.getQosPolicyId());
-            QosNeutronUtils.removeFromQosPortsCache(removeQos.getQosPolicyId(), port);
-        } else {
-            Network network =  neutronVpnManager.getNeutronNetwork(port.getNetworkId());
-            if (network != null && network.getAugmentation(QosNetworkExtension.class) != null) {
-                Uuid networkQosUuid = network.getAugmentation(QosNetworkExtension.class).getQosPolicyId();
-                if (networkQosUuid != null) {
-                    QosNeutronUtils.handleNeutronPortRemove(dataBroker, odlInterfaceRpcService,
-                            mdsalUtils, port, networkQosUuid);
-                }
-            }
-        }
     }
 
     @Override
index e61c66e5ba2f671456c48464bef191288c3fabbd..c190dbe28333bf8f4776ffe1f4355a712e90948d 100644 (file)
@@ -66,6 +66,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.ser
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
@@ -96,6 +97,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 public class QosNeutronUtils {
     private static final Logger LOG = LoggerFactory.getLogger(QosNeutronUtils.class);
     private static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
@@ -290,6 +292,25 @@ public class QosNeutronUtils {
         });
     }
 
+    public static void handleNeutronPortRemove(DataBroker db, OdlInterfaceRpcService odlInterfaceRpcService,
+                                               IMdsalApiManager mdsalUtils, Port port, Uuid qosUuid, Interface intrf) {
+        LOG.trace("Handling Port removal and Qos associated: port: {} qos: {}", port.getUuid(), qosUuid);
+        QosPolicy qosPolicy = QosNeutronUtils.qosPolicyMap.get(qosUuid);
+
+        final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+        portDataStoreCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
+            WriteTransaction wrtConfigTxn = db.newWriteOnlyTransaction();
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            if (qosPolicy != null && qosPolicy.getDscpmarkingRules() != null
+                    && !qosPolicy.getDscpmarkingRules().isEmpty()) {
+                unsetPortDscpMark(db, odlInterfaceRpcService, mdsalUtils, port, intrf);
+            }
+            futures.add(wrtConfigTxn.submit());
+            return futures;
+        });
+    }
+
+
     public static void handleNeutronNetworkQosUpdate(DataBroker db, OdlInterfaceRpcService odlInterfaceRpcService,
                                                      INeutronVpnManager neutronVpnManager,
                                                      IMdsalApiManager mdsalUtils,
@@ -534,6 +555,29 @@ public class QosNeutronUtils {
         qosServiceConfiguredPorts.remove(port.getUuid());
     }
 
+    public static void unsetPortDscpMark(DataBroker dataBroker, OdlInterfaceRpcService odlInterfaceRpcService,
+                                         IMdsalApiManager mdsalUtils, Port port, Interface intrf) {
+        LOG.trace("Removing dscp marking rule from Port {}", port);
+
+        BigInteger dpnId = getDpIdFromInterface(intrf);
+        String ifName = port.getUuid().getValue();
+
+        if (dpnId.equals(BigInteger.ZERO)) {
+            LOG.error("Unable to retrieve DPN Id for interface {}", ifName);
+            return;
+        }
+        IpAddress ipAddress = port.getFixedIps().get(0).getIpAddress();
+        unbindservice(dataBroker, ifName);
+        syncFlow(dataBroker, dpnId, NwConstants.DEL_FLOW, mdsalUtils, (short) 0, ifName, ipAddress, intrf);
+    }
+
+    private static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
+                                                           .interfaces.rev140508.interfaces.state.Interface ifState) {
+        String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+        NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+        return BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+    }
+
     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
         BigInteger nodeId = BigInteger.ZERO;
         try {
@@ -612,14 +656,35 @@ public class QosNeutronUtils {
         return bridgeEntryIdBuilder.build();
     }
 
+    public  static  void removeStaleFlowEntry(DataBroker db, IMdsalApiManager mdsalUtils,
+                                                OdlInterfaceRpcService odlInterfaceRpcService, Interface intrf) {
+        List<MatchInfo> matches = new ArrayList<>();
+
+        BigInteger dpnId = getDpIdFromInterface(intrf);
+
+        Integer ifIndex = intrf.getIfIndex();
+        matches.add(new MatchMetadata(MetaDataUtil.getLportTagMetaData(ifIndex), MetaDataUtil.METADATA_MASK_LPORT_TAG));
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.QOS_DSCP_TABLE,
+                getQosFlowId(NwConstants.QOS_DSCP_TABLE, dpnId, ifIndex),
+                QosConstants.QOS_DEFAULT_FLOW_PRIORITY, "QoSRemoveFlow", 0, 0, NwConstants.COOKIE_QOS_TABLE,
+                matches, null);
+        mdsalUtils.removeFlow(flowEntity);
+    }
+
     private static void syncFlow(DataBroker db, BigInteger dpnId, int addOrRemove,
                                  IMdsalApiManager mdsalUtils, Short dscpValue,
                                  String ifName, IpAddress ipAddress) {
+        Interface ifState = getInterfaceStateFromOperDS(ifName, db);
+        syncFlow(db, dpnId, addOrRemove, mdsalUtils, dscpValue, ifName, ipAddress, ifState);
+    }
+
+    private static void syncFlow(DataBroker db, BigInteger dpnId, int addOrRemove,
+                                 IMdsalApiManager mdsalUtils, Short dscpValue,
+                                 String ifName, IpAddress ipAddress, Interface ifState) {
         List<MatchInfo> matches = new ArrayList<>();
         List<InstructionInfo> instructions = new ArrayList<>();
         List<ActionInfo> actionsInfos = new ArrayList<>();
 
-        Interface ifState = getInterfaceStateFromOperDS(ifName, db);
         if (ifState == null) {
             LOG.trace("Could not find the ifState for interface {}", ifName);
             return;