[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 3/4] Add new functionality to VIF interface to support RSS
This patch adds the necessary extra functionality into the VIF interface to make use of the new control ring to support NDIS RSS in XENNET. The VIF interface version is bumped to 6 and the PDO revision adjusted accordingly. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/revision.h | 7 +- include/vif_interface.h | 146 +++++++++++++++++++- src/xenvif/frontend.c | 316 +++++++++++++++++++++++++++++++++++++++++++- src/xenvif/frontend.h | 44 ++++++- src/xenvif/receiver.c | 336 +++++++++++++++++++++++++++++++++++++++++------ src/xenvif/receiver.h | 32 +++++ src/xenvif/transmitter.c | 38 +++++- src/xenvif/vif.c | 207 +++++++++++++++++++++++++++++ src/xenvif/vif.h | 1 + 9 files changed, 1073 insertions(+), 54 deletions(-) diff --git a/include/revision.h b/include/revision.h index 6458bfd..14b7b15 100644 --- a/include/revision.h +++ b/include/revision.h @@ -44,9 +44,10 @@ 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 diff --git a/include/vif_interface.h b/include/vif_interface.h index 5a064fd..853554d 100644 --- a/include/vif_interface.h +++ b/include/vif_interface.h @@ -50,20 +50,44 @@ 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_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 @@ -366,6 +390,7 @@ typedef VOID \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: @@ -427,6 +452,35 @@ typedef NTSTATUS 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, @@ -579,6 +633,52 @@ typedef VOID 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 @@ -822,7 +922,41 @@ struct _XENVIF_VIF_INTERFACE_V5 { 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 @@ -833,6 +967,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V5 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER #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 diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c index e950552..b682b2c 100644 --- a/src/xenvif/frontend.c +++ b/src/xenvif/frontend.c @@ -56,6 +56,15 @@ typedef struct _XENVIF_FRONTEND_STATISTICS { 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; @@ -95,6 +104,8 @@ struct _XENVIF_FRONTEND { NET_IFINDEX InterfaceIndex; PSOCKADDR_INET AddressTable; ULONG AddressCount; + + XENVIF_FRONTEND_HASH Hash; }; static const PCHAR @@ -1790,6 +1801,295 @@ FrontendIsSplit( 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 @@ -2045,11 +2345,20 @@ FrontendEnable( 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"); @@ -2073,7 +2382,7 @@ FrontendDisable( { Trace("====>\n"); - FrontendNotifyMulticastAddresses(Frontend, FALSE); + (VOID) FrontendNotifyMulticastAddresses(Frontend, FALSE); TransmitterDisable(__FrontendGetTransmitter(Frontend)); ReceiverDisable(__FrontendGetReceiver(Frontend)); @@ -2461,6 +2770,7 @@ FrontendInitialize( FdoGetStoreInterface(PdoGetFdo(Pdo), &(*Frontend)->StoreInterface); FrontendSetMaxQueues(*Frontend); + (*Frontend)->Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_UNSPECIFIED; status = MacInitialize(*Frontend, &(*Frontend)->Mac); if (!NT_SUCCESS(status)) @@ -2526,6 +2836,7 @@ fail7: fail6: Error("fail6\n"); + RtlZeroMemory(&(*Frontend)->Hash, sizeof (XENVIF_FRONTEND_HASH)); (*Frontend)->MaxQueues = 0; RtlZeroMemory(&(*Frontend)->StoreInterface, @@ -2616,6 +2927,7 @@ FrontendTeardown( MacTeardown(__FrontendGetMac(Frontend)); Frontend->Mac = NULL; + RtlZeroMemory(&Frontend->Hash, sizeof (XENVIF_FRONTEND_HASH)); Frontend->MaxQueues = 0; RtlZeroMemory(&Frontend->StoreInterface, diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h index 65daac4..513e812 100644 --- a/src/xenvif/frontend.h +++ b/src/xenvif/frontend.h @@ -202,7 +202,49 @@ FrontendSetFilterLevel( 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 diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c index 9b4c3b3..3d37ad2 100644 --- a/src/xenvif/receiver.c +++ b/src/xenvif/receiver.c @@ -67,6 +67,11 @@ typedef struct _XENVIF_RECEIVER_FRAGMENT { 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) @@ -101,11 +106,13 @@ typedef struct _XENVIF_RECEIVER_RING { 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; @@ -117,23 +124,23 @@ typedef struct _XENVIF_RECEIVER_PACKET { } 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' @@ -269,6 +276,7 @@ __ReceiverRingPutPacket( Packet->TagControlInformation = 0; RtlZeroMemory(&Packet->Info, sizeof (XENVIF_PACKET_INFO)); + RtlZeroMemory(&Packet->Hash, sizeof (XENVIF_PACKET_HASH)); Mdl->MappedSystemVa = Mdl->StartVa; Mdl->ByteOffset = 0; @@ -746,11 +754,12 @@ __ReceiverRingBuildSegment( if (Segment == NULL) goto fail1; - Segment->Info = Packet->Info; - Segment->Offset = Packet->Offset; - Segment->Flags = Packet->Flags; - Segment->MaximumSegmentSize = Packet->MaximumSegmentSize; - Segment->TagControlInformation = Packet->TagControlInformation; + RtlCopyMemory(Segment, + Packet, + FIELD_OFFSET(XENVIF_RECEIVER_PACKET, Mdl)); + + // The segment contains no data as yet + Segment->Length = 0; Mdl = &Segment->Mdl; @@ -1178,9 +1187,8 @@ ReceiverRingProcessPacket( 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; @@ -1194,16 +1202,25 @@ ReceiverRingProcessPacket( 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) { @@ -1213,12 +1230,6 @@ ReceiverRingProcessPacket( 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; @@ -1432,6 +1443,7 @@ __ReceiverRingReleaseLock( Packet->MaximumSegmentSize, Packet->TagControlInformation, &Packet->Info, + &Packet->Hash, Packet); } @@ -1472,17 +1484,24 @@ __ReceiverRingIsStopped( 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 @@ -1539,7 +1558,7 @@ __ReceiverRingReturnPacket( if (__ReceiverRingIsStopped(Ring)) { __ReceiverRingStart(Ring); - __ReceiverRingTrigger(Ring); + __ReceiverRingTrigger(Ring, TRUE); } if (!Locked) @@ -1809,6 +1828,7 @@ ReceiverRingPoll( BOOLEAN Extra; ULONG Info; USHORT MaximumSegmentSize; + XENVIF_PACKET_HASH Hash; PXENVIF_RECEIVER_PACKET Packet; uint16_t flags; PMDL TailMdl; @@ -1820,6 +1840,7 @@ ReceiverRingPoll( Extra = FALSE; Info = 0; MaximumSegmentSize = 0; + RtlZeroMemory(&Hash, sizeof (Hash)); Packet = NULL; flags = 0; TailMdl = NULL; @@ -1884,6 +1905,35 @@ ReceiverRingPoll( 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; @@ -1940,6 +1990,14 @@ ReceiverRingPoll( 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))); @@ -1952,6 +2010,7 @@ ReceiverRingPoll( Error = FALSE; Info = 0; MaximumSegmentSize = 0; + RtlZeroMemory(&Hash, sizeof (Hash)); Packet = NULL; flags = 0; TailMdl = NULL; @@ -1963,6 +2022,7 @@ ReceiverRingPoll( ASSERT3P(Packet, ==, NULL); ASSERT3U(flags, ==, 0); ASSERT3U(MaximumSegmentSize, ==, 0); + ASSERT(IsZeroMemory(&Hash, sizeof (Hash))); ASSERT3P(TailMdl, ==, NULL); ASSERT(EOP); @@ -2158,7 +2218,7 @@ ReceiverRingWatchdog( Ring->DebugCallback); // Try to move things along - ReceiverRingPoll(Ring); + __ReceiverRingTrigger(Ring, TRUE); __ReceiverRingSend(Ring, TRUE); } @@ -2679,6 +2739,7 @@ __ReceiverRingTeardown( 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)); @@ -3486,6 +3547,19 @@ ReceiverWaitForPackets( } 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, IN ULONG Index @@ -3497,3 +3571,191 @@ ReceiverSend( __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; +} diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h index 7188dfa..7846f0b 100644 --- a/src/xenvif/receiver.h +++ b/src/xenvif/receiver.h @@ -107,9 +107,41 @@ ReceiverReturnPacket( ); 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 diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c index 9406cab..18f664d 100644 --- a/src/xenvif/transmitter.c +++ b/src/xenvif/transmitter.c @@ -2524,6 +2524,32 @@ done: } 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 ) @@ -3087,8 +3113,8 @@ TransmitterRingWatchdog( Ring->DebugCallback); // Try to move things along + __TransmitterRingTrigger(Ring); __TransmitterRingSend(Ring); - (VOID) TransmitterRingPoll(Ring); } PacketsQueued = Ring->PacketsQueued; @@ -4772,6 +4798,7 @@ TransmitterQueuePacket( PUCHAR StartVa; PXENVIF_PACKET_PAYLOAD Payload; PXENVIF_PACKET_INFO Info; + ULONG Value; ULONG Index; PXENVIF_TRANSMITTER_RING Ring; NTSTATUS status; @@ -4805,20 +4832,21 @@ TransmitterQueuePacket( 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); diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c index ce94a56..5501e25 100644 --- a/src/xenvif/vif.c +++ b/src/xenvif/vif.c @@ -319,6 +319,42 @@ done: } 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, IN PLIST_ENTRY List @@ -671,6 +707,82 @@ VifReceiverSetBackfillSize( 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, @@ -1009,6 +1121,36 @@ static struct _XENVIF_VIF_INTERFACE_V5 VifInterfaceVersion5 = { 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, @@ -1141,6 +1283,23 @@ VifGetInterface( 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; @@ -1186,6 +1345,7 @@ __VifReceiverQueuePacketVersion1( IN USHORT MaximumSegmentSize, IN USHORT TagControlInformation, IN PXENVIF_PACKET_INFO Info, + IN PXENVIF_PACKET_HASH Hash, IN PVOID Cookie ) { @@ -1194,6 +1354,8 @@ __VifReceiverQueuePacketVersion1( LIST_ENTRY List; NTSTATUS status; + UNREFERENCED_PARAMETER(Hash); + InfoVersion1 = __VifAllocate(sizeof (struct _XENVIF_PACKET_INFO_V1)); status = STATUS_NO_MEMORY; @@ -1247,6 +1409,34 @@ fail1: 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, @@ -1257,6 +1447,7 @@ VifReceiverQueuePacket( IN USHORT MaximumSegmentSize, IN USHORT TagControlInformation, IN PXENVIF_PACKET_INFO Info, + IN PXENVIF_PACKET_HASH Hash, IN PVOID Cookie ) { @@ -1271,11 +1462,25 @@ VifReceiverQueuePacket( 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, @@ -1285,6 +1490,7 @@ VifReceiverQueuePacket( MaximumSegmentSize, TagControlInformation, Info, + Hash, Cookie); break; @@ -1334,6 +1540,7 @@ VifTransmitterReturnPacket( case 4: case 5: + case 6: Context->Callback(Context->Argument, XENVIF_TRANSMITTER_RETURN_PACKET, Cookie, diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h index 6cda4b7..6894ca2 100644 --- a/src/xenvif/vif.h +++ b/src/xenvif/vif.h @@ -78,6 +78,7 @@ VifReceiverQueuePacket( IN USHORT MaximumSegmentSize, IN USHORT TagControlInformation, IN PXENVIF_PACKET_INFO Info, + IN PXENVIF_PACKET_HASH Hash, IN PVOID Cookie ); -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |