|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 2/2] xennet: improve NBL batching receive path
Raise NblBatchMax default to 32 (max 64). Split batches at EtherType
boundaries and set NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE per batch.
In __ReceiverPushPackets, sample Returned before the InterlockedAdd
so it is read prior to the implicit full memory barrier that
InterlockedAdd provides. Use the return value of InterlockedAdd
directly as Indicated and remove the now-redundant KeMemoryBarrier.
Return early when queue is empty.
Assisted-by: Claude (AI assistant)
Signed-off-by: david ambu <david.preetham@xxxxxxxxxx>
---
src/xennet.inf | 6 +++
src/xennet/adapter.c | 13 +++++
src/xennet/adapter.h | 8 +++
src/xennet/receiver.c | 112 +++++++++++++++++++++++++++++++-----------
4 files changed, 109 insertions(+), 30 deletions(-)
diff --git a/src/xennet.inf b/src/xennet.inf
index 55e11a2..79730e8 100644
--- a/src/xennet.inf
+++ b/src/xennet.inf
@@ -186,6 +186,11 @@ HKR, Ndi\params\*NumRSSQueues, Default,
0, "8"
HKR, Ndi\params\*NumRSSQueues, Min, 0, "1"
HKR, Ndi\params\*NumRSSQueues, Max, 0, "8"
+HKR, Ndi\Params\NblBatchMax, ParamDesc,
0, %NblBatchMax%
+HKR, Ndi\Params\NblBatchMax, Type,
0, "int"
+HKR, Ndi\Params\NblBatchMax, Default,
0, "32"
+HKR, Ndi\Params\NblBatchMax, Min,
0, "1"
+HKR, Ndi\Params\NblBatchMax, Max,
0, "64"
[XenNet_Inst.Services]
AddService=xennet,0x02,XenNet_Service,XenNet_EventLog
@@ -248,6 +253,7 @@ Enabled="Enabled"
Enabled-Rx="Rx Enabled"
Enabled-Tx="Tx Enabled"
Enabled-TxRx="Rx & Tx Enabled"
+NblBatchMax="Max Receive Indicate NBLS"
SERVICE_BOOT_START=0x0
SERVICE_SYSTEM_START=0x1
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index f79c0c8..6e5a95a 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -63,6 +63,7 @@ typedef struct _PROPERTIES {
int lrov6;
int rss;
int numrssqueues;
+ int nblbatchmax;
} PROPERTIES, *PPROPERTIES;
typedef struct _XENNET_RSS {
@@ -1480,6 +1481,17 @@ AdapterGetHandle(
return Adapter->NdisAdapterHandle;
}
+ULONG
+AdapterGetNblMaxBatchSize(
+ IN PXENNET_ADAPTER Adapter
+ )
+{
+ ULONG val = (ULONG)Adapter->Properties.nblbatchmax;
+ if (val == 0 || val > NBL_BATCH_SIZE_MAX)
+ return NBL_BATCH_SIZE_DEFAULT;
+ return val;
+}
+
PXENVIF_VIF_INTERFACE
AdapterGetVifInterface(
IN PXENNET_ADAPTER Adapter
@@ -2939,6 +2951,7 @@ AdapterGetAdvancedSettings(
READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue",
1, Handle);
READ_PROPERTY(Adapter->Properties.rss, L"*RSS", 1, Handle);
READ_PROPERTY(Adapter->Properties.numrssqueues, L"*NumRSSQueues", 8,
Handle);
+ READ_PROPERTY(Adapter->Properties.nblbatchmax, L"NblBatchMax",
NBL_BATCH_SIZE_DEFAULT, Handle);
NdisCloseConfiguration(Handle);
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index 2ea0345..a54cb4d 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -121,4 +121,12 @@ AdapterQueryInformation(
IN PNDIS_OID_REQUEST Request
);
+#define NBL_BATCH_SIZE_DEFAULT 32
+#define NBL_BATCH_SIZE_MAX 64
+
+extern ULONG
+AdapterGetNblMaxBatchSize(
+ IN PXENNET_ADAPTER Adapter
+ );
+
#endif // _XENNET_ADAPTER_H_
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index b4cf4f0..55492f2 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -34,6 +34,7 @@
#include <procgrp.h>
#include <tcpip.h>
#include <xen.h>
+#include <ethernet.h>
#include "util.h"
#include "receiver.h"
@@ -64,6 +65,7 @@ struct _XENNET_RECEIVER {
typedef struct _NET_BUFFER_LIST_RESERVED {
PVOID Cookie;
+ USHORT EtherType;
} NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST,
MiniportReserved));
@@ -120,6 +122,7 @@ __ReceiverAllocateNetBufferList(
IN PMDL Mdl,
IN ULONG Offset,
IN ULONG Length,
+ IN PXENVIF_PACKET_INFO Info,
IN PVOID Cookie
)
{
@@ -156,10 +159,27 @@ __ReceiverAllocateNetBufferList(
if (NetBufferList != NULL) {
PNET_BUFFER_LIST_RESERVED ListReserved;
+ USHORT EtherType = 0;
+
+ if (Info->EthernetHeader.Length != 0) {
+ PUCHAR Buffer;
+ PETHERNET_HEADER EthernetHeader;
+
+ Buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority |
MdlMappingNoExecute);
+ if (Buffer != NULL) {
+ EthernetHeader = (PETHERNET_HEADER)(Buffer + Offset +
Info->EthernetHeader.Offset);
+ EtherType = ETHERNET_HEADER_IS_TAGGED(EthernetHeader) ?
+ EthernetHeader->Tagged.TypeOrLength :
+ EthernetHeader->Untagged.TypeOrLength;
+ if (EtherType <= ETHERNET_MTU)
+ EtherType = 0;
+ }
+ }
ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
ASSERT3P(ListReserved->Cookie, ==, NULL);
ListReserved->Cookie = Cookie;
+ ListReserved->EtherType = EtherType;
}
return NetBufferList;
@@ -178,6 +198,7 @@ __ReceiverReleaseNetBufferList(
ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
Cookie = ListReserved->Cookie;
ListReserved->Cookie = NULL;
+ ListReserved->EtherType = 0;
if (Cache)
__ReceiverPutNetBufferList(Receiver, NetBufferList);
@@ -240,12 +261,12 @@ __ReceiverReceivePacket(
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;
UNREFERENCED_PARAMETER(MaximumSegmentSize);
- UNREFERENCED_PARAMETER(Info);
NetBufferList = __ReceiverAllocateNetBufferList(Receiver,
Mdl,
Offset,
Length,
+ Info,
Cookie);
if (NetBufferList == NULL)
goto fail1;
@@ -328,9 +349,11 @@ fail1:
return NULL;
}
-static FORCEINLINE VOID __IndicateReceiveNetBufferLists(
+
+static FORCEINLINE VOID
+__IndicateReceiveNetBufferLists(
IN PXENNET_RECEIVER Receiver,
- IN PNET_BUFFER_LIST NetBufferLists,
+ IN PNET_BUFFER_LIST Remaining,
IN NDIS_PORT_NUMBER PortNumber,
IN ULONG NumberOfNetBufferLists,
IN ULONG ReceiveFlags
@@ -339,39 +362,70 @@ static FORCEINLINE VOID __IndicateReceiveNetBufferLists(
PXENNET_ADAPTER Adapter = Receiver->Adapter;
NDIS_HANDLE MiniportAdapterHandle = AdapterGetHandle(Adapter);
PXENVIF_VIF_INTERFACE VifInterface;
- ULONG Count;
+ ULONG Count = 0;
+ ULONG NblMaxBatch = AdapterGetNblMaxBatchSize(Adapter);
+
+ while (Remaining != NULL) {
+ PNET_BUFFER_LIST BatchTail = Remaining;
+ PNET_BUFFER_LIST NextNbl;
+ ULONG BatchCount = 1;
+ ULONG BatchFlags;
+ USHORT FirstEth;
+
+ FirstEth = ((PNET_BUFFER_LIST_RESERVED)
+ NET_BUFFER_LIST_MINIPORT_RESERVED(Remaining))->EtherType;
+ NextNbl = NET_BUFFER_LIST_NEXT_NBL(BatchTail);
+
+ while (NextNbl != NULL && BatchCount < NblMaxBatch) {
+ USHORT CurEth;
+ CurEth = ((PNET_BUFFER_LIST_RESERVED)
+ NET_BUFFER_LIST_MINIPORT_RESERVED(NextNbl))->EtherType;
+ if (CurEth != FirstEth)
+ break;
+ BatchTail = NextNbl;
+ NextNbl = NET_BUFFER_LIST_NEXT_NBL(BatchTail);
+ BatchCount++;
+ }
- VifInterface = AdapterGetVifInterface(Receiver->Adapter);
+ NET_BUFFER_LIST_NEXT_NBL(BatchTail) = NULL;
- Count = 0;
- while (NetBufferLists != NULL) {
- PNET_BUFFER_LIST Next;
-
- Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferLists);
- NET_BUFFER_LIST_NEXT_NBL(NetBufferLists) = NULL;
+ BatchFlags = ReceiveFlags;
+ if (FirstEth != 0)
+ BatchFlags |= NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE;
+ else
+ BatchFlags &= ~NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE;
NdisMIndicateReceiveNetBufferLists(MiniportAdapterHandle,
- NetBufferLists,
+ Remaining,
PortNumber,
- 1,
- ReceiveFlags);
+ BatchCount,
+ BatchFlags);
+
+ if (BatchFlags & NDIS_RECEIVE_FLAGS_RESOURCES) {
+ PNET_BUFFER_LIST Current = Remaining;
+
+ VifInterface = AdapterGetVifInterface(Receiver->Adapter);
+
+ while (Current != NULL) {
+ PNET_BUFFER_LIST Next = NET_BUFFER_LIST_NEXT_NBL(Current);
+ NET_BUFFER_LIST_NEXT_NBL(Current) = NULL;
- if (ReceiveFlags & NDIS_RECEIVE_FLAGS_RESOURCES) {
- PVOID Cookie;
+ PVOID Cookie = __ReceiverReleaseNetBufferList(Receiver,
+ Current,
+ FALSE);
- Cookie = __ReceiverReleaseNetBufferList(Receiver,
- NetBufferLists,
- FALSE);
+ XENVIF_VIF(ReceiverReturnPacket,
+ VifInterface,
+ Cookie);
- XENVIF_VIF(ReceiverReturnPacket,
- VifInterface,
- Cookie);
+ Current = Next;
+ }
- (VOID) InterlockedIncrement(&Receiver->Returned);
+ (VOID)InterlockedAdd(&Receiver->Returned, BatchCount);
}
- Count++;
- NetBufferLists = Next;
+ Count += BatchCount;
+ Remaining = NextNbl;
}
ASSERT3U(Count, ==, NumberOfNetBufferLists);
}
@@ -402,13 +456,11 @@ __ReceiverPushPackets(
KeReleaseSpinLockFromDpcLevel(&Queue->Lock);
- (VOID) InterlockedAdd(&Receiver->Indicated, Count);
+ if (Count == 0)
+ return;
Returned = Receiver->Returned;
-
- KeMemoryBarrier();
-
- Indicated = Receiver->Indicated;
+ Indicated = InterlockedAdd(&Receiver->Indicated, Count);
Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL |
NDIS_RECEIVE_FLAGS_PERFECT_FILTERED;
--
2.51.0.windows.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |