Skip to content

Commit

Permalink
datapath-windows: Add netlink command vport delete
Browse files Browse the repository at this point in the history
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 <sghinet@cloudbasesolutions.com>
Acked-by: Nithin Raju <nithin@vmware.com>
Acked-by: Ankur Sharma <ankursharma@vmware.com>
Acked-by: Eitan Eliahu <eliahue@vmware.com>
Acked-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com>
Tested-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
  • Loading branch information
nithinrajub authored and blp committed Oct 13, 2014
1 parent 8d9f1e0 commit 611531c
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 7 deletions.
112 changes: 110 additions & 2 deletions datapath-windows/ovsext/Datapath.c
Expand Up @@ -95,7 +95,8 @@ static NetlinkCmdHandler OvsGetPidCmdHandler,
OvsGetDpCmdHandler,
OvsSetDpCmdHandler,
OvsGetVportCmdHandler,
OvsNewVportCmdHandler;
OvsNewVportCmdHandler,
OvsDeleteVportCmdHandler;

NetlinkCmdHandler OvsGetNetdevCmdHandler;

Expand Down Expand Up @@ -199,7 +200,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 = {
Expand Down Expand Up @@ -1880,6 +1886,108 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
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,
NlMsgAttrsLen((PNL_MSG_HDR)msgIn),
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
Expand Down
21 changes: 16 additions & 5 deletions datapath-windows/ovsext/Vport.c
Expand Up @@ -133,24 +133,35 @@ HvTeardownPort(POVS_SWITCH_CONTEXT switchContext,

VOID
HvDeletePort(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);
}


Expand Down

0 comments on commit 611531c

Please sign in to comment.