[ovs-dev,3/4] datapath-windows: Removed single switch activation restriction
diff mbox

Message ID 1441199397-20449-4-git-send-email-svinturis@cloudbasesolutions.com
State Deferred
Headers show

Commit Message

Sorin Vinturis Sept. 30, 2015, 1:29 p.m. UTC
Signed-off-by: Sorin Vinturis <svinturis@cloudbasesolutions.com>
---
 datapath-windows/ovsext/Switch.c | 144 +++++++++++++++++++++------------------
 1 file changed, 76 insertions(+), 68 deletions(-)

Patch
diff mbox

diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c
index f176fa0..7ea8c68 100644
--- a/datapath-windows/ovsext/Switch.c
+++ b/datapath-windows/ovsext/Switch.c
@@ -35,7 +35,6 @@ 
 #include "Debug.h"
 
 POVS_SWITCH_CONTEXT gOvsSwitchContext;
-LONG volatile gOvsInAttach;
 UINT64 ovsTimeIncrementPerTick;
 
 extern NDIS_HANDLE gOvsExtDriverHandle;
@@ -50,7 +49,8 @@  volatile LONG      gOvsSwitchContextRefCount = 0;
 
 static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
                                    POVS_SWITCH_CONTEXT *switchContextOut);
-static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
+static NDIS_STATUS OvsInitSwitchContext(NDIS_HANDLE ndisFilterHandle);
+static POVS_SWITCH_CONTEXT OvsAllocateSwitchContext(NDIS_HANDLE ndisFilterHandle);
 static VOID OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext);
 static VOID OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
 static NDIS_STATUS OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext);
