\param TagControlInformation The VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set)
\param Info Header information for the packet
\param Hash Hash information for the packet
+ \param More A flag to indicate whether more packets will be queued for the same CPU
\param Cookie Cookie that should be passed to XENVIF_RECEIVER_RETURN_PACKET method
\b XENVIF_MAC_STATE_CHANGE:
IN PVOID Cookie
);
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKET_V5)(
+ IN PINTERFACE Interface,
+ IN PMDL Mdl,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions,
+ IN USHORT MaximumSegmentSize,
+ IN USHORT TagControlInformation,
+ IN PXENVIF_PACKET_HASH Hash,
+ IN PVOID Cookie
+ );
+
/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKET
\brief Queue a packet at the provider's transmit side
\param MaximumSegmentSize The TCP MSS (used only if OffloadOptions.OffloadIpVersion[4|6]LargePacket is set)
\param TagControlInformation The VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set)
\param Hash Hash information for the packet
+ \param More A flag to indicate whether there will more packets queued with the same value of Hash
\param Cookie A cookie specified by the caller that will be passed to the XENVIF_TRANSMITTER_RETURN_PACKET callback
*/
typedef NTSTATUS
IN USHORT MaximumSegmentSize,
IN USHORT TagControlInformation,
IN PXENVIF_PACKET_HASH Hash,
+ IN BOOLEAN More,
IN PVOID Cookie
);
XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions;
XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE ReceiverSetBackfillSize;
XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize;
- XENVIF_VIF_TRANSMITTER_QUEUE_PACKET TransmitterQueuePacket;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKET_V5 TransmitterQueuePacket;
XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS TransmitterQueryOffloadOptions;
XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE TransmitterQueryLargePacketSize;
XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize;
\ingroup interfaces
*/
struct _XENVIF_VIF_INTERFACE_V6 {
+ INTERFACE Interface;
+ XENVIF_VIF_ACQUIRE Acquire;
+ XENVIF_VIF_RELEASE Release;
+ XENVIF_VIF_ENABLE Enable;
+ XENVIF_VIF_DISABLE Disable;
+ XENVIF_VIF_QUERY_STATISTIC QueryStatistic;
+ XENVIF_VIF_QUERY_RING_COUNT QueryRingCount;
+ XENVIF_VIF_UPDATE_HASH_MAPPING UpdateHashMapping;
+ XENVIF_VIF_RECEIVER_RETURN_PACKET ReceiverReturnPacket;
+ XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions;
+ XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE ReceiverSetBackfillSize;
+ XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize;
+ XENVIF_VIF_RECEIVER_SET_HASH_ALGORITHM ReceiverSetHashAlgorithm;
+ XENVIF_VIF_RECEIVER_QUERY_HASH_CAPABILITIES ReceiverQueryHashCapabilities;
+ XENVIF_VIF_RECEIVER_UPDATE_HASH_PARAMETERS ReceiverUpdateHashParameters;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKET_V5 TransmitterQueuePacket;
+ XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS TransmitterQueryOffloadOptions;
+ XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE TransmitterQueryLargePacketSize;
+ XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize;
+ XENVIF_VIF_MAC_QUERY_STATE MacQueryState;
+ XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE MacQueryMaximumFrameSize;
+ XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS MacQueryPermanentAddress;
+ XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS MacQueryCurrentAddress;
+ XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES MacQueryMulticastAddresses;
+ XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES MacSetMulticastAddresses;
+ XENVIF_VIF_MAC_SET_FILTER_LEVEL MacSetFilterLevel;
+ XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
+};
+
+/*! \struct _XENVIF_VIF_INTERFACE_V7
+ \brief VIF interface version 7
+ \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V7 {
INTERFACE Interface;
XENVIF_VIF_ACQUIRE Acquire;
XENVIF_VIF_RELEASE Release;
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
};
-typedef struct _XENVIF_VIF_INTERFACE_V6 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+typedef struct _XENVIF_VIF_INTERFACE_V7 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
/*! \def XENVIF_VIF
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENVIF_VIF_INTERFACE_VERSION_MIN 2
-#define XENVIF_VIF_INTERFACE_VERSION_MAX 6
+#define XENVIF_VIF_INTERFACE_VERSION_MAX 7
#endif // _XENVIF_INTERFACE_H
; DisplayName Section DeviceID
; ----------- ------- --------
-%XenNetName% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_NET&REV_0800000B
-%XenNetName% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0001&DEV_NET&REV_0800000B
-%XenNetName% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0002&DEV_NET&REV_0800000B
+%XenNetName% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_NET&REV_0800000C
+%XenNetName% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0001&DEV_NET&REV_0800000C
+%XenNetName% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0002&DEV_NET&REV_0800000C
[XenNet_Inst]
Characteristics=0x84
USHORT TagControlInformation;
PXENVIF_PACKET_INFO Info;
PXENVIF_PACKET_HASH Hash;
+ BOOLEAN More;
PVOID Cookie;
Mdl = va_arg(Arguments, PMDL);
TagControlInformation = va_arg(Arguments, USHORT);
Info = va_arg(Arguments, PXENVIF_PACKET_INFO);
Hash = va_arg(Arguments, PXENVIF_PACKET_HASH);
+ More = va_arg(Arguments, BOOLEAN);
Cookie = va_arg(Arguments, PVOID);
ReceiverQueuePacket(Adapter->Receiver,
TagControlInformation,
Info,
Hash,
+ More,
Cookie);
break;
}
#include "dbg_print.h"
#include "assert.h"
+typedef struct _XENNET_RECEIVER_QUEUE {
+ PNET_BUFFER_LIST Head;
+ PNET_BUFFER_LIST Tail;
+ ULONG Count;
+} XENNET_RECEIVER_QUEUE, *PXENNET_RECEIVER_QUEUE;
+
struct _XENNET_RECEIVER {
PXENNET_ADAPTER Adapter;
NDIS_HANDLE NetBufferListPool;
PNET_BUFFER_LIST PutList;
PNET_BUFFER_LIST GetList[HVM_MAX_VCPUS];
+ XENNET_RECEIVER_QUEUE Queue[HVM_MAX_VCPUS];
LONG InNDIS;
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
};
C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST, MiniportReserved));
+static FORCEINLINE PNET_BUFFER_LIST
+__ReceiverGetNetBufferList(
+ IN PXENNET_RECEIVER Receiver
+ )
+{
+ ULONG Index;
+ PNET_BUFFER_LIST NetBufferList;
+
+ Index = KeGetCurrentProcessorNumberEx(NULL);
+
+ NetBufferList = Receiver->GetList[Index];
+
+ if (NetBufferList == NULL)
+ Receiver->GetList[Index] =
+ InterlockedExchangePointer(&Receiver->PutList, NULL);
+
+ NetBufferList = Receiver->GetList[Index];
+
+ if (NetBufferList == NULL)
+ return NULL;
+
+ Receiver->GetList[Index] = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+ NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+ return NetBufferList;
+}
+
+static FORCEINLINE VOID
+__ReceiverPutNetBufferList(
+ IN PXENNET_RECEIVER Receiver,
+ IN PNET_BUFFER_LIST NetBufferList
+ )
+{
+ PNET_BUFFER_LIST Old;
+ PNET_BUFFER_LIST New;
+
+ ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
+
+ do {
+ Old = Receiver->PutList;
+
+ NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = Old;
+ New = NetBufferList;
+ } while (InterlockedCompareExchangePointer(&Receiver->PutList, New, Old) != Old);
+}
+
static PNET_BUFFER_LIST
__ReceiverAllocateNetBufferList(
IN PXENNET_RECEIVER Receiver,
IN PVOID Cookie
)
{
- ULONG Index;
PNET_BUFFER_LIST NetBufferList;
PNET_BUFFER_LIST_RESERVED ListReserved;
ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
- Index = KeGetCurrentProcessorNumberEx(NULL);
-
- if (Receiver->GetList[Index] == NULL)
- Receiver->GetList[Index] = InterlockedExchangePointer(&Receiver->PutList, NULL);
-
- NetBufferList = Receiver->GetList[Index];
+ NetBufferList = __ReceiverGetNetBufferList(Receiver);
if (NetBufferList != NULL) {
PNET_BUFFER NetBuffer;
- Receiver->GetList[Index] = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
- NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = NULL;
NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = NULL;
NET_BUFFER_LIST_INFO(NetBufferList, NetBufferListHashInfo) = NULL;
Cookie = ListReserved->Cookie;
ListReserved->Cookie = NULL;
- if (Cache) {
- PNET_BUFFER_LIST Old;
- PNET_BUFFER_LIST New;
-
- ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
-
- do {
- Old = Receiver->PutList;
-
- NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = Old;
- New = NetBufferList;
- } while (InterlockedCompareExchangePointer(&Receiver->PutList, New, Old) != Old);
- } else {
+ if (Cache)
+ __ReceiverPutNetBufferList(Receiver, NetBufferList);
+ else
NdisFreeNetBufferList(NetBufferList);
- }
return Cookie;
}
}
static VOID
-__ReceiverPushPacket(
+__ReceiverPushPackets(
IN PXENNET_RECEIVER Receiver,
- IN PNET_BUFFER_LIST NetBufferList
+ IN ULONG Index
)
{
ULONG Flags;
LONG InNDIS;
+ PXENNET_RECEIVER_QUEUE Queue;
+ PNET_BUFFER_LIST NetBufferList;
+ ULONG Count;
InNDIS = InterlockedIncrement(&Receiver->InNDIS);
- Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
+ Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL |
+ NDIS_RECEIVE_FLAGS_PERFECT_FILTERED;
+
if (InNDIS > IN_NDIS_MAX)
Flags |= NDIS_RECEIVE_FLAGS_RESOURCES;
+ Queue = &Receiver->Queue[Index];
+
+ NetBufferList = Queue->Head;
+ Count = Queue->Count;
+
+ RtlZeroMemory(Queue, sizeof (XENNET_RECEIVER_QUEUE));
+
NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Receiver->Adapter),
NetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
- 1,
+ Count,
Flags);
if (Flags & NDIS_RECEIVE_FLAGS_RESOURCES)
IN USHORT TagControlInformation,
IN PXENVIF_PACKET_INFO Info,
IN PXENVIF_PACKET_HASH Hash,
+ IN BOOLEAN More,
IN PVOID Cookie
)
{
PXENVIF_VIF_INTERFACE VifInterface;
PNET_BUFFER_LIST NetBufferList;
+ ULONG Index;
+ PXENNET_RECEIVER_QUEUE Queue;
VifInterface = AdapterGetVifInterface(Receiver->Adapter);
Info,
Hash,
Cookie);
-
- if (NetBufferList != NULL) {
- __ReceiverPushPacket(Receiver, NetBufferList);
- } else {
+ if (NetBufferList == NULL) {
XENVIF_VIF(ReceiverReturnPacket,
VifInterface,
Cookie);
+ return;
}
+
+ Index = KeGetCurrentProcessorNumberEx(NULL);
+
+ Queue = &Receiver->Queue[Index];
+
+ if (Queue->Head == NULL) {
+ ASSERT3U(Queue->Count, ==, 0);
+ Queue->Head = Queue->Tail = NetBufferList;
+ } else {
+ NET_BUFFER_LIST_NEXT_NBL(Queue->Tail) = NetBufferList;
+ Queue->Tail = NetBufferList;
+ }
+ Queue->Count++;
+
+ if (!More)
+ __ReceiverPushPackets(Receiver, Index);
}
PXENVIF_VIF_OFFLOAD_OPTIONS
IN USHORT TagControlInformation,
IN PXENVIF_PACKET_INFO Info,
IN PXENVIF_PACKET_HASH Hash,
+ IN BOOLEAN More,
IN PVOID Cookie
);
XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions;
USHORT TagControlInformation;
USHORT MaximumSegmentSize;
+ XENVIF_PACKET_HASH Hash;
ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
OffloadOptions.Value &= Transmitter->OffloadOptions.Value;
- ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
- RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
+ switch (NET_BUFFER_LIST_GET_HASH_FUNCTION(NetBufferList)) {
+ case NdisHashFunctionToeplitz:
+ Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ;
+ break;
- __TransmitterGetNetBufferList(Transmitter, NetBufferList);
+ default:
+ Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_NONE;
+ break;
+ }
- NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
- while (NetBuffer != NULL) {
- PNET_BUFFER NetBufferListNext = NET_BUFFER_NEXT_NB(NetBuffer);
- PVOID Cookie = NetBufferList;
- XENVIF_PACKET_HASH Hash;
- NTSTATUS status;
+ switch (NET_BUFFER_LIST_GET_HASH_TYPE(NetBufferList)) {
+ case NDIS_HASH_IPV4:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4;
+ break;
- __TransmitterGetNetBufferList(Transmitter, NetBufferList);
+ case NDIS_HASH_TCP_IPV4:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4_TCP;
+ break;
- switch (NET_BUFFER_LIST_GET_HASH_FUNCTION(NetBufferList)) {
- case NdisHashFunctionToeplitz:
- Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ;
- break;
+ case NDIS_HASH_IPV6:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6;
+ break;
- default:
- Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_NONE;
- break;
- }
+ case NDIS_HASH_TCP_IPV6:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6_TCP;
+ break;
- switch (NET_BUFFER_LIST_GET_HASH_TYPE(NetBufferList)) {
- case NDIS_HASH_IPV4:
- Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4;
+ default:
break;
+ }
- case NDIS_HASH_TCP_IPV4:
- Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4_TCP;
- break;
+ Hash.Value = NET_BUFFER_LIST_GET_HASH_VALUE(NetBufferList);
- case NDIS_HASH_IPV6:
- Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6;
- break;
+ ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+ RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
- case NDIS_HASH_TCP_IPV6:
- Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6_TCP;
- break;
+ __TransmitterGetNetBufferList(Transmitter, NetBufferList);
- default:
- break;
- }
+ NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+ while (NetBuffer != NULL) {
+ PNET_BUFFER NetBufferListNext = NET_BUFFER_NEXT_NB(NetBuffer);
+ PVOID Cookie = NetBufferList;
+ NTSTATUS status;
- Hash.Value = NET_BUFFER_LIST_GET_HASH_VALUE(NetBufferList);
+ __TransmitterGetNetBufferList(Transmitter, NetBufferList);
status = XENVIF_VIF(TransmitterQueuePacket,
AdapterGetVifInterface(Transmitter->Adapter),
MaximumSegmentSize,
TagControlInformation,
&Hash,
+ (NetBufferListNext != NULL) ? TRUE : FALSE,
Cookie);
if (!NT_SUCCESS(status)) {
__TransmitterReturnPacket(Transmitter, Cookie,