[ovs-dev] [PATCH 3/5] datapath-windows: Multiple NBLs support for ingress data path

Sorin Vinturis svinturis at cloudbasesolutions.com
Thu Apr 23 21:05:15 UTC 2015


Added support for creating and handling multiple NBLs with only one NB
for ingress data path.

Signed-off-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
Reported-by: Alessandro Pilotti <apilotti at cloudbasesolutions.com>
Reported-at: https://github.com/openvswitch/ovs-issues/issues/2

---
 datapath-windows/ovsext/PacketIO.c | 91 ++++++++++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 19 deletions(-)

diff --git a/datapath-windows/ovsext/PacketIO.c b/datapath-windows/ovsext/PacketIO.c
index 69d7110..7d20ef2 100644
--- a/datapath-windows/ovsext/PacketIO.c
+++ b/datapath-windows/ovsext/PacketIO.c
@@ -44,6 +44,10 @@ extern NDIS_STRING ovsExtFriendlyNameUC;
 static VOID OvsFinalizeCompletionList(OvsCompletionList *completionList);
 static VOID OvsCompleteNBLIngress(POVS_SWITCH_CONTEXT switchContext,
                     PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags);
+static NTSTATUS OvsCreateNewNBLsFromMultipleNBs(
+                    POVS_SWITCH_CONTEXT switchContext,
+                    PNET_BUFFER_LIST *curNbl,
+                    PNET_BUFFER_LIST *nextNbl);
 
 __inline VOID
 OvsInitCompletionList(OvsCompletionList *completionList,
@@ -235,6 +239,7 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext,
         OvsFlowKey key;
         UINT64 hash;
         PNET_BUFFER curNb;
+        POVS_BUFFER_CONTEXT ctx;
         BOOLEAN isRecv = FALSE;
 
         nextNbl = curNbl->Next;
@@ -259,18 +264,35 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext,
         }
 #endif
 
-        /* Ethernet Header is a guaranteed safe access. */
-        curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
-        if (curNb->Next != NULL) {
-            /* XXX: This case is not handled yet. */
+        ctx = OvsInitExternalNBLContext(switchContext, curNbl, isRecv);
+        if (ctx == NULL) {
             RtlInitUnicodeString(&filterReason,
-                L"Dropping NBLs with multiple NBs");
+                L"Cannot allocate external NBL context.");
+
             OvsStartNBLIngressError(switchContext, curNbl,
                                     sendCompleteFlags, &filterReason,
                                     NDIS_STATUS_RESOURCES);
             continue;
-        } else {
-            POVS_BUFFER_CONTEXT ctx;
+        }
+
+        /* Ethernet Header is a guaranteed safe access. */
+        curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);
+        if (curNb->Next != NULL) {
+            /* Create a NET_BUFFER_LIST for each NET_BUFFER. */
+            status = OvsCreateNewNBLsFromMultipleNBs(switchContext,
+                                                     &curNbl,
+                                                     &nextNbl);
+            if (!NT_SUCCESS(status)) {
+                RtlInitUnicodeString(&filterReason,
+                                     L"Cannot allocate NBLs with single NB.");
+
+                OvsStartNBLIngressError(switchContext, curNbl,
+                                        sendCompleteFlags, &filterReason,
+                                        NDIS_STATUS_RESOURCES);
+                continue;
+            }
+        }
+        {
             OvsFlow *flow;
 
             /* Take the DispatchLock so none of the VPORTs disconnect while
@@ -281,18 +303,6 @@ OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext,
             NdisAcquireRWLockRead(switchContext->dispatchLock, &lockState,
                                   dispatch);
 
-            ctx = OvsInitExternalNBLContext(switchContext, curNbl, isRecv);
-            if (ctx == NULL) {
-                RtlInitUnicodeString(&filterReason,
-                                     L"Cannot allocate external NBL context.");
-
-                OvsStartNBLIngressError(switchContext, curNbl,
-                                        sendCompleteFlags, &filterReason,
-                                        NDIS_STATUS_RESOURCES);
-                NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
-                continue;
-            }
-
             vport = OvsFindVportByPortIdAndNicIndex(switchContext, sourcePort,
                                                     sourceIndex);
             if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) {
@@ -483,3 +493,46 @@ OvsExtCancelSendNBL(NDIS_HANDLE filterModuleContext,
     /* All send requests get completed synchronously, so there is no need to
      * implement this callback. */
 }
+
+static NTSTATUS
+OvsCreateNewNBLsFromMultipleNBs(POVS_SWITCH_CONTEXT switchContext,
+                                PNET_BUFFER_LIST *curNbl,
+                                PNET_BUFFER_LIST *nextNbl)
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    PNET_BUFFER_LIST newNbls = NULL;
+    PNET_BUFFER_LIST lastNbl = NULL;
+    PNET_BUFFER_LIST nbl = NULL;
+    POVS_BUFFER_CONTEXT bufContext = NULL;
+    BOOLEAN error = TRUE;
+
+    do {
+        /* Decrement buffer context reference count. */
+        bufContext = (POVS_BUFFER_CONTEXT)
+            NET_BUFFER_LIST_CONTEXT_DATA_START(*curNbl);
+        InterlockedDecrement((volatile LONG*)&bufContext->refCount);
+
+        /* Create new NBLs from curNbl with multiple net buffers. */
+        newNbls = OvsPartialCopyToMultipleNBLs(switchContext,
+                                               *curNbl, 0, 0, TRUE);
+        if (NULL == newNbls) {
+            OVS_LOG_ERROR("Failed to allocate NBLs with single NB.");
+            status = NDIS_STATUS_RESOURCES;
+            break;
+        }
+
+        nbl = newNbls;
+        while (nbl) {
+            lastNbl = nbl;
+            nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+        }
+        lastNbl->Next = *nextNbl;
+        *nextNbl = newNbls->Next;
+        *curNbl = newNbls;
+        (*curNbl)->Next = NULL;
+
+        error = FALSE;
+    } while (error);
+
+    return status;
+}
-- 
1.9.0.msysgit.0



More information about the dev mailing list