#define DEFINE_REVISION_TABLE \
DEFINE_REVISION(0x08000002, 1, 2, 0, 0), \
DEFINE_REVISION(0x08000005, 1, 2, 1, 1), \
- DEFINE_REVISION(0x08000007, 1, 3, 1, 1)
+ DEFINE_REVISION(0x08000007, 1, 3, 1, 1), \
+ DEFINE_REVISION(0x08000008, 1, 4, 1, 1)
// Revisions 0x08000003, 0x08000004 and 0x08000006 are already in use
// in the master branch.
#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
*/
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) */
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
#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
#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 */
#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
*/
\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;
\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
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
/*! \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
/*! \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
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;
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;
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
#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
ULONGLONG Value[XENVIF_VIF_STATISTIC_COUNT];
} XENVIF_FRONTEND_STATISTICS, *PXENVIF_FRONTEND_STATISTICS;
+
struct _XENVIF_FRONTEND {
PXENVIF_PDO Pdo;
PCHAR Path;
MacDisconnect(__FrontendGetMac(Frontend));
+ Frontend->Split = FALSE;
Frontend->NumQueues = 0;
fail4:
ReceiverDisconnect(__FrontendGetReceiver(Frontend));
MacDisconnect(__FrontendGetMac(Frontend));
+ Frontend->Split = FALSE;
Frontend->NumQueues = 0;
XENBUS_DEBUG(Deregister,
IN PXENVIF_FRONTEND Frontend
);
+extern BOOLEAN
+FrontendIsSplit(
+ IN PXENVIF_FRONTEND Frontend
+ );
+
extern PCHAR
FrontendFormatPath(
IN PXENVIF_FRONTEND Frontend,
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;
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);
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);
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;
RtlZeroMemory(Mdl, sizeof (MDL) + sizeof (PFN_NUMBER));
- Info = Packet->Info;
-
- __ReceiverFree(Info);
- Packet->Info = NULL;
-
ASSERT(IsZeroMemory(Packet, sizeof (XENVIF_RECEIVER_PACKET)));
}
Ring->PacketCache,
Locked);
- ASSERT(IsZeroMemory(Packet->Info, sizeof (XENVIF_PACKET_INFO)));
+ ASSERT(IsZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO)));
return Packet;
}
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;
PETHERNET_HEADER EthernetHeader;
ULONG Offset;
- Info = Packet->Info;
+ Info = &Packet->Info;
PayloadLength = Packet->Length - Info->Length;
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),
Receiver = Ring->Receiver;
- Info = Packet->Info;
+ Info = &Packet->Info;
Payload.Mdl = &Packet->Mdl;
Payload.Offset = Packet->Offset + Info->Length;
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;
Receiver = Ring->Receiver;
- Info = Packet->Info;
+ Info = &Packet->Info;
InfoVa = MmGetSystemAddressForMdlSafe(&Packet->Mdl, NormalPagePriority);
ASSERT(InfoVa != NULL);
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;
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) {
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);
Frontend = Receiver->Frontend;
Mac = FrontendGetMac(Frontend);
- Info = Packet->Info;
+ Info = &Packet->Info;
Payload.Mdl = Packet->Mdl.Next;
Payload.Offset = 0;
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;
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;
// 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);
Packet->Mdl.ByteCount = Packet->Offset;
- Info = Packet->Info;
+ Info = &Packet->Info;
status = ParsePacket(StartVa, ReceiverRingPullup, Ring, &Payload, Info);
if (!NT_SUCCESS(status)) {
ReceiverRingProcessTag(Ring, Packet);
ReceiverRingProcessChecksum(Ring, Packet);
- Packet->Cookie = Ring;
-
(*Count)++;
}
}
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
)
{
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;
#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));
if (~rsp->flags & NETRXF_more_data) { // EOP
ASSERT(Packet != NULL);
- ASSERT3P(Packet->Cookie, ==, NULL);
if (Error) {
FrontendIncrementStatistic(Frontend,
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);
}
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();
KeSetEvent(&Receiver->Event, 0, FALSE);
}
+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
);
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,
#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;
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;
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
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,
}
static BOOLEAN
-TransmitterRingPullup(
+TransmitterPullup(
IN PVOID Argument,
IN PUCHAR DestinationVa,
IN OUT PXENVIF_PACKET_PAYLOAD Payload,
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;
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;
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);
ASSERT3P(Buffer->Context, ==, Packet);
Buffer->Context = NULL;
- Packet->Value--;
+ --Packet->Reference;
__TransmitterPutBuffer(Ring, Buffer);
}
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;
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);
Fragment->Context = NULL;
Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
- Packet->Value--;
+ --Packet->Reference;
__TransmitterPutFragment(Ring, Fragment);
}
ASSERT3P(Fragment, ==, NULL);
- while (Packet->Value != 1) {
+ while (Packet->Reference != 1) {
PLIST_ENTRY ListEntry;
ASSERT(State->Count != 0);
Fragment->Context = NULL;
Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
- Packet->Value--;
+ --Packet->Reference;
__TransmitterPutFragment(Ring, Fragment);
}
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);
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;
status = STATUS_NO_MEMORY;
if (Fragment == NULL)
- goto fail3;
+ goto fail2;
Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_BUFFER;
Fragment->Context = Buffer;
TRUE,
&Fragment->Entry);
if (!NT_SUCCESS(status))
- goto fail4;
+ goto fail3;
Fragment->Offset = 0;
Fragment->Length = Mdl->ByteCount + Payload->Length;
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);
// 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);
Info->TcpOptions.Offset += sizeof (ETHERNET_TAG);
}
- if (State->Send.OffloadOptions.OffloadIpVersion4LargePacket) {
+ if (Packet->OffloadOptions.OffloadIpVersion4LargePacket) {
PIP_HEADER IpHeader;
PTCP_HEADER TcpHeader;
ULONG Length;
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;
// 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);
return STATUS_SUCCESS;
-fail5:
- Error("fail5\n");
+fail4:
+ Error("fail4\n");
ASSERT(State->Count != 0);
--State->Count;
Fragment->Entry);
Fragment->Entry = NULL;
-fail4:
- Error("fail4\n");
+fail3:
+ Error("fail3\n");
Fragment->Context = NULL;
Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
__TransmitterPutFragment(Ring, Fragment);
-fail3:
- Error("fail3\n");
-
- Mdl->ByteCount = 0;
-
fail2:
Error("fail2\n");
- Packet->Value--;
+ --Packet->Reference;
Buffer->Context = NULL;
__TransmitterPutBuffer(Ring, Buffer);
fail1:
Error("fail1 (%08x)\n", status);
- ASSERT3U(Packet->Value, ==, 0);
+ ASSERT3U(Packet->Reference, ==, 0);
return status;
}
}
if (Packet != NULL)
- Packet->Value--;
+ --Packet->Reference;
__TransmitterPutFragment(Ring, Fragment);
}
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;
}
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;
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);
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) {
if (Transmitter->AlwaysCopy != 0 ||
(!NT_SUCCESS(status) && status == STATUS_BUFFER_OVERFLOW)) {
- ASSERT3U(State->Count, ==, Packet->Value);
+ ASSERT3U(State->Count, ==, Packet->Reference);
status = __TransmitterRingCopyPayload(Ring);
}
if (!NT_SUCCESS(status))
goto fail2;
- ASSERT3U(State->Count, ==, Packet->Value);
+ ASSERT3U(State->Count, ==, Packet->Reference);
Ring->PacketsPrepared++;
return STATUS_SUCCESS;
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)));
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;
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;
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;
req = NULL;
FirstRequest = TRUE;
- PacketLength = 0;
while (State->Count != 0) {
--State->Count;
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;
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;
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
// 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)));
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++;
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,
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;
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);
ListEntry = NextEntry;
}
- ListEntry = List.Flink;
if (!IsListEmpty(&List)) {
+ ListEntry = List.Flink;
+
RemoveEntryList(&List);
- InitializeListHead(&List);
AppendTailList(&Ring->PacketQueue, ListEntry);
+
Ring->PacketsQueued += Count;
}
}
PXENVIF_TRANSMITTER_REQUEST Request;
ListEntry = RemoveHeadList(&Ring->RequestQueue);
+ ASSERT3P(ListEntry, !=, &Ring->RequestQueue);
+
RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
Request = CONTAINING_RECORD(ListEntry,
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)) {
__TransmitterRingPushRequests(Ring);
}
+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,
)
{
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
// 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);
}
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);
}
static BOOLEAN
-__TransmitterGetPacketHeadersPullup(
+TransmitterGetPacketHeadersVersion2Pullup(
IN PVOID Argument,
IN PUCHAR DestinationVa,
IN OUT PXENVIF_PACKET_PAYLOAD Payload,
}
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);
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
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
);
);
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
}
static VOID
-VifReceiverReturnPackets(
+VifReceiverReturnPacketsVersion1(
IN PINTERFACE Interface,
IN PLIST_ENTRY List
)
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);
}
static NTSTATUS
-VifTransmitterQueuePackets(
+VifTransmitterQueuePacketsVersion2(
IN PINTERFACE Interface,
IN PLIST_ENTRY List
)
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
Trace("====>\n");
Context->Frontend = PdoGetFrontend(Context->Pdo);
+ Context->Version = Interface->Version;
Trace("<====\n");
ASSERT(!Context->Enabled);
+ Context->Version = 0;
Context->Frontend = NULL;
Trace("<====\n");
VifEnable,
VifDisable,
VifQueryStatistic,
- VifReceiverReturnPackets,
+ VifReceiverReturnPacketsVersion1,
VifReceiverSetOffloadOptions,
VifReceiverQueryRingSize,
- VifTransmitterGetPacketHeaders,
- VifTransmitterQueuePackets,
+ VifTransmitterGetPacketHeadersVersion2,
+ VifTransmitterQueuePacketsVersion2,
VifTransmitterQueryOffloadOptions,
VifTransmitterQueryLargePacketSize,
VifTransmitterQueryRingSize,
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,
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;
}
}
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
)
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
// 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