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 <nit...@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 aaf8caf..54b9103 100644 --- a/datapath-windows/ovsext/Datapath.c +++ b/datapath-windows/ovsext/Datapath.c @@ -1747,7 +1747,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[] = { @@ -1831,6 +1831,7 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, } else { OvsInitBridgeInternalVport(vport); } + vportInitialized = TRUE; if (nlError == NL_ERROR_SUCCESS) { vport->ovsState = OVS_STATE_CONNECTED; @@ -1905,7 +1906,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); @@ -2102,29 +2108,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 6d02a0d..a850b15 100644 --- a/datapath-windows/ovsext/Vport.c +++ b/datapath-windows/ovsext/Vport.c @@ -117,8 +117,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 { @@ -130,7 +129,6 @@ HvTeardownPort(POVS_SWITCH_CONTEXT switchContext, } - VOID HvDeletePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParams) @@ -151,11 +149,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."); } @@ -445,7 +439,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; @@ -933,13 +927,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) { @@ -947,6 +954,9 @@ OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext, switchContext->virtualExternalPortId = 0; switchContext->virtualExternalVport = NULL; OvsFreeMemory(vport); + if (vportDeallocated) { + *vportDeallocated = TRUE; + } return; } else { ASSERT(switchContext->numPhysicalNics); @@ -977,17 +987,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) @@ -1124,7 +1173,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); } } /* @@ -1133,7 +1182,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++) { @@ -1145,8 +1195,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 73face6..bd9cec2 100644 --- a/datapath-windows/ovsext/Vport.h +++ b/datapath-windows/ovsext/Vport.h @@ -205,7 +205,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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev