/*! 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
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;
NDIS_PNP_CAPABILITIES Capabilities;
NDIS_OFFLOAD Offload;
PROPERTIES Properties;
+ XENNET_RSS Rss;
PXENNET_RECEIVER Receiver;
PXENNET_TRANSMITTER Transmitter;
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'
USHORT MaximumSegmentSize;
USHORT TagControlInformation;
PXENVIF_PACKET_INFO Info;
+ PXENVIF_PACKET_HASH Hash;
PVOID Cookie;
Mdl = va_arg(Arguments, PMDL);
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,
MaximumSegmentSize,
TagControlInformation,
Info,
+ Hash,
Cookie);
break;
}
#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,
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
}
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;
&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:
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);
)
{
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;
(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;
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);