DEFINE_REVISION(0x08000003, 1, 3, 0, 0), \
DEFINE_REVISION(0x08000004, 1, 3, 2, 1), \
DEFINE_REVISION(0x08000006, 1, 4, 2, 1), \
- DEFINE_REVISION(0x08000009, 1, 5, 2, 1)
+ DEFINE_REVISION(0x08000009, 1, 5, 2, 1), \
+ DEFINE_REVISION(0x0800000B, 1, 6, 2, 1)
-// Revision 0x08000005, 0x08000007 and 0x08000008 are already in use in
-// the staging-8.1 branch.
+// Revision 0x08000005, 0x08000007, 0x08000008 and 0x0800000A are already
+// in use in the staging-8.1 branch.
#endif // _REVISION_H
/*! 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_UNSPECIFIED,
+ /*! Toeplitz hash */
+ XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ
} XENVIF_PACKET_HASH_ALGORITHM, *PXENVIF_PACKET_HASH_ALGORITHM;
-/*! \struct _XENVIF_PACKET_HASH_V1
+typedef enum _XENVIF_PACKET_HASH_TYPE {
+ /*! None (value should be ignored) */
+ XENVIF_PACKET_HASH_TYPE_NONE = 0,
+ /*! IPv4 header only */
+ XENVIF_PACKET_HASH_TYPE_IPV4,
+ /*! IPv4 and TCP headers */
+ XENVIF_PACKET_HASH_TYPE_IPV4_TCP,
+ /*! IPv6 header only */
+ XENVIF_PACKET_HASH_TYPE_IPV6,
+ /*! IPv6 and TCP headers */
+ XENVIF_PACKET_HASH_TYPE_IPV6_TCP
+} XENVIF_PACKET_HASH_TYPE, *PXENVIF_PACKET_HASH_TYPE;
+
+struct _XENVIF_PACKET_HASH_V1 {
+ /*! Hash algorithm used to calculate value */
+ XENVIF_PACKET_HASH_ALGORITHM Algorithm;
+ /*! Calculated value */
+ ULONG Value;
+};
+
+/*! \struct _XENVIF_PACKET_HASH_V2
\brief Hash information
*/
-struct _XENVIF_PACKET_HASH_V1 {
+struct _XENVIF_PACKET_HASH_V2 {
/*! Hash algorithm used to calculate value */
XENVIF_PACKET_HASH_ALGORITHM Algorithm;
+ /*! Scope of hash */
+ XENVIF_PACKET_HASH_TYPE Type;
/*! Calculated value */
ULONG Value;
};
-typedef struct _XENVIF_PACKET_HASH_V1 XENVIF_PACKET_HASH, *PXENVIF_PACKET_HASH;
+typedef struct _XENVIF_PACKET_HASH_V2 XENVIF_PACKET_HASH, *PXENVIF_PACKET_HASH;
/*! \struct _XENVIF_PACKET_HEADER_V1
\brief Packet header information
\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 Hash Hash information for the packet
\param Cookie Cookie that should be passed to XENVIF_RECEIVER_RETURN_PACKET method
\b XENVIF_MAC_STATE_CHANGE:
OUT PULONGLONG Value
);
+/*! \typedef XENVIF_VIF_QUERY_RING_COUNT
+ \brief Query the number of shared rings between frontend
+ and backend
+
+ \param Interface The interface header
+ \param Count Buffer to receive the count
+*/
+typedef VOID
+(*XENVIF_VIF_QUERY_RING_COUNT)(
+ IN PINTERFACE Interface,
+ OUT PULONG Count
+ );
+
+/*! \typedef XENVIF_VIF_UPDATE_HASH_MAPPING
+ \brief Update the mapping of hash to transmitter/receiver ring
+
+ The default mapping is hash % number-of-rings
+
+ \param Interface The interface header
+ \param Mapping The mapping table
+ \param Size The size of the mapping table
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_UPDATE_HASH_MAPPING)(
+ IN PINTERFACE Interface,
+ IN PPROCESSOR_NUMBER Mapping,
+ IN ULONG Size
+ );
+
typedef VOID
(*XENVIF_VIF_RECEIVER_RETURN_PACKETS_V1)(
IN PINTERFACE Interface,
OUT PULONG Size
);
+/*! \typedef XENVIF_VIF_RECEIVER_SET_HASH_ALGORITHM
+ \brief Select a hash alorithm
+
+ \param Interface The interface header
+ \param Algorithm The algorithm to enable (or
+ XENVIF_PACKET_HASH_ALGORITHM_NONE to disable hashing)
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_RECEIVER_SET_HASH_ALGORITHM)(
+ IN PINTERFACE Interface,
+ IN XENVIF_PACKET_HASH_ALGORITHM Algorithm
+ );
+
+/*! \typedef XENVIF_VIF_RECEIVER_QUERY_HASH_CAPABILITIES
+ \brief Query any algorithm-specific capabilities.
+
+ \param Interface The interface header
+ \param ... Additional capabilities reported by the selected algorithm
+
+ \b XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ:
+ \param Types Mask of hash types supported
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_RECEIVER_QUERY_HASH_CAPABILITIES)(
+ IN PINTERFACE Interface,
+ ...
+ );
+
+/*! \typedef XENVIF_VIF_RECEIVER_UPDATE_HASH_PARAMETERS
+ \brief Set parameters of currently selected algorithm.
+
+ \param Interface The interface header
+ \param ... Additional parameters required by the selected algorithm
+
+ \b XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ:
+ \param Types Mask of hash types enabled
+ \param Key Pointer to a 40-byte array containing the hash key
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_RECEIVER_UPDATE_HASH_PARAMETERS)(
+ IN PINTERFACE Interface,
+ ...
+ );
+
+#define XENVIF_VIF_HASH_KEY_SIZE 40
+
/*! \typedef XENVIF_VIF_MAC_QUERY_STATE
\brief Query the current MAC (link) state
XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
};
-typedef struct _XENVIF_VIF_INTERFACE_V5 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+/*! \struct _XENVIF_VIF_INTERFACE_V6
+ \brief VIF interface version 6
+ \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V6 {
+ INTERFACE Interface;
+ XENVIF_VIF_ACQUIRE Acquire;
+ XENVIF_VIF_RELEASE Release;
+ XENVIF_VIF_ENABLE Enable;
+ XENVIF_VIF_DISABLE Disable;
+ XENVIF_VIF_QUERY_STATISTIC QueryStatistic;
+ XENVIF_VIF_QUERY_RING_COUNT QueryRingCount;
+ XENVIF_VIF_UPDATE_HASH_MAPPING UpdateHashMapping;
+ XENVIF_VIF_RECEIVER_RETURN_PACKET ReceiverReturnPacket;
+ XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS ReceiverSetOffloadOptions;
+ XENVIF_VIF_RECEIVER_SET_BACKFILL_SIZE ReceiverSetBackfillSize;
+ XENVIF_VIF_RECEIVER_QUERY_RING_SIZE ReceiverQueryRingSize;
+ XENVIF_VIF_RECEIVER_SET_HASH_ALGORITHM ReceiverSetHashAlgorithm;
+ XENVIF_VIF_RECEIVER_QUERY_HASH_CAPABILITIES ReceiverQueryHashCapabilities;
+ XENVIF_VIF_RECEIVER_UPDATE_HASH_PARAMETERS ReceiverUpdateHashParameters;
+ XENVIF_VIF_TRANSMITTER_QUEUE_PACKET TransmitterQueuePacket;
+ XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS TransmitterQueryOffloadOptions;
+ XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE TransmitterQueryLargePacketSize;
+ XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE TransmitterQueryRingSize;
+ XENVIF_VIF_MAC_QUERY_STATE MacQueryState;
+ XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE MacQueryMaximumFrameSize;
+ XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS MacQueryPermanentAddress;
+ XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS MacQueryCurrentAddress;
+ XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES MacQueryMulticastAddresses;
+ XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES MacSetMulticastAddresses;
+ XENVIF_VIF_MAC_SET_FILTER_LEVEL MacSetFilterLevel;
+ XENVIF_VIF_MAC_QUERY_FILTER_LEVEL MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V6 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 5
+#define XENVIF_VIF_INTERFACE_VERSION_MAX 6
#endif // _XENVIF_INTERFACE_H
ULONGLONG Value[XENVIF_VIF_STATISTIC_COUNT];
} XENVIF_FRONTEND_STATISTICS, *PXENVIF_FRONTEND_STATISTICS;
+#define XENVIF_FRONTEND_MAXIMUM_HASH_MAPPING_SIZE 128
+
+typedef struct _XENVIF_FRONTEND_HASH {
+ XENVIF_PACKET_HASH_ALGORITHM Algorithm;
+ ULONG Flags;
+ UCHAR Key[XENVIF_VIF_HASH_KEY_SIZE];
+ ULONG Mapping[XENVIF_FRONTEND_MAXIMUM_HASH_MAPPING_SIZE];
+ ULONG Size;
+} XENVIF_FRONTEND_HASH, *PXENVIF_FRONTEND_HASH;
struct _XENVIF_FRONTEND {
PXENVIF_PDO Pdo;
NET_IFINDEX InterfaceIndex;
PSOCKADDR_INET AddressTable;
ULONG AddressCount;
+
+ XENVIF_FRONTEND_HASH Hash;
};
static const PCHAR
return __FrontendIsSplit(Frontend);
}
+static FORCEINLINE NTSTATUS
+__FrontendUpdateHash(
+ IN PXENVIF_FRONTEND Frontend
+ )
+{
+ PXENVIF_FRONTEND_HASH Hash = &Frontend->Hash;
+ PXENVIF_CONTROLLER Controller;
+ ULONG Zero = 0;
+ ULONG Size;
+ PULONG Mapping;
+ ULONG Flags;
+ NTSTATUS status;
+
+ Controller = __FrontendGetController(Frontend);
+
+ switch (Hash->Algorithm) {
+ case XENVIF_PACKET_HASH_ALGORITHM_NONE:
+ Size = 1;
+ Mapping = &Zero;
+ Flags = 0;
+ break;
+
+ case XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ:
+ Size = Hash->Size;
+ Mapping = Hash->Mapping;
+ Flags = Hash->Flags;
+ break;
+
+ case XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED:
+ default:
+ (VOID) ControllerSetHashAlgorithm(Controller,
+ XEN_NETIF_CTRL_HASH_ALGORITHM_NONE);
+ goto done;
+ }
+
+ status = ControllerSetHashAlgorithm(Controller,
+ XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = ControllerSetHashMappingSize(Controller, Size);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ status = ControllerSetHashMapping(Controller, Mapping, Size, 0);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ status = ControllerSetHashKey(Controller, Hash->Key, XENVIF_VIF_HASH_KEY_SIZE);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
+ status = ControllerSetHashFlags(Controller, Flags);
+ if (!NT_SUCCESS(status))
+ goto fail5;
+
+done:
+ return STATUS_SUCCESS;
+
+fail5:
+ Error("fail5\n");
+
+fail4:
+ Error("fail4\n");
+
+fail3:
+ Error("fail3\n");
+
+fail2:
+ Error("fail2\n");
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+NTSTATUS
+FrontendUpdateHash(
+ IN PXENVIF_FRONTEND Frontend
+ )
+{
+ KIRQL Irql;
+ NTSTATUS status;
+
+ KeAcquireSpinLock(&Frontend->Lock, &Irql);
+ status = __FrontendUpdateHash(Frontend);
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return status;
+}
+
+NTSTATUS
+FrontendSetHashAlgorithm(
+ IN PXENVIF_FRONTEND Frontend,
+ IN XENVIF_PACKET_HASH_ALGORITHM Algorithm
+ )
+{
+ PXENVIF_FRONTEND_HASH Hash = &Frontend->Hash;
+ KIRQL Irql;
+ NTSTATUS status;
+
+ KeAcquireSpinLock(&Frontend->Lock, &Irql);
+
+ if (Algorithm == Hash->Algorithm)
+ goto done;
+
+ switch (Algorithm) {
+ case XENVIF_PACKET_HASH_ALGORITHM_NONE:
+ case XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED:
+ case XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ:
+ status = STATUS_SUCCESS;
+ break;
+
+ default:
+ status = STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ Info("%s: %s\n", __FrontendGetPath(Frontend),
+ (Algorithm == XENVIF_PACKET_HASH_ALGORITHM_NONE) ? "NONE" :
+ (Algorithm == XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED) ? "UNSPECIFIED" :
+ (Algorithm == XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ) ? "TOEPLITZ" :
+ "");
+
+ Hash->Algorithm = Algorithm;
+
+done:
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n");
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return status;
+}
+
+NTSTATUS
+FrontendQueryHashTypes(
+ IN PXENVIF_FRONTEND Frontend,
+ OUT PULONG Types
+ )
+{
+ KIRQL Irql;
+ ULONG Flags;
+ NTSTATUS status;
+
+ KeAcquireSpinLock(&Frontend->Lock, &Irql);
+
+ status = ControllerGetHashFlags(__FrontendGetController(Frontend),
+ &Flags);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ *Types = 0;
+ if (Flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4)
+ *Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV4;
+ if (Flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP)
+ *Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV4_TCP;
+ if (Flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6)
+ *Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV6;
+ if (Flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP)
+ *Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV6_TCP;
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return status;
+}
+
+NTSTATUS
+FrontendSetHashMapping(
+ IN PXENVIF_FRONTEND Frontend,
+ IN PULONG Mapping,
+ IN ULONG Size
+ )
+{
+ PXENVIF_FRONTEND_HASH Hash = &Frontend->Hash;
+ KIRQL Irql;
+ NTSTATUS status;
+
+ KeAcquireSpinLock(&Frontend->Lock, &Irql);
+
+ status = STATUS_INVALID_PARAMETER;
+ if (Size > XENVIF_FRONTEND_MAXIMUM_HASH_MAPPING_SIZE)
+ goto fail1;
+
+ RtlCopyMemory(Hash->Mapping, Mapping, sizeof (ULONG) * Size);
+ Hash->Size = Size;
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return status;
+}
+
+NTSTATUS
+FrontendSetHashKey(
+ IN PXENVIF_FRONTEND Frontend,
+ IN PUCHAR Key
+ )
+{
+ PXENVIF_FRONTEND_HASH Hash = &Frontend->Hash;
+ KIRQL Irql;
+
+ KeAcquireSpinLock(&Frontend->Lock, &Irql);
+
+ RtlCopyMemory(Hash->Key, Key, XENVIF_VIF_HASH_KEY_SIZE);
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FrontendSetHashTypes(
+ IN PXENVIF_FRONTEND Frontend,
+ IN ULONG Types
+ )
+{
+ PXENVIF_FRONTEND_HASH Hash = &Frontend->Hash;
+ KIRQL Irql;
+ ULONG Flags;
+
+ KeAcquireSpinLock(&Frontend->Lock, &Irql);
+
+ Flags = 0;
+ if (Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV4))
+ Flags |= XEN_NETIF_CTRL_HASH_TYPE_IPV4;
+ if (Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV4_TCP))
+ Flags |= XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP;
+ if (Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV6))
+ Flags |= XEN_NETIF_CTRL_HASH_TYPE_IPV6;
+ if (Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV6_TCP))
+ Flags |= XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP;
+
+ Hash->Flags = Flags;
+
+ KeReleaseSpinLock(&Frontend->Lock, Irql);
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+FrontendGetQueue(
+ IN PXENVIF_FRONTEND Frontend,
+ IN ULONG Value
+ )
+{
+ PXENVIF_FRONTEND_HASH Hash = &Frontend->Hash;
+ ULONG Queue;
+
+ switch (Hash->Algorithm) {
+ case XENVIF_PACKET_HASH_ALGORITHM_NONE:
+ case XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED:
+ Queue = Value % __FrontendGetNumQueues(Frontend);
+ break;
+
+ case XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ:
+ Queue = Hash->Mapping[Value % Hash->Size];
+ break;
+
+ default:
+ ASSERT(FALSE);
+ Queue = 0;
+ break;
+ }
+
+ return Queue;
+}
+
static NTSTATUS
FrontendConnect(
IN PXENVIF_FRONTEND Frontend
if (!NT_SUCCESS(status))
goto fail3;
- FrontendNotifyMulticastAddresses(Frontend, TRUE);
+ status = __FrontendUpdateHash(Frontend);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
+ (VOID) FrontendNotifyMulticastAddresses(Frontend, TRUE);
Trace("<====\n");
return STATUS_SUCCESS;
+fail4:
+ Error("fail4\n");
+
+ TransmitterDisable(__FrontendGetTransmitter(Frontend));
+
fail3:
Error("fail3\n");
{
Trace("====>\n");
- FrontendNotifyMulticastAddresses(Frontend, FALSE);
+ (VOID) FrontendNotifyMulticastAddresses(Frontend, FALSE);
TransmitterDisable(__FrontendGetTransmitter(Frontend));
ReceiverDisable(__FrontendGetReceiver(Frontend));
FdoGetStoreInterface(PdoGetFdo(Pdo), &(*Frontend)->StoreInterface);
FrontendSetMaxQueues(*Frontend);
+ (*Frontend)->Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED;
status = MacInitialize(*Frontend, &(*Frontend)->Mac);
if (!NT_SUCCESS(status))
fail6:
Error("fail6\n");
+ RtlZeroMemory(&(*Frontend)->Hash, sizeof (XENVIF_FRONTEND_HASH));
(*Frontend)->MaxQueues = 0;
RtlZeroMemory(&(*Frontend)->StoreInterface,
MacTeardown(__FrontendGetMac(Frontend));
Frontend->Mac = NULL;
+ RtlZeroMemory(&Frontend->Hash, sizeof (XENVIF_FRONTEND_HASH));
Frontend->MaxQueues = 0;
RtlZeroMemory(&Frontend->StoreInterface,
extern VOID
FrontendAdvertiseIpAddresses(
- IN PXENVIF_FRONTEND Frontend
+ IN PXENVIF_FRONTEND Frontend
+ );
+
+extern NTSTATUS
+FrontendUpdateHash(
+ IN PXENVIF_FRONTEND Frontend
+ );
+
+extern NTSTATUS
+FrontendSetHashAlgorithm(
+ IN PXENVIF_FRONTEND Frontend,
+ IN XENVIF_PACKET_HASH_ALGORITHM Algorithm
+ );
+
+extern NTSTATUS
+FrontendQueryHashTypes(
+ IN PXENVIF_FRONTEND Frontend,
+ OUT PULONG Types
+ );
+
+extern NTSTATUS
+FrontendSetHashMapping(
+ IN PXENVIF_FRONTEND Frontend,
+ IN PULONG Mapping,
+ IN ULONG Order
+ );
+
+extern NTSTATUS
+FrontendSetHashKey(
+ IN PXENVIF_FRONTEND Frontend,
+ IN PUCHAR Key
+ );
+
+extern NTSTATUS
+FrontendSetHashTypes(
+ IN PXENVIF_FRONTEND Frontend,
+ IN ULONG Types
+ );
+
+extern ULONG
+FrontendGetQueue(
+ IN PXENVIF_FRONTEND Frontend,
+ IN ULONG Index
);
#endif // _XENVIF_FRONTEND_H
PXENBUS_GNTTAB_ENTRY Entry;
} XENVIF_RECEIVER_FRAGMENT, *PXENVIF_RECEIVER_FRAGMENT;
+typedef struct _XENVIF_RECEIVER_HASH {
+ XENVIF_PACKET_HASH_ALGORITHM Algorithm;
+ ULONG Types;
+} XENVIF_RECEIVER_HASH, *PXENVIF_RECEIVER_HASH;
+
#define XENVIF_RECEIVER_RING_SIZE (__CONST_RING_SIZE(netif_rx, PAGE_SIZE))
#define XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID (XENVIF_RECEIVER_RING_SIZE - 1)
PXENBUS_DEBUG_CALLBACK DebugCallback;
PXENVIF_THREAD WatchdogThread;
LIST_ENTRY PacketList;
+ XENVIF_RECEIVER_HASH Hash;
} XENVIF_RECEIVER_RING, *PXENVIF_RECEIVER_RING;
typedef struct _XENVIF_RECEIVER_PACKET {
LIST_ENTRY ListEntry;
XENVIF_PACKET_INFO Info;
+ XENVIF_PACKET_HASH Hash;
ULONG Offset;
ULONG Length;
XENVIF_PACKET_CHECKSUM_FLAGS Flags;
} XENVIF_RECEIVER_PACKET, *PXENVIF_RECEIVER_PACKET;
struct _XENVIF_RECEIVER {
- PXENVIF_FRONTEND Frontend;
- XENBUS_CACHE_INTERFACE CacheInterface;
- XENBUS_GNTTAB_INTERFACE GnttabInterface;
- XENBUS_EVTCHN_INTERFACE EvtchnInterface;
- PXENVIF_RECEIVER_RING *Ring;
- LONG Loaned;
- LONG Returned;
- KEVENT Event;
- ULONG CalculateChecksums;
- ULONG AllowGsoPackets;
- ULONG DisableIpVersion4Gso;
- ULONG DisableIpVersion6Gso;
- ULONG IpAlignOffset;
- ULONG AlwaysPullup;
- XENBUS_STORE_INTERFACE StoreInterface;
- XENBUS_DEBUG_INTERFACE DebugInterface;
- PXENBUS_DEBUG_CALLBACK DebugCallback;
+ PXENVIF_FRONTEND Frontend;
+ XENBUS_CACHE_INTERFACE CacheInterface;
+ XENBUS_GNTTAB_INTERFACE GnttabInterface;
+ XENBUS_EVTCHN_INTERFACE EvtchnInterface;
+ PXENVIF_RECEIVER_RING *Ring;
+ LONG Loaned;
+ LONG Returned;
+ KEVENT Event;
+ ULONG CalculateChecksums;
+ ULONG AllowGsoPackets;
+ ULONG DisableIpVersion4Gso;
+ ULONG DisableIpVersion6Gso;
+ ULONG IpAlignOffset;
+ ULONG AlwaysPullup;
+ XENBUS_STORE_INTERFACE StoreInterface;
+ XENBUS_DEBUG_INTERFACE DebugInterface;
+ PXENBUS_DEBUG_CALLBACK DebugCallback;
};
#define XENVIF_RECEIVER_TAG 'ECER'
Packet->TagControlInformation = 0;
RtlZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO));
+ RtlZeroMemory(&Packet->Hash, sizeof (XENVIF_PACKET_HASH));
Mdl->MappedSystemVa = Mdl->StartVa;
Mdl->ByteOffset = 0;
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;
+ RtlCopyMemory(Segment,
+ Packet,
+ FIELD_OFFSET(XENVIF_RECEIVER_PACKET, Mdl));
+
+ // The segment contains no data as yet
+ Segment->Length = 0;
Mdl = &Segment->Mdl;
PXENVIF_FRONTEND Frontend;
PXENVIF_MAC Mac;
ULONG Length;
- XENVIF_PACKET_CHECKSUM_FLAGS Flags;
- USHORT MaximumSegmentSize;
XENVIF_PACKET_PAYLOAD Payload;
+ PXENVIF_RECEIVER_PACKET New;
PXENVIF_PACKET_INFO Info;
PUCHAR StartVa;
PETHERNET_HEADER EthernetHeader;
ASSERT3U(Packet->Offset, ==, 0);
Length = Packet->Length;
- Flags = Packet->Flags;
- MaximumSegmentSize = Packet->MaximumSegmentSize;
ASSERT3U(Packet->TagControlInformation, ==, 0);
Payload.Mdl = &Packet->Mdl;
Payload.Offset = 0;
Payload.Length = Length;
- // Get a new packet structure that will just contain the header after parsing
- Packet = __ReceiverRingGetPacket(Ring, TRUE);
+ // Get a new packet structure that will just contain the header after
+ // parsing. We need to preserve metadata from the original.
+
+ New = __ReceiverRingGetPacket(Ring, TRUE);
+
+ RtlCopyMemory(New,
+ Packet,
+ FIELD_OFFSET(XENVIF_RECEIVER_PACKET, Mdl));
+
+ Packet = New;
+
+ // Override offset to align
+ Packet->Offset = Receiver->IpAlignOffset;
status = STATUS_NO_MEMORY;
if (Packet == NULL) {
goto fail1;
}
- // Copy in the extracted metadata
- Packet->Offset = Receiver->IpAlignOffset;
- Packet->Length = Length;
- Packet->Flags = Flags;
- Packet->MaximumSegmentSize = MaximumSegmentSize;
-
StartVa = MmGetSystemAddressForMdlSafe(&Packet->Mdl, NormalPagePriority);
ASSERT(StartVa != NULL);
StartVa += Packet->Offset;
Packet->MaximumSegmentSize,
Packet->TagControlInformation,
&Packet->Info,
+ &Packet->Hash,
Packet);
}
static FORCEINLINE VOID
__ReceiverRingTrigger(
- IN PXENVIF_RECEIVER_RING Ring
+ IN PXENVIF_RECEIVER_RING Ring,
+ IN BOOLEAN Locked
)
{
PXENVIF_RECEIVER Receiver;
Receiver = Ring->Receiver;
+ if (!Locked)
+ __ReceiverRingAcquireLock(Ring);
+
if (Ring->Connected)
(VOID) XENBUS_EVTCHN(Trigger,
&Receiver->EvtchnInterface,
Ring->Channel);
+
+ if (!Locked)
+ __ReceiverRingReleaseLock(Ring);
}
static FORCEINLINE VOID
if (__ReceiverRingIsStopped(Ring)) {
__ReceiverRingStart(Ring);
- __ReceiverRingTrigger(Ring);
+ __ReceiverRingTrigger(Ring, TRUE);
}
if (!Locked)
BOOLEAN Extra;
ULONG Info;
USHORT MaximumSegmentSize;
+ XENVIF_PACKET_HASH Hash;
PXENVIF_RECEIVER_PACKET Packet;
uint16_t flags;
PMDL TailMdl;
Extra = FALSE;
Info = 0;
MaximumSegmentSize = 0;
+ RtlZeroMemory(&Hash, sizeof (Hash));
Packet = NULL;
flags = 0;
TailMdl = NULL;
MaximumSegmentSize = extra->u.gso.size;
break;
+ case XEN_NETIF_EXTRA_TYPE_HASH:
+ Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ;
+
+ switch (extra->u.hash.type) {
+ case _XEN_NETIF_CTRL_HASH_TYPE_IPV4:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4;
+ break;
+
+ case _XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4_TCP;
+ break;
+
+ case _XEN_NETIF_CTRL_HASH_TYPE_IPV6:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6;
+ break;
+
+ case _XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP:
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6_TCP;
+ break;
+
+ default:
+ ASSERT(FALSE);
+ Hash.Type = XENVIF_PACKET_HASH_TYPE_NONE;
+ break;
+ }
+
+ Hash.Value = *(uint32_t *)extra->u.hash.value;
+ break;
+
default:
ASSERT(FALSE);
break;
Packet->MaximumSegmentSize = MaximumSegmentSize;
}
+ if (Info & (1 << XEN_NETIF_EXTRA_TYPE_HASH)) {
+ ASSERT3U(Hash.Algorithm, ==, XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ);
+
+ if (Hash.Algorithm == Ring->Hash.Algorithm &&
+ ((1u << Hash.Type) & Ring->Hash.Types))
+ Packet->Hash = Hash;
+ }
+
Packet->Flags.Value = flags;
ASSERT(IsZeroMemory(&Packet->ListEntry, sizeof (LIST_ENTRY)));
Error = FALSE;
Info = 0;
MaximumSegmentSize = 0;
+ RtlZeroMemory(&Hash, sizeof (Hash));
Packet = NULL;
flags = 0;
TailMdl = NULL;
ASSERT3P(Packet, ==, NULL);
ASSERT3U(flags, ==, 0);
ASSERT3U(MaximumSegmentSize, ==, 0);
+ ASSERT(IsZeroMemory(&Hash, sizeof (Hash)));
ASSERT3P(TailMdl, ==, NULL);
ASSERT(EOP);
Ring->DebugCallback);
// Try to move things along
- ReceiverRingPoll(Ring);
+ __ReceiverRingTrigger(Ring, TRUE);
__ReceiverRingSend(Ring, TRUE);
}
Receiver = Ring->Receiver;
Frontend = Receiver->Frontend;
+ RtlZeroMemory(&Ring->Hash, sizeof (XENVIF_RECEIVER_HASH));
RtlZeroMemory(&Ring->TimerDpc, sizeof (KDPC));
RtlZeroMemory(&Ring->Timer, sizeof (KTIMER));
RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
}
}
+VOID
+ReceiverTrigger(
+ IN PXENVIF_RECEIVER Receiver,
+ IN ULONG Index
+ )
+{
+ PXENVIF_RECEIVER_RING Ring;
+
+ Ring = Receiver->Ring[Index];
+
+ __ReceiverRingTrigger(Ring, FALSE);
+}
+
VOID
ReceiverSend(
IN PXENVIF_RECEIVER Receiver,
__ReceiverRingSend(Ring, FALSE);
}
+
+NTSTATUS
+ReceiverSetHashAlgorithm(
+ IN PXENVIF_RECEIVER Receiver,
+ IN XENVIF_PACKET_HASH_ALGORITHM Algorithm
+ )
+{
+ PXENVIF_FRONTEND Frontend;
+ KIRQL Irql;
+ LONG Index;
+ NTSTATUS status;
+
+ Frontend = Receiver->Frontend;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+
+ for (Index = 0;
+ Index < (LONG)FrontendGetMaxQueues(Frontend);
+ ++Index) {
+ PXENVIF_RECEIVER_RING Ring;
+
+ Ring = Receiver->Ring[Index];
+ if (Ring == NULL)
+ break;
+
+ __ReceiverRingAcquireLock(Ring);
+ Ring->Hash.Algorithm = Algorithm;
+ __ReceiverRingReleaseLock(Ring);
+ }
+
+ KeLowerIrql(Irql);
+
+ status = FrontendSetHashAlgorithm(Frontend, Algorithm);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = FrontendUpdateHash(Frontend);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+NTSTATUS
+ReceiverQueryHashCapabilities(
+ IN PXENVIF_RECEIVER Receiver,
+ OUT PULONG Types
+ )
+{
+ PXENVIF_FRONTEND Frontend;
+ NTSTATUS status;
+
+ Frontend = Receiver->Frontend;
+
+ status = FrontendQueryHashTypes(Frontend, Types);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+NTSTATUS
+ReceiverUpdateHashParameters(
+ IN PXENVIF_RECEIVER Receiver,
+ IN ULONG Types,
+ IN PUCHAR Key
+ )
+{
+ PXENVIF_FRONTEND Frontend;
+ KIRQL Irql;
+ LONG Index;
+ NTSTATUS status;
+
+ Frontend = Receiver->Frontend;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &Irql);
+
+ for (Index = 0;
+ Index < (LONG)FrontendGetMaxQueues(Frontend);
+ ++Index) {
+ PXENVIF_RECEIVER_RING Ring;
+
+ Ring = Receiver->Ring[Index];
+ if (Ring == NULL)
+ break;
+
+ __ReceiverRingAcquireLock(Ring);
+ Ring->Hash.Types = Types;
+ __ReceiverRingReleaseLock(Ring);
+ }
+
+ KeLowerIrql(Irql);
+
+ status = FrontendSetHashTypes(Frontend, Types);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = FrontendSetHashKey(Frontend, Key);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = FrontendUpdateHash(Frontend);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+NTSTATUS
+ReceiverUpdateHashMapping(
+ IN PXENVIF_RECEIVER Receiver,
+ IN PPROCESSOR_NUMBER ProcessorMapping,
+ IN ULONG Size
+ )
+{
+ PXENVIF_FRONTEND Frontend;
+ PULONG QueueMapping;
+ ULONG NumQueues;
+ ULONG Index;
+ NTSTATUS status;
+
+ Frontend = Receiver->Frontend;
+
+ QueueMapping = __ReceiverAllocate(sizeof (ULONG) * Size);
+
+ status = STATUS_NO_MEMORY;
+ if (QueueMapping == NULL)
+ goto fail1;
+
+ NumQueues = FrontendGetNumQueues(Frontend);
+
+ status = STATUS_INVALID_PARAMETER;
+ for (Index = 0; Index < Size; Index++) {
+ QueueMapping[Index] = KeGetProcessorIndexFromNumber(&ProcessorMapping[Index]);
+
+ if (QueueMapping[Index] >= NumQueues)
+ goto fail2;
+ }
+
+ status = FrontendSetHashMapping(Frontend, QueueMapping, Size);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ status = FrontendUpdateHash(Frontend);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
+ __ReceiverFree(QueueMapping);
+
+ return STATUS_SUCCESS;
+
+fail4:
+ Error("fail4\n");
+
+fail3:
+ Error("fail3\n");
+
+fail2:
+ Error("fail2\n");
+
+ __ReceiverFree(QueueMapping);
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
IN PVOID Cookie
);
+extern VOID
+ReceiverTrigger(
+ IN PXENVIF_RECEIVER Receiver,
+ IN ULONG Index
+ );
+
extern VOID
ReceiverSend(
IN PXENVIF_RECEIVER Receiver,
IN ULONG Index
);
+NTSTATUS
+ReceiverSetHashAlgorithm(
+ IN PXENVIF_RECEIVER Receiver,
+ IN XENVIF_PACKET_HASH_ALGORITHM Algorithm
+ );
+
+NTSTATUS
+ReceiverQueryHashCapabilities(
+ IN PXENVIF_RECEIVER Receiver,
+ OUT PULONG Types
+ );
+
+NTSTATUS
+ReceiverUpdateHashParameters(
+ IN PXENVIF_RECEIVER Receiver,
+ IN ULONG Types,
+ IN PUCHAR Key
+ );
+
+NTSTATUS
+ReceiverUpdateHashMapping(
+ IN PXENVIF_RECEIVER Receiver,
+ IN PPROCESSOR_NUMBER ProcessorMapping,
+ IN ULONG Order
+ );
+
#endif // _XENVIF_RECEIVER_H
#undef XENVIF_TRANSMITTER_BATCH
}
+static FORCEINLINE VOID
+__TransmitterRingTrigger(
+ IN PXENVIF_TRANSMITTER_RING Ring
+ )
+{
+ PXENVIF_TRANSMITTER Transmitter;
+ PXENVIF_FRONTEND Frontend;
+
+ Transmitter = Ring->Transmitter;
+ Frontend = Transmitter->Frontend;
+
+ if (!Ring->Connected)
+ return;
+
+ if (FrontendIsSplit(Frontend)) {
+ ASSERT(Ring->Channel != NULL);
+
+ (VOID) XENBUS_EVTCHN(Trigger,
+ &Transmitter->EvtchnInterface,
+ Ring->Channel);
+ } else {
+ ReceiverTrigger(FrontendGetReceiver(Frontend),
+ Ring->Index);
+ }
+}
+
static FORCEINLINE VOID
__TransmitterRingSend(
IN PXENVIF_TRANSMITTER_RING Ring
Ring->DebugCallback);
// Try to move things along
+ __TransmitterRingTrigger(Ring);
__TransmitterRingSend(Ring);
- (VOID) TransmitterRingPoll(Ring);
}
PacketsQueued = Ring->PacketsQueued;
PUCHAR StartVa;
PXENVIF_PACKET_PAYLOAD Payload;
PXENVIF_PACKET_INFO Info;
+ ULONG Value;
ULONG Index;
PXENVIF_TRANSMITTER_RING Ring;
NTSTATUS status;
switch (Hash->Algorithm) {
case XENVIF_PACKET_HASH_ALGORITHM_NONE:
- Index = __TransmitterHashPacket(Packet);
+ Value = __TransmitterHashPacket(Packet);
break;
case XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED:
- Index = Hash->Value;
+ case XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ:
+ Value = Hash->Value;
break;
default:
ASSERT(FALSE);
- Index = 0;
+ Value = 0;
break;
}
- Index %= FrontendGetNumQueues(Frontend);
+ Index = FrontendGetQueue(Frontend, Value);
Ring = Transmitter->Ring[Index];
__TransmitterRingQueuePacket(Ring, Packet);
return status;
}
+static VOID
+VifQueryRingCount(
+ IN PINTERFACE Interface,
+ OUT PULONG Count
+ )
+{
+ PXENVIF_VIF_CONTEXT Context = Interface->Context;
+
+ AcquireMrswLockShared(&Context->Lock);
+
+ *Count = FrontendGetNumQueues(Context->Frontend);
+
+ ReleaseMrswLockShared(&Context->Lock);
+}
+
+static NTSTATUS
+VifUpdateHashMapping(
+ IN PINTERFACE Interface,
+ IN PPROCESSOR_NUMBER Mapping,
+ IN ULONG Order
+ )
+{
+ PXENVIF_VIF_CONTEXT Context = Interface->Context;
+ NTSTATUS status;
+
+ AcquireMrswLockShared(&Context->Lock);
+
+ status = ReceiverUpdateHashMapping(FrontendGetReceiver(Context->Frontend),
+ Mapping,
+ Order);
+
+ ReleaseMrswLockShared(&Context->Lock);
+
+ return status;
+}
+
static VOID
VifReceiverReturnPacketsVersion1(
IN PINTERFACE Interface,
ReleaseMrswLockShared(&Context->Lock);
}
+static NTSTATUS
+VifReceiverSetHashAlgorithm(
+ IN PINTERFACE Interface,
+ IN XENVIF_PACKET_HASH_ALGORITHM Algorithm
+ )
+{
+ PXENVIF_VIF_CONTEXT Context = Interface->Context;
+ NTSTATUS status;
+
+ AcquireMrswLockShared(&Context->Lock);
+
+ status = ReceiverSetHashAlgorithm(FrontendGetReceiver(Context->Frontend),
+ Algorithm);
+
+ ReleaseMrswLockShared(&Context->Lock);
+
+ return status;
+}
+
+static NTSTATUS
+VifReceiverQueryHashCapabilities(
+ IN PINTERFACE Interface,
+ ...
+ )
+{
+ PXENVIF_VIF_CONTEXT Context = Interface->Context;
+ va_list Arguments;
+ PULONG Types;
+ NTSTATUS status;
+
+ AcquireMrswLockShared(&Context->Lock);
+
+ va_start(Arguments, Interface);
+
+ Types = va_arg(Arguments, PULONG);
+
+ status = ReceiverQueryHashCapabilities(FrontendGetReceiver(Context->Frontend),
+ Types);
+
+ va_end(Arguments);
+
+ ReleaseMrswLockShared(&Context->Lock);
+
+ return status;
+}
+
+static NTSTATUS
+VifReceiverUpdateHashParameters(
+ IN PINTERFACE Interface,
+ ...
+ )
+{
+ PXENVIF_VIF_CONTEXT Context = Interface->Context;
+ va_list Arguments;
+ ULONG Types;
+ PUCHAR Key;
+ NTSTATUS status;
+
+ AcquireMrswLockShared(&Context->Lock);
+
+ va_start(Arguments, Interface);
+
+ Types = va_arg(Arguments, ULONG);
+ Key = va_arg(Arguments, PUCHAR);
+
+ status = ReceiverUpdateHashParameters(FrontendGetReceiver(Context->Frontend),
+ Types,
+ Key);
+
+ va_end(Arguments);
+
+ ReleaseMrswLockShared(&Context->Lock);
+
+ return status;
+}
+
static VOID
VifMacQueryState(
IN PINTERFACE Interface,
VifMacQueryFilterLevel
};
+static struct _XENVIF_VIF_INTERFACE_V6 VifInterfaceVersion6 = {
+ { sizeof (struct _XENVIF_VIF_INTERFACE_V6), 6, NULL, NULL, NULL },
+ VifAcquire,
+ VifRelease,
+ VifEnable,
+ VifDisable,
+ VifQueryStatistic,
+ VifQueryRingCount,
+ VifUpdateHashMapping,
+ VifReceiverReturnPacket,
+ VifReceiverSetOffloadOptions,
+ VifReceiverSetBackfillSize,
+ VifReceiverQueryRingSize,
+ VifReceiverSetHashAlgorithm,
+ VifReceiverQueryHashCapabilities,
+ VifReceiverUpdateHashParameters,
+ VifTransmitterQueuePacket,
+ VifTransmitterQueryOffloadOptions,
+ VifTransmitterQueryLargePacketSize,
+ VifTransmitterQueryRingSize,
+ VifMacQueryState,
+ VifMacQueryMaximumFrameSize,
+ VifMacQueryPermanentAddress,
+ VifMacQueryCurrentAddress,
+ VifMacQueryMulticastAddresses,
+ VifMacSetMulticastAddresses,
+ VifMacSetFilterLevel,
+ VifMacQueryFilterLevel
+};
+
NTSTATUS
VifInitialize(
IN PXENVIF_PDO Pdo,
status = STATUS_SUCCESS;
break;
}
+ case 6: {
+ struct _XENVIF_VIF_INTERFACE_V6 *VifInterface;
+
+ VifInterface = (struct _XENVIF_VIF_INTERFACE_V6 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENVIF_VIF_INTERFACE_V6))
+ break;
+
+ *VifInterface = VifInterfaceVersion6;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;
IN USHORT MaximumSegmentSize,
IN USHORT TagControlInformation,
IN PXENVIF_PACKET_INFO Info,
+ IN PXENVIF_PACKET_HASH Hash,
IN PVOID Cookie
)
{
LIST_ENTRY List;
NTSTATUS status;
+ UNREFERENCED_PARAMETER(Hash);
+
InfoVersion1 = __VifAllocate(sizeof (struct _XENVIF_PACKET_INFO_V1));
status = STATUS_NO_MEMORY;
Cookie);
}
+static FORCEINLINE VOID
+__VifReceiverQueuePacketVersion4(
+ 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 PXENVIF_PACKET_HASH Hash,
+ IN PVOID Cookie
+ )
+{
+ UNREFERENCED_PARAMETER(Hash);
+
+ Context->Callback(Context->Argument,
+ XENVIF_RECEIVER_QUEUE_PACKET,
+ Mdl,
+ Offset,
+ Length,
+ Flags,
+ MaximumSegmentSize,
+ TagControlInformation,
+ Info,
+ Cookie);
+}
+
VOID
VifReceiverQueuePacket(
IN PXENVIF_VIF_CONTEXT Context,
IN USHORT MaximumSegmentSize,
IN USHORT TagControlInformation,
IN PXENVIF_PACKET_INFO Info,
+ IN PXENVIF_PACKET_HASH Hash,
IN PVOID Cookie
)
{
MaximumSegmentSize,
TagControlInformation,
Info,
+ Hash,
Cookie);
break;
case 4:
case 5:
+ __VifReceiverQueuePacketVersion4(Context,
+ Mdl,
+ Offset,
+ Length,
+ Flags,
+ MaximumSegmentSize,
+ TagControlInformation,
+ Info,
+ Hash,
+ Cookie);
+ break;
+
+ case 6:
Context->Callback(Context->Argument,
XENVIF_RECEIVER_QUEUE_PACKET,
Mdl,
MaximumSegmentSize,
TagControlInformation,
Info,
+ Hash,
Cookie);
break;
case 4:
case 5:
+ case 6:
Context->Callback(Context->Argument,
XENVIF_TRANSMITTER_RETURN_PACKET,
Cookie,
IN USHORT MaximumSegmentSize,
IN USHORT TagControlInformation,
IN PXENVIF_PACKET_INFO Info,
+ IN PXENVIF_PACKET_HASH Hash,
IN PVOID Cookie
);