@@ -71,7 +71,6 @@  OvsExtAttach(NDIS_HANDLE ndisFilterHandle,
 {
     NDIS_STATUS status = NDIS_STATUS_FAILURE;
     NDIS_FILTER_ATTRIBUTES ovsExtAttributes;
-    POVS_SWITCH_CONTEXT switchContext = NULL;
 
     UNREFERENCED_PARAMETER(filterDriverContext);
 
@@ -89,31 +88,18 @@  OvsExtAttach(NDIS_HANDLE ndisFilterHandle,
         goto cleanup;
     }
 
-    if (gOvsSwitchContext) {
-        OVS_LOG_TRACE("Exit: Failed to create OVS Switch, only one datapath is"
-                      "supported, %p.", gOvsSwitchContext);
-        goto cleanup;
-    }
-
-    if (InterlockedCompareExchange(&gOvsInAttach, 1, 0)) {
-        /* Just fail the request. */
-        OVS_LOG_TRACE("Exit: Failed to create OVS Switch, since another attach"
-                      "instance is in attach process.");
-        goto cleanup;
-    }
-
-    status = OvsInitIpHelper(ndisFilterHandle);
-    if (status != STATUS_SUCCESS) {
-        OVS_LOG_ERROR("Exit: Failed to initialize IP helper.");
-        goto cleanup;
-    }
-
-    status = OvsCreateSwitch(ndisFilterHandle, &switchContext);
-    if (status != NDIS_STATUS_SUCCESS) {
-        OvsCleanupIpHelper();
-        goto cleanup;
+    if (gOvsSwitchContext == NULL) {
+        status = OvsInitSwitchContext(ndisFilterHandle);
+        if (status != NDIS_STATUS_SUCCESS) {
+            OVS_LOG_ERROR("Exit: Failed to initialize switch context.");
+            goto cleanup;
+        }
+    } else {
+        if (!OvsAcquireSwitchContext()) {
+            status = STATUS_DEVICE_NOT_READY;
+            goto cleanup;
+        }
     }
-    ASSERT(switchContext);
 
     /*
      * Register the switch context with NDIS so NDIS can pass it back to the
@@ -126,26 +112,17 @@  OvsExtAttach(NDIS_HANDLE ndisFilterHandle,
     ovsExtAttributes.Flags = 0;
 
     NDIS_DECLARE_FILTER_MODULE_CONTEXT(OVS_SWITCH_CONTEXT);
-    status = NdisFSetAttributes(ndisFilterHandle, switchContext, &ovsExtAttributes);
+    status = NdisFSetAttributes(ndisFilterHandle, gOvsSwitchContext, &ovsExtAttributes);
     if (status != NDIS_STATUS_SUCCESS) {
         OVS_LOG_ERROR("Failed to set attributes.");
         OvsCleanupIpHelper();
         goto cleanup;
     }
 
-    /* Setup the state machine. */
-    switchContext->controlFlowState = OvsSwitchAttached;
-    switchContext->dataFlowState = OvsSwitchPaused;
-
-    gOvsSwitchContextRefCount = 1;
-    gOvsSwitchContext = switchContext;
-    KeMemoryBarrier();
-
 cleanup:
-    gOvsInAttach = FALSE;
     if (status != NDIS_STATUS_SUCCESS) {
-        if (switchContext != NULL) {
-            OvsDeleteSwitch(switchContext);
+        if (gOvsSwitchContext != NULL) {
+            OvsDeleteSwitch(gOvsSwitchContext);
         }
     }
     OVS_LOG_TRACE("Exit: status %x", status);
@@ -154,6 +131,30 @@  cleanup:
 }
 
 
+NDIS_STATUS
+OvsInitSwitchContext(NDIS_HANDLE ndisFilterHandle)
+{
+    NDIS_STATUS status = STATUS_SUCCESS;
+
+    OvsAcquireCtrlLock(TRUE);
+    if (gOvsSwitchContext == NULL) {
+        status = OvsCreateSwitch(ndisFilterHandle, &gOvsSwitchContext);
+        ASSERT(gOvsSwitchContext);
+
+        if (gOvsSwitchContext) {
+            /* Setup the state machine. */
+            gOvsSwitchContext->controlFlowState = OvsSwitchAttached;
+            gOvsSwitchContext->dataFlowState = OvsSwitchPaused;
+        }
+
+        gOvsSwitchContextRefCount = 1;
+    }
+    OvsReleaseCtrlLock();
+
+    return status;
+}
+
+
 /*
  * --------------------------------------------------------------------------
  *  This function allocated the switch context, and initializes its necessary
@@ -171,13 +172,24 @@  OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
 
     OVS_LOG_TRACE("Enter: Create switch object");
 
-    switchContext = (POVS_SWITCH_CONTEXT) OvsAllocateMemoryWithTag(
-        sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG);
+    switchContext = OvsAllocateSwitchContext(ndisFilterHandle);
     if (switchContext == NULL) {
-        status = NDIS_STATUS_RESOURCES;
+       OVS_LOG_ERROR("Exit: Failed to allocate switch context.");
+       status = NDIS_STATUS_RESOURCES;
+       goto exit;
+    }
+
+    status = OvsInitIpHelper(ndisFilterHandle);
+    if (status != NDIS_STATUS_SUCCESS) {
+        OVS_LOG_ERROR("Exit: Failed to initialize IP helper.");
+        goto create_switch_done;
+    }
+
+    status = OvsInitTunnelFilter(gOvsExtDriverObject, gOvsDeviceObject);
+    if (status != NDIS_STATUS_SUCCESS) {
+        OVS_LOG_ERROR("Exit: Failed to initialize tunnel filter.");
         goto create_switch_done;
     }
-    RtlZeroMemory(switchContext, sizeof(OVS_SWITCH_CONTEXT));
 
     /* Initialize the switch. */
     hostSwitchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS;
@@ -199,22 +211,14 @@  OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
     RtlCopyMemory(&switchContext->NdisSwitchHandlers, &hostSwitchHandler,
                   sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS));
 
-    status = OvsInitSwitchContext(switchContext);
-    if (status != NDIS_STATUS_SUCCESS) {
-        OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
-        switchContext = NULL;
-        goto create_switch_done;
-    }
+    *switchContextOut = switchContext;
 
-    status = OvsInitTunnelFilter(gOvsExtDriverObject, gOvsDeviceObject);
+create_switch_done:
     if (status != NDIS_STATUS_SUCCESS) {
-        OvsUninitSwitchContext(switchContext);
-        goto create_switch_done;
+        OvsDeleteSwitch(switchContext);
     }
 
-    *switchContextOut = switchContext;
-
-create_switch_done:
+exit:
     OVS_LOG_TRACE("Exit: switchContext: %p status: %#lx",
                   switchContext, status);
     return status;
@@ -349,16 +353,20 @@  OvsExtPause(NDIS_HANDLE filterModuleContext,
     return NDIS_STATUS_SUCCESS;
 }
 
-static NDIS_STATUS
-OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
+static POVS_SWITCH_CONTEXT
+OvsAllocateSwitchContext(NDIS_HANDLE ndisFilterHandle)
 {
-    int i;
+    POVS_SWITCH_CONTEXT switchContext = NULL;
     NTSTATUS status;
 
-    OVS_LOG_TRACE("Enter: switchContext: %p", switchContext);
+    switchContext = (POVS_SWITCH_CONTEXT)OvsAllocateMemoryWithTag(
+        sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG);
+    if (switchContext == NULL) {
+        return switchContext;
+    }
+    RtlZeroMemory(switchContext, sizeof(OVS_SWITCH_CONTEXT));
 
-    switchContext->dispatchLock =
-        NdisAllocateRWLock(switchContext->NdisFilterHandle);
+    switchContext->dispatchLock = NdisAllocateRWLock(ndisFilterHandle);
 
     switchContext->portNoHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
         sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
@@ -409,18 +417,20 @@  OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
         OvsDeleteFlowTable(&switchContext->datapath);
         OvsCleanupBufferPool(switchContext);
 
-        OVS_LOG_TRACE("Exit: Failed to init switchContext");
-        return NDIS_STATUS_RESOURCES;
+        OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
+        switchContext = NULL;
+
+        return switchContext;
     }
 
-    for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
+    for (int i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
         InitializeListHead(&switchContext->ovsPortNameHashArray[i]);
         InitializeListHead(&switchContext->portIdHashArray[i]);
         InitializeListHead(&switchContext->portNoHashArray[i]);
         InitializeListHead(&switchContext->tunnelVportsArray[i]);
     }
 
-    for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {
+    for (int i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {
         InitializeListHead(&switchContext->pidHashArray[i]);
     }
 
@@ -430,9 +440,7 @@  OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
     switchContext->dpNo = OVS_DP_NUMBER;
     ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;
 
-    OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p",
-                  switchContext);
-    return NDIS_STATUS_SUCCESS;
+    return switchContext;
 }
 
 static VOID