This change includes the following: [1] Handler for subscribe/unsubscribe to a packet queue associated with a socket pid. [2] Allocation of per socket packet queue on a packet subscription. [3] Removal of static allocated queues. [4] Freeing the packet queue (on user mode process termination).
Signed-off-by: Eitan Eliahu <elia...@vmware.com> --- datapath-windows/include/OvsDpInterfaceExt.h | 7 +- datapath-windows/ovsext/Datapath.c | 66 ++++++++++++++++++- datapath-windows/ovsext/Datapath.h | 6 +- datapath-windows/ovsext/Driver.c | 1 + datapath-windows/ovsext/Event.c | 3 +- datapath-windows/ovsext/Ioctl.c | 2 - datapath-windows/ovsext/User.c | 98 +++++++++------------------- datapath-windows/ovsext/User.h | 20 +++--- 8 files changed, 115 insertions(+), 88 deletions(-) diff --git a/datapath-windows/include/OvsDpInterfaceExt.h b/datapath-windows/include/OvsDpInterfaceExt.h index e9faecc..1e8a42d 100644 --- a/datapath-windows/include/OvsDpInterfaceExt.h +++ b/datapath-windows/include/OvsDpInterfaceExt.h @@ -78,6 +78,7 @@ enum ovs_win_control_cmd { OVS_CTRL_CMD_WIN_GET_PID, OVS_CTRL_CMD_WIN_PEND_REQ, OVS_CTRL_CMD_MC_SUBSCRIBE_REQ, + OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ, /* This command is logically belong to the Vport family */ OVS_CTRL_CMD_EVENT_NOTIFY @@ -85,8 +86,10 @@ enum ovs_win_control_cmd { /* NL Attributes for joining/unjoining an MC group */ enum ovs_nl_mcast_attr { - OVS_NL_ATTR_MCAST_GRP, /* (UINT32) Join an MC group */ - OVS_NL_ATTR_MCAST_JOIN, /* (UINT8) 1/0 - Join/Unjoin */ + OVS_NL_ATTR_MCAST_GRP, /* (UINT32) Join an MC group */ + OVS_NL_ATTR_MCAST_JOIN, /* (UINT8) 1/0 - Join/Unjoin */ + OVS_NL_ATTR_PACKET_SUBSCRIBE, /* (UNINT8): 1/0 - subscribe/unsubscribe */ + OVS_NL_ATTR_PACKET_PID, /* (UNINT32) netlink PID to receive upcalls */ __OVS_NL_ATTR_CTRL_MAX }; #define OVS_WIN_CONTROL_ATTR_MAX (__OVS_NL_ATTR_CTRL_MAX - 1) diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c index 93ff8b8..1ede944 100644 --- a/datapath-windows/ovsext/Datapath.c +++ b/datapath-windows/ovsext/Datapath.c @@ -23,6 +23,8 @@ #if defined OVS_USE_NL_INTERFACE && OVS_USE_NL_INTERFACE == 1 #include "precomp.h" +#include "Switch.h" +#include "User.h" #include "Datapath.h" #include "Jhash.h" #include "Switch.h" @@ -90,6 +92,7 @@ typedef struct _NETLINK_FAMILY { static NetlinkCmdHandler OvsGetPidCmdHandler, OvsPendEventCmdHandler, OvsSubscribeEventCmdHandler, + OvsSubscribePacketCmdHandler, OvsReadEventCmdHandler, OvsNewDpCmdHandler, OvsGetDpCmdHandler, @@ -132,6 +135,11 @@ NETLINK_CMD nlControlFamilyCmdOps[] = { .supportedDevOp = OVS_WRITE_DEV_OP, .validateDpIndex = TRUE, }, + { .cmd = OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ, + .handler = OvsSubscribePacketCmdHandler, + .supportedDevOp = OVS_WRITE_DEV_OP, + .validateDpIndex = TRUE, + }, { .cmd = OVS_CTRL_CMD_EVENT_NOTIFY, .handler = OvsReadEventCmdHandler, .supportedDevOp = OVS_READ_EVENT_DEV_OP, @@ -338,7 +346,6 @@ OvsInit() gOvsCtrlLock = &ovsCtrlLockObj; NdisAllocateSpinLock(gOvsCtrlLock); OvsInitEventQueue(); - OvsUserInit(); } VOID @@ -349,7 +356,6 @@ OvsCleanup() NdisFreeSpinLock(gOvsCtrlLock); gOvsCtrlLock = NULL; } - OvsUserCleanup(); } VOID @@ -1061,7 +1067,7 @@ OvsSubscribeEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; rc = NlAttrParse(&msgIn->nlMsg, sizeof (*msgIn), - NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, attrs, 2); + NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, attrs, ARRAY_SIZE(attrs)); if (!rc) { status = STATUS_INVALID_PARAMETER; goto done; @@ -1960,7 +1966,9 @@ OvsSetVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0); if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) { PSTR portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); +#if DBG UINT32 portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); +#endif /* the port name is expected to be null-terminated */ ASSERT(portName[portNameLen - 1] == '\0'); @@ -2291,4 +2299,56 @@ cleanup: OvsReleaseCtrlLock(); return status; } + + +/* + * -------------------------------------------------------------------------- + * Handler for the subscription for a packet queue + * -------------------------------------------------------------------------- + */ +static NTSTATUS +OvsSubscribePacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, + UINT32 *replyLen) +{ + NDIS_STATUS status; + BOOLEAN rc; + UINT8 join; + UINT32 pid; + PNL_ATTR attrs[2]; + const NL_POLICY policy[] = { + [OVS_NL_ATTR_PACKET_PID] = {.type = NL_A_U32 }, + [OVS_NL_ATTR_PACKET_SUBSCRIBE] = {.type = NL_A_U8 } + }; + + UNREFERENCED_PARAMETER(replyLen); + + POVS_OPEN_INSTANCE instance = + (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; + POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; + + rc = NlAttrParse(&msgIn->nlMsg, sizeof (*msgIn), + NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, attrs, ARRAY_SIZE(attrs)); + if (!rc) { + status = STATUS_INVALID_PARAMETER; + goto done; + } + + join = NlAttrGetU8(attrs[OVS_NL_ATTR_PACKET_PID]); + pid = NlAttrGetU32(attrs[OVS_NL_ATTR_PACKET_PID]); + + /* The socket subscribed with must be the same socket we perform receive*/ + ASSERT(pid == instance->pid); + + status = OvsSubscribeDpIoctl(instance, pid, join); + + /* + * XXX Need to add this instance to a global data structure + * which hold all packet based instances. The data structure (hash) + * should be searched through the pid field of the instance for + * placing the missed packet into the correct queue + */ +done: + return status; +} + #endif /* OVS_USE_NL_INTERFACE */ diff --git a/datapath-windows/ovsext/Datapath.h b/datapath-windows/ovsext/Datapath.h index b9c7417..f5105a3 100644 --- a/datapath-windows/ovsext/Datapath.h +++ b/datapath-windows/ovsext/Datapath.h @@ -51,6 +51,10 @@ typedef struct _OVS_DEVICE_EXTENSION { INT pidCount; } OVS_DEVICE_EXTENSION, *POVS_DEVICE_EXTENSION; +// forward declaration +typedef struct _OVS_USER_PACKET_QUEUE OVS_USER_PACKET_QUEUE, + *POVS_USER_PACKET_QUEUE; + /* * Private context for each handle on the device. */ @@ -58,7 +62,7 @@ typedef struct _OVS_OPEN_INSTANCE { UINT32 cookie; PFILE_OBJECT fileObject; PVOID eventQueue; - PVOID packetQueue; + POVS_USER_PACKET_QUEUE packetQueue; UINT32 pid; /* diff --git a/datapath-windows/ovsext/Driver.c b/datapath-windows/ovsext/Driver.c index 79d2edf..0a9c35a 100644 --- a/datapath-windows/ovsext/Driver.c +++ b/datapath-windows/ovsext/Driver.c @@ -16,6 +16,7 @@ #include "precomp.h" #include "Switch.h" +#include "User.h" #include "Datapath.h" #ifdef OVS_DBG_MOD diff --git a/datapath-windows/ovsext/Event.c b/datapath-windows/ovsext/Event.c index d80f3fd..656f719 100644 --- a/datapath-windows/ovsext/Event.c +++ b/datapath-windows/ovsext/Event.c @@ -16,8 +16,9 @@ #include "precomp.h" -#include "Datapath.h" #include "Switch.h" +#include "User.h" +#include "Datapath.h" #include "Vport.h" #include "Event.h" diff --git a/datapath-windows/ovsext/Ioctl.c b/datapath-windows/ovsext/Ioctl.c index 655925b..304310d 100644 --- a/datapath-windows/ovsext/Ioctl.c +++ b/datapath-windows/ovsext/Ioctl.c @@ -109,7 +109,6 @@ OvsInit() { OvsInitIoctl(); OvsInitEventQueue(); - OvsUserInit(); } VOID @@ -117,7 +116,6 @@ OvsCleanup() { OvsCleanupEventQueue(); OvsCleanupIoctl(); - OvsUserCleanup(); } VOID diff --git a/datapath-windows/ovsext/User.c b/datapath-windows/ovsext/User.c index f24c4e3..b39a7a9 100644 --- a/datapath-windows/ovsext/User.c +++ b/datapath-windows/ovsext/User.c @@ -22,11 +22,11 @@ #include "precomp.h" -#include "Datapath.h" #include "Switch.h" #include "Vport.h" #include "Event.h" #include "User.h" +#include "Datapath.h" #include "PacketIO.h" #include "Checksum.h" #include "NetProto.h" @@ -39,8 +39,6 @@ #define OVS_DBG_MOD OVS_DBG_USER #include "Debug.h" -OVS_USER_PACKET_QUEUE ovsPacketQueues[OVS_MAX_NUM_PACKET_QUEUES]; - POVS_PACKET_QUEUE_ELEM OvsGetNextPacket(POVS_OPEN_INSTANCE instance); extern PNDIS_SPIN_LOCK gOvsCtrlLock; extern POVS_SWITCH_CONTEXT gOvsSwitchContext; @@ -50,34 +48,6 @@ static VOID _MapNlAttrToOvsPktExec(PNL_ATTR *nlAttrs, PNL_ATTR *keyAttrs, OvsPacketExecute *execute); extern NL_POLICY nlFlowKeyPolicy[]; -NTSTATUS -OvsUserInit() -{ - UINT32 i; - POVS_USER_PACKET_QUEUE queue; - for (i = 0; i < OVS_MAX_NUM_PACKET_QUEUES; i++) { - queue = &ovsPacketQueues[i]; - RtlZeroMemory(queue, sizeof (*queue)); - InitializeListHead(&queue->packetList); - NdisAllocateSpinLock(&queue->queueLock); - } - return STATUS_SUCCESS; -} - -VOID -OvsUserCleanup() -{ - UINT32 i; - POVS_USER_PACKET_QUEUE queue; - for (i = 0; i < OVS_MAX_NUM_PACKET_QUEUES; i++) { - queue = &ovsPacketQueues[i]; - ASSERT(IsListEmpty(&queue->packetList)); - ASSERT(queue->instance == NULL); - ASSERT(queue->pendingIrp == NULL); - NdisFreeSpinLock(&queue->queueLock); - } -} - static VOID OvsPurgePacketQueue(POVS_USER_PACKET_QUEUE queue, POVS_OPEN_INSTANCE instance) @@ -105,7 +75,6 @@ OvsPurgePacketQueue(POVS_USER_PACKET_QUEUE queue, } } - VOID OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance) { @@ -120,8 +89,11 @@ OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance) if (queue) { PDRIVER_CANCEL cancelRoutine; NdisAcquireSpinLock(&queue->queueLock); + ASSERT(queue->instance == instance); + /* XXX Should not happen */ if (queue->instance != instance) { NdisReleaseSpinLock(&queue->queueLock); + NdisFreeSpinLock(&queue->queueLock); return; } @@ -130,7 +102,6 @@ OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance) queue->numPackets = 0; } queue->instance = NULL; - queue->queueId = OVS_MAX_NUM_PACKET_QUEUES; instance->packetQueue = NULL; irp = queue->pendingIrp; queue->pendingIrp = NULL; @@ -141,6 +112,7 @@ OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance) } } NdisReleaseSpinLock(&queue->queueLock); + NdisFreeSpinLock(&queue->queueLock); } LIST_FORALL_SAFE(&tmp, link, next) { RemoveEntryList(link); @@ -150,44 +122,38 @@ OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance) if (irp) { OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS); } + if (queue) { + OvsFreeMemory(queue); + } } NTSTATUS -OvsSubscribeDpIoctl(PFILE_OBJECT fileObject, - PVOID inputBuffer, - UINT32 inputLength) +OvsSubscribeDpIoctl(PVOID instanceP, + UINT32 pid, + UINT8 join) { - POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; - UINT32 queueId; POVS_USER_PACKET_QUEUE queue; - if (inputLength < sizeof (UINT32)) { - return STATUS_INVALID_PARAMETER; - } - queueId = *(UINT32 *)inputBuffer; - if (instance->packetQueue && queueId >= OVS_MAX_NUM_PACKET_QUEUES) { - /* - * unsubscribe - */ + POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)instanceP; + + if (instance->packetQueue && !join) { + /* unsubscribe */ OvsCleanupPacketQueue(instance); - } else if (instance->packetQueue == NULL && - queueId < OVS_MAX_NUM_PACKET_QUEUES) { - queue = &ovsPacketQueues[queueId]; - NdisAcquireSpinLock(&queue->queueLock); - if (ovsPacketQueues[queueId].instance) { - if (ovsPacketQueues[queueId].instance != instance) { - NdisReleaseSpinLock(&queue->queueLock); - return STATUS_INSUFFICIENT_RESOURCES; - } else { - NdisReleaseSpinLock(&queue->queueLock); - return STATUS_SUCCESS; - } + } else if (instance->packetQueue == NULL && join) { + queue = (POVS_USER_PACKET_QUEUE) OvsAllocateMemory(sizeof *queue); + if (queue == NULL) { + return STATUS_NO_MEMORY; } - queue->queueId = queueId; + instance->packetQueue = queue; + RtlZeroMemory(queue, sizeof (*queue)); + NdisAllocateSpinLock(&queue->queueLock); + NdisAcquireSpinLock(&queue->queueLock); + InitializeListHead(&queue->packetList); + queue->pid = pid; queue->instance = instance; instance->packetQueue = queue; - ASSERT(IsListEmpty(&queue->packetList)); NdisReleaseSpinLock(&queue->queueLock); } else { + /* user mode should call only once for subscribe */ return STATUS_INVALID_PARAMETER; } return STATUS_SUCCESS; @@ -624,14 +590,12 @@ OvsGetNextPacket(POVS_OPEN_INSTANCE instance) POVS_USER_PACKET_QUEUE -OvsGetQueue(UINT32 queueId) +OvsGetQueue(UINT32 pid) { - POVS_USER_PACKET_QUEUE queue; - if (queueId >= OVS_MAX_NUM_PACKET_QUEUES) { - return NULL; - } - queue = &ovsPacketQueues[queueId]; - return queue->instance != NULL ? queue : NULL; + /* XXX To be implementd. Return the queue assoiated with the pid*/ + UNREFERENCED_PARAMETER(pid); + ASSERT(FALSE); + return NULL; } VOID diff --git a/datapath-windows/ovsext/User.h b/datapath-windows/ovsext/User.h index 550915a..0c18e2f 100644 --- a/datapath-windows/ovsext/User.h +++ b/datapath-windows/ovsext/User.h @@ -21,6 +21,7 @@ #ifndef __USER_H_ #define __USER_H_ 1 + #include "Datapath.h" /* @@ -28,7 +29,6 @@ * more than 32 queues for processing packets to * userspace */ -#define OVS_MAX_NUM_PACKET_QUEUES 32 #define OVS_DEFAULT_PACKET_QUEUE 1 #define OVS_MAX_PACKET_QUEUE_LEN 4096 @@ -40,7 +40,7 @@ #define OVS_MAX_PACKETS_PER_TUNNEL 1024 typedef struct _OVS_USER_PACKET_QUEUE { - UINT32 queueId; + UINT32 pid; UINT32 numPackets; LIST_ENTRY packetList; PVOID instance; @@ -67,10 +67,6 @@ typedef struct _OVS_USER_STATS { UINT32 l4Csum; } OVS_USER_STATS, *POVS_USER_STATS; - -NTSTATUS OvsUserInit(); -VOID OvsUserCleanup(); - VOID OvsCleanupPacketQueue(struct _OVS_OPEN_INSTANCE *instance); POVS_PACKET_QUEUE_ELEM OvsCreateQueueNlPacket(PVOID userData, @@ -96,14 +92,14 @@ NTSTATUS OvsCreateAndAddPackets(PVOID userData, LIST_ENTRY *list, UINT32 *num); -NTSTATUS OvsSubscribeDpIoctl(PFILE_OBJECT fileObject, - PVOID inputBuffer, - UINT32 inputLength); +NTSTATUS OvsSubscribeDpIoctl(PVOID instanceP, + UINT32 pid, + UINT8 join); NTSTATUS OvsReadDpIoctl(PFILE_OBJECT fileObject, - PVOID outputBuffer, - UINT32 outputLength, - UINT32 *replyLen); + PVOID outputBuffer, + UINT32 outputLength, + UINT32 *replyLen); NTSTATUS OvsExecuteDpIoctl(OvsPacketExecute *execute); NTSTATUS OvsPurgeDpIoctl(PFILE_OBJECT fileObject); -- 1.9.4.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev