[ovs-dev] [PATCH v2 5/7] datapath-windows: Add support for multiple event queue in Event.c
Yin Lin
yinlin10 at gmail.com
Tue Jul 26 03:05:51 UTC 2016
Acked-By: Yin Lin <linyi at vmware.com>
On Mon, Jul 25, 2016 at 5:04 PM, Sairam Venugopal <vsairam at vmware.com>
wrote:
> Update Event.c to have multiple event queues and mechanism to retrieve the
> associated queue. Introduce OvsPostCtEvent and OvsRemoveCtEventEntry
> similar to OvsPostVportEvent and OvsRemoveVportEventEntry.
>
> v2: Added Acked-By
>
> Signed-off-by: Sairam Venugopal <vsairam at vmware.com>
> Acked-by: Paul Boca <pboca at cloudbasesolutions.com>
> Acked-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>
> ---
> datapath-windows/ovsext/Event.c | 265
> +++++++++++++++++++++++++++++++++-------
> datapath-windows/ovsext/Event.h | 17 ++-
> 2 files changed, 239 insertions(+), 43 deletions(-)
>
> diff --git a/datapath-windows/ovsext/Event.c
> b/datapath-windows/ovsext/Event.c
> index 8ff0322..cb0dc92 100644
> --- a/datapath-windows/ovsext/Event.c
> +++ b/datapath-windows/ovsext/Event.c
> @@ -26,36 +26,62 @@
> #define OVS_DBG_MOD OVS_DBG_EVENT
> #include "Debug.h"
>
> -LIST_ENTRY ovsEventQueue;
> -static NDIS_SPIN_LOCK eventQueueLock;
> -UINT32 ovsNumEventQueue;
> +LIST_ENTRY ovsEventQueueArr[OVS_MCAST_EVENT_TYPES_MAX];
> +static NDIS_SPIN_LOCK eventQueueLockArr[OVS_MCAST_EVENT_TYPES_MAX];
> +UINT32 ovsNumEventQueueArr[OVS_MCAST_EVENT_TYPES_MAX];
>
> NTSTATUS
> OvsInitEventQueue()
> {
> - InitializeListHead(&ovsEventQueue);
> - NdisAllocateSpinLock(&eventQueueLock);
> + for (int i = 0; i < OVS_MCAST_EVENT_TYPES_MAX; i++) {
> + InitializeListHead(&ovsEventQueueArr[i]);
> + NdisAllocateSpinLock(&eventQueueLockArr[i]);
> + }
> return STATUS_SUCCESS;
> }
>
> VOID
> OvsCleanupEventQueue()
> {
> - ASSERT(IsListEmpty(&ovsEventQueue));
> - ASSERT(ovsNumEventQueue == 0);
> - NdisFreeSpinLock(&eventQueueLock);
> + for (int i = 0; i < OVS_MCAST_EVENT_TYPES_MAX; i++) {
> + ASSERT(IsListEmpty(&ovsEventQueueArr[i]));
> + ASSERT(ovsNumEventQueueArr[i] == 0);
> + NdisFreeSpinLock(&eventQueueLockArr[i]);
> + }
> }
>
> static __inline VOID
> -OvsAcquireEventQueueLock()
> +OvsAcquireEventQueueLock(int eventId)
> {
> - NdisAcquireSpinLock(&eventQueueLock);
> + NdisAcquireSpinLock(&eventQueueLockArr[eventId]);
> }
>
> static __inline VOID
> -OvsReleaseEventQueueLock()
> +OvsReleaseEventQueueLock(int eventId)
> {
> - NdisReleaseSpinLock(&eventQueueLock);
> + NdisReleaseSpinLock(&eventQueueLockArr[eventId]);
> +}
> +
> +NDIS_STATUS
> +OvsGetMcastEventId(UINT32 protocol, UINT32 mcastMask, UINT32 *eventId)
> +{
> + switch (protocol) {
> + case NETLINK_GENERIC:
> + *eventId = OVS_MCAST_VPORT_EVENT;
> + return NDIS_STATUS_SUCCESS;
> + case NETLINK_NETFILTER:
> + if ((mcastMask & OVS_EVENT_CT_NEW)
> + || (mcastMask & OVS_EVENT_CT_DELETE)) {
> + *eventId = OVS_MCAST_CT_EVENT;
> + return NDIS_STATUS_SUCCESS;
> + }
> + break;
> + default:
> + goto error;
> + }
> +
> +error:
> + return NDIS_STATUS_INVALID_PARAMETER;
> }
>
> /*
> @@ -68,14 +94,17 @@ OvsCleanupEvent(POVS_OPEN_INSTANCE instance)
> {
> POVS_EVENT_QUEUE queue;
> PIRP irp = NULL;
> + UINT32 eventId;
> queue = (POVS_EVENT_QUEUE)instance->eventQueue;
> if (queue) {
> POVS_EVENT_QUEUE_ELEM elem;
> PLIST_ENTRY link, next;
>
> - OvsAcquireEventQueueLock();
> + /* Handle the error */
> + OvsGetMcastEventId(instance->protocol, instance->mcastMask,
> &eventId);
> + OvsAcquireEventQueueLock(eventId);
> RemoveEntryList(&queue->queueLink);
> - ovsNumEventQueue--;
> + ovsNumEventQueueArr[eventId]--;
> if (queue->pendingIrp) {
> PDRIVER_CANCEL cancelRoutine;
> irp = queue->pendingIrp;
> @@ -86,7 +115,7 @@ OvsCleanupEvent(POVS_OPEN_INSTANCE instance)
> }
> }
> instance->eventQueue = NULL;
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(eventId);
> if (irp) {
> OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);
> }
> @@ -115,7 +144,7 @@ OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event)
> POVS_EVENT_QUEUE queue;
> PLIST_ENTRY link;
> LIST_ENTRY list;
> - PLIST_ENTRY entry;
> + PLIST_ENTRY entry;
> PIRP irp;
>
> InitializeListHead(&list);
> @@ -123,9 +152,9 @@ OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event)
> OVS_LOG_TRACE("Enter: portNo: %#x, status: %#x", event->portNo,
> event->type);
>
> - OvsAcquireEventQueueLock();
> + OvsAcquireEventQueueLock(OVS_MCAST_VPORT_EVENT);
>
> - LIST_FORALL(&ovsEventQueue, link) {
> + LIST_FORALL(&ovsEventQueueArr[OVS_MCAST_VPORT_EVENT], link) {
> queue = CONTAINING_RECORD(link, OVS_EVENT_QUEUE, queueLink);
> if ((event->type & queue->mask) == 0) {
> continue;
> @@ -137,7 +166,7 @@ OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event)
>
> if (elem == NULL) {
> OVS_LOG_WARN("Fail to allocate memory for event");
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(OVS_MCAST_VPORT_EVENT);
> return;
> }
>
> @@ -157,7 +186,7 @@ OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event)
> }
> }
> }
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(OVS_MCAST_VPORT_EVENT);
> while (!IsListEmpty(&list)) {
> entry = RemoveHeadList(&list);
> irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
> @@ -189,17 +218,25 @@ OvsSubscribeEventIoctl(PFILE_OBJECT fileObject,
> NTSTATUS status = STATUS_SUCCESS;
> POVS_OPEN_INSTANCE instance;
> POVS_EVENT_QUEUE queue = NULL;
> + UINT32 eventId;
>
> OVS_LOG_TRACE("Enter: fileObject: %p, inputLength: %d", fileObject,
> inputLength);
>
> - if (inputLength < sizeof (OVS_EVENT_SUBSCRIBE) ||
> - (request->mask & OVS_EVENT_MASK_ALL) == 0) {
> - OVS_LOG_TRACE("Exit: subscribe failed with invalid request.");
> + if (request->protocol == NETLINK_GENERIC) {
> + if (inputLength < sizeof (OVS_EVENT_SUBSCRIBE) ||
> + (request->mask & OVS_EVENT_MASK_ALL) == 0) {
> + OVS_LOG_TRACE("Exit: subscribe failed with invalid request.");
> + return STATUS_INVALID_PARAMETER;
> + }
> + }
> +
> + status = OvsGetMcastEventId(request->protocol, request->mask,
> &eventId);
> + if (status != NDIS_STATUS_SUCCESS) {
> return STATUS_INVALID_PARAMETER;
> }
>
> - OvsAcquireEventQueueLock();
> + OvsAcquireEventQueueLock(eventId);
>
> instance = OvsGetOpenInstance(fileObject, request->dpNo);
>
> @@ -214,9 +251,23 @@ OvsSubscribeEventIoctl(PFILE_OBJECT fileObject,
> */
> queue = (POVS_EVENT_QUEUE)instance->eventQueue;
> if (request->subscribe && queue) {
> - if (queue->mask != request->mask) {
> + if (request->protocol == NETLINK_GENERIC
> + && queue->mask != request->mask) {
> status = STATUS_INVALID_PARAMETER;
> - OVS_LOG_WARN("Can not chnage mask when the queue is
> subscribed");
> + OVS_LOG_WARN("Can not change mask when the queue is
> subscribed");
> + goto done_event_subscribe;
> + }
> + if (request->protocol == NETLINK_NETFILTER) {
> + if (queue->mask == request->mask) {
> + /* Resubscribing to subscribed event */
> + status = STATUS_SUCCESS;
> + goto done_event_subscribe;
> + } else {
> + /* Update the instance and queue mask to reflect this */
> + queue->mask |= request->mask;
> + instance->mcastMask |= request->mask;
> + }
> + status = STATUS_SUCCESS;
> goto done_event_subscribe;
> }
> } else if (!request->subscribe && queue == NULL) {
> @@ -234,20 +285,28 @@ OvsSubscribeEventIoctl(PFILE_OBJECT fileObject,
> }
> InitializeListHead(&queue->elemList);
> queue->mask = request->mask;
> + queue->mcastEventId = eventId;
> queue->pendingIrp = NULL;
> queue->numElems = 0;
> - InsertHeadList(&ovsEventQueue, &queue->queueLink);
> - ovsNumEventQueue++;
> + InsertHeadList(&ovsEventQueueArr[eventId], &queue->queueLink);
> + ovsNumEventQueueArr[eventId]++;
> instance->eventQueue = queue;
> + instance->mcastMask = request->mask;
> queue->instance = instance;
> } else {
> queue = (POVS_EVENT_QUEUE)instance->eventQueue;
> - RemoveEntryList(&queue->queueLink);
> - ovsNumEventQueue--;
> - instance->eventQueue = NULL;
> + queue->mask &= ~(request->mask);
> + instance->mcastMask &= ~(request->mask);
> + if (!queue->mask) {
> + /* No other mcast group exists */
> + RemoveEntryList(&queue->queueLink);
> + ovsNumEventQueueArr[eventId]--;
> + instance->eventQueue = NULL;
> + instance->mcastMask = 0;
> + }
> }
> done_event_subscribe:
> - if (!request->subscribe && queue) {
> + if (!request->subscribe && queue && !queue->mask) {
> POVS_EVENT_QUEUE_ELEM elem;
> PLIST_ENTRY link, next;
> PIRP irp = NULL;
> @@ -260,7 +319,7 @@ done_event_subscribe:
> irp = NULL;
> }
> }
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(eventId);
> if (irp) {
> OvsCompleteIrpRequest(queue->pendingIrp, 0, STATUS_SUCCESS);
> }
> @@ -270,7 +329,7 @@ done_event_subscribe:
> }
> OvsFreeMemoryWithTag(queue, OVS_EVENT_POOL_TAG);
> } else {
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(eventId);
> }
> OVS_LOG_TRACE("Exit: subscribe event with status: %#x.", status);
> return status;
> @@ -294,6 +353,8 @@ OvsCancelIrp(PDEVICE_OBJECT deviceObject,
> PFILE_OBJECT fileObject;
> POVS_EVENT_QUEUE queue;
> POVS_OPEN_INSTANCE instance;
> + UINT32 eventId;
> + NDIS_STATUS status;
>
> UNREFERENCED_PARAMETER(deviceObject);
>
> @@ -305,17 +366,30 @@ OvsCancelIrp(PDEVICE_OBJECT deviceObject,
> if (fileObject == NULL) {
> goto done;
> }
> - OvsAcquireEventQueueLock();
> +
> instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;
> - if (instance == NULL || instance->eventQueue == NULL) {
> - OvsReleaseEventQueueLock();
> + if (instance == NULL) {
> + goto done;
> + }
> +
> + status = OvsGetMcastEventId(instance->protocol,
> + instance->mcastMask,
> + &eventId);
> + if (status != NDIS_STATUS_SUCCESS) {
> + goto done;
> + }
> +
> + OvsAcquireEventQueueLock(eventId);
> + if (instance->eventQueue == NULL) {
> + OvsReleaseEventQueueLock(eventId);
> goto done;
> }
> +
> queue = instance->eventQueue;
> if (queue->pendingIrp == irp) {
> queue->pendingIrp = NULL;
> }
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(eventId);
> done:
> OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED);
> }
> @@ -346,6 +420,7 @@ OvsWaitEventIoctl(PIRP irp,
> POVS_OPEN_INSTANCE instance;
> BOOLEAN cancelled = FALSE;
> PDRIVER_CANCEL cancelRoutine;
> + UINT32 eventId;
>
> OVS_LOG_TRACE("Enter: inputLength: %u", inputLength);
>
> @@ -362,7 +437,14 @@ OvsWaitEventIoctl(PIRP irp,
> return STATUS_INVALID_PARAMETER;
> }
>
> - OvsAcquireEventQueueLock();
> + status = OvsGetMcastEventId(instance->protocol,
> + instance->mcastMask,
> + &eventId);
> + if (status != NDIS_STATUS_SUCCESS) {
> + return STATUS_INVALID_PARAMETER;
> + }
> + OvsAcquireEventQueueLock(eventId);
> +
> queue = (POVS_EVENT_QUEUE)instance->eventQueue;
> if (queue == NULL) {
> OVS_LOG_TRACE("Exit: Event queue does not exist");
> @@ -388,7 +470,7 @@ OvsWaitEventIoctl(PIRP irp,
> }
>
> unlock:
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(eventId);
> if (cancelled) {
> OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED);
> OVS_LOG_INFO("Event IRP cancelled: %p", irp);
> @@ -414,7 +496,7 @@ OvsRemoveVportEventEntry(POVS_OPEN_INSTANCE instance,
> POVS_EVENT_QUEUE queue;
> POVS_EVENT_QUEUE_ELEM elem;
>
> - OvsAcquireEventQueueLock();
> + OvsAcquireEventQueueLock(OVS_MCAST_VPORT_EVENT);
>
> queue = (POVS_EVENT_QUEUE)instance->eventQueue;
>
> @@ -432,6 +514,105 @@ OvsRemoveVportEventEntry(POVS_OPEN_INSTANCE instance,
> }
>
> remove_event_done:
> - OvsReleaseEventQueueLock();
> + OvsReleaseEventQueueLock(OVS_MCAST_VPORT_EVENT);
> + return status;
> +}
> +
> +/*
> + *
> --------------------------------------------------------------------------
> + * OvsPostCtEvent - used to post a Conntrack related event
> + *
> + * Side effects: User thread may be woken up.
> + * XXX - Try to consolidate PostEvent for Vport/Ct events
> + *
> --------------------------------------------------------------------------
> + */
> +VOID
> +OvsPostCtEvent(POVS_CT_EVENT_ENTRY ctEvent)
> +{
> + POVS_EVENT_QUEUE_ELEM elem;
> + POVS_EVENT_QUEUE queue;
> + PLIST_ENTRY link;
> + LIST_ENTRY list;
> + PLIST_ENTRY entry;
> + PIRP irp;
> +
> + InitializeListHead(&list);
> +
> + OvsAcquireEventQueueLock(OVS_MCAST_CT_EVENT);
> +
> + LIST_FORALL(&ovsEventQueueArr[OVS_MCAST_CT_EVENT], link) {
> + queue = CONTAINING_RECORD(link, OVS_EVENT_QUEUE, queueLink);
> + if ((ctEvent->type & queue->mask) == 0) {
> + continue;
> + }
> + ctEvent->type &= queue->mask;
> +
> + elem = (POVS_EVENT_QUEUE_ELEM)OvsAllocateMemoryWithTag(
> + sizeof(*elem), OVS_EVENT_POOL_TAG);
> +
> + if (elem == NULL) {
> + OvsReleaseEventQueueLock(OVS_MCAST_CT_EVENT);
> + return;
> + }
> +
> + RtlCopyMemory(&elem->ctEvent, ctEvent, sizeof elem->ctEvent);
> + InsertTailList(&queue->elemList, &elem->link);
> + queue->numElems++;
> +
> + if (queue->pendingIrp != NULL) {
> + PDRIVER_CANCEL cancelRoutine;
> + irp = queue->pendingIrp;
> + queue->pendingIrp = NULL;
> + cancelRoutine = IoSetCancelRoutine(irp, NULL);
> + if (cancelRoutine) {
> + InsertTailList(&list, &irp->Tail.Overlay.ListEntry);
> + }
> + }
> + }
> +
> + OvsReleaseEventQueueLock(OVS_MCAST_CT_EVENT);
> + while (!IsListEmpty(&list)) {
> + entry = RemoveHeadList(&list);
> + irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
> + OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);
> + }
> +}
> +
> +/*
> +
> *--------------------------------------------------------------------------
> + * Poll event queued in the event queue.always synchronous.
> + *
> + * Results:
> + * STATUS_SUCCESS event was dequeued
> + * STATUS_UNSUCCESSFUL the queue is empty.
> + *
> --------------------------------------------------------------------------
> + */
> +NTSTATUS
> +OvsRemoveCtEventEntry(POVS_OPEN_INSTANCE instance,
> + POVS_CT_EVENT_ENTRY entry)
> +{
> + NTSTATUS status = STATUS_UNSUCCESSFUL;
> + POVS_EVENT_QUEUE queue;
> + POVS_EVENT_QUEUE_ELEM elem;
> +
> + OvsAcquireEventQueueLock(OVS_MCAST_CT_EVENT);
> +
> + queue = (POVS_EVENT_QUEUE)instance->eventQueue;
> +
> + if (queue == NULL) {
> + ASSERT(queue);
> + goto remove_event_done;
> + }
> +
> + if (queue->numElems) {
> + elem = (POVS_EVENT_QUEUE_ELEM)RemoveHeadList(&queue->elemList);
> + *entry = elem->ctEvent;
> + OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG);
> + queue->numElems--;
> + status = STATUS_SUCCESS;
> + }
> +
> +remove_event_done:
> + OvsReleaseEventQueueLock(OVS_MCAST_CT_EVENT);
> return status;
> }
> diff --git a/datapath-windows/ovsext/Event.h
> b/datapath-windows/ovsext/Event.h
> index 255594c..b579463 100644
> --- a/datapath-windows/ovsext/Event.h
> +++ b/datapath-windows/ovsext/Event.h
> @@ -16,16 +16,28 @@
>
> #ifndef __EVENT_H_
> #define __EVENT_H_ 1
> +#include "Conntrack.h"
> +
> +typedef struct _OVS_CT_EVENT_ENTRY {
> + OVS_CT_ENTRY entry;
> + UINT8 type;
> + UINT64 pad[10];
> +} OVS_CT_EVENT_ENTRY, *POVS_CT_EVENT_ENTRY;
>
> typedef struct _OVS_EVENT_QUEUE_ELEM {
> LIST_ENTRY link;
> - OVS_VPORT_EVENT_ENTRY vportEvent;
> + union {
> + OVS_VPORT_EVENT_ENTRY vportEvent;
> + OVS_CT_EVENT_ENTRY ctEvent;
> + };
> } OVS_EVENT_QUEUE_ELEM, *POVS_EVENT_QUEUE_ELEM;
>
> typedef struct _OVS_EVENT_QUEUE {
> LIST_ENTRY queueLink;
> LIST_ENTRY elemList;
> UINT32 mask;
> + UINT32 mcastEventId;
> + UINT32 protocol;
> UINT16 numElems;
> BOOLEAN pollAll;
> PIRP pendingIrp;
> @@ -39,6 +51,7 @@ struct _OVS_OPEN_INSTANCE;
>
> VOID OvsCleanupEvent(struct _OVS_OPEN_INSTANCE *instance);
> VOID OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event);
> +VOID OvsPostCtEvent(POVS_CT_EVENT_ENTRY ctEvent);
> NTSTATUS OvsSubscribeEventIoctl(PFILE_OBJECT fileObject, PVOID
> inputBuffer,
> UINT32 inputLength);
> NTSTATUS OvsPollEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer,
> @@ -48,5 +61,7 @@ NTSTATUS OvsWaitEventIoctl(PIRP irp, PFILE_OBJECT
> fileObject,
> PVOID inputBuffer, UINT32 inputLength);
> NTSTATUS OvsRemoveVportEventEntry(POVS_OPEN_INSTANCE instance,
> POVS_VPORT_EVENT_ENTRY entry);
> +NTSTATUS OvsRemoveCtEventEntry(POVS_OPEN_INSTANCE instance,
> + POVS_CT_EVENT_ENTRY entry);
>
> #endif /* __EVENT_H_ */
> --
> 2.9.0.windows.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
More information about the dev
mailing list