[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH] Add support for NDIS RSS
Update to VIF interface version 6 and make use of the extra functionality provided to support NDIS RSS. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/vif_interface.h | 146 +++++++++++++++++- src/xennet.inf | 14 +- src/xennet/adapter.c | 376 ++++++++++++++++++++++++++++++++++++++++++++++- src/xennet/receiver.c | 44 ++++++ src/xennet/receiver.h | 1 + src/xennet/transmitter.c | 33 ++++- 6 files changed, 603 insertions(+), 11 deletions(-) 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/xennet.inf b/src/xennet.inf index edee6f6..b6e6628 100644 --- a/src/xennet.inf +++ b/src/xennet.inf @@ -61,9 +61,9 @@ xennet_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll ; DisplayName Section DeviceID ; ----------- ------- -------- -%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_NET&REV_08000009 -%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0001&DEV_NET&REV_08000009 -%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0002&DEV_NET&REV_08000009 +%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_NET&REV_0800000B +%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0001&DEV_NET&REV_0800000B +%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0002&DEV_NET&REV_0800000B [XenNet_Inst] Characteristics=0x84 @@ -159,6 +159,13 @@ HKR, Ndi\params\LROIPv6, Optional, 0, "0" HKR, Ndi\params\LROIPv6\enum, "0", 0, %Disabled% HKR, Ndi\params\LROIPv6\enum, "1", 0, %Enabled% +HKR, Ndi\params\*RSS, ParamDesc, 0, %RSS% +HKR, Ndi\params\*RSS, Type, 0, "enum" +HKR, Ndi\params\*RSS, Default, 0, "1" +HKR, Ndi\params\*RSS, Optional, 0, "0" +HKR, Ndi\params\*RSS\enum, "0", 0, %Disabled% +HKR, Ndi\params\*RSS\enum, "1", 0, %Enabled% + [XenNet_Inst.Services] AddService=xennet,0x02,XenNet_Service,XenNet_EventLog @@ -202,6 +209,7 @@ LSOV2IPv4="Large Send Offload V2 (IPv4)" LSOV2IPv6="Large Send Offload V2 (IPv6)" LROIPv4="Large Receive Offload (IPv4)" LROIPv6="Large Receive Offload (IPv6)" +RSS="Receive Side Scaling" HeaderDataSplit="Header Data Split" Disabled="Disabled" Enabled="Enabled" diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c index 4e2f7fa..3614aa7 100644 --- a/src/xennet/adapter.c +++ b/src/xennet/adapter.c @@ -60,8 +60,17 @@ typedef struct _PROPERTIES { int lsov6; int lrov4; int lrov6; + int rss; } PROPERTIES, *PPROPERTIES; +typedef struct _XENNET_RSS { + BOOLEAN Supported; + BOOLEAN HashEnabled; + BOOLEAN ScaleEnabled; + ULONG Types; + UCHAR Key[NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_1]; +} XENNET_RSS, *PXENNET_RSS; + struct _XENNET_ADAPTER { XENVIF_VIF_INTERFACE VifInterface; XENBUS_STORE_INTERFACE StoreInterface; @@ -77,6 +86,7 @@ struct _XENNET_ADAPTER { NDIS_PNP_CAPABILITIES Capabilities; NDIS_OFFLOAD Offload; PROPERTIES Properties; + XENNET_RSS Rss; PXENNET_RECEIVER Receiver; PXENNET_TRANSMITTER Transmitter; @@ -138,6 +148,8 @@ static NDIS_OID XennetSupportedOids[] = OID_PNP_CAPABILITIES, OID_PNP_QUERY_POWER, OID_PNP_SET_POWER, + OID_GEN_RECEIVE_SCALE_PARAMETERS, + OID_GEN_RECEIVE_HASH, }; #define ADAPTER_POOL_TAG 'AteN' @@ -211,6 +223,7 @@ AdapterVifCallback( USHORT MaximumSegmentSize; USHORT TagControlInformation; PXENVIF_PACKET_INFO Info; + PXENVIF_PACKET_HASH Hash; PVOID Cookie; Mdl = va_arg(Arguments, PMDL); @@ -220,6 +233,7 @@ AdapterVifCallback( MaximumSegmentSize = va_arg(Arguments, USHORT); TagControlInformation = va_arg(Arguments, USHORT); Info = va_arg(Arguments, PXENVIF_PACKET_INFO); + Hash = va_arg(Arguments, PXENVIF_PACKET_HASH); Cookie = va_arg(Arguments, PVOID); ReceiverQueuePacket(Adapter->Receiver, @@ -230,6 +244,7 @@ AdapterVifCallback( MaximumSegmentSize, TagControlInformation, Info, + Hash, Cookie); break; } @@ -672,6 +687,232 @@ invalid_parameter: #undef TX_ENABLED #undef CHANGE +static VOID +AdapterDisableRSSHash( + IN PXENNET_ADAPTER Adapter + ) +{ + Adapter->Rss.ScaleEnabled = FALSE; + Adapter->Rss.HashEnabled = FALSE; + + (VOID) XENVIF_VIF(ReceiverSetHashAlgorithm, + &Adapter->VifInterface, + XENVIF_PACKET_HASH_ALGORITHM_NONE); +} + +static NDIS_STATUS +AdapterUpdateRSSTable( + IN PXENNET_ADAPTER Adapter, + IN PCCHAR Table, + IN ULONG TableSize + ) +{ + PROCESSOR_NUMBER Mapping[NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_1]; + ULONG Index; + NTSTATUS status; + + if (TableSize == 0) { + AdapterDisableRSSHash(Adapter); + return NDIS_STATUS_SUCCESS; + } + + RtlZeroMemory(Mapping, sizeof (Mapping)); + for (Index = 0; Index < TableSize; Index++) { + Mapping[Index].Group = 0; + Mapping[Index].Number = Table[Index]; + } + + status = XENVIF_VIF(UpdateHashMapping, + &Adapter->VifInterface, + Mapping, + TableSize); + + return (NT_SUCCESS(status)) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_INVALID_DATA; +} + +static NDIS_STATUS +AdapterUpdateRSSKey( + IN PXENNET_ADAPTER Adapter, + IN PUCHAR Key, + IN ULONG KeySize + ) +{ + NTSTATUS status; + + if (KeySize == 0) { + AdapterDisableRSSHash(Adapter); + return NDIS_STATUS_SUCCESS; + } + + RtlZeroMemory(Adapter->Rss.Key, NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_1); + RtlCopyMemory(Adapter->Rss.Key, Key, KeySize); + + status = XENVIF_VIF(ReceiverUpdateHashParameters, + &Adapter->VifInterface, + Adapter->Rss.Types, + Adapter->Rss.Key); + + return (NT_SUCCESS(status)) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_INVALID_DATA; +} + +static NDIS_STATUS +AdapterUpdateRSSHash( + IN PXENNET_ADAPTER Adapter, + IN ULONG Information + ) +{ + ULONG HashType = NDIS_RSS_HASH_TYPE_FROM_HASH_INFO(Information); + ULONG HashFunc = NDIS_RSS_HASH_FUNC_FROM_HASH_INFO(Information); + NTSTATUS status; + + if (HashFunc == 0) { + AdapterDisableRSSHash(Adapter); + return NDIS_STATUS_SUCCESS; + } + + if (HashFunc != NdisHashFunctionToeplitz) + return NDIS_STATUS_FAILURE; + + if (HashType == 0) + return NDIS_STATUS_FAILURE; + + if (HashType & ~(NDIS_HASH_TCP_IPV4 | + NDIS_HASH_IPV4 | + NDIS_HASH_TCP_IPV6 | + NDIS_HASH_IPV6)) + return NDIS_STATUS_FAILURE; + + status = XENVIF_VIF(ReceiverSetHashAlgorithm, + &Adapter->VifInterface, + XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ); + if (!NT_SUCCESS(status)) + return NDIS_STATUS_FAILURE; + + Adapter->Rss.Types = 0; + + if (HashType & NDIS_HASH_TCP_IPV4) + Adapter->Rss.Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV4_TCP; + + if (HashType & NDIS_HASH_IPV4) + Adapter->Rss.Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV4; + + if (HashType & NDIS_HASH_TCP_IPV6) + Adapter->Rss.Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV6_TCP; + + if (HashType & NDIS_HASH_IPV6) + Adapter->Rss.Types |= 1 << XENVIF_PACKET_HASH_TYPE_IPV6; + + status = XENVIF_VIF(ReceiverUpdateHashParameters, + &Adapter->VifInterface, + Adapter->Rss.Types, + Adapter->Rss.Key); + + return (NT_SUCCESS(status)) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_INVALID_DATA; +} + +static NDIS_STATUS +AdapterGetReceiveScaleParameters( + IN PXENNET_ADAPTER Adapter, + IN PNDIS_RECEIVE_SCALE_PARAMETERS Parameters + ) +{ + NDIS_STATUS ndisStatus; + + ASSERT3U(Parameters->Header.Type, ==, NDIS_OBJECT_TYPE_RSS_PARAMETERS); + ASSERT3U(Parameters->Header.Revision, ==, NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_1); + ASSERT3U(Parameters->Header.Size, >=, NDIS_SIZEOF_RECEIVE_SCALE_PARAMETERS_REVISION_1); + + if (!Adapter->Rss.Supported) + return NDIS_STATUS_NOT_SUPPORTED; + + if (!Adapter->Properties.rss) + return NDIS_STATUS_NOT_SUPPORTED; + + if (Adapter->Rss.HashEnabled) + return NDIS_STATUS_NOT_SUPPORTED; + + if (!(Parameters->Flags & NDIS_RSS_PARAM_FLAG_DISABLE_RSS)) { + Adapter->Rss.ScaleEnabled = TRUE; + } else { + AdapterDisableRSSHash(Adapter); + return NDIS_STATUS_SUCCESS; + } + + if (!(Parameters->Flags & NDIS_RSS_PARAM_FLAG_HASH_INFO_UNCHANGED)) { + ndisStatus = AdapterUpdateRSSHash(Adapter, Parameters->HashInformation); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail; + } + + if (!(Parameters->Flags & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED)) { + ndisStatus = AdapterUpdateRSSKey(Adapter, + (PUCHAR)Parameters + Parameters->HashSecretKeyOffset, + Parameters->HashSecretKeySize); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail; + } + + if (!(Parameters->Flags & NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED)) { + ndisStatus = AdapterUpdateRSSTable(Adapter, + (PCCHAR)Parameters + Parameters->IndirectionTableOffset, + Parameters->IndirectionTableSize); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail; + } + + return NDIS_STATUS_SUCCESS; + +fail: + AdapterDisableRSSHash(Adapter); + return ndisStatus; +} + +static NDIS_STATUS +AdapterGetReceiveHashParameters( + IN PXENNET_ADAPTER Adapter, + IN PNDIS_RECEIVE_HASH_PARAMETERS Parameters + ) +{ + NDIS_STATUS ndisStatus; + + ASSERT3U(Parameters->Header.Type, ==, NDIS_OBJECT_TYPE_DEFAULT); + ASSERT3U(Parameters->Header.Revision, ==, NDIS_RECEIVE_HASH_PARAMETERS_REVISION_1); + ASSERT3U(Parameters->Header.Size, >=, NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1); + + if (!Adapter->Rss.Supported) + return NDIS_STATUS_NOT_SUPPORTED; + + if (Adapter->Rss.ScaleEnabled) + return NDIS_STATUS_NOT_SUPPORTED; + + if (Parameters->Flags & NDIS_RECEIVE_HASH_FLAG_ENABLE_HASH) { + Adapter->Rss.HashEnabled = TRUE; + } else { + AdapterDisableRSSHash(Adapter); + return NDIS_STATUS_SUCCESS; + } + + if (!(Parameters->Flags & NDIS_RECEIVE_HASH_FLAG_HASH_INFO_UNCHANGED)) { + ndisStatus = AdapterUpdateRSSHash(Adapter, Parameters->HashInformation); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail; + } + + if (!(Parameters->Flags & NDIS_RECEIVE_HASH_FLAG_HASH_KEY_UNCHANGED)) { + ndisStatus = AdapterUpdateRSSKey(Adapter, + (PUCHAR)Parameters + Parameters->HashSecretKeyOffset, + Parameters->HashSecretKeySize); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail; + } + + return NDIS_STATUS_SUCCESS; + +fail: + AdapterDisableRSSHash(Adapter); + return ndisStatus; +} + static NDIS_STATUS AdapterQueryGeneralStatistics( IN PXENNET_ADAPTER Adapter, @@ -1047,6 +1288,59 @@ fail1: return NDIS_STATUS_BUFFER_TOO_SHORT; } +static FORCEINLINE NDIS_STATUS +AdapterReceiveHash( + IN PXENNET_ADAPTER Adapter, + IN PNDIS_RECEIVE_HASH_PARAMETERS Params, + IN ULONG BufferLength, + IN OUT PULONG BytesWritten + ) +{ + ULONG HashType; + ULONG HashFunc; + + if (BufferLength < NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1 + + sizeof (Adapter->Rss.Key)) + goto fail1; + + Params->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + Params->Header.Revision = NDIS_RECEIVE_HASH_PARAMETERS_REVISION_1; + Params->Header.Size = NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1; + + Params->Flags = (Adapter->Rss.HashEnabled) ? NDIS_RECEIVE_HASH_FLAG_ENABLE_HASH : 0; + + HashFunc = NdisHashFunctionToeplitz; + HashType = 0; + + if (Adapter->Rss.Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV4_TCP)) + HashType |= NDIS_HASH_TCP_IPV4; + + if (Adapter->Rss.Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV4)) + HashType |= NDIS_HASH_IPV4; + + if (Adapter->Rss.Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV6_TCP)) + HashType |= NDIS_HASH_TCP_IPV6; + + if (Adapter->Rss.Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV6)) + HashType |= NDIS_HASH_IPV6; + + Params->HashInformation = NDIS_RSS_HASH_INFO_FROM_TYPE_AND_FUNC(HashType, HashFunc); + Params->HashSecretKeySize = sizeof (Adapter->Rss.Key); + Params->HashSecretKeyOffset = NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1; + + RtlCopyMemory((PUCHAR)Params + Params->HashSecretKeyOffset, + Adapter->Rss.Key, + Params->HashSecretKeySize); + + *BytesWritten = NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1 + + sizeof (Adapter->Rss.Key); + return NDIS_STATUS_SUCCESS; + +fail1: + *BytesWritten = 0; + return NDIS_STATUS_BUFFER_TOO_SHORT; +} + NDIS_HANDLE AdapterGetHandle( IN PXENNET_ADAPTER Adapter @@ -1693,6 +1987,30 @@ AdapterSetInformation( } break; + case OID_GEN_RECEIVE_SCALE_PARAMETERS: + BytesNeeded = NDIS_SIZEOF_RECEIVE_SCALE_PARAMETERS_REVISION_1; + if (BufferLength >= BytesNeeded) { + ndisStatus = AdapterGetReceiveScaleParameters(Adapter, + (PNDIS_RECEIVE_SCALE_PARAMETERS)Buffer); + if (ndisStatus == NDIS_STATUS_SUCCESS) + BytesRead = sizeof(NDIS_RECEIVE_SCALE_PARAMETERS); + } else { + ndisStatus = NDIS_STATUS_INVALID_LENGTH; + } + break; + + case OID_GEN_RECEIVE_HASH: + BytesNeeded = NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1; + if (BufferLength >= BytesNeeded) { + ndisStatus = AdapterGetReceiveHashParameters(Adapter, + (PNDIS_RECEIVE_HASH_PARAMETERS)Buffer); + if (ndisStatus == NDIS_STATUS_SUCCESS) + BytesRead = sizeof(NDIS_RECEIVE_HASH_PARAMETERS); + } else { + ndisStatus = NDIS_STATUS_INVALID_LENGTH; + } + break; + case OID_GEN_INTERRUPT_MODERATION: case OID_GEN_MACHINE_NAME: Warn = FALSE; @@ -2238,6 +2556,15 @@ AdapterQueryInformation( &BytesWritten); break; + case OID_GEN_RECEIVE_HASH: + BytesNeeded = NDIS_SIZEOF_RECEIVE_HASH_PARAMETERS_REVISION_1 + + sizeof (Adapter->Rss.Key); + ndisStatus = AdapterReceiveHash(Adapter, + (PNDIS_RECEIVE_HASH_PARAMETERS)Buffer, + BufferLength, + &BytesWritten); + break; + case OID_IP4_OFFLOAD_STATS: case OID_IP6_OFFLOAD_STATS: case OID_GEN_SUPPORTED_GUIDS: @@ -2385,6 +2712,7 @@ AdapterGetAdvancedSettings( READ_PROPERTY(Adapter->Properties.lrov4, L"LROIPv4", 1, Handle); READ_PROPERTY(Adapter->Properties.lrov6, L"LROIPv6", 1, Handle); READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue", 1, Handle); + READ_PROPERTY(Adapter->Properties.rss, L"*RSS", 1, Handle); NdisCloseConfiguration(Handle); @@ -2428,7 +2756,10 @@ AdapterSetGeneralAttributes( ) { NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES Attribs; + ULONG Types; + NDIS_RECEIVE_SCALE_CAPABILITIES Rss; NDIS_STATUS ndisStatus; + NTSTATUS status; RtlZeroMemory(&Attribs, sizeof(Attribs)); Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; @@ -2462,7 +2793,6 @@ AdapterSetGeneralAttributes( (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress); Attribs.PhysicalMediumType = NdisPhysicalMedium802_3; - Attribs.RecvScaleCapabilities = NULL; Attribs.AccessType = NET_IF_ACCESS_BROADCAST; Attribs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; Attribs.ConnectionType = NET_IF_CONNECTION_DEDICATED; @@ -2489,6 +2819,50 @@ AdapterSetGeneralAttributes( Attribs.SupportedOidList = XennetSupportedOids; Attribs.SupportedOidListLength = sizeof(XennetSupportedOids); + Attribs.RecvScaleCapabilities = NULL; + + if (!Adapter->Properties.rss) { + Info("RSS DISABLED\n"); + goto done; + } + + status = XENVIF_VIF(ReceiverSetHashAlgorithm, + &Adapter->VifInterface, + XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ); + if (!NT_SUCCESS(status)) + goto done; + + status = XENVIF_VIF(ReceiverQueryHashCapabilities, + &Adapter->VifInterface, + &Types); + if (!NT_SUCCESS(status)) + goto done; + + RtlZeroMemory(&Rss, sizeof(Rss)); + Rss.Header.Type = NDIS_OBJECT_TYPE_RSS_CAPABILITIES; + Rss.Header.Revision = NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_1; + Rss.Header.Size = NDIS_SIZEOF_RECEIVE_SCALE_CAPABILITIES_REVISION_1; + + Rss.CapabilitiesFlags = NDIS_RSS_CAPS_MESSAGE_SIGNALED_INTERRUPTS | + NDIS_RSS_CAPS_CLASSIFICATION_AT_ISR | + NDIS_RSS_CAPS_CLASSIFICATION_AT_DPC | + NdisHashFunctionToeplitz; + + if (Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV4_TCP)) + Rss.CapabilitiesFlags |= NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV4; + + if (Types & (1 << XENVIF_PACKET_HASH_TYPE_IPV6_TCP)) + Rss.CapabilitiesFlags |= NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6; + + XENVIF_VIF(QueryRingCount, + &Adapter->VifInterface, + &Rss.NumberOfReceiveQueues); + Rss.NumberOfInterruptMessages = Rss.NumberOfReceiveQueues; + + Adapter->Rss.Supported = TRUE; + Attribs.RecvScaleCapabilities = &Rss; + +done: ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c index 7645a8c..843df2b 100644 --- a/src/xennet/receiver.c +++ b/src/xennet/receiver.c @@ -83,6 +83,11 @@ __ReceiverAllocateNetBufferList( Receiver->GetList = NET_BUFFER_LIST_NEXT_NBL(NetBufferList); NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL; + NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = NULL; + NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = NULL; + NET_BUFFER_LIST_INFO(NetBufferList, NetBufferListHashInfo) = NULL; + NET_BUFFER_LIST_INFO(NetBufferList, NetBufferListHashValue) = NULL; + NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList); NET_BUFFER_FIRST_MDL(NetBuffer) = Mdl; NET_BUFFER_CURRENT_MDL(NetBuffer) = Mdl; @@ -174,6 +179,7 @@ __ReceiverReceivePacket( IN USHORT MaximumSegmentSize, IN USHORT TagControlInformation, IN PXENVIF_PACKET_INFO Info, + IN PXENVIF_PACKET_HASH Hash, IN PVOID Cookie ) { @@ -220,6 +226,42 @@ __ReceiverReceivePacket( NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = Ieee8021QInfo.Value; } + switch (Hash->Algorithm) { + case XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ: + NET_BUFFER_LIST_SET_HASH_FUNCTION(NetBufferList, + NdisHashFunctionToeplitz); + break; + + default: + break; + } + + switch (Hash->Type) { + case XENVIF_PACKET_HASH_TYPE_IPV4: + NET_BUFFER_LIST_SET_HASH_TYPE(NetBufferList, + NDIS_HASH_IPV4); + break; + + case XENVIF_PACKET_HASH_TYPE_IPV4_TCP: + NET_BUFFER_LIST_SET_HASH_TYPE(NetBufferList, + NDIS_HASH_TCP_IPV4); + break; + + case XENVIF_PACKET_HASH_TYPE_IPV6: + NET_BUFFER_LIST_SET_HASH_TYPE(NetBufferList, + NDIS_HASH_IPV6); + break; + + case XENVIF_PACKET_HASH_TYPE_IPV6_TCP: + NET_BUFFER_LIST_SET_HASH_TYPE(NetBufferList, + NDIS_HASH_TCP_IPV6); + break; + } + + NET_BUFFER_LIST_SET_HASH_VALUE(NetBufferList, + Hash->Value); + + return NetBufferList; fail2: @@ -384,6 +426,7 @@ ReceiverQueuePacket( IN USHORT MaximumSegmentSize, IN USHORT TagControlInformation, IN PXENVIF_PACKET_INFO Info, + IN PXENVIF_PACKET_HASH Hash, IN PVOID Cookie ) { @@ -400,6 +443,7 @@ ReceiverQueuePacket( MaximumSegmentSize, TagControlInformation, Info, + Hash, Cookie); if (NetBufferList != NULL) { diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h index e6b2af1..73ffc7e 100644 --- a/src/xennet/receiver.h +++ b/src/xennet/receiver.h @@ -65,6 +65,7 @@ ReceiverQueuePacket( IN USHORT MaximumSegmentSize, IN USHORT TagControlInformation, IN PXENVIF_PACKET_INFO Info, + IN PXENVIF_PACKET_HASH Hash, IN PVOID Cookie ); diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c index eaf5267..432198c 100644 --- a/src/xennet/transmitter.c +++ b/src/xennet/transmitter.c @@ -292,7 +292,38 @@ TransmitterSendNetBufferLists( __TransmitterGetNetBufferList(Transmitter, NetBufferList); - Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_NONE; + switch (NET_BUFFER_LIST_GET_HASH_FUNCTION(NetBufferList)) { + case NdisHashFunctionToeplitz: + Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_TOEPLITZ; + break; + + default: + Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_NONE; + break; + } + + switch (NET_BUFFER_LIST_GET_HASH_TYPE(NetBufferList)) { + case NDIS_HASH_IPV4: + Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4; + break; + + case NDIS_HASH_TCP_IPV4: + Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV4_TCP; + break; + + case NDIS_HASH_IPV6: + Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6; + break; + + case NDIS_HASH_TCP_IPV6: + Hash.Type = XENVIF_PACKET_HASH_TYPE_IPV6_TCP; + break; + + default: + break; + } + + Hash.Value = NET_BUFFER_LIST_GET_HASH_VALUE(NetBufferList); status = XENVIF_VIF(TransmitterQueuePacket, AdapterGetVifInterface(Transmitter->Adapter), -- 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 |