[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 3/3] Introduce VIF interface version 4
This greatly simplifies the interface with XENNET by queuing single packets on both the transmit and receive side, negating the need for a shared packet structures and bringing static hash calculation into XENVIF. Crucially this also means that XENNET no longer needs to use the XENBUS_CACHE interface which allows it to be patched to avoid the race introduced by commit 026aa32c "Make sure XENBUS interfaces are released when going into S4". Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/revision.h | 5 +- include/vif_interface.h | 243 ++++++++++------- src/xenvif/frontend.c | 3 + src/xenvif/frontend.h | 5 + src/xenvif/receiver.c | 295 ++++++++++++++------- src/xenvif/receiver.h | 8 +- src/xenvif/transmitter.c | 660 ++++++++++++++++++++++++++++++++--------------- src/xenvif/transmitter.h | 27 +- src/xenvif/vif.c | 211 ++++++++++++--- src/xenvif/vif.h | 24 +- 10 files changed, 1041 insertions(+), 440 deletions(-) diff --git a/include/revision.h b/include/revision.h index 77d1405..eda8871 100644 --- a/include/revision.h +++ b/include/revision.h @@ -42,6 +42,9 @@ #define DEFINE_REVISION_TABLE \ DEFINE_REVISION(0x08000002, 1, 2, 0, 0), \ DEFINE_REVISION(0x08000003, 1, 3, 0, 0), \ - DEFINE_REVISION(0x08000004, 1, 3, 2, 1) + DEFINE_REVISION(0x08000004, 1, 3, 2, 1), \ + DEFINE_REVISION(0x08000006, 1, 4, 2, 1) + +// Revision 0x08000005 is already in use in the staging-8.1 branch. #endif // _REVISION_H diff --git a/include/vif_interface.h b/include/vif_interface.h index f6b6298..27c5d2d 100644 --- a/include/vif_interface.h +++ b/include/vif_interface.h @@ -43,6 +43,28 @@ #include <ifdef.h> #include <ethernet.h> +/*! \enum _XENVIF_PACKET_HASH_ALGORITHM + \brief Hash algorithm +*/ +typedef enum _XENVIF_PACKET_HASH_ALGORITHM { + /*! None (value should be ignored) */ + XENVIF_PACKET_HASH_ALGORITHM_NONE = 0, + /*! Unspecified hash (value can be used) */ + XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED +} XENVIF_PACKET_HASH_ALGORITHM, *PXENVIF_PACKET_HASH_ALGORITHM; + +/*! \struct _XENVIF_PACKET_HASH_V1 + \brief Hash information +*/ +struct _XENVIF_PACKET_HASH_V1 { + /*! Hash algorithm used to calculate value */ + XENVIF_PACKET_HASH_ALGORITHM Algorithm; + /*! Calculated value */ + ULONG Value; +}; + +typedef struct _XENVIF_PACKET_HASH_V1 XENVIF_PACKET_HASH, *PXENVIF_PACKET_HASH; + /*! \struct _XENVIF_PACKET_HEADER_V1 \brief Packet header information */ @@ -53,14 +75,25 @@ struct _XENVIF_PACKET_HEADER_V1 { ULONG Length; }; -/*! \struct _XENVIF_PACKET_INFO_V1 +struct _XENVIF_PACKET_INFO_V1 { + ULONG Length; + USHORT TagControlInformation; + BOOLEAN IsAFragment; + struct _XENVIF_PACKET_HEADER_V1 EthernetHeader; + struct _XENVIF_PACKET_HEADER_V1 LLCSnapHeader; + struct _XENVIF_PACKET_HEADER_V1 IpHeader; + struct _XENVIF_PACKET_HEADER_V1 IpOptions; + struct _XENVIF_PACKET_HEADER_V1 TcpHeader; + struct _XENVIF_PACKET_HEADER_V1 TcpOptions; + struct _XENVIF_PACKET_HEADER_V1 UdpHeader; +}; + +/*! \struct _XENVIF_PACKET_INFO_V2 \brief Packet information */ -struct _XENVIF_PACKET_INFO_V1 { +struct _XENVIF_PACKET_INFO_V2 { /*! Total length of all headers */ ULONG Length; - /*! VLAN TCI if present (0 indicates not present) */ - USHORT TagControlInformation; /*! TRUE if the packet is an IP fragment */ BOOLEAN IsAFragment; /*! Ethernet header (stripped of any VLAN tag) */ @@ -79,7 +112,7 @@ struct _XENVIF_PACKET_INFO_V1 { struct _XENVIF_PACKET_HEADER_V1 UdpHeader; }; -typedef struct _XENVIF_PACKET_INFO_V1 XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO; +typedef struct _XENVIF_PACKET_INFO_V2 XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO; #pragma warning(push) #pragma warning(disable:4214) // nonstandard extension used : bit field types other than int @@ -120,32 +153,18 @@ typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 XENVIF_PACKET_CHECKSUM_FLAGS, *P #pragma warning(pop) -/*! \struct _XENVIF_RECEIVER_PACKET_V1 - \brief Receive-side packet structure -*/ struct _XENVIF_RECEIVER_PACKET_V1 { - /*! List entry used for chaining packets together */ LIST_ENTRY ListEntry; - /*! Pointer to packet information */ struct _XENVIF_PACKET_INFO_V1 *Info; - /*! Offset of start of packet in MDL */ ULONG Offset; - /*! Total length of packet */ ULONG Length; - /*! Checksum flags */ struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 Flags; - /*! TCP MSS if the packet contains a TCP large segment */ USHORT MaximumSegmentSize; - /*! Opaque cookie used to store context information for packet return */ PVOID Cookie; - /*! MDL referencing the initial buffer of the packet */ MDL Mdl; - /*! PFN information, which must always follow an MDL */ PFN_NUMBER __Pfn; }; -typedef struct _XENVIF_RECEIVER_PACKET_V1 XENVIF_RECEIVER_PACKET, *PXENVIF_RECEIVER_PACKET; - #pragma warning(push) #pragma warning(disable:4214) // nonstandard extension used : bit field types other than int #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union @@ -190,32 +209,18 @@ typedef struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 XENVIF_VIF_OFFLOAD_OPTIONS, *PXENV #pragma pack(push, 1) -/*! \struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 - \brief Packet information passed from subscriber to provider on - transmit side packet send - - To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures - this structure must be at most the size of 3 pointer types. -*/ struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 { - /*! Offload options for this packet */ XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions; - /*! TCP MSS (used only if OffloadOptions.OffloadIpVersion[4|6]LargePacket is set) */ USHORT MaximumSegmentSize; - /*! VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set) */ USHORT TagControlInformation; }; -typedef struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 XENVIF_TRANSMITTER_PACKET_SEND_INFO, *PXENVIF_TRANSMITTER_PACKET_SEND_INFO; - /*! \enum _XENVIF_TRANSMITTER_PACKET_STATUS \brief Transmit-side packet status */ typedef enum _XENVIF_TRANSMITTER_PACKET_STATUS { - /*! Packet was queued for the backend */ - XENVIF_TRANSMITTER_PACKET_PENDING = 1, /*! Packet has been successfully processed by the backend */ - XENVIF_TRANSMITTER_PACKET_OK, + XENVIF_TRANSMITTER_PACKET_OK = 2, /*! Packet was dropped */ XENVIF_TRANSMITTER_PACKET_DROPPED, /*! There was a problem handling the packet */ @@ -244,30 +249,17 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 XENVIF_TRANSMITTER_ #pragma pack(pop) -/*! \struct _XENVIF_TRANSMITTER_PACKET_V2 - \brief Transmit-side packet structure (v2) -*/ struct _XENVIF_TRANSMITTER_PACKET_V2 { - /*! List entry used for chaining packets together */ - LIST_ENTRY ListEntry; - /*! Opaque cookie used to store context information for packet return */ - PVOID Cookie; - /*! Hash value set by subscriber */ - ULONG Value; - /*! Packet information passed from subscriber to provider */ - XENVIF_TRANSMITTER_PACKET_SEND_INFO Send; - /*! Packet information passed from provider to subscriber on packet return */ - XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion; - /*! Packet data MDL */ - PMDL Mdl; - /*! Offset into MDL to start of packet */ - ULONG Offset; - /*! Packet length */ - ULONG Length; + LIST_ENTRY ListEntry; + PVOID Cookie; + ULONG Value; + struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 Send; + struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 Completion; + PMDL Mdl; + ULONG Offset; + ULONG Length; }; -typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET; - /*! \enum _XENVIF_VIF_STATISTIC \brief Interface statistics */ @@ -327,10 +319,10 @@ typedef enum _XENVIF_MAC_FILTER_LEVEL { \brief Type of callback (see \ref XENVIF_VIF_CALLBACK) */ typedef enum _XENVIF_VIF_CALLBACK_TYPE { - /*! Return transmit side packets to the subscriber */ - XENVIF_TRANSMITTER_RETURN_PACKETS = 0, - /*! Queue receive side packets at the subscriber */ - XENVIF_RECEIVER_QUEUE_PACKETS, + /*! Return a transmit side packet to the subscriber */ + XENVIF_TRANSMITTER_RETURN_PACKET = 0, + /*! Queue a receive side packet at the subscriber */ + XENVIF_RECEIVER_QUEUE_PACKET, /*! Notify the subscriber of a MAC (link) state has change */ XENVIF_MAC_STATE_CHANGE } XENVIF_VIF_CALLBACK_TYPE, *PXENVIF_VIF_CALLBACK_TYPE; @@ -362,11 +354,19 @@ typedef VOID \param Type The callback type \param ... Additional paramaters required by \a Type - \b XENVIF_TRANSMITTER_RETURN_PACKETS: - \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET + \b XENVIF_TRANSMITTER_RETURN_PACKET: + \param Cookie Cookie supplied to XENVIF_TRANSMITTER_QUEUE_PACKET + \param Completion Packet completion information - \b XENVIF_RECEIVER_QUEUE_PACKETS: - \param List List of XENVIF_TRANSMITTER_PACKET + \b XENVIF_RECEIVER_QUEUE_PACKET: + \param Mdl The initial MDL of the packet + \param Offset The offset of the packet data in the initial MDL + \param Length The total length of the packet + \param Flags Packet checksum flags + \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 Info Header information for the packet + \param Cookie Cookie that should be passed to XENVIF_RECEIVER_RETURN_PACKET method \b XENVIF_MAC_STATE_CHANGE: No additional arguments @@ -427,47 +427,65 @@ typedef NTSTATUS OUT PULONGLONG Value ); -/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKETS - \brief Return packets queues for receive by \ref XENVIF_VIF_CALLBACK - (Type = \ref XENVIF_RECEIVER_QUEUE_PACKETS) - - \param Interface The interface header - \param List List of \ref _XENVIF_RECEIVER_PACKET_V1 -*/ typedef VOID -(*XENVIF_VIF_RECEIVER_RETURN_PACKETS)( +(*XENVIF_VIF_RECEIVER_RETURN_PACKETS_V1)( IN PINTERFACE Interface, IN PLIST_ENTRY List ); -/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS - \brief Get the packet headers into supplied buffer +/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKET + \brief Return packets queued for receive by \ref XENVIF_VIF_CALLBACK + (Type = \ref XENVIF_RECEIVER_QUEUE_PACKET) \param Interface The interface header - \param Packet The packet to acquire headers for. - \param Headers The buffer to receive headers. - \param Info The offsets into Headers for relevant headers + \param Cookie Cookie passed to XENVIF_RECEIVER_QUEUE_PACKET callback */ -typedef NTSTATUS -(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)( - IN PINTERFACE Interface, - IN PXENVIF_TRANSMITTER_PACKET Packet, - OUT PVOID Headers, - OUT PXENVIF_PACKET_INFO Info +typedef VOID +(*XENVIF_VIF_RECEIVER_RETURN_PACKET)( + IN PINTERFACE Interface, + IN PVOID Cookie ); -/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS - \brief Queue transmit side packets at the provider +typedef NTSTATUS +(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS_V2)( + IN PINTERFACE Interface, + IN struct _XENVIF_TRANSMITTER_PACKET_V2 *Packet, + OUT PVOID Headers, + OUT PXENVIF_PACKET_INFO Info + ); - \param Interface The interface header - \param List List of XENVIF_TRANSMITTER_PACKET -*/ typedef NTSTATUS -(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS)( +(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2)( IN PINTERFACE Interface, IN PLIST_ENTRY List ); +/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKET + \brief Queue a packet at the provider's transmit side + + \param Interface The interface header + \param Mdl The initial MDL of the packet + \param Offset The offset of the packet data in the initial MDL + \param Length The total length of the packet + \param OffloadOptions The requested offload options for this packet + \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 Cookie A cookie specified by the caller that will be passed to the XENVIF_TRANSMITTER_RETURN_PACKET callback +*/ +typedef VOID +(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKET)( + 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_QUERY_OFFLOAD_OPTIONS \brief Query the available set of transmit side offload options @@ -524,7 +542,7 @@ typedef VOID /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE \brief Query the maximum number of transmit side packets that can - be queued in the shared ring between frontend and backend + be queued in each shared ring between frontend and backend \param Interface The interface header \param Size Buffer to receive the maximum number of packets @@ -537,7 +555,7 @@ typedef VOID /*! \typedef XENVIF_VIF_RECEIVER_QUERY_RING_SIZE \brief Query the maximum number of receive side packets that can - be queued in the shared ring between backend and frontend + be queued in each shared ring between backend and frontend \param Interface The interface header \param Size Buffer to receive the maximum number of packets @@ -685,11 +703,11 @@ struct _XENVIF_VIF_INTERFACE_V2 { XENVIF_VIF_ENABLE Enable; XENVIF_VIF_DISABLE Disable; XENVIF_VIF_QUERY_STATISTIC QueryStatistic; - XENVIF_VIF_RECEIVER_RETURN_PACKETS ReceiverReturnPackets; + XENVIF_VIF_RECEIVER_RETURN_PACKETS_V1 ReceiverReturnPacketsVersion1; XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions; XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize; - XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS TransmitterGetPacketHeaders; - XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS TransmitterQueuePackets; + XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS_V2 TransmitterGetPacketHeadersVersion2; + XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2 TransmitterQueuePacketsVersion2; XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS TransmitterQueryOffloadOptions; XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE TransmitterQueryLargePacketSize; XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize; @@ -714,12 +732,41 @@ struct _XENVIF_VIF_INTERFACE_V3 { XENVIF_VIF_ENABLE Enable; XENVIF_VIF_DISABLE Disable; XENVIF_VIF_QUERY_STATISTIC QueryStatistic; - XENVIF_VIF_RECEIVER_RETURN_PACKETS ReceiverReturnPackets; + XENVIF_VIF_RECEIVER_RETURN_PACKETS_V1 ReceiverReturnPacketsVersion1; + XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions; + XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE ReceiverSetBackfillSize; + XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize; + XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS_V2 TransmitterGetPacketHeadersVersion2; + XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2 TransmitterQueuePacketsVersion2; + 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_V4 + \brief VIF interface version 4 + \ingroup interfaces +*/ +struct _XENVIF_VIF_INTERFACE_V4 { + 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_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_TRANSMITTER_GET_PACKET_HEADERS TransmitterGetPacketHeaders; - XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS TransmitterQueuePackets; + XENVIF_VIF_TRANSMITTER_QUEUE_PACKET TransmitterQueuePacket; XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS TransmitterQueryOffloadOptions; XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE TransmitterQueryLargePacketSize; XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize; @@ -733,7 +780,7 @@ struct _XENVIF_VIF_INTERFACE_V3 { XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel; }; -typedef struct _XENVIF_VIF_INTERFACE_V3 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE; +typedef struct _XENVIF_VIF_INTERFACE_V4 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE; /*! \def XENVIF_VIF \brief Macro at assist in method invocation @@ -744,6 +791,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V3 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER #endif // _WINDLL #define XENVIF_VIF_INTERFACE_VERSION_MIN 2 -#define XENVIF_VIF_INTERFACE_VERSION_MAX 3 +#define XENVIF_VIF_INTERFACE_VERSION_MAX 4 #endif // _XENVIF_INTERFACE_H diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c index b066d0b..a43a534 100644 --- a/src/xenvif/frontend.c +++ b/src/xenvif/frontend.c @@ -56,6 +56,7 @@ typedef struct _XENVIF_FRONTEND_STATISTICS { ULONGLONG Value[XENVIF_VIF_STATISTIC_COUNT]; } XENVIF_FRONTEND_STATISTICS, *PXENVIF_FRONTEND_STATISTICS; + struct _XENVIF_FRONTEND { PXENVIF_PDO Pdo; PCHAR Path; @@ -1898,6 +1899,7 @@ fail5: MacDisconnect(__FrontendGetMac(Frontend)); + Frontend->Split = FALSE; Frontend->NumQueues = 0; fail4: @@ -1938,6 +1940,7 @@ FrontendDisconnect( ReceiverDisconnect(__FrontendGetReceiver(Frontend)); MacDisconnect(__FrontendGetMac(Frontend)); + Frontend->Split = FALSE; Frontend->NumQueues = 0; XENBUS_DEBUG(Deregister, diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h index eda9e3d..d90f977 100644 --- a/src/xenvif/frontend.h +++ b/src/xenvif/frontend.h @@ -127,6 +127,11 @@ FrontendIsSplit( IN PXENVIF_FRONTEND Frontend ); +extern BOOLEAN +FrontendIsSplit( + IN PXENVIF_FRONTEND Frontend + ); + extern PCHAR FrontendFormatPath( IN PXENVIF_FRONTEND Frontend, diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c index 030f84f..53f322f 100644 --- a/src/xenvif/receiver.c +++ b/src/xenvif/receiver.c @@ -105,6 +105,19 @@ typedef struct _XENVIF_RECEIVER_RING { LIST_ENTRY PacketList; } XENVIF_RECEIVER_RING, *PXENVIF_RECEIVER_RING; +typedef struct _XENVIF_RECEIVER_PACKET { + LIST_ENTRY ListEntry; + XENVIF_PACKET_INFO Info; + ULONG Offset; + ULONG Length; + XENVIF_PACKET_CHECKSUM_FLAGS Flags; + USHORT MaximumSegmentSize; + USHORT TagControlInformation; + PXENVIF_RECEIVER_RING Ring; + MDL Mdl; + PFN_NUMBER __Pfn; +} XENVIF_RECEIVER_PACKET, *PXENVIF_RECEIVER_PACKET; + struct _XENVIF_RECEIVER { PXENVIF_FRONTEND Frontend; XENBUS_CACHE_INTERFACE CacheInterface; @@ -149,29 +162,19 @@ ReceiverPacketCtor( IN PVOID Object ) { + PXENVIF_RECEIVER_RING Ring = Argument; PXENVIF_RECEIVER_PACKET Packet = Object; - PXENVIF_PACKET_INFO Info; - PMDL Mdl; - PUCHAR StartVa; - NTSTATUS status; - - UNREFERENCED_PARAMETER(Argument); + PMDL Mdl; + PUCHAR StartVa; + NTSTATUS status; ASSERT(IsZeroMemory(Packet, sizeof (XENVIF_RECEIVER_PACKET))); - Info = __ReceiverAllocate(sizeof (XENVIF_PACKET_INFO)); - - status = STATUS_NO_MEMORY; - if (Info == NULL) - goto fail1; - - Packet->Info = Info; - Mdl = __AllocatePage(); status = STATUS_NO_MEMORY; if (Mdl == NULL) - goto fail2; + goto fail1; StartVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); ASSERT(StartVa != NULL); @@ -186,13 +189,9 @@ ReceiverPacketCtor( ExFreePool(Mdl); - return STATUS_SUCCESS; + Packet->Ring = Ring; -fail2: - Error("fail2\n"); - - __ReceiverFree(Info); - Packet->Info = NULL; + return STATUS_SUCCESS; fail1: Error("fail1 (%08x)\n", status); @@ -208,11 +207,12 @@ ReceiverPacketDtor( IN PVOID Object ) { + PXENVIF_RECEIVER_RING Ring = Argument; PXENVIF_RECEIVER_PACKET Packet = Object; PMDL Mdl; - PXENVIF_PACKET_INFO Info; - UNREFERENCED_PARAMETER(Argument); + ASSERT3P(Packet->Ring, ==, Ring); + Packet->Ring = NULL; Mdl = &Packet->Mdl; @@ -222,11 +222,6 @@ ReceiverPacketDtor( RtlZeroMemory(Mdl, sizeof (MDL) + sizeof (PFN_NUMBER)); - Info = Packet->Info; - - __ReceiverFree(Info); - Packet->Info = NULL; - ASSERT(IsZeroMemory(Packet, sizeof (XENVIF_RECEIVER_PACKET))); } @@ -248,7 +243,7 @@ __ReceiverRingGetPacket( Ring->PacketCache, Locked); - ASSERT(IsZeroMemory(Packet->Info, sizeof (XENVIF_PACKET_INFO))); + ASSERT(IsZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO))); return Packet; } @@ -273,9 +268,9 @@ __ReceiverRingPutPacket( Packet->Length = 0; Packet->Flags.Value = 0; Packet->MaximumSegmentSize = 0; - Packet->Cookie = NULL; + Packet->TagControlInformation = 0; - RtlZeroMemory(Packet->Info, sizeof (XENVIF_PACKET_INFO)); + RtlZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO)); Mdl->MappedSystemVa = Mdl->StartVa; Mdl->ByteOffset = 0; @@ -395,7 +390,7 @@ ReceiverRingProcessTag( PETHERNET_HEADER EthernetHeader; ULONG Offset; - Info = Packet->Info; + Info = &Packet->Info; PayloadLength = Packet->Length - Info->Length; @@ -410,7 +405,7 @@ ReceiverRingProcessTag( Ring->OffloadOptions.OffloadTagManipulation == 0) return; - Info->TagControlInformation = NTOHS(EthernetHeader->Tagged.Tag.ControlInformation); + Packet->TagControlInformation = NTOHS(EthernetHeader->Tagged.Tag.ControlInformation); Offset = FIELD_OFFSET(ETHERNET_TAGGED_HEADER, Tag); RtlMoveMemory((PUCHAR)EthernetHeader + sizeof (ETHERNET_TAG), @@ -464,7 +459,7 @@ ReceiverRingProcessChecksum( Receiver = Ring->Receiver; - Info = Packet->Info; + Info = &Packet->Info; Payload.Mdl = &Packet->Mdl; Payload.Offset = Packet->Offset + Info->Length; @@ -478,8 +473,8 @@ ReceiverRingProcessChecksum( Payload.Offset = 0; } - flags = (uint16_t)(ULONG_PTR)Packet->Cookie; - ASSERT3U(Packet->Flags.Value, ==, 0); + flags = (uint16_t)Packet->Flags.Value; + Packet->Flags.Value = 0; if (Info->IpHeader.Length == 0) return; @@ -743,7 +738,7 @@ __ReceiverRingBuildSegment( Receiver = Ring->Receiver; - Info = Packet->Info; + Info = &Packet->Info; InfoVa = MmGetSystemAddressForMdlSafe(&Packet->Mdl, NormalPagePriority); ASSERT(InfoVa != NULL); @@ -755,7 +750,11 @@ __ReceiverRingBuildSegment( if (Segment == NULL) goto fail1; + Segment->Info = Packet->Info; Segment->Offset = Packet->Offset; + Segment->Flags = Packet->Flags; + Segment->MaximumSegmentSize = Packet->MaximumSegmentSize; + Segment->TagControlInformation = Packet->TagControlInformation; Mdl = &Segment->Mdl; @@ -769,9 +768,6 @@ __ReceiverRingBuildSegment( RtlCopyMemory(StartVa, InfoVa, Info->Length); Mdl->ByteCount += Info->Length; - *Segment->Info = *Packet->Info; - Segment->Cookie = Packet->Cookie; - // Adjust the info for the next segment IpHeader = (PIP_HEADER)(InfoVa + Info->IpHeader.Offset); if (IpHeader->Version == 4) { @@ -916,11 +912,11 @@ ReceiverRingProcessLargePacket( Receiver = Ring->Receiver; Frontend = Receiver->Frontend; - Info = Packet->Info; + Info = &Packet->Info; ASSERT(Info->IpHeader.Offset != 0); ASSERT(Info->TcpHeader.Offset != 0); - flags = (uint16_t)(ULONG_PTR)Packet->Cookie; + flags = (uint16_t)Packet->Flags.Value; ASSERT(flags & NETRXF_csum_blank); ASSERT(flags & NETRXF_data_validated); @@ -1089,7 +1085,7 @@ ReceiverRingProcessStandardPacket( Frontend = Receiver->Frontend; Mac = FrontendGetMac(Frontend); - Info = Packet->Info; + Info = &Packet->Info; Payload.Mdl = Packet->Mdl.Next; Payload.Offset = 0; @@ -1177,24 +1173,24 @@ fail1: static VOID ReceiverRingProcessPacket( - IN PXENVIF_RECEIVER_RING Ring, - IN PXENVIF_RECEIVER_PACKET Packet, - OUT PLIST_ENTRY List + IN PXENVIF_RECEIVER_RING Ring, + IN PXENVIF_RECEIVER_PACKET Packet, + OUT PLIST_ENTRY List ) { - PXENVIF_RECEIVER Receiver; - PXENVIF_FRONTEND Frontend; - PXENVIF_MAC Mac; - ULONG Length; - USHORT MaximumSegmentSize; - PVOID Cookie; - XENVIF_PACKET_PAYLOAD Payload; - PXENVIF_PACKET_INFO Info; - PUCHAR StartVa; - PETHERNET_HEADER EthernetHeader; - PETHERNET_ADDRESS DestinationAddress; - ETHERNET_ADDRESS_TYPE Type; - NTSTATUS status; + PXENVIF_RECEIVER Receiver; + PXENVIF_FRONTEND Frontend; + PXENVIF_MAC Mac; + ULONG Length; + XENVIF_PACKET_CHECKSUM_FLAGS Flags; + USHORT MaximumSegmentSize; + XENVIF_PACKET_PAYLOAD Payload; + PXENVIF_PACKET_INFO Info; + PUCHAR StartVa; + PETHERNET_HEADER EthernetHeader; + PETHERNET_ADDRESS DestinationAddress; + ETHERNET_ADDRESS_TYPE Type; + NTSTATUS status; Receiver = Ring->Receiver; Frontend = Receiver->Frontend; @@ -1202,8 +1198,9 @@ ReceiverRingProcessPacket( ASSERT3U(Packet->Offset, ==, 0); Length = Packet->Length; + Flags = Packet->Flags; MaximumSegmentSize = Packet->MaximumSegmentSize; - Cookie = Packet->Cookie; + ASSERT3U(Packet->TagControlInformation, ==, 0); Payload.Mdl = &Packet->Mdl; Payload.Offset = 0; @@ -1223,8 +1220,8 @@ ReceiverRingProcessPacket( // Copy in the extracted metadata Packet->Offset = Receiver->IpAlignOffset; Packet->Length = Length; + Packet->Flags = Flags; Packet->MaximumSegmentSize = MaximumSegmentSize; - Packet->Cookie = Cookie; StartVa = MmGetSystemAddressForMdlSafe(&Packet->Mdl, NormalPagePriority); ASSERT(StartVa != NULL); @@ -1232,7 +1229,7 @@ ReceiverRingProcessPacket( Packet->Mdl.ByteCount = Packet->Offset; - Info = Packet->Info; + Info = &Packet->Info; status = ParsePacket(StartVa, ReceiverRingPullup, Ring, &Payload, Info); if (!NT_SUCCESS(status)) { @@ -1361,8 +1358,6 @@ ReceiverRingProcessPackets( ReceiverRingProcessTag(Ring, Packet); ReceiverRingProcessChecksum(Ring, Packet); - Packet->Cookie = Ring; - (*Count)++; } } @@ -1378,6 +1373,79 @@ __ReceiverRingAcquireLock( KeAcquireSpinLockAtDpcLevel(&Ring->Lock); } +static FORCEINLINE VOID +__ReceiverQueuePacketVersion1( + IN PXENVIF_RECEIVER Receiver, + 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 PVOID Cookie + ) +{ + struct _XENVIF_PACKET_INFO_V1 *InfoVersion1; + struct _XENVIF_RECEIVER_PACKET_V1 *PacketVersion1; + PXENVIF_FRONTEND Frontend; + PXENVIF_VIF_CONTEXT Context; + LIST_ENTRY List; + NTSTATUS status; + + InfoVersion1 = __ReceiverAllocate(sizeof (struct _XENVIF_PACKET_INFO_V1)); + + status = STATUS_NO_MEMORY; + if (InfoVersion1 == NULL) + goto fail1; + + InfoVersion1->Length = Info->Length; + InfoVersion1->TagControlInformation = TagControlInformation; + InfoVersion1->IsAFragment = Info->IsAFragment; + InfoVersion1->EthernetHeader = Info->EthernetHeader; + InfoVersion1->LLCSnapHeader = Info->LLCSnapHeader; + InfoVersion1->IpHeader = Info->IpHeader; + InfoVersion1->IpOptions = Info->IpOptions; + InfoVersion1->TcpHeader = Info->TcpHeader; + InfoVersion1->TcpOptions = Info->TcpOptions; + InfoVersion1->UdpHeader = Info->UdpHeader; + + PacketVersion1 = __ReceiverAllocate(sizeof (struct _XENVIF_RECEIVER_PACKET_V1)); + + status = STATUS_NO_MEMORY; + if (PacketVersion1 == NULL) + goto fail2; + + PacketVersion1->Info = InfoVersion1; + PacketVersion1->Offset = Offset; + PacketVersion1->Length = Length; + PacketVersion1->Flags = Flags; + PacketVersion1->MaximumSegmentSize = MaximumSegmentSize; + PacketVersion1->Cookie = Cookie; + PacketVersion1->Mdl = *Mdl; + PacketVersion1->__Pfn = MmGetMdlPfnArray(Mdl)[0]; + + Frontend = Receiver->Frontend; + Context = PdoGetVifContext(FrontendGetPdo(Frontend)); + + InitializeListHead(&List); + + InsertTailList(&List, &PacketVersion1->ListEntry); + + VifReceiverQueuePacketsVersion1(Context, &List); + ASSERT(IsListEmpty(&List)); + + return; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + ReceiverReturnPacket(Receiver, Cookie); +} + static DECLSPEC_NOINLINE VOID ReceiverRingAcquireLock( IN PXENVIF_RECEIVER_RING Ring @@ -1393,12 +1461,18 @@ __ReceiverRingReleaseLock( ) { PXENVIF_RECEIVER Receiver; + PXENVIF_FRONTEND Frontend; + PXENVIF_VIF_CONTEXT Context; + ULONG Version; LIST_ENTRY List; ULONG Count; ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); Receiver = Ring->Receiver; + Frontend = Receiver->Frontend; + Context = PdoGetVifContext(FrontendGetPdo(Frontend)); + Version = VifGetVersion(Context); InitializeListHead(&List); Count = 0; @@ -1415,13 +1489,39 @@ __ReceiverRingReleaseLock( #pragma prefast(disable:26110) KeReleaseSpinLockFromDpcLevel(&Ring->Lock); - if (!IsListEmpty(&List)) { - PXENVIF_FRONTEND Frontend; + while (!IsListEmpty(&List)) { + PLIST_ENTRY ListEntry; + PXENVIF_RECEIVER_PACKET Packet; - Frontend = Receiver->Frontend; + ListEntry = RemoveHeadList(&List); + ASSERT3P(ListEntry, !=, &List); - VifReceiverQueuePackets(PdoGetVifContext(FrontendGetPdo(Frontend)), - &List); + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); + + Packet = CONTAINING_RECORD(ListEntry, + XENVIF_RECEIVER_PACKET, + ListEntry); + + if (Version < 4) + __ReceiverQueuePacketVersion1(Receiver, + &Packet->Mdl, + Packet->Offset, + Packet->Length, + Packet->Flags, + Packet->MaximumSegmentSize, + Packet->TagControlInformation, + &Packet->Info, + Packet); + else + VifReceiverQueuePacket(Context, + &Packet->Mdl, + Packet->Offset, + Packet->Length, + Packet->Flags, + Packet->MaximumSegmentSize, + Packet->TagControlInformation, + &Packet->Info, + Packet); } ASSERT(IsListEmpty(&List)); @@ -1902,7 +2002,6 @@ ReceiverRingPoll( if (~rsp->flags & NETRXF_more_data) { // EOP ASSERT(Packet != NULL); - ASSERT3P(Packet->Cookie, ==, NULL); if (Error) { FrontendIncrementStatistic(Frontend, @@ -1916,7 +2015,7 @@ ReceiverRingPoll( Packet->MaximumSegmentSize = MaximumSegmentSize; } - Packet->Cookie = (PVOID)(flags & (NETRXF_csum_blank | NETRXF_data_validated)); + Packet->Flags.Value = flags & (NETRXF_csum_blank | NETRXF_data_validated); ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY))); InsertTailList(&Ring->PacketList, &Packet->ListEntry); @@ -3345,35 +3444,21 @@ ReceiverQueryRingSize( } VOID -ReceiverReturnPackets( +ReceiverReturnPacket( IN PXENVIF_RECEIVER Receiver, - IN PLIST_ENTRY List + IN PVOID Cookie ) { - ULONG Count; + PXENVIF_RECEIVER_PACKET Packet = Cookie; + PXENVIF_RECEIVER_RING Ring; LONG Loaned; LONG Returned; - Count = 0; - while (!IsListEmpty(List)) { - PLIST_ENTRY ListEntry; - PXENVIF_RECEIVER_PACKET Packet; - PXENVIF_RECEIVER_RING Ring; - - ListEntry = RemoveHeadList(List); - ASSERT3P(ListEntry, !=, List); - - RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); - - Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry); - - Ring = Packet->Cookie; + Ring = Packet->Ring; - __ReceiverRingReturnPacket(Ring, Packet, FALSE); - Count++; - } + __ReceiverRingReturnPacket(Ring, Packet, FALSE); - Returned = __InterlockedAdd(&Receiver->Returned, Count); + Returned = InterlockedIncrement(&Receiver->Returned); // Make sure Loaned is not sampled before Returned KeMemoryBarrier(); @@ -3386,6 +3471,32 @@ ReceiverReturnPackets( } VOID +ReceiverReturnPacketsVersion1( + IN PXENVIF_RECEIVER Receiver, + IN PLIST_ENTRY List + ) +{ + while (!IsListEmpty(List)) { + PLIST_ENTRY ListEntry; + struct _XENVIF_RECEIVER_PACKET_V1 *PacketVersion1; + + ListEntry = RemoveHeadList(List); + ASSERT3P(ListEntry, !=, List); + + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); + + PacketVersion1 = CONTAINING_RECORD(ListEntry, + struct _XENVIF_RECEIVER_PACKET_V1, + ListEntry); + + ReceiverReturnPacket(Receiver, PacketVersion1->Cookie); + + __ReceiverFree(PacketVersion1->Info); + __ReceiverFree(PacketVersion1); + } +} + +VOID ReceiverWaitForPackets( IN PXENVIF_RECEIVER Receiver ) diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h index e4ab7a7..042e1da 100644 --- a/src/xenvif/receiver.h +++ b/src/xenvif/receiver.h @@ -101,12 +101,18 @@ ReceiverSetBackfillSize( ); extern VOID -ReceiverReturnPackets( +ReceiverReturnPacketsVersion1( IN PXENVIF_RECEIVER Receiver, IN PLIST_ENTRY List ); extern VOID +ReceiverReturnPacket( + IN PXENVIF_RECEIVER Receiver, + IN PVOID Cookie + ); + +extern VOID ReceiverSend( IN PXENVIF_RECEIVER Receiver, IN ULONG Index diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c index 35ec80a..75bf5fe 100644 --- a/src/xenvif/transmitter.c +++ b/src/xenvif/transmitter.c @@ -64,6 +64,24 @@ #define MAXNAMELEN 128 +#define XENVIF_TRANSMITTER_MAXIMUM_HEADER_LENGTH 512 + +typedef struct _XENVIF_TRANSMITTER_PACKET { + LIST_ENTRY ListEntry; + PVOID Cookie; + ULONG Reference; + XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions; + USHORT MaximumSegmentSize; + USHORT TagControlInformation; + XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion; + PMDL Mdl; + ULONG Offset; + ULONG Length; + PUCHAR Header; + XENVIF_PACKET_INFO Info; + XENVIF_PACKET_PAYLOAD Payload; +} XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET; + typedef struct _XENVIF_TRANSMITTER_REQUEST_ARP_PARAMETERS { IPV4_ADDRESS Address; } XENVIF_TRANSMITTER_REQUEST_ARP_PARAMETERS, *PXENVIF_TRANSMITTER_REQUEST_ARP_PARAMETERS; @@ -139,10 +157,6 @@ typedef struct _XENVIF_TRANSMITTER_FRAGMENT { typedef struct _XENVIF_TRANSMITTER_STATE { PXENVIF_TRANSMITTER_PACKET Packet; - XENVIF_TRANSMITTER_PACKET_SEND_INFO Send; - PUCHAR StartVa; - XENVIF_PACKET_INFO Info; - XENVIF_PACKET_PAYLOAD Payload; LIST_ENTRY List; ULONG Count; } XENVIF_TRANSMITTER_STATE, *PXENVIF_TRANSMITTER_STATE; @@ -252,24 +266,54 @@ TransmitterPacketReleaseLock( static NTSTATUS TransmitterPacketCtor( - IN PVOID Argument, - IN PVOID Object + IN PVOID Argument, + IN PVOID Object ) { + PXENVIF_TRANSMITTER_PACKET Packet = Object; + PUCHAR Header; + NTSTATUS status; + UNREFERENCED_PARAMETER(Argument); - UNREFERENCED_PARAMETER(Object); + + ASSERT(IsZeroMemory(Packet, sizeof (XENVIF_TRANSMITTER_PACKET))); + + Header = __TransmitterAllocate(XENVIF_TRANSMITTER_MAXIMUM_HEADER_LENGTH); + + status = STATUS_NO_MEMORY; + if (Header == NULL) + goto fail1; + + Packet->Header = Header; return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + ASSERT(IsZeroMemory(Packet, sizeof (XENVIF_TRANSMITTER_PACKET))); + + return status; } static VOID TransmitterPacketDtor( - IN PVOID Argument, - IN PVOID Object + IN PVOID Argument, + IN PVOID Object ) { + PXENVIF_TRANSMITTER_PACKET Packet = Object; + PUCHAR Header; + UNREFERENCED_PARAMETER(Argument); - UNREFERENCED_PARAMETER(Object); + + Header = Packet->Header; + Packet->Header = NULL; + + ASSERT(IsZeroMemory(Header, XENVIF_TRANSMITTER_MAXIMUM_HEADER_LENGTH)); + __TransmitterFree(Header); + + ASSERT(IsZeroMemory(Packet, sizeof (XENVIF_TRANSMITTER_PACKET))); } static FORCEINLINE PXENVIF_TRANSMITTER_PACKET @@ -289,7 +333,21 @@ __TransmitterPutPacket( IN PXENVIF_TRANSMITTER_PACKET Packet ) { - RtlZeroMemory(Packet, sizeof(XENVIF_TRANSMITTER_PACKET)); + ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY))); + ASSERT3U(Packet->Reference, ==, 0); + + Packet->Mdl = NULL; + Packet->Offset = 0; + Packet->Length = 0; + Packet->OffloadOptions.Value = 0; + Packet->MaximumSegmentSize = 0; + Packet->TagControlInformation = 0; + RtlZeroMemory(&Packet->Completion, sizeof (XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO)); + Packet->Cookie = NULL; + + RtlZeroMemory(Packet->Header, XENVIF_TRANSMITTER_MAXIMUM_HEADER_LENGTH); + RtlZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO)); + RtlZeroMemory(&Packet->Payload, sizeof (XENVIF_PACKET_PAYLOAD)); XENBUS_CACHE(Put, &Transmitter->CacheInterface, @@ -721,7 +779,7 @@ TransmitterRingDebugCallback( } static BOOLEAN -TransmitterRingPullup( +TransmitterPullup( IN PVOID Argument, IN PUCHAR DestinationVa, IN OUT PXENVIF_PACKET_PAYLOAD Payload, @@ -800,10 +858,10 @@ __TransmitterRingCopyPayload( State = &Ring->State; Packet = State->Packet; - Payload = State->Payload; + Payload = Packet->Payload; ASSERT(Packet != NULL); - ASSERT3U(Packet->Value, ==, 1); + ASSERT3U(Packet->Reference, ==, 1); while (Payload.Length != 0) { PMDL Mdl; @@ -818,14 +876,14 @@ __TransmitterRingCopyPayload( goto fail1; Buffer->Context = Packet; - Packet->Value++; + Packet->Reference++; Mdl = Buffer->Mdl; Length = __min(Payload.Length, PAGE_SIZE); MdlMappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); - TransmitterRingPullup(Ring, MdlMappedSystemVa, &Payload, Length); + (VOID) TransmitterPullup(Transmitter, MdlMappedSystemVa, &Payload, Length); Mdl->ByteCount = Length; @@ -884,14 +942,14 @@ fail2: ASSERT3P(Buffer->Context, ==, Packet); Buffer->Context = NULL; - Packet->Value--; + --Packet->Reference; __TransmitterPutBuffer(Ring, Buffer); fail1: Error("fail1 (%08x)\n", status); - while (Packet->Value != 1) { + while (Packet->Reference != 1) { PLIST_ENTRY ListEntry; ASSERT(State->Count != 0); @@ -927,7 +985,7 @@ fail1: ASSERT3P(Buffer->Context, ==, Packet); Buffer->Context = NULL; - Packet->Value--; + --Packet->Reference; __TransmitterPutBuffer(Ring, Buffer); } @@ -956,10 +1014,10 @@ __TransmitterRingGrantPayload( State = &Ring->State; Packet = State->Packet; - Payload = &State->Payload; + Payload = &Packet->Payload; ASSERT(Packet != NULL); - ASSERT3U(Packet->Value, ==, 1); + ASSERT3U(Packet->Reference, ==, 1); Mdl = Payload->Mdl; Offset = Payload->Offset; @@ -988,7 +1046,7 @@ __TransmitterRingGrantPayload( Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_PACKET; Fragment->Context = Packet; - Packet->Value++; + Packet->Reference++; Pfn = MmGetMdlPfnArray(Mdl)[MdlOffset / PAGE_SIZE]; PageOffset = MdlOffset & (PAGE_SIZE - 1); @@ -1045,7 +1103,7 @@ fail2: Fragment->Context = NULL; Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID; - Packet->Value--; + --Packet->Reference; __TransmitterPutFragment(Ring, Fragment); } @@ -1056,7 +1114,7 @@ fail1: ASSERT3P(Fragment, ==, NULL); - while (Packet->Value != 1) { + while (Packet->Reference != 1) { PLIST_ENTRY ListEntry; ASSERT(State->Count != 0); @@ -1083,7 +1141,7 @@ fail1: Fragment->Context = NULL; Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID; - Packet->Value--; + --Packet->Reference; __TransmitterPutFragment(Ring, Fragment); } @@ -1117,10 +1175,11 @@ __TransmitterRingPrepareHeader( State = &Ring->State; Packet = State->Packet; - Payload = &State->Payload; - Info = &State->Info; - ASSERT3U(Packet->Value, ==, 0); + Payload = &Packet->Payload; + Info = &Packet->Info; + + ASSERT3U(Packet->Reference, ==, 0); Buffer = __TransmitterGetBuffer(Ring); @@ -1129,18 +1188,14 @@ __TransmitterRingPrepareHeader( goto fail1; Buffer->Context = Packet; - Packet->Value++; + Packet->Reference++; Mdl = Buffer->Mdl; StartVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); ASSERT(StartVa != NULL); - status = ParsePacket(StartVa, TransmitterRingPullup, Ring, Payload, Info); - if (!NT_SUCCESS(status)) - goto fail2; - - State->StartVa = StartVa; + RtlCopyMemory(StartVa, Packet->Header, Info->Length); Mdl->ByteCount = Info->Length; @@ -1148,7 +1203,7 @@ __TransmitterRingPrepareHeader( status = STATUS_NO_MEMORY; if (Fragment == NULL) - goto fail3; + goto fail2; Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_BUFFER; Fragment->Context = Buffer; @@ -1166,7 +1221,7 @@ __TransmitterRingPrepareHeader( TRUE, &Fragment->Entry); if (!NT_SUCCESS(status)) - goto fail4; + goto fail3; Fragment->Offset = 0; Fragment->Length = Mdl->ByteCount + Payload->Length; @@ -1178,7 +1233,7 @@ __TransmitterRingPrepareHeader( ASSERT(Info->EthernetHeader.Length != 0); EthernetHeader = (PETHERNET_HEADER)(StartVa + Info->EthernetHeader.Offset); - if (State->Send.OffloadOptions.OffloadTagManipulation) { + if (Packet->OffloadOptions.OffloadTagManipulation) { ULONG Offset; Offset = FIELD_OFFSET(ETHERNET_TAGGED_HEADER, Tag); @@ -1189,9 +1244,10 @@ __TransmitterRingPrepareHeader( // Insert the tag EthernetHeader->Tagged.Tag.ProtocolID = HTONS(ETHERTYPE_TPID); - EthernetHeader->Tagged.Tag.ControlInformation = HTONS(State->Send.TagControlInformation); + EthernetHeader->Tagged.Tag.ControlInformation = HTONS(Packet->TagControlInformation); ASSERT(ETHERNET_HEADER_IS_TAGGED(EthernetHeader)); + Packet->Length += sizeof (ETHERNET_TAG); Mdl->ByteCount += sizeof (ETHERNET_TAG); Fragment->Length += sizeof (ETHERNET_TAG); @@ -1215,7 +1271,7 @@ __TransmitterRingPrepareHeader( Info->TcpOptions.Offset += sizeof (ETHERNET_TAG); } - if (State->Send.OffloadOptions.OffloadIpVersion4LargePacket) { + if (Packet->OffloadOptions.OffloadIpVersion4LargePacket) { PIP_HEADER IpHeader; PTCP_HEADER TcpHeader; ULONG Length; @@ -1242,20 +1298,20 @@ __TransmitterRingPrepareHeader( IpHeader->Version4.PacketLength = HTONS((USHORT)Length); // IP checksum calulcation must be offloaded for large packets - State->Send.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1; + Packet->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1; // TCP checksum calulcation must be offloaded for large packets TcpHeader->Checksum = ChecksumPseudoHeader(StartVa, Info); - State->Send.OffloadOptions.OffloadIpVersion4TcpChecksum = 1; + Packet->OffloadOptions.OffloadIpVersion4TcpChecksum = 1; // If the MSS is such that the payload would constitute only a single fragment then // we no longer need trate the packet as a large packet. - ASSERT3U(State->Send.MaximumSegmentSize, <=, Payload->Length); - if (State->Send.MaximumSegmentSize == Payload->Length) - State->Send.OffloadOptions.OffloadIpVersion4LargePacket = 0; + ASSERT3U(Packet->MaximumSegmentSize, <=, Payload->Length); + if (Packet->MaximumSegmentSize == Payload->Length) + Packet->OffloadOptions.OffloadIpVersion4LargePacket = 0; } - if (State->Send.OffloadOptions.OffloadIpVersion6LargePacket) { + if (Packet->OffloadOptions.OffloadIpVersion6LargePacket) { PIP_HEADER IpHeader; PTCP_HEADER TcpHeader; ULONG Length; @@ -1282,29 +1338,29 @@ __TransmitterRingPrepareHeader( // TCP checksum calulcation must be offloaded for large packets TcpHeader->Checksum = ChecksumPseudoHeader(StartVa, Info); - State->Send.OffloadOptions.OffloadIpVersion6TcpChecksum = 1; + Packet->OffloadOptions.OffloadIpVersion6TcpChecksum = 1; // If the MSS is such that the payload would constitute only a single fragment then // we no longer need treat the packet as a large packet. - ASSERT3U(State->Send.MaximumSegmentSize, <=, Payload->Length); - if (State->Send.MaximumSegmentSize == Payload->Length) - State->Send.OffloadOptions.OffloadIpVersion6LargePacket = 0; + ASSERT3U(Packet->MaximumSegmentSize, <=, Payload->Length); + if (Packet->MaximumSegmentSize == Payload->Length) + Packet->OffloadOptions.OffloadIpVersion6LargePacket = 0; } // Non-GSO packets must not exceed MTU - if (!State->Send.OffloadOptions.OffloadIpVersion4LargePacket && - !State->Send.OffloadOptions.OffloadIpVersion6LargePacket) { + if (!Packet->OffloadOptions.OffloadIpVersion4LargePacket && + !Packet->OffloadOptions.OffloadIpVersion6LargePacket) { ULONG MaximumFrameSize; MacQueryMaximumFrameSize(Mac, &MaximumFrameSize); if (Fragment->Length > MaximumFrameSize) { status = STATUS_INVALID_PARAMETER; - goto fail5; + goto fail4; } } - if (State->Send.OffloadOptions.OffloadIpVersion4HeaderChecksum) { + if (Packet->OffloadOptions.OffloadIpVersion4HeaderChecksum) { PIP_HEADER IpHeader; ASSERT(Info->IpHeader.Length != 0); @@ -1316,8 +1372,8 @@ __TransmitterRingPrepareHeader( return STATUS_SUCCESS; -fail5: - Error("fail5\n"); +fail4: + Error("fail4\n"); ASSERT(State->Count != 0); --State->Count; @@ -1335,8 +1391,8 @@ fail5: Fragment->Entry); Fragment->Entry = NULL; -fail4: - Error("fail4\n"); +fail3: + Error("fail3\n"); Fragment->Context = NULL; Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID; @@ -1346,15 +1402,10 @@ fail4: __TransmitterPutFragment(Ring, Fragment); -fail3: - Error("fail3\n"); - - Mdl->ByteCount = 0; - fail2: Error("fail2\n"); - Packet->Value--; + --Packet->Reference; Buffer->Context = NULL; __TransmitterPutBuffer(Ring, Buffer); @@ -1362,7 +1413,7 @@ fail2: fail1: Error("fail1 (%08x)\n", status); - ASSERT3U(Packet->Value, ==, 0); + ASSERT3U(Packet->Reference, ==, 0); return status; } @@ -1461,7 +1512,7 @@ __TransmitterRingUnprepareFragments( } if (Packet != NULL) - Packet->Value--; + --Packet->Reference; __TransmitterPutFragment(Ring, Fragment); } @@ -1478,11 +1529,6 @@ __TransmitterRingUnprepareFragments( if (Packet != NULL) { Ring->PacketsUnprepared++; - RtlZeroMemory(&State->Payload, sizeof (XENVIF_PACKET_PAYLOAD)); - - Packet->Send = State->Send; - RtlZeroMemory(&State->Send, sizeof (XENVIF_TRANSMITTER_PACKET_SEND_INFO)); - State->Packet = NULL; } @@ -1493,8 +1539,8 @@ __TransmitterRingUnprepareFragments( static FORCEINLINE NTSTATUS __TransmitterRingPreparePacket( - IN PXENVIF_TRANSMITTER_RING Ring, - IN PXENVIF_TRANSMITTER_PACKET Packet + IN PXENVIF_TRANSMITTER_RING Ring, + IN PXENVIF_TRANSMITTER_PACKET Packet ) { PXENVIF_TRANSMITTER Transmitter; @@ -1511,14 +1557,6 @@ __TransmitterRingPreparePacket( State->Packet = Packet; - State->Send = Packet->Send; - RtlZeroMemory(&Packet->Send, sizeof (XENVIF_TRANSMITTER_PACKET_SEND_INFO)); - - Payload = &State->Payload; - Payload->Mdl = Packet->Mdl; - Payload->Offset = Packet->Offset; - Payload->Length = Packet->Length; - InitializeListHead(&State->List); ASSERT3U(State->Count, ==, 0); @@ -1526,9 +1564,10 @@ __TransmitterRingPreparePacket( if (!NT_SUCCESS(status)) goto fail1; - ASSERT3U(State->Count, ==, Packet->Value); + ASSERT3U(State->Count, ==, Packet->Reference); - Info = &State->Info; + Info = &Packet->Info; + Payload = &Packet->Payload; // Is the packet too short? if (Info->Length + Payload->Length < ETHERNET_MIN) { @@ -1584,7 +1623,7 @@ __TransmitterRingPreparePacket( if (Transmitter->AlwaysCopy != 0 || (!NT_SUCCESS(status) && status == STATUS_BUFFER_OVERFLOW)) { - ASSERT3U(State->Count, ==, Packet->Value); + ASSERT3U(State->Count, ==, Packet->Reference); status = __TransmitterRingCopyPayload(Ring); } @@ -1593,7 +1632,7 @@ __TransmitterRingPreparePacket( if (!NT_SUCCESS(status)) goto fail2; - ASSERT3U(State->Count, ==, Packet->Value); + ASSERT3U(State->Count, ==, Packet->Reference); Ring->PacketsPrepared++; return STATUS_SUCCESS; @@ -1606,17 +1645,9 @@ fail2: fail1: Error("fail1 (%08x)\n", status); - State->StartVa = NULL; - RtlZeroMemory(&State->Info, sizeof (XENVIF_PACKET_INFO)); - ASSERT(IsListEmpty(&State->List)); RtlZeroMemory(&State->List, sizeof (LIST_ENTRY)); - RtlZeroMemory(&State->Payload, sizeof (XENVIF_PACKET_PAYLOAD)); - - Packet->Send = State->Send; - RtlZeroMemory(&State->Send, sizeof (XENVIF_TRANSMITTER_PACKET_SEND_INFO)); - State->Packet = NULL; ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE))); @@ -2002,11 +2033,10 @@ __TransmitterRingPostFragments( PXENVIF_FRONTEND Frontend; PXENVIF_TRANSMITTER_STATE State; PXENVIF_TRANSMITTER_PACKET Packet; - PXENVIF_PACKET_PAYLOAD Payload; + XENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions; RING_IDX req_prod; RING_IDX rsp_cons; ULONG Extra; - ULONG PacketLength; BOOLEAN FirstRequest; PLIST_ENTRY ListEntry; PXENVIF_TRANSMITTER_FRAGMENT Fragment; @@ -2018,12 +2048,15 @@ __TransmitterRingPostFragments( State = &Ring->State; Packet = State->Packet; - Payload = &State->Payload; + + if (Packet != NULL) + OffloadOptions = Packet->OffloadOptions; + else + OffloadOptions.Value = 0; ASSERT(!IsListEmpty(&State->List)); ASSERT(State->Count != 0); ASSERT3U(State->Count, <=, XEN_NETIF_NR_SLOTS_MIN); - ASSERT(IMPLY(Packet != NULL, State->Count == Packet->Value)); req_prod = Ring->Front.req_prod_pvt; rsp_cons = Ring->Front.rsp_cons; @@ -2033,8 +2066,8 @@ __TransmitterRingPostFragments( XENVIF_TRANSMITTER_FRAGMENT, ListEntry); - Extra = (State->Send.OffloadOptions.OffloadIpVersion4LargePacket || - State->Send.OffloadOptions.OffloadIpVersion6LargePacket || + Extra = (OffloadOptions.OffloadIpVersion4LargePacket || + OffloadOptions.OffloadIpVersion6LargePacket || Fragment->Type == XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL) ? 1 : 0; @@ -2048,7 +2081,6 @@ __TransmitterRingPostFragments( req = NULL; FirstRequest = TRUE; - PacketLength = 0; while (State->Count != 0) { --State->Count; @@ -2078,14 +2110,14 @@ __TransmitterRingPostFragments( if (FirstRequest) { FirstRequest = FALSE; - if (State->Send.OffloadOptions.OffloadIpVersion4TcpChecksum || - State->Send.OffloadOptions.OffloadIpVersion4UdpChecksum || - State->Send.OffloadOptions.OffloadIpVersion6TcpChecksum || - State->Send.OffloadOptions.OffloadIpVersion6UdpChecksum) + if (OffloadOptions.OffloadIpVersion4TcpChecksum || + OffloadOptions.OffloadIpVersion4UdpChecksum || + OffloadOptions.OffloadIpVersion6TcpChecksum || + OffloadOptions.OffloadIpVersion6UdpChecksum) req->flags |= NETTXF_csum_blank | NETTXF_data_validated; - if (State->Send.OffloadOptions.OffloadIpVersion4LargePacket || - State->Send.OffloadOptions.OffloadIpVersion6LargePacket || + if (OffloadOptions.OffloadIpVersion4LargePacket || + OffloadOptions.OffloadIpVersion6LargePacket || Fragment->Type == XENVIF_TRANSMITTER_FRAGMENT_TYPE_MULTICAST_CONTROL) { struct netif_extra_info *extra; @@ -2096,17 +2128,17 @@ __TransmitterRingPostFragments( req_prod++; Ring->RequestsPosted++; - if (State->Send.OffloadOptions.OffloadIpVersion4LargePacket || - State->Send.OffloadOptions.OffloadIpVersion6LargePacket) { - ASSERT(State->Send.MaximumSegmentSize != 0); + if (OffloadOptions.OffloadIpVersion4LargePacket || + OffloadOptions.OffloadIpVersion6LargePacket) { + ASSERT(Packet->MaximumSegmentSize != 0); extra->type = XEN_NETIF_EXTRA_TYPE_GSO; extra->flags = 0; - extra->u.gso.type = (State->Send.OffloadOptions.OffloadIpVersion4LargePacket) ? + extra->u.gso.type = (OffloadOptions.OffloadIpVersion4LargePacket) ? XEN_NETIF_GSO_TYPE_TCPV4 : - XEN_NETIF_GSO_TYPE_TCPV6;; - extra->u.gso.size = State->Send.MaximumSegmentSize; + XEN_NETIF_GSO_TYPE_TCPV6; + extra->u.gso.size = Packet->MaximumSegmentSize; extra->u.gso.pad = 0; extra->u.gso.features = 0; @@ -2129,9 +2161,6 @@ __TransmitterRingPostFragments( req->flags |= NETTXF_extra_info; } - - // The first fragment length is the length of the entire packet - PacketLength = Fragment->Length; } // Store a copy of the request in case we need to fake a response ourselves @@ -2151,14 +2180,14 @@ __TransmitterRingPostFragments( // Set the initial completion information if (Packet != NULL) { - PUCHAR StartVa; - PXENVIF_PACKET_INFO Info; - PETHERNET_HEADER Header; + PUCHAR StartVa; + PXENVIF_PACKET_INFO Info; + PXENVIF_PACKET_PAYLOAD Payload; + PETHERNET_HEADER Header; - ASSERT(PacketLength != 0); - - StartVa = State->StartVa; - Info = &State->Info; + StartVa = Packet->Header; + Info = &Packet->Info; + Payload = &Packet->Payload; ASSERT(IsZeroMemory(&Packet->Completion, sizeof (XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO))); @@ -2166,14 +2195,9 @@ __TransmitterRingPostFragments( Header = (PETHERNET_HEADER)(StartVa + Info->EthernetHeader.Offset); Packet->Completion.Type = GET_ETHERNET_ADDRESS_TYPE(&Header->Untagged.DestinationAddress); - Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_PENDING; - Packet->Completion.PacketLength = (USHORT)PacketLength; + Packet->Completion.PacketLength = (USHORT)Packet->Length; Packet->Completion.PayloadLength = (USHORT)Payload->Length; - State->StartVa = NULL; - RtlZeroMemory(&State->Info, sizeof (XENVIF_PACKET_INFO)); - RtlZeroMemory(&State->Payload, sizeof (XENVIF_PACKET_PAYLOAD)); - RtlZeroMemory(&State->Send, sizeof (XENVIF_TRANSMITTER_PACKET_SEND_INFO)); State->Packet = NULL; Ring->PacketsSent++; @@ -2268,7 +2292,7 @@ __TransmitterRingCompletePacket( Transmitter = Ring->Transmitter; Frontend = Transmitter->Frontend; - ASSERT(Packet->Completion.Status != XENVIF_TRANSMITTER_PACKET_PENDING); + ASSERT(Packet->Completion.Status != 0); if (Packet->Completion.Status != XENVIF_TRANSMITTER_PACKET_OK) { FrontendIncrementStatistic(Frontend, @@ -2447,10 +2471,10 @@ TransmitterRingPoll( continue; } - Packet->Value--; + --Packet->Reference; if (rsp->status != NETIF_RSP_OKAY && - Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_PENDING) { + Packet->Completion.Status == 0) { switch (rsp->status) { case NETIF_RSP_DROPPED: Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED; @@ -2468,10 +2492,10 @@ TransmitterRingPoll( RtlZeroMemory(rsp, sizeof (netif_tx_response_t)); - if (Packet->Value != 0) + if (Packet->Reference != 0) continue; - if (Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_PENDING) + if (Packet->Completion.Status == 0) Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_OK; __TransmitterRingCompletePacket(Ring, Packet); @@ -2589,11 +2613,12 @@ TransmitterRingSwizzle( ListEntry = NextEntry; } - ListEntry = List.Flink; if (!IsListEmpty(&List)) { + ListEntry = List.Flink; + RemoveEntryList(&List); - InitializeListHead(&List); AppendTailList(&Ring->PacketQueue, ListEntry); + Ring->PacketsQueued += Count; } } @@ -2632,6 +2657,8 @@ TransmitterRingSchedule( PXENVIF_TRANSMITTER_REQUEST Request; ListEntry = RemoveHeadList(&Ring->RequestQueue); + ASSERT3P(ListEntry, !=, &Ring->RequestQueue); + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); Request = CONTAINING_RECORD(ListEntry, @@ -2669,13 +2696,15 @@ TransmitterRingSchedule( PXENVIF_TRANSMITTER_PACKET Packet; ListEntry = RemoveHeadList(&Ring->PacketQueue); + ASSERT3P(ListEntry, !=, &Ring->PacketQueue); + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry); - Packet->Value = 0; + Packet->Reference = 0; status = __TransmitterRingPreparePacket(Ring, Packet); if (!NT_SUCCESS(status)) { @@ -2712,20 +2741,70 @@ TransmitterRingSchedule( } static FORCEINLINE VOID +__TransmitterReturnPacketVersion2( + IN PXENVIF_TRANSMITTER Transmitter, + IN PVOID Cookie, + IN PXENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion + ) +{ + struct _XENVIF_TRANSMITTER_PACKET_V2 *PacketVersion2; + PXENVIF_FRONTEND Frontend; + PXENVIF_VIF_CONTEXT Context; + LIST_ENTRY List; + + PacketVersion2 = Cookie; + PacketVersion2->Completion = *Completion; + + Frontend = Transmitter->Frontend; + Context = PdoGetVifContext(FrontendGetPdo(Frontend)); + + InitializeListHead(&List); + + ASSERT(IsZeroMemory(&PacketVersion2->ListEntry, sizeof (LIST_ENTRY))); + InsertTailList(&List, &PacketVersion2->ListEntry); + + VifTransmitterReturnPacketsVersion2(Context, &List); + ASSERT(IsListEmpty(&List)); +} + +static FORCEINLINE VOID __TransmitterReturnPackets( IN PXENVIF_TRANSMITTER Transmitter, IN PLIST_ENTRY List ) { PXENVIF_FRONTEND Frontend; - - if (IsListEmpty(List)) - return; + PXENVIF_VIF_CONTEXT Context; + ULONG Version; Frontend = Transmitter->Frontend; + Context = PdoGetVifContext(FrontendGetPdo(Frontend)); + Version = VifGetVersion(Context); + + while (!IsListEmpty(List)) { + PLIST_ENTRY ListEntry; + PXENVIF_TRANSMITTER_PACKET Packet; - VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)), - List); + ListEntry = RemoveHeadList(List); + ASSERT3P(ListEntry, !=, List); + + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); + + Packet = CONTAINING_RECORD(ListEntry, + XENVIF_TRANSMITTER_PACKET, + ListEntry); + + if (Version < 4) + __TransmitterReturnPacketVersion2(Transmitter, + Packet->Cookie, + &Packet->Completion); + else + VifTransmitterReturnPacket(Context, + Packet->Cookie, + &Packet->Completion); + + __TransmitterPutPacket(Transmitter, Packet); + } } static FORCEINLINE BOOLEAN @@ -2837,13 +2916,12 @@ __TransmitterRingReleaseLock( // thread could be simuntaneously adding to the list. do { - PLIST_ENTRY ListEntry; - TransmitterRingSwizzle(Ring); TransmitterRingSchedule(Ring); - ListEntry = Ring->PacketComplete.Flink; if (!IsListEmpty(&Ring->PacketComplete)) { + PLIST_ENTRY ListEntry = Ring->PacketComplete.Flink; + RemoveEntryList(&Ring->PacketComplete); InitializeListHead(&Ring->PacketComplete); AppendTailList(&List, ListEntry); @@ -3752,21 +3830,24 @@ __TransmitterRingTeardown( } static FORCEINLINE VOID -__TransmitterRingQueuePackets( +__TransmitterRingQueuePacket( IN PXENVIF_TRANSMITTER_RING Ring, - IN PLIST_ENTRY List + IN PXENVIF_TRANSMITTER_PACKET Packet ) { + PLIST_ENTRY ListEntry; ULONG_PTR Old; ULONG_PTR LockBit; ULONG_PTR New; + ListEntry = &Packet->ListEntry; + do { Old = (ULONG_PTR)Ring->Lock; LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT; - List->Flink->Blink = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT); - New = (ULONG_PTR)List->Blink; + ListEntry->Blink = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT); + New = (ULONG_PTR)ListEntry; ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0); New |= LockBit; } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock, (PVOID)New, (PVOID)Old) != Old); @@ -4485,7 +4566,7 @@ TransmitterTeardown( } static BOOLEAN -__TransmitterGetPacketHeadersPullup( +TransmitterGetPacketHeadersVersion2Pullup( IN PVOID Argument, IN PUCHAR DestinationVa, IN OUT PXENVIF_PACKET_PAYLOAD Payload, @@ -4546,22 +4627,22 @@ fail1: } NTSTATUS -TransmitterGetPacketHeaders( - IN PXENVIF_TRANSMITTER Transmitter, - IN PXENVIF_TRANSMITTER_PACKET Packet, - OUT PVOID Headers, - OUT PXENVIF_PACKET_INFO Info +TransmitterGetPacketHeadersVersion2( + IN PXENVIF_TRANSMITTER Transmitter, + IN struct _XENVIF_TRANSMITTER_PACKET_V2 *PacketVersion2, + OUT PVOID Headers, + OUT PXENVIF_PACKET_INFO Info ) { - XENVIF_PACKET_PAYLOAD Payload; - NTSTATUS status; + XENVIF_PACKET_PAYLOAD Payload; + NTSTATUS status; - Payload.Mdl = Packet->Mdl; - Payload.Offset = Packet->Offset; - Payload.Length = Packet->Length; + Payload.Mdl = PacketVersion2->Mdl; + Payload.Offset = PacketVersion2->Offset; + Payload.Length = PacketVersion2->Length; status = ParsePacket(Headers, - __TransmitterGetPacketHeadersPullup, + TransmitterGetPacketHeadersVersion2Pullup, Transmitter, &Payload, Info); @@ -4574,70 +4655,241 @@ fail1: return status; } -VOID -TransmitterQueuePackets( - IN PXENVIF_TRANSMITTER Transmitter, - IN PLIST_ENTRY List +static FORCEINLINE VOID +__TransmitterHashAccumulate( + IN OUT PULONG Accumulator, + IN PUCHAR Array, + IN ULONG Length ) { - PXENVIF_TRANSMITTER_RING Ring; - PXENVIF_FRONTEND Frontend; - LONG NumQueues; + ULONG Current; + ULONG Index; - Frontend = Transmitter->Frontend; - NumQueues = FrontendGetNumQueues(Frontend); + Current = *Accumulator; + + for (Index = 0; Index < Length; Index++) { + ULONG Overflow; + + Current = (Current << 4) + Array[Index]; + + Overflow = Current & 0x000fff00; + if (Overflow != 0) { + Current ^= Overflow >> 8; + Current ^= Overflow; + } + } + + *Accumulator = Current; +} + +static FORCEINLINE ULONG +__TransmitterHashPacket( + IN PXENVIF_TRANSMITTER_PACKET Packet + ) +{ + PUCHAR StartVa; + PXENVIF_PACKET_INFO Info; + PIP_HEADER IpHeader; + ULONG Value; + + Value = 0; + + StartVa = Packet->Header; + Info = &Packet->Info; + + if (Info->TcpHeader.Length == 0 && Info->UdpHeader.Length == 0) + goto done; + + ASSERT(Info->IpHeader.Length != 0); + IpHeader = (PIP_HEADER)(StartVa + Info->IpHeader.Offset); - if (NumQueues == 1) { - Ring = Transmitter->Ring[0]; + if (IpHeader->Version == 4) { + PIPV4_HEADER Version4 = &IpHeader->Version4; - __TransmitterRingQueuePackets(Ring, List); + __TransmitterHashAccumulate(&Value, + Version4->SourceAddress.Byte, + IPV4_ADDRESS_LENGTH); + __TransmitterHashAccumulate(&Value, + Version4->DestinationAddress.Byte, + IPV4_ADDRESS_LENGTH); } else { - while (!IsListEmpty(List)) { - PXENVIF_TRANSMITTER_PACKET Packet; - LIST_ENTRY HashList; - ULONG Index; + PIPV6_HEADER Version6 = &IpHeader->Version6; - InitializeListHead(&HashList); - Index = 0; + ASSERT3U(IpHeader->Version, ==, 6); - while (!IsListEmpty(List)) { - PLIST_ENTRY ListEntry; - ULONG Hash; + __TransmitterHashAccumulate(&Value, + Version6->SourceAddress.Byte, + IPV6_ADDRESS_LENGTH); + __TransmitterHashAccumulate(&Value, + Version6->DestinationAddress.Byte, + IPV6_ADDRESS_LENGTH); + } - ListEntry = RemoveHeadList(List); - ASSERT3P(ListEntry, !=, List); + if (Info->TcpHeader.Length != 0) { + PTCP_HEADER TcpHeader; - RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); + TcpHeader = (PTCP_HEADER)(StartVa + Info->TcpHeader.Offset); - Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry); + __TransmitterHashAccumulate(&Value, + (PUCHAR)&TcpHeader->SourcePort, + sizeof (USHORT)); + __TransmitterHashAccumulate(&Value, + (PUCHAR)&TcpHeader->DestinationPort, + sizeof (USHORT)); + } else { + PUDP_HEADER UdpHeader; - Hash = Packet->Value % NumQueues; - if (Hash != Index) { - if (!IsListEmpty(&HashList)) { - Ring = Transmitter->Ring[Index]; - ASSERT3P(Ring, !=, NULL); + ASSERT(Info->UdpHeader.Length != 0); - __TransmitterRingQueuePackets(Ring, &HashList); - InitializeListHead(&HashList); - } + UdpHeader = (PUDP_HEADER)(StartVa + Info->UdpHeader.Offset); - Index = Hash; - } + __TransmitterHashAccumulate(&Value, + (PUCHAR)&UdpHeader->SourcePort, + sizeof (USHORT)); + __TransmitterHashAccumulate(&Value, + (PUCHAR)&UdpHeader->DestinationPort, + sizeof (USHORT)); + } - InsertTailList(&HashList, ListEntry); - } +done: + return Value; +} + +NTSTATUS +TransmitterQueuePacket( + IN PXENVIF_TRANSMITTER Transmitter, + 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 + ) +{ + PXENVIF_FRONTEND Frontend; + PXENVIF_TRANSMITTER_PACKET Packet; + PUCHAR StartVa; + PXENVIF_PACKET_PAYLOAD Payload; + PXENVIF_PACKET_INFO Info; + ULONG Index; + PXENVIF_TRANSMITTER_RING Ring; + NTSTATUS status; - if (!IsListEmpty(&HashList)) { - Ring = Transmitter->Ring[Index]; - ASSERT3P(Ring, !=, NULL); + Frontend = Transmitter->Frontend; - __TransmitterRingQueuePackets(Ring, &HashList); - InitializeListHead(&HashList); - } + Packet = __TransmitterGetPacket(Transmitter); - ASSERT(IsListEmpty(&HashList)); - } + status = STATUS_NO_MEMORY; + if (Packet == NULL) + goto fail1; + + Packet->Mdl = Mdl; + Packet->Offset = Offset; + Packet->Length = Length; + Packet->OffloadOptions = OffloadOptions; + Packet->MaximumSegmentSize = MaximumSegmentSize; + Packet->TagControlInformation = TagControlInformation; + Packet->Cookie = Cookie; + + StartVa = Packet->Header; + + Payload = &Packet->Payload; + Payload->Mdl = Packet->Mdl; + Payload->Offset = Packet->Offset; + Payload->Length = Packet->Length; + + Info = &Packet->Info; + + status = ParsePacket(StartVa, TransmitterPullup, Transmitter, Payload, Info); + if (!NT_SUCCESS(status)) + goto fail2; + + switch (Hash->Algorithm) { + case XENVIF_PACKET_HASH_ALGORITHM_NONE: + Index = __TransmitterHashPacket(Packet); + break; + + case XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED: + Index = Hash->Value; + break; + + default: + ASSERT(FALSE); + Index = 0; + break; + } + + Index %= FrontendGetNumQueues(Frontend); + Ring = Transmitter->Ring[Index]; + + __TransmitterRingQueuePacket(Ring, Packet); + + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + + __TransmitterPutPacket(Transmitter, Packet); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +TransmitterQueuePacketsVersion2( + IN PXENVIF_TRANSMITTER Transmitter, + IN PLIST_ENTRY List + ) +{ + LIST_ENTRY Reject; + + InitializeListHead(&Reject); + + while (!IsListEmpty(List)) { + PLIST_ENTRY ListEntry; + struct _XENVIF_TRANSMITTER_PACKET_V2 *PacketVersion2; + XENVIF_PACKET_HASH Hash; + NTSTATUS status; + + ListEntry = RemoveHeadList(List); + ASSERT3P(ListEntry, !=, List); + + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); + + PacketVersion2 = CONTAINING_RECORD(ListEntry, + struct _XENVIF_TRANSMITTER_PACKET_V2, + ListEntry); + + Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED; + Hash.Value = PacketVersion2->Value; + + status = TransmitterQueuePacket(Transmitter, + PacketVersion2->Mdl, + PacketVersion2->Offset, + PacketVersion2->Length, + PacketVersion2->Send.OffloadOptions, + PacketVersion2->Send.MaximumSegmentSize, + PacketVersion2->Send.TagControlInformation, + &Hash, + PacketVersion2); + if (!NT_SUCCESS(status)) + InsertTailList(&Reject, &PacketVersion2->ListEntry); + } + + ASSERT(IsListEmpty(List)); + + if (!IsListEmpty(&Reject)) { + PLIST_ENTRY ListEntry = Reject.Flink; + + RemoveEntryList(&Reject); + AppendTailList(List, ListEntry); } + + return (IsListEmpty(List)) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; } VOID diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h index 04f1f6e..0b7f654 100644 --- a/src/xenvif/transmitter.h +++ b/src/xenvif/transmitter.h @@ -115,8 +115,21 @@ TransmitterQueryRingSize( OUT PULONG Size ); -extern VOID -TransmitterQueuePackets( +extern NTSTATUS +TransmitterQueuePacket( + IN PXENVIF_TRANSMITTER Transmitter, + 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 + ); + +extern NTSTATUS +TransmitterQueuePacketsVersion2( IN PXENVIF_TRANSMITTER Transmitter, IN PLIST_ENTRY List ); @@ -135,11 +148,11 @@ TransmitterQueryLargePacketSize( ); extern NTSTATUS -TransmitterGetPacketHeaders( - IN PXENVIF_TRANSMITTER Transmitter, - IN PXENVIF_TRANSMITTER_PACKET Packet, - OUT PVOID Headers, - OUT PXENVIF_PACKET_INFO Info +TransmitterGetPacketHeadersVersion2( + IN PXENVIF_TRANSMITTER Transmitter, + IN struct _XENVIF_TRANSMITTER_PACKET_V2 *Packet, + OUT PVOID Headers, + OUT PXENVIF_PACKET_INFO Info ); #endif // _XENVIF_TRANSMITTER_H diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c index ac4d454..76365d2 100644 --- a/src/xenvif/vif.c +++ b/src/xenvif/vif.c @@ -317,7 +317,7 @@ done: } static VOID -VifReceiverReturnPackets( +VifReceiverReturnPacketsVersion1( IN PINTERFACE Interface, IN PLIST_ENTRY List ) @@ -326,30 +326,45 @@ VifReceiverReturnPackets( AcquireMrswLockShared(&Context->Lock); - ReceiverReturnPackets(FrontendGetReceiver(Context->Frontend), - List); + ReceiverReturnPacketsVersion1(FrontendGetReceiver(Context->Frontend), + List); + + ReleaseMrswLockShared(&Context->Lock); +} + +static VOID +VifReceiverReturnPacket( + IN PINTERFACE Interface, + IN PVOID Cookie + ) +{ + PXENVIF_VIF_CONTEXT Context = Interface->Context; + + AcquireMrswLockShared(&Context->Lock); + + ReceiverReturnPacket(FrontendGetReceiver(Context->Frontend), + Cookie); ReleaseMrswLockShared(&Context->Lock); } static NTSTATUS -VifTransmitterGetPacketHeaders( - IN PINTERFACE Interface, - IN PXENVIF_TRANSMITTER_PACKET Packet, - OUT PVOID Headers, - OUT PXENVIF_PACKET_INFO Info +VifTransmitterGetPacketHeadersVersion2( + IN PINTERFACE Interface, + IN struct _XENVIF_TRANSMITTER_PACKET_V2 *Packet, + OUT PVOID Headers, + OUT PXENVIF_PACKET_INFO Info ) { - PXENVIF_VIF_CONTEXT Context = Interface->Context; - NTSTATUS status; + PXENVIF_VIF_CONTEXT Context = Interface->Context; + NTSTATUS status; AcquireMrswLockShared(&Context->Lock); - ASSERT3U(VifGetVersion(Context), >=, 2); - status = TransmitterGetPacketHeaders(FrontendGetTransmitter(Context->Frontend), - Packet, - Headers, - Info); + status = TransmitterGetPacketHeadersVersion2(FrontendGetTransmitter(Context->Frontend), + Packet, + Headers, + Info); ReleaseMrswLockShared(&Context->Lock); @@ -357,7 +372,7 @@ VifTransmitterGetPacketHeaders( } static NTSTATUS -VifTransmitterQueuePackets( +VifTransmitterQueuePacketsVersion2( IN PINTERFACE Interface, IN PLIST_ENTRY List ) @@ -369,20 +384,64 @@ VifTransmitterQueuePackets( status = STATUS_UNSUCCESSFUL; if (Context->Enabled == FALSE) - goto fail1; + goto done; - ASSERT3U(VifGetVersion(Context), >=, 2); - TransmitterQueuePackets(FrontendGetTransmitter(Context->Frontend), - List); + status = TransmitterQueuePacketsVersion2(FrontendGetTransmitter(Context->Frontend), + List); +done: ReleaseMrswLockShared(&Context->Lock); - return STATUS_SUCCESS; + return status; +} -fail1: +static VOID +VifTransmitterQueuePacket( + 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 + ) +{ + PXENVIF_VIF_CONTEXT Context = Interface->Context; + NTSTATUS status; + + AcquireMrswLockShared(&Context->Lock); + + status = STATUS_UNSUCCESSFUL; + if (Context->Enabled == FALSE) + goto done; + + ASSERT3U(VifGetVersion(Context), >=, 4); + status = TransmitterQueuePacket(FrontendGetTransmitter(Context->Frontend), + Mdl, + Offset, + Length, + OffloadOptions, + MaximumSegmentSize, + TagControlInformation, + Hash, + Cookie); + +done: ReleaseMrswLockShared(&Context->Lock); - return status; + if (!NT_SUCCESS(status)) { + XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion; + + RtlZeroMemory(&Completion, sizeof (XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO)); + + Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED; + + VifTransmitterReturnPacket(Context, + Cookie, + &Completion); + } } static VOID @@ -652,6 +711,7 @@ VifAcquire( Trace("====>\n"); Context->Frontend = PdoGetFrontend(Context->Pdo); + Context->Version = Interface->Version; Trace("<====\n"); @@ -678,6 +738,7 @@ VifRelease( ASSERT(!Context->Enabled); + Context->Version = 0; Context->Frontend = NULL; Trace("<====\n"); @@ -693,11 +754,11 @@ static struct _XENVIF_VIF_INTERFACE_V2 VifInterfaceVersion2 = { VifEnable, VifDisable, VifQueryStatistic, - VifReceiverReturnPackets, + VifReceiverReturnPacketsVersion1, VifReceiverSetOffloadOptions, VifReceiverQueryRingSize, - VifTransmitterGetPacketHeaders, - VifTransmitterQueuePackets, + VifTransmitterGetPacketHeadersVersion2, + VifTransmitterQueuePacketsVersion2, VifTransmitterQueryOffloadOptions, VifTransmitterQueryLargePacketSize, VifTransmitterQueryRingSize, @@ -718,12 +779,37 @@ static struct _XENVIF_VIF_INTERFACE_V3 VifInterfaceVersion3 = { VifEnable, VifDisable, VifQueryStatistic, - VifReceiverReturnPackets, + VifReceiverReturnPacketsVersion1, VifReceiverSetOffloadOptions, VifReceiverSetBackfillSize, VifReceiverQueryRingSize, - VifTransmitterGetPacketHeaders, - VifTransmitterQueuePackets, + VifTransmitterGetPacketHeadersVersion2, + VifTransmitterQueuePacketsVersion2, + VifTransmitterQueryOffloadOptions, + VifTransmitterQueryLargePacketSize, + VifTransmitterQueryRingSize, + VifMacQueryState, + VifMacQueryMaximumFrameSize, + VifMacQueryPermanentAddress, + VifMacQueryCurrentAddress, + VifMacQueryMulticastAddresses, + VifMacSetMulticastAddresses, + VifMacSetFilterLevel, + VifMacQueryFilterLevel +}; + +static struct _XENVIF_VIF_INTERFACE_V4 VifInterfaceVersion4 = { + { sizeof (struct _XENVIF_VIF_INTERFACE_V4), 4, NULL, NULL, NULL }, + VifAcquire, + VifRelease, + VifEnable, + VifDisable, + VifQueryStatistic, + VifReceiverReturnPacket, + VifReceiverSetOffloadOptions, + VifReceiverSetBackfillSize, + VifReceiverQueryRingSize, + VifTransmitterQueuePacket, VifTransmitterQueryOffloadOptions, VifTransmitterQueryLargePacketSize, VifTransmitterQueryRingSize, @@ -835,13 +921,28 @@ VifGetInterface( status = STATUS_SUCCESS; break; } + case 4: { + struct _XENVIF_VIF_INTERFACE_V4 *VifInterface; + + VifInterface = (struct _XENVIF_VIF_INTERFACE_V4 *)Interface; + + status = STATUS_BUFFER_OVERFLOW; + if (Size < sizeof (struct _XENVIF_VIF_INTERFACE_V4)) + break; + + *VifInterface = VifInterfaceVersion4; + + ASSERT3U(Interface->Version, ==, Version); + Interface->Context = Context; + + status = STATUS_SUCCESS; + break; + } default: status = STATUS_NOT_SUPPORTED; break; } - Context->Version = Version; - return status; } @@ -873,18 +974,43 @@ VifTeardown( } VOID -VifReceiverQueuePackets( +VifReceiverQueuePacketsVersion1( IN PXENVIF_VIF_CONTEXT Context, IN PLIST_ENTRY List ) { Context->Callback(Context->Argument, - XENVIF_RECEIVER_QUEUE_PACKETS, + XENVIF_RECEIVER_QUEUE_PACKET, List); } VOID -VifTransmitterReturnPackets( +VifReceiverQueuePacket( + IN PXENVIF_VIF_CONTEXT Context, + 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 PVOID Cookie + ) +{ + Context->Callback(Context->Argument, + XENVIF_RECEIVER_QUEUE_PACKET, + Mdl, + Offset, + Length, + Flags, + MaximumSegmentSize, + TagControlInformation, + Info, + Cookie); +} + +VOID +VifTransmitterReturnPacketsVersion2( IN PXENVIF_VIF_CONTEXT Context, IN PLIST_ENTRY List ) @@ -892,10 +1018,25 @@ VifTransmitterReturnPackets( ASSERT3U(VifGetVersion(Context), >=, 2); Context->Callback(Context->Argument, - XENVIF_TRANSMITTER_RETURN_PACKETS, + XENVIF_TRANSMITTER_RETURN_PACKET, List); } +VOID +VifTransmitterReturnPacket( + IN PXENVIF_VIF_CONTEXT Context, + IN PVOID Cookie, + IN PXENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion + ) +{ + ASSERT3U(VifGetVersion(Context), >=, 4); + + Context->Callback(Context->Argument, + XENVIF_TRANSMITTER_RETURN_PACKET, + Cookie, + Completion); +} + PXENVIF_THREAD VifGetMacThread( IN PXENVIF_VIF_CONTEXT Context diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h index a842b79..ebb4337 100644 --- a/src/xenvif/vif.h +++ b/src/xenvif/vif.h @@ -63,17 +63,37 @@ VifTeardown( // CALLBACKS extern VOID -VifReceiverQueuePackets( +VifReceiverQueuePacketsVersion1( IN PXENVIF_VIF_CONTEXT Context, IN PLIST_ENTRY List ); extern VOID -VifTransmitterReturnPackets( +VifReceiverQueuePacket( + IN PXENVIF_VIF_CONTEXT Context, + 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 PVOID Cookie + ); + +extern VOID +VifTransmitterReturnPacketsVersion2( IN PXENVIF_VIF_CONTEXT Context, IN PLIST_ENTRY List ); +extern VOID +VifTransmitterReturnPacket( + IN PXENVIF_VIF_CONTEXT Context, + IN PVOID Cookie, + IN PXENVIF_TRANSMITTER_PACKET_COMPLETION_INFO Completion + ); + extern PXENVIF_THREAD VifGetMacThread( IN PXENVIF_VIF_CONTEXT Context -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |