diff options
-rw-r--r-- | datapath-windows/ovsext/Datapath.c | 38 | ||||
-rw-r--r-- | datapath-windows/ovsext/Vport.c | 96 | ||||
-rw-r--r-- | 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 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); |