[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