|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 1/2] Introduce per-dpc rate limits for XenVif / XeNet Rx path.
This patch allows XenNet to keep track of how many packets have
been processed in a "batch" (per DPC), and to ask XenVif to stop
the current batch once some predefined limit has been met.
Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx>
---
include/revision.h | 3 +-
include/vif_interface.h | 7 ++-
src/xenvif/receiver.c | 79 ++++++++++++++++++-------
src/xenvif/vif.c | 124 ++++++++++++++++++++++++++++++++++------
src/xenvif/vif.h | 2 +-
5 files changed, 173 insertions(+), 42 deletions(-)
diff --git a/include/revision.h b/include/revision.h
index 39476b2..475700d 100644
--- a/include/revision.h
+++ b/include/revision.h
@@ -44,6 +44,7 @@
DEFINE_REVISION(0x0800000C, 1, 7, 2, 1), \
DEFINE_REVISION(0x0800000D, 1, 8, 2, 1), \
DEFINE_REVISION(0x09000000, 1, 8, 2, 1), \
- DEFINE_REVISION(0x09000001, 2, 8, 2, 1)
+ DEFINE_REVISION(0x09000001, 2, 8, 2, 1), \
+ DEFINE_REVISION(0x09000002, 2, 9, 2, 1)
#endif // _REVISION_H
diff --git a/include/vif_interface.h b/include/vif_interface.h
index 20de314..c034657 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -928,7 +928,10 @@ struct _XENVIF_VIF_INTERFACE_V8 {
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
};
-typedef struct _XENVIF_VIF_INTERFACE_V8 XENVIF_VIF_INTERFACE,
*PXENVIF_VIF_INTERFACE;
+/* V9 is exactly the same as V8 */
+typedef struct _XENVIF_VIF_INTERFACE_V8 XENVIF_VIF_INTERFACE_V9;
+
+typedef XENVIF_VIF_INTERFACE_V9 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
/*! \def XENVIF_VIF
\brief Macro at assist in method invocation
@@ -939,6 +942,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V8
XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER
#endif // _WINDLL
#define XENVIF_VIF_INTERFACE_VERSION_MIN 6
-#define XENVIF_VIF_INTERFACE_VERSION_MAX 8
+#define XENVIF_VIF_INTERFACE_VERSION_MAX 9
#endif // _XENVIF_INTERFACE_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 505505e..0c1be81 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;
@@ -1338,43 +1340,53 @@ __ReceiverRingSwizzle(
PXENVIF_VIF_CONTEXT Context;
LIST_ENTRY List;
PLIST_ENTRY ListEntry;
+ BOOLEAN AllFlushed;
+ BOOLEAN NdisFinishedBatch;
Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;
Context = PdoGetVifContext(FrontendGetPdo(Frontend));
+ AllFlushed = TRUE;
+ NdisFinishedBatch = FALSE;
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) &&
+ (!NdisFinishedBatch || Ring->FinalFlush)) {
PXENVIF_RECEIVER_PACKET Packet;
PXENVIF_PACKET_INFO Info;
PUCHAR BaseVa;
@@ -1527,7 +1539,7 @@ __ReceiverRingSwizzle(
(VOID) InterlockedIncrement(&Receiver->Loaned);
- VifReceiverQueuePacket(Context,
+ NdisFinishedBatch = VifReceiverQueuePacket(Context,
Ring->Index,
&Packet->Mdl,
Packet->Offset,
@@ -1537,9 +1549,28 @@ __ReceiverRingSwizzle(
Packet->TagControlInformation,
&Packet->Info,
&Packet->Hash,
- !IsListEmpty(&Ring->PacketComplete) ? TRUE :
FALSE,
+ !IsListEmpty(&Ring->PacketComplete), /* Keep
this in - resets counts in xennet */
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 +2021,7 @@ ReceiverRingPoll(
Count = 0;
- if (!Ring->Enabled)
+ if (!Ring->Enabled || (Ring->Backpressured && !Ring->FinalFlush))
goto done;
for (;;) {
@@ -2963,8 +2994,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);
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index 69ced78..b026e5b 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -918,6 +918,36 @@ static struct _XENVIF_VIF_INTERFACE_V8
VifInterfaceVersion8 = {
VifMacQueryFilterLevel
};
+static XENVIF_VIF_INTERFACE_V9 VifInterfaceVersion9 = {
+ { sizeof (XENVIF_VIF_INTERFACE_V9), 9, NULL, NULL, NULL },
+ VifAcquire,
+ VifRelease,
+ VifEnable,
+ VifDisable,
+ VifQueryStatistic,
+ VifQueryRingCount,
+ VifUpdateHashMapping,
+ VifReceiverReturnPacket,
+ VifReceiverSetOffloadOptions,
+ VifReceiverSetBackfillSize,
+ VifReceiverQueryRingSize,
+ VifReceiverSetHashAlgorithm,
+ VifReceiverQueryHashCapabilities,
+ VifReceiverUpdateHashParameters,
+ VifTransmitterQueuePacket,
+ VifTransmitterQueryOffloadOptions,
+ VifTransmitterQueryLargePacketSize,
+ VifTransmitterQueryRingSize,
+ VifMacQueryState,
+ VifMacQueryMaximumFrameSize,
+ VifMacQueryPermanentAddress,
+ VifMacQueryCurrentAddress,
+ VifMacQueryMulticastAddresses,
+ VifMacSetMulticastAddresses,
+ VifMacSetFilterLevel,
+ VifMacQueryFilterLevel
+};
+
NTSTATUS
VifInitialize(
IN PXENVIF_PDO Pdo,
@@ -1033,6 +1063,23 @@ VifGetInterface(
status = STATUS_SUCCESS;
break;
}
+ case 9: {
+ XENVIF_VIF_INTERFACE_V9 *VifInterface;
+
+ VifInterface = (XENVIF_VIF_INTERFACE_V9 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (XENVIF_VIF_INTERFACE_V9))
+ break;
+
+ *VifInterface = VifInterfaceVersion9;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;
@@ -1133,7 +1180,7 @@ __VifReceiverQueuePacketVersion7(
}
static FORCEINLINE VOID
-__VifReceiverQueuePacket(
+__VifReceiverQueuePacketVersion8(
IN PXENVIF_VIF_CONTEXT Context,
IN ULONG Index,
IN PMDL Mdl,
@@ -1164,7 +1211,42 @@ __VifReceiverQueuePacket(
}
-VOID
+static FORCEINLINE BOOLEAN
+__VifReceiverQueuePacket(
+ IN PXENVIF_VIF_CONTEXT Context,
+ IN ULONG Index,
+ IN PMDL Mdl,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN XENVIF_PACKET_CHECKSUM_FLAGS Flags,
+ IN USHORT MaximumSegmentSize,
+ IN USHORT TagControlInformation,
+ IN PXENVIF_PACKET_INFO Info,
+ IN PXENVIF_PACKET_HASH Hash,
+ IN BOOLEAN More,
+ IN PVOID Cookie
+ )
+{
+ BOOLEAN Finished = FALSE;
+ Context->Callback(Context->Argument,
+ XENVIF_RECEIVER_QUEUE_PACKET,
+ Index,
+ Mdl,
+ Offset,
+ Length,
+ Flags,
+ MaximumSegmentSize,
+ TagControlInformation,
+ Info,
+ Hash,
+ More,
+ Cookie,
+ &Finished);
+ return Finished;
+}
+
+
+BOOLEAN /* Returns NDIS finished batch for this DPC */
VifReceiverQueuePacket(
IN PXENVIF_VIF_CONTEXT Context,
IN ULONG Index,
@@ -1181,6 +1263,7 @@ VifReceiverQueuePacket(
)
{
KIRQL Irql;
+ BOOLEAN Finished = FALSE;
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
@@ -1216,7 +1299,22 @@ VifReceiverQueuePacket(
break;
case 8:
- __VifReceiverQueuePacket(Context,
+ __VifReceiverQueuePacketVersion8(Context,
+ Index,
+ Mdl,
+ Offset,
+ Length,
+ Flags,
+ MaximumSegmentSize,
+ TagControlInformation,
+ Info,
+ Hash,
+ More,
+ Cookie);
+ break;
+
+ case 9:
+ Finished = __VifReceiverQueuePacket(Context,
Index,
Mdl,
Offset,
@@ -1236,6 +1334,8 @@ VifReceiverQueuePacket(
}
KeLowerIrql(Irql);
+
+ return Finished;
}
VOID
@@ -1245,20 +1345,12 @@ VifTransmitterReturnPacket(
IN PXENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion
)
{
- switch (Context->Version) {
- case 6:
- case 7:
- case 8:
- Context->Callback(Context->Argument,
- XENVIF_TRANSMITTER_RETURN_PACKET,
- Cookie,
- Completion);
- break;
+ BUG_ON(Context->Version < 6);
- default:
- ASSERT(FALSE);
- break;
- }
+ Context->Callback(Context->Argument,
+ XENVIF_TRANSMITTER_RETURN_PACKET,
+ Cookie,
+ Completion);
}
PXENVIF_THREAD
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index b83a767..054cef1 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -62,7 +62,7 @@ VifTeardown(
// CALLBACKS
-extern VOID
+extern BOOLEAN
VifReceiverQueuePacket(
IN PXENVIF_VIF_CONTEXT Context,
IN ULONG Index,
--
2.25.0.windows.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |