[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] Rate limit per DPC in Xenvif only.


  • To: <win-pv-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
  • Date: Fri, 20 May 2022 15:14:15 +0100
  • Authentication-results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: Owen Smith <owen.smith@xxxxxxxxxx>, Martin Harvey <Martin.Harvey@xxxxxxxxxx>
  • Delivery-date: Fri, 20 May 2022 14:14:46 +0000
  • Ironport-data: A9a23:cGRApa1/5aiUgr5JUvbD5ZRxkn2cJEfYwER7XKvMYLTBsI5bpzUAm GNJW27UOK6NYjCgeYh1ad7g/EoCvJbXmoJqTFFqpC1hF35El5HIVI+TRqvS04J+DSFhoGZPt Zh2hgzodZhsJpPkjk7xdOCn9xGQ7InQLlbGILes1htZGEk1EU/NtTo5w7Rj2tMy2YDga++wk YiaT/P3aQfNNwFcagr424rbwP+4lK2v0N+wlgVWicFj5DcypVFMZH4sDfjZw0/DaptVBoaHq 9Prl9lVyI97EyAFUbtJmp6jGqEDryW70QKm0hK6UID66vROS7BbPg/W+5PwZG8O4whlkeydx /1pvIfuWRoVZpSdhccCfj5oGHhAMpB/reqvzXiX6aR/zmXDenrohf5vEFs3LcsT/eMf7WNmr KJCbmpXN1ba2rzwkOnTpupE36zPKOHuNZkDu3cmzTjDE/s3aZvCX7/L9ZlT2zJYasVmQqqFP pFAOWAHgBLoMh5hIFw5BMIEx8iXilvbSBkIr1i/nP9ii4TU5FMoi+W8WDbPQfSVRMMQhljdq m/Y8mDRBhABKMfZ2TeD6mirhOLEgWX8Qo16KVGj3qc02hvJnDVVUUBIEwvgyRWktqKgc/ZWM BIE5xZ2lPkv11OGaen2BiO3nUfR63bwROFs//0GBBClk/SJuF7AXjZYEVate/R96pZoGGVCO kuh2oqwWGcx6OD9pWe1rO/8kN+kBcQCwYbujwcgRBBN3dTsqZpbYvnnHoc6S/7dYjEY9FjNL 9G2QMsW3ex7YTYjjfnTwLw+q2vESmL1ZgA0/B7LeWmu8xl0YoWoD6TxtwWBvacQfNjAFQfb1 JThpyR5xLlRZaxhaQTXGLlddF1Xz6vt3MLgba5HQMB6qmXFF4+LdoFM+jBuTHqFwe5dEQIFl HT74FsLjLcKZSPCRfYuP+qZVpR7pYC9RI+Nfq2FMbJzjm1ZKVbvENdGPhXLgQgAUSEEzMkCB HtsWZ33XSpKV/42k2beqiV0+eZD+x3SDFj7HfjTpylLG5LFDJJJYd/p6GezU90=
  • Ironport-hdrordr: A9a23:3znjA6DqnTpzMLzlHemm55DYdb4zR+YMi2TC1yhKJiC9Ffbo8v xG/c5rsiMc5wxxZJhNo7290cq7MBHhHPxOgbX5VI3KNGKNhILBFvAH0WKI+VPd8kPFmtK1rZ 0QEJRDNA==
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

From: Owen Smith <owen.smith@xxxxxxxxxx>

Change the receive algorithm, such that, for any particular receive DPC,
only a fixed number of packets can be pushed up the stack. Under higher
load conditions, another DPC is scheduled to process the remainder
before any more packets are removed from the descriptor ring.

This functionality currently local to xenvif. A more complete
solution, where xennet determines when to finish a batch
of packets will be included in a subsequent patch.

Signed-off-by: Martin Harvey <Martin.Harvey@xxxxxxxxxx>

