Acked-by: Paul Boca <pb...@cloudbasesolutions.com>
> -----Original Message----- > From: dev [mailto:dev-boun...@openvswitch.org] On Behalf Of Sairam > Venugopal > Sent: Thursday, July 14, 2016 2:39 AM > To: dev@openvswitch.org > Subject: [ovs-dev] [PATCH 7/9] datapath-windows: Add support for multiple > event queue in Event.c > > Update Event.c to have multiple event queues and mechanism to retrieve the > associated queue. Introduce OvsPostCtEvent and OvsRemoveCtEventEntry > similar to OvsPostVportEvent and OvsRemoveVportEventEntry. > > Signed-off-by: Sairam Venugopal <vsai...@vmware.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..ffc32a6 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_ENTRIES_MAX]; > +static NDIS_SPIN_LOCK > eventQueueLockArr[OVS_MCAST_EVENT_ENTRIES_MAX]; > +UINT32 ovsNumEventQueueArr[OVS_MCAST_EVENT_ENTRIES_MAX]; > > NTSTATUS > OvsInitEventQueue() > { > - InitializeListHead(&ovsEventQueue); > - NdisAllocateSpinLock(&eventQueueLock); > + for (int i = 0; i < OVS_MCAST_EVENT_ENTRIES_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_ENTRIES_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@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev