|
[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 |