Ported-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvif/receiver.c | 82 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 61 insertions(+), 21 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 505505e..f8bfdd4 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -99,6 +99,8 @@ typedef struct _XENVIF_RECEIVER_RING {
     BOOLEAN                     Connected;
     BOOLEAN                     Enabled;
     BOOLEAN                     Stopped;
+    BOOLEAN                     Backpressured;
+    BOOLEAN                     FinalFlush;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
     ULONG                       BackfillSize;
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
@@ -148,6 +150,8 @@ struct _XENVIF_RECEIVER {
 
 #define XENVIF_RECEIVER_TAG 'ECER'
 
+#define RX_BUFFERING_MAX             2048 // X-ref XenNet IN_NDIS_MAX (half in 
NDIS half elsewhere)
+
 static FORCEINLINE PVOID
 __ReceiverAllocate(
     IN  ULONG   Length
@@ -1338,43 +1342,53 @@ __ReceiverRingSwizzle(
     PXENVIF_VIF_CONTEXT         Context;
     LIST_ENTRY                  List;
     PLIST_ENTRY                 ListEntry;
+    BOOLEAN                     AllFlushed;
+    ULONG                       PushedUpstream;
 
     Receiver = Ring->Receiver;
     Frontend = Receiver->Frontend;
     Context = PdoGetVifContext(FrontendGetPdo(Frontend));
+    AllFlushed = TRUE;
+    PushedUpstream = 0;
 
     InitializeListHead(&List);
 
-    ListEntry = InterlockedExchangePointer(&Ring->PacketQueue, NULL);
+    if (IsListEmpty(&Ring->PacketComplete) || Ring->FinalFlush)
+    {
+        ListEntry = InterlockedExchangePointer(&Ring->PacketQueue, NULL);
 
-    // Packets are held in the queue in reverse order so that the most
-    // recent is always head of the list. This is necessary to allow
-    // addition to the list to be done atomically.
+        // Packets are held in the queue in reverse order so that the most
+        // recent is always head of the list. This is necessary to allow
+        // addition to the list to be done atomically.
 
-    while (ListEntry != NULL) {
-        PLIST_ENTRY NextEntry;
+        while (ListEntry != NULL) {
+            PLIST_ENTRY NextEntry;
 
-        NextEntry = ListEntry->Blink;
-        ListEntry->Flink = ListEntry->Blink = ListEntry;
+            NextEntry = ListEntry->Blink;
+            ListEntry->Flink = ListEntry->Blink = ListEntry;
 
-        InsertHeadList(&List, ListEntry);
+            InsertHeadList(&List, ListEntry);
 
-        ListEntry = NextEntry;
-    }
+            ListEntry = NextEntry;
+        }
 
-    while (!IsListEmpty(&List)) {
-        PXENVIF_RECEIVER_PACKET Packet;
+        while (!IsListEmpty(&List)) {
+            PXENVIF_RECEIVER_PACKET Packet;
 
-        ListEntry = RemoveHeadList(&List);
-        ASSERT3P(ListEntry, !=, &List);
+            ListEntry = RemoveHeadList(&List);
+            ASSERT3P(ListEntry, !=, &List);
 
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+            RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-        Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, 
ListEntry);
-        ReceiverRingProcessPacket(Ring, Packet);
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, 
ListEntry);
+            ReceiverRingProcessPacket(Ring, Packet);
+        }
+    } else {
+        AllFlushed = FALSE;
     }
 
-    while (!IsListEmpty(&Ring->PacketComplete)) {
+    while (!IsListEmpty(&Ring->PacketComplete) &&
+           ((PushedUpstream < RX_BUFFERING_MAX) || Ring->FinalFlush)) {
         PXENVIF_RECEIVER_PACKET Packet;
         PXENVIF_PACKET_INFO     Info;
         PUCHAR                  BaseVa;
@@ -1382,6 +1396,8 @@ __ReceiverRingSwizzle(
         PETHERNET_ADDRESS       DestinationAddress;
         ETHERNET_ADDRESS_TYPE   Type;
 
+        PushedUpstream++;
+
         ListEntry = RemoveHeadList(&Ring->PacketComplete);
         ASSERT3P(ListEntry, !=, &Ring->PacketComplete);
 
@@ -1537,9 +1553,29 @@ __ReceiverRingSwizzle(
                                Packet->TagControlInformation,
                                &Packet->Info,
                                &Packet->Hash,
-                               !IsListEmpty(&Ring->PacketComplete) ? TRUE : 
FALSE,
+                               ((!IsListEmpty(&Ring->PacketComplete)) &&
+                               ((PushedUpstream < RX_BUFFERING_MAX) || 
Ring->FinalFlush)) ? TRUE : FALSE,
                                Packet);
     }
+
+    if (!IsListEmpty(&Ring->PacketComplete))
+        AllFlushed = FALSE;
+
+    if (!AllFlushed) {
+        //Re-run remainder from back of DPC queue.
+        Ring->Backpressured = TRUE;
+        if (KeInsertQueueDpc(&Ring->QueueDpc, NULL, NULL))
+            Ring->QueueDpcs++;
+    } else {
+        if ((Ring->Backpressured) && !Ring->FinalFlush) {
+            //Not any more - restart dataflow from initial ring poll.
+            Ring->Backpressured = FALSE;
+
+            //PollDpc zeroed before final flush, don't queue it here.
+            if (KeInsertQueueDpc(&Ring->PollDpc, NULL, NULL))
+                Ring->PollDpcs++;
+        }
+    }
 }
 
 static FORCEINLINE VOID
@@ -1990,7 +2026,7 @@ ReceiverRingPoll(
 
     Count = 0;
 
-    if (!Ring->Enabled)
+    if (!Ring->Enabled || (Ring->Backpressured && !Ring->FinalFlush))
         goto done;
 
     for (;;) {
@@ -2963,8 +2999,12 @@ __ReceiverRingTeardown(
     Ring->BackfillSize = 0;
     Ring->OffloadOptions.Value = 0;
 
+    Ring->FinalFlush = TRUE;
+    KeInsertQueueDpc(&Ring->QueueDpc, NULL, NULL);
     KeFlushQueuedDpcs();
     RtlZeroMemory(&Ring->QueueDpc, sizeof (KDPC));
+    Ring->Backpressured = FALSE;
+    Ring->FinalFlush = FALSE;
 
     ThreadAlert(Ring->WatchdogThread);
     ThreadJoin(Ring->WatchdogThread);
-- 
2.25.0.windows.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.