[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.