[ovs-dev] [PATCH 4/7 v3] datapath-windows: Changes to OvsRemoveAndDeleteVport()

Nithin Raju nithin at vmware.com
Wed Nov 19 01:42:45 UTC 2014


In this patch, we add changes to OvsRemoveAndDeleteVport() to allow the
caller to specify if a vport is being deleted because it got deleted on
Hyper-V or if it got deleted from OVS userspace.

The reason we need to make the distinction is to be able to delete the
vport from the relevant hash tables.

If a port has been deleted from all the hash tables ie. has been deleted
from Hyper-V as well as OVS userspace, it gets deallocated.

Signed-off-by: Nithin Raju <nithin at vmware.com>
Acked-by: Ankur Sharma <ankursharma at vmware.com>
---
 datapath-windows/ovsext/Datapath.c |   38 +++++---------
 datapath-windows/ovsext/Vport.c    |   96 +++++++++++++++++++++++++++---------
 datapath-windows/ovsext/Vport.h    |    4 +-
 3 files changed, 89 insertions(+), 49 deletions(-)

diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c
index ca83b1e..2cc149c 100644
--- a/datapath-windows/ovsext/Datapath.c
+++ b/datapath-windows/ovsext/Datapath.c
@@ -1729,7 +1729,7 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     ULONG portNameLen;
     UINT32 portType;
     BOOLEAN isBridgeInternal = FALSE;
-    BOOLEAN vportAllocated = FALSE;
+    BOOLEAN vportAllocated = FALSE, vportInitialized = FALSE;
     BOOLEAN addInternalPortAsNetdev = FALSE;
 
     static const NL_POLICY ovsVportPolicy[] = {
@@ -1806,6 +1806,7 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
         } else {
             OvsInitBridgeInternalVport(vport);
         }
+        vportInitialized = TRUE;
 
         if (nlError == NL_ERROR_SUCCESS) {
             vport->ovsState = OVS_STATE_CONNECTED;
@@ -1880,7 +1881,12 @@ Cleanup:
             usrParamsCtx->outputBuffer;
 
         if (vport && vportAllocated == TRUE) {
-            OvsRemoveAndDeleteVport(gOvsSwitchContext, vport);
+            if (vportInitialized == TRUE) {
+                if (OvsIsTunnelVportType(portType)) {
+                    OvsCleanupVxlanTunnel(vport);
+                }
+            }
+            OvsFreeMemory(vport);
         }
 
         BuildErrorMsg(msgIn, msgError, nlError);
@@ -2066,29 +2072,11 @@ OvsDeleteVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                                    usrParamsCtx->outputLength,
                                    gOvsSwitchContext->dpNo);
 
-    if (vport->hvDeleted || OvsIsTunnelVportType(vport->ovsType)) {
-        /*
-         * The associated hyper-v switch port is not in created state, or,
-         * there is no hyper-v switch port counterpart (for logical ports).
-         * This means that this datapath port is not mapped to a living
-         * hyper-v switc hport. We can destroy and remove the vport from the
-         * list.
-        */
-        OvsRemoveAndDeleteVport(gOvsSwitchContext, vport);
-    } else {
-        /* The associated hyper-v switch port is in the created state, and the
-         * datapath port is mapped to a living hyper-v switch port. We cannot
-         * destroy the vport and cannot remove it from the list of vports.
-         * Instead, we mark the datapath (ovs) part of the vport as
-         * "not created", i.e. we set vport->portNo = OVS_PORT_NUMBER_INVALID.
-        */
-        RemoveEntryList(&vport->ovsNameLink);
-        InitializeListHead(&vport->ovsNameLink);
-        RemoveEntryList(&vport->portNoLink);
-        InitializeListHead(&vport->portNoLink);
-        vport->portNo = OVS_DPPORT_NUMBER_INVALID;
-        vport->ovsName[0] = '\0';
-    }
+    /*
+     * Mark the port as deleted from OVS userspace. If the port does not exist
+     * on the Hyper-V switch, it gets deallocated. Otherwise, it stays.
+     */
+    OvsRemoveAndDeleteVport(gOvsSwitchContext, vport, FALSE, TRUE, NULL);
 
     *replyLen = msgOut->nlMsg.nlmsgLen;
 
diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c
index 5c9795d..a740b31 100644
--- a/datapath-windows/ovsext/Vport.c
+++ b/datapath-windows/ovsext/Vport.c
@@ -174,8 +174,7 @@ HvTeardownPort(POVS_SWITCH_CONTEXT switchContext,
     vport = OvsFindVportByPortIdAndNicIndex(switchContext,
                                             portParam->PortId, 0);
     if (vport) {
-        /* add assertion here
-         */
+        /* add assertion here */
         vport->portState = NdisSwitchPortStateTeardown;
         vport->ovsState = OVS_STATE_PORT_TEAR_DOWN;
     } else {
@@ -187,7 +186,6 @@ HvTeardownPort(POVS_SWITCH_CONTEXT switchContext,
 }
 
 
-
 VOID
 HvDeletePort(POVS_SWITCH_CONTEXT switchContext,
              PNDIS_SWITCH_PORT_PARAMETERS portParams)
@@ -208,11 +206,7 @@ HvDeletePort(POVS_SWITCH_CONTEXT switchContext,
      * delete will delete the vport.
     */
     if (vport) {
-        if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {
-            OvsRemoveAndDeleteVport(switchContext, vport);
-        } else {
-            vport->hvDeleted = TRUE;
-        }
+        OvsRemoveAndDeleteVport(switchContext, vport, TRUE, FALSE, NULL);
     } else {
         OVS_LOG_WARN("Vport not present.");
     }
@@ -502,7 +496,7 @@ HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,
     portNo = vport->portNo;
     if (vport->portType == NdisSwitchPortTypeExternal &&
         vport->nicIndex != 0) {
-        OvsRemoveAndDeleteVport(switchContext, vport);
+        OvsRemoveAndDeleteVport(switchContext, vport, TRUE, FALSE, NULL);
     }
     vport->nicState = NdisSwitchNicStateUnknown;
     vport->ovsState = OVS_STATE_PORT_CREATED;
@@ -990,13 +984,26 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,
  * --------------------------------------------------------------------------
  * Provides functionality that is partly complementatry to
  * InitOvsVportCommon()/InitHvVportCommon().
+ *
+ * 'hvDelete' indicates if caller is removing the vport as a result of the
+ * port being removed on the Hyper-V switch.
+ * 'ovsDelete' indicates if caller is removing the vport as a result of the
+ * port being removed from OVS userspace.
  * --------------------------------------------------------------------------
  */
 VOID
 OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
-                        POVS_VPORT_ENTRY vport)
+                        POVS_VPORT_ENTRY vport,
+                        BOOLEAN hvDelete,
+                        BOOLEAN ovsDelete,
+                        BOOLEAN *vportDeallocated)
 {
     BOOLEAN hvSwitchPort = FALSE;
+    BOOLEAN deletedOnOvs = FALSE, deletedOnHv = FALSE;
+
+    if (vportDeallocated) {
+        *vportDeallocated = FALSE;
+    }
 
     if (vport->isExternal) {
         if (vport->nicIndex == 0) {
@@ -1004,6 +1011,9 @@ OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
             switchContext->virtualExternalPortId = 0;
             switchContext->virtualExternalVport = NULL;
             OvsFreeMemory(vport);
+            if (vportDeallocated) {
+                *vportDeallocated = TRUE;
+            }
             return;
         } else {
             ASSERT(switchContext->numPhysicalNics);
@@ -1034,17 +1044,56 @@ OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
         break;
     }
 
-    RemoveEntryList(&vport->ovsNameLink);
-    RemoveEntryList(&vport->portIdLink);
-    RemoveEntryList(&vport->portNoLink);
-    if (hvSwitchPort) {
-        switchContext->numHvVports--;
-    } else {
-        switchContext->numNonHvVports--;
+    /*
+     * 'hvDelete' == TRUE indicates that the port should be removed from the
+     * 'portIdHashArray', while 'ovsDelete' == TRUE indicates that the port
+     * should be removed from 'portNoHashArray' and the 'ovsPortNameHashArray'.
+     *
+     * Both 'hvDelete' and 'ovsDelete' can be set to TRUE by the caller.
+     */
+    if (vport->hvDeleted == TRUE) {
+        deletedOnHv = TRUE;
+    }
+    if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {
+        deletedOnOvs = TRUE;
     }
-    OvsFreeMemory(vport);
-}
 
+    if (hvDelete && !deletedOnHv) {
+        vport->hvDeleted = TRUE;
+
+        /* Remove the port from the relevant lists. */
+        RemoveEntryList(&vport->portIdLink);
+        InitializeListHead(&vport->portIdLink);
+        deletedOnHv = TRUE;
+    }
+    if (ovsDelete && !deletedOnOvs) {
+        vport->portNo = OVS_DPPORT_NUMBER_INVALID;
+        vport->ovsName[0] = '\0';
+
+        /* Remove the port from the relevant lists. */
+        RemoveEntryList(&vport->ovsNameLink);
+        InitializeListHead(&vport->ovsNameLink);
+        RemoveEntryList(&vport->portNoLink);
+        InitializeListHead(&vport->portNoLink);
+        deletedOnOvs = TRUE;
+    }
+
+    /*
+     * Deallocate the port if it has been deleted on the Hyper-V switch as well
+     * as OVS userspace.
+     */
+    if (deletedOnHv && deletedOnOvs) {
+        if (hvSwitchPort) {
+            switchContext->numHvVports--;
+        } else {
+            switchContext->numNonHvVports--;
+        }
+        OvsFreeMemory(vport);
+        if (vportDeallocated) {
+            *vportDeallocated = TRUE;
+        }
+    }
+}
 
 NDIS_STATUS
 OvsAddConfiguredSwitchPorts(POVS_SWITCH_CONTEXT switchContext)
@@ -1181,7 +1230,7 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
         LIST_FORALL_SAFE(head, link, next) {
             POVS_VPORT_ENTRY vport;
             vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink);
-            OvsRemoveAndDeleteVport(switchContext, vport);
+            OvsRemoveAndDeleteVport(switchContext, vport, TRUE, TRUE, NULL);
         }
     }
     /*
@@ -1190,7 +1239,8 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
      */
     if (switchContext->virtualExternalVport) {
         OvsRemoveAndDeleteVport(switchContext,
-            (POVS_VPORT_ENTRY)switchContext->virtualExternalVport);
+            (POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE,
+            NULL);
     }
 
     for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {
@@ -1202,8 +1252,8 @@ OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
             vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
             ASSERT(OvsIsTunnelVportType(vport->ovsType) ||
                    (vport->ovsType == OVS_VPORT_TYPE_INTERNAL &&
-                    vport->isBridgeInternal));
-            OvsRemoveAndDeleteVport(switchContext, vport);
+                    vport->isBridgeInternal) || vport->hvDeleted == TRUE);
+            OvsRemoveAndDeleteVport(switchContext, vport, TRUE, TRUE, NULL);
         }
     }
 
diff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h
index e266caa..4ee41e4 100644
--- a/datapath-windows/ovsext/Vport.h
+++ b/datapath-windows/ovsext/Vport.h
@@ -207,7 +207,9 @@ OvsIsBridgeInternalVport(POVS_VPORT_ENTRY vport)
 }
 
 VOID OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
-                             POVS_VPORT_ENTRY vport);
+                             POVS_VPORT_ENTRY vport,
+                             BOOLEAN hvDelete, BOOLEAN ovsDelete,
+                             BOOLEAN *vportDeallocated);
 
 NDIS_STATUS InitHvVportCommon(POVS_SWITCH_CONTEXT switchContext,
                               POVS_VPORT_ENTRY vport);
-- 
1.7.4.1




More information about the dev mailing list