[ovs-dev] [PATCH v2 5/7] datapath-windows: Add support for multiple event queue in Event.c

Sairam Venugopal vsairam at vmware.com
Tue Jul 26 00:04:41 UTC 2016


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




More information about the dev mailing list