OvsDeleteVportCmdHandler a. [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ, .optional = TRUE }, exceeds 79 chars. b. We should do all msgOut related validations before doing the parsing.
Acked-by: Ankur Sharma <ankursha...@vmware.com> ________________________________________ From: Samuel Ghinet <sghi...@cloudbasesolutions.com> Sent: Tuesday, September 30, 2014 8:00 AM To: dev@openvswitch.org Cc: Alin Serdean; Nithin Raju; Eitan Eliahu; Ankur Sharma Subject: [PATCH 12/14] datapath-windows: Add netlink command vport delete Deletion of a vport is now handled both by the netlink command vport delete and the hyper-v switch port delete handler. If a netlink command vport delete is requested on a vport that has no hyper-v switch port counterpart (i.e., it is a tunnel port, or or the hyper-v switch virtual nic is disconnected), the vport is deleted and removed. If the hyper-v switch port delete is requested (i.e. the VNic is disconnecting) and the ovs (datapath) part is deleted (i.e. was deleted by netlink command vport delete, or was never created by an netlink command vport new), then the hyper-v switch port delete function handler deletes and removes the vport. If the hyper-v switch port delete is requested while its datapath counterpart is still alive, or, when the netlink command vport delete is requested while the hyper-v switch port is still alive, the port is only marked that it's part is deleted - the field hvDeleted was added to OVS_VPORT_ENTRY to specify if the hyper-v switch port side was deleted; if the ovs (datapath) port number is invalid, then it means that the ovs (datapath) side of the port is deleted (or, not created). Signed-off-by: Samuel Ghinet <sghi...@cloudbasesolutions.com> --- datapath-windows/ovsext/Datapath.c | 109 ++++++++++++++++++++++++++++++++++++- datapath-windows/ovsext/Vport.c | 23 +++++--- 2 files changed, 123 insertions(+), 9 deletions(-) diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c index dc03961..7897330 100644 --- a/datapath-windows/ovsext/Datapath.c +++ b/datapath-windows/ovsext/Datapath.c @@ -104,7 +104,8 @@ static NetlinkCmdHandler OvsGetPidCmdHandler, OvsSetDpCmdHandler, OvsReadEventCmdHandler, OvsGetVportCmdHandler, - OvsNewVportCmdHandler; + OvsNewVportCmdHandler, + OvsDeleteVportCmdHandler; static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); @@ -201,7 +202,12 @@ NETLINK_CMD nlVportFamilyCmdOps[] = { .handler = OvsNewVportCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE - } + }, + { .cmd = OVS_VPORT_CMD_DEL, + .handler = OvsDeleteVportCmdHandler, + .supportedDevOp = OVS_TRANSACTION_DEV_OP, + .validateDpIndex = TRUE + }, }; NETLINK_FAMILY nlVportFamilyOps = { @@ -1811,6 +1817,105 @@ Cleanup: return STATUS_SUCCESS; } +static NTSTATUS +OvsDeleteVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, + UINT32 *replyLen) +{ + NDIS_STATUS status = STATUS_SUCCESS; + LOCK_STATE_EX lockState; + + POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; + POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; + POVS_VPORT_ENTRY vport = NULL; + NL_ERROR nlError = NL_ERROR_SUCCESS; + PSTR portName = NULL; + UINT32 portNameLen = 0; + + static const NL_POLICY ovsVportPolicy[] = { + [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE }, + [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ, .optional = TRUE }, + }; + PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)]; + + ASSERT(usrParamsCtx->inputBuffer != NULL); + + if (!NlAttrParse((PNL_MSG_HDR)msgIn, + NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, + ovsVportPolicy, vportAttrs, ARRAY_SIZE(vportAttrs))) { + return STATUS_INVALID_PARAMETER; + } + + if (msgOut == NULL || usrParamsCtx->outputLength < sizeof *msgOut) { + return STATUS_NDIS_INVALID_LENGTH; + } + + OvsAcquireCtrlLock(); + if (!gOvsSwitchContext) { + OvsReleaseCtrlLock(); + return STATUS_INVALID_PARAMETER; + } + OvsReleaseCtrlLock(); + + NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0); + if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) { + portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); + portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); + + /* the port name is expected to be null-terminated */ + ASSERT(portName[portNameLen - 1] == '\0'); + + vport = OvsFindVportByOvsName(gOvsSwitchContext, portName); + } + else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) { + vport = OvsFindVportByPortNo(gOvsSwitchContext, + NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO])); + } + + if (!vport) { + nlError = NL_ERROR_NODEV; + goto Cleanup; + } + + status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer, + 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. + */ + vport->portNo = OVS_DPPORT_NUMBER_INVALID; + vport->ovsName[0] = '\0'; + } + + *replyLen = msgOut->nlMsg.nlmsgLen; + +Cleanup: + NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); + + if (nlError != NL_ERROR_SUCCESS) { + POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) + usrParamsCtx->outputBuffer; + + BuildErrorMsg(msgIn, msgError, nlError); + *replyLen = msgError->nlMsg.nlmsgLen; + } + + return STATUS_SUCCESS; +} + /* * -------------------------------------------------------------------------- * Utility function to map the output buffer in an IRP. The buffer is assumed diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c index 7cee140..d90fd2b 100644 --- a/datapath-windows/ovsext/Vport.c +++ b/datapath-windows/ovsext/Vport.c @@ -121,28 +121,37 @@ HvOnTeardownPort(POVS_SWITCH_CONTEXT switchContext, VPORT_PORT_EXIT(portParam); } - - VOID HvOnDeletePort(POVS_SWITCH_CONTEXT switchContext, - PNDIS_SWITCH_PORT_PARAMETERS portParam) + PNDIS_SWITCH_PORT_PARAMETERS portParams) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; - VPORT_PORT_ENTER(portParam); + VPORT_PORT_ENTER(portParams); NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, - portParam->PortId, 0); + portParams->PortId, 0); + + /* + * XXX: we can only destroy and remove the port if its datapath port + * counterpart was deleted. If the datapath port counterpart is present, + * we only mark the vport for deletion, so that a netlink command vport + * delete will delete the vport. + */ if (vport) { - OvsRemoveAndDeleteVport(switchContext, vport); + if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) { + OvsRemoveAndDeleteVport(switchContext, vport); + } else { + vport->hvDeleted = TRUE; + } } else { OVS_LOG_WARN("Vport not present."); } NdisReleaseRWLock(switchContext->dispatchLock, &lockState); - VPORT_PORT_EXIT(portParam); + VPORT_PORT_EXIT(portParams); } -- 1.8.3.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev