summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--datapath-windows/ovsext/Datapath.c38
-rw-r--r--datapath-windows/ovsext/Vport.c96
-rw-r--r--datapath-windows/ovsext/Vport.h4
3 files changed, 89 insertions, 49 deletions
diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c
index ca83b1e97..2cc149c54 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 5c9795d2c..a740b311e 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 e266caa58..4ee41e47d 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);