Handling RACE conditions in bind/unbind service
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / statehelpers / OvsInterfaceStateUpdateHelper.java
index b686e7d79d08f796e86529e3ad0a48858311ad0c..5c7546d40a61c16d0332926c2398bcbf9290d3ef 100644 (file)
@@ -8,10 +8,11 @@
 package org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+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.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.interfacemanager.IfmConstants;
 import org.opendaylight.genius.interfacemanager.IfmUtil;
 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
@@ -23,15 +24,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-
 public class OvsInterfaceStateUpdateHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
 
@@ -64,21 +60,32 @@ public class OvsInterfaceStateUpdateHelper {
             return futures;
         }
 
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+
+        // For tunnels, derive the final opstate based on the bfd tunnel monitoring status
+        if (modifyTunnel(iface, opstateModified)
+                && InterfaceManagerCommonUtils.checkIfBfdStateIsDown(iface.getName())) {
+            operStatusNew = Interface.OperStatus.Down;
+            opstateModified = operStatusNew.equals(operStatusOld);
+        }
+
+        if (!opstateModified && !hardwareAddressModified) {
+            LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
+            return futures;
+        }
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
         if (hardwareAddressModified) {
             LOG.debug("Hw-Address Modified for Port: {}", interfaceName);
             PhysAddress physAddress = new PhysAddress(macAddressNew.getValue());
             ifaceBuilder.setPhysAddress(physAddress);
         }
-        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
-        String dpnId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
         // modify the attributes in interface operational DS
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                handleInterfaceStateUpdates(interfaceName, transaction, dataBroker,
-                        ifaceBuilder, opstateModified, flowCapableNodeConnectorNew.getName(), operStatusNew, dpnId);
+        handleInterfaceStateUpdates(iface, transaction, dataBroker, ifaceBuilder, opstateModified, interfaceName,
+                flowCapableNodeConnectorNew.getName(), operStatusNew);
 
         // start/stop monitoring based on opState
-        if(modifyTunnel(iface, opstateModified)){
+        if (modifyTunnel(iface, opstateModified)) {
             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
                     iface.getName(), operStatusNew);
         }
@@ -87,76 +94,68 @@ public class OvsInterfaceStateUpdateHelper {
         return futures;
     }
 
-    public static void updateInterfaceStateOnNodeRemove(String interfaceName, FlowCapableNodeConnector flowCapableNodeConnector,
-                                                        DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
-                                                        WriteTransaction transaction, String dpnId){
+    public static void updateInterfaceStateOnNodeRemove(String interfaceName,
+            FlowCapableNodeConnector flowCapableNodeConnector, DataBroker dataBroker,
+            AlivenessMonitorService alivenessMonitorService, WriteTransaction transaction) {
         LOG.debug("Updating interface oper-status to UNKNOWN for : {}", interfaceName);
 
         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                handleInterfaceStateUpdates(interfaceName,transaction, dataBroker,
-                        ifaceBuilder, true, flowCapableNodeConnector.getName(),
-                        Interface.OperStatus.Unknown, dpnId);
-        if (InterfaceManagerCommonUtils.isTunnelInterface(iface)){
+                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+        handleInterfaceStateUpdates(iface,transaction, dataBroker,
+                        ifaceBuilder, true, interfaceName, flowCapableNodeConnector.getName(),
+                        Interface.OperStatus.Unknown);
+        if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
                     interfaceName, Interface.OperStatus.Unknown);
         }
     }
 
-    public static Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector){
-        Interface.OperStatus operStatus =
-                (flowCapableNodeConnector.getState().isLive() &&
-                        !flowCapableNodeConnector.getConfiguration().isPORTDOWN())
-                        ? Interface.OperStatus.Up: Interface.OperStatus.Down;
+    public static Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) {
+        Interface.OperStatus operStatus = flowCapableNodeConnector.getState().isLive()
+                && !flowCapableNodeConnector.getConfiguration().isPORTDOWN()
+                 ? Interface.OperStatus.Up : Interface.OperStatus.Down;
         return operStatus;
     }
 
-    public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
-    handleInterfaceStateUpdates(String interfaceName, WriteTransaction transaction,
-                                DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
-                                String portName,
-                                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState,String dpnId){
-        LOG.debug("updating interface state entry for {}", interfaceName);
-        boolean isParentInterface = (interfaceName.equals(portName))?true:false;
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
-                InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
-        if (!IfmUtil.isTunnelType(iface, null) && isParentInterface) {
-            interfaceName = new StringBuilder(dpnId).append(IfmConstants.OF_URI_SEPARATOR).append(interfaceName).toString();
-        }
-        InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
-        ifaceBuilder.setKey(new InterfaceKey(interfaceName));
+    public static void handleInterfaceStateUpdates(
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            WriteTransaction transaction, DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
+            String interfaceName, String portName, Interface.OperStatus opState) {
         // if interface config DS is null, do the update only for the lower-layer-interfaces
         // which have no corresponding config entries
-        if(iface == null && !isParentInterface){
-            return null;
+        if (iface == null && !interfaceName.equals(portName)) {
+            return;
         }
+        LOG.debug("updating interface state entry for {}", interfaceName);
+        InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
+        ifaceBuilder.setKey(new InterfaceKey(interfaceName));
         if (modifyOpState(iface, opStateModified)) {
             LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
             ifaceBuilder.setOperStatus(opState);
         }
         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
-
-        return iface;
     }
 
-    public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
-                                                     IfTunnel ifTunnel, String interfaceName,
-                                                     Interface.OperStatus operStatus){
-
+    public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService,
+            DataBroker dataBroker, IfTunnel ifTunnel, String interfaceName, Interface.OperStatus operStatus) {
         LOG.debug("handling tunnel monitoring updates for {} due to opstate modification", interfaceName);
-        if (operStatus == Interface.OperStatus.Down || operStatus == Interface.OperStatus.Unknown)
+        if (operStatus == Interface.OperStatus.Down || operStatus == Interface.OperStatus.Unknown) {
             AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, ifTunnel, interfaceName);
-        else
+        } else {
             AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, ifTunnel, interfaceName);
+        }
     }
 
-    public static boolean modifyOpState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
-                                        boolean opStateModified){
-        return (opStateModified && (iface == null || iface != null && iface.isEnabled()));
+    public static boolean modifyOpState(
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            boolean opStateModified) {
+        return opStateModified && (iface == null || iface != null && iface.isEnabled());
     }
 
-    public static boolean modifyTunnel(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
-                                       boolean opStateModified){
+    public static boolean modifyTunnel(
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+            boolean opStateModified) {
         return modifyOpState(iface, opStateModified) && iface != null && iface.getAugmentation(IfTunnel.class) != null;
     }
 }