[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 |