From 6fa4db059df598c7f482c8a5d85dc7982fbc1041 Mon Sep 17 00:00:00 2001 From: Yuri Benditovich Date: Sun, 1 Mar 2020 08:14:49 +0200 Subject: [PATCH] netkvm: define VIRTIO_NET_F_HASH_REPORT and ack it When this feature is acked this changes the layout of virtio header. It contains additional 8 bytes where the device reports hash and hash type. Signed-off-by: Yuri Benditovich --- NetKVM/Common/ParaNdis-Common.cpp | 19 ++++++++++++++++--- NetKVM/Common/ParaNdis-RSS.h | 2 +- NetKVM/Common/ndis56common.h | 1 + NetKVM/Common/virtio_net.h | 20 ++++++++++++++++++++ NetKVM/wlh/ParaNdis6-RSS.cpp | 30 ++++++++++++++++++++++-------- 5 files changed, 60 insertions(+), 12 deletions(-) diff --git a/NetKVM/Common/ParaNdis-Common.cpp b/NetKVM/Common/ParaNdis-Common.cpp index 1e4fc1e7..c99057cc 100755 --- a/NetKVM/Common/ParaNdis-Common.cpp +++ b/NetKVM/Common/ParaNdis-Common.cpp @@ -409,6 +409,7 @@ static void DumpVirtIOFeatures(PPARANDIS_ADAPTER pContext) {VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS" }, {VIRTIO_NET_F_RSC_EXT, "VIRTIO_NET_F_RSC_EXT" }, {VIRTIO_NET_F_RSS, "VIRTIO_NET_F_RSS" }, + {VIRTIO_NET_F_HASH_REPORT, "VIRTIO_NET_F_HASH_REPORT" }, }; UINT i; for (i = 0; i < sizeof(Features)/sizeof(Features[0]); ++i) @@ -816,18 +817,28 @@ NDIS_STATUS ParaNdis_InitializeContext( #if PARANDIS_SUPPORT_RSS pContext->bMultiQueue = pContext->bControlQueueSupported && AckFeature(pContext, VIRTIO_NET_F_MQ); - if (virtio_is_feature_enabled(pContext->u64HostFeatures, VIRTIO_NET_F_RSS) && pContext->bControlQueueSupported) + bool bRSS = virtio_is_feature_enabled(pContext->u64HostFeatures, VIRTIO_NET_F_RSS); + bool bHash = virtio_is_feature_enabled(pContext->u64HostFeatures, VIRTIO_NET_F_HASH_REPORT); + + if ((bHash || bRSS) && pContext->bControlQueueSupported && virtio_is_feature_enabled(pContext->u64HostFeatures, VIRTIO_F_VERSION_1)) { struct virtio_net_config cfg = {}; virtio_get_config(&pContext->IODevice, FIELD_OFFSET(struct virtio_net_config, duplex), &cfg.duplex, 8); pContext->DeviceRSSCapabilities.SupportedHashes = cfg.supported_hash_types; pContext->DeviceRSSCapabilities.MaxKeySize = cfg.rss_max_key_size; pContext->DeviceRSSCapabilities.MaxIndirectEntries = cfg.rss_max_indirection_table_length; - if (ParaNdis6_IsDeviceRSSCapable(pContext)) + + ParaNdis6_CheckDeviceRSSCapabilities(pContext, bRSS, bHash); + + if (bRSS) { pContext->bRSSSupportedByDevice = AckFeature(pContext, VIRTIO_NET_F_RSS); pContext->bRSSSupportedByDevicePersistent = pContext->bRSSSupportedByDevice; } + if (bHash) + { + pContext->bHashReportedByDevice = AckFeature(pContext, VIRTIO_NET_F_HASH_REPORT); + } } if (pContext->bRSSSupportedByDevice) { @@ -877,7 +888,9 @@ NDIS_STATUS ParaNdis_InitializeContext( pContext->bAnyLayout = AckFeature(pContext, VIRTIO_F_ANY_LAYOUT); if (AckFeature(pContext, VIRTIO_F_VERSION_1)) { - pContext->nVirtioHeaderSize = sizeof(virtio_net_hdr_v1); + pContext->nVirtioHeaderSize = pContext->bHashReportedByDevice ? + sizeof(virtio_net_hdr_v1_hash) : sizeof(virtio_net_hdr_v1); + pContext->bAnyLayout = true; DPrintf(0, "[%s] Assuming VIRTIO_F_ANY_LAYOUT for V1 device\n", __FUNCTION__); if (AckFeature(pContext, VIRTIO_F_RING_PACKED)) diff --git a/NetKVM/Common/ParaNdis-RSS.h b/NetKVM/Common/ParaNdis-RSS.h index b3489304..2d87c50f 100644 --- a/NetKVM/Common/ParaNdis-RSS.h +++ b/NetKVM/Common/ParaNdis-RSS.h @@ -79,7 +79,7 @@ NDIS_STATUS ParaNdis6_RSSSetReceiveHash(PARANDIS_ADAPTER *pContext, UINT ParamsLength, PUINT ParamsBytesRead); -BOOLEAN ParaNdis6_IsDeviceRSSCapable(PARANDIS_ADAPTER *pContext); +void ParaNdis6_CheckDeviceRSSCapabilities(PARANDIS_ADAPTER *pContext, bool& bRss, bool& bHash); /* for engineering tests only */ void ParaNdis6_EnableDeviceRssSupport(PARANDIS_ADAPTER *pContext, BOOLEAN b); diff --git a/NetKVM/Common/ndis56common.h b/NetKVM/Common/ndis56common.h index f5b9ff19..c62b0672 100755 --- a/NetKVM/Common/ndis56common.h +++ b/NetKVM/Common/ndis56common.h @@ -500,6 +500,7 @@ typedef struct _tagPARANDIS_ADAPTER BOOLEAN bDeviceInitialized; BOOLEAN bRSSSupportedByDevice; BOOLEAN bRSSSupportedByDevicePersistent; + BOOLEAN bHashReportedByDevice; #if PARANDIS_SUPPORT_RSS BOOLEAN bRSSOffloadSupported; diff --git a/NetKVM/Common/virtio_net.h b/NetKVM/Common/virtio_net.h index 5701bf55..e3bf6f57 100644 --- a/NetKVM/Common/virtio_net.h +++ b/NetKVM/Common/virtio_net.h @@ -59,6 +59,7 @@ #define VIRTIO_NET_F_GUEST_RSC4_DONT_USE 41 /* reserved */ #define VIRTIO_NET_F_GUEST_RSC6_DONT_USE 42 /* reserved */ +#define VIRTIO_NET_F_HASH_REPORT 57 #define VIRTIO_NET_F_RSS 60 #define VIRTIO_NET_F_RSC_EXT 61 @@ -116,6 +117,18 @@ struct virtio_net_config { #define VIRTIO_NET_RSS_HASH_TYPE_TCP_EX (1 << 7) #define VIRTIO_NET_RSS_HASH_TYPE_UDP_EX (1 << 8) +#define VIRTIO_NET_HASH_REPORT_NONE 0 +#define VIRTIO_NET_HASH_REPORT_IPv4 1 +#define VIRTIO_NET_HASH_REPORT_TCPv4 2 +#define VIRTIO_NET_HASH_REPORT_UDPv4 3 +#define VIRTIO_NET_HASH_REPORT_IPv6 4 +#define VIRTIO_NET_HASH_REPORT_TCPv6 5 +#define VIRTIO_NET_HASH_REPORT_UDPv6 6 +#define VIRTIO_NET_HASH_REPORT_IPv6_EX 7 +#define VIRTIO_NET_HASH_REPORT_TCPv6_EX 8 +#define VIRTIO_NET_HASH_REPORT_UDPv6_EX 9 +#define VIRTIO_NET_HASH_REPORT_MAX VIRTIO_NET_HASH_REPORT_UDPv6_EX + /* * This header comes first in the scatter-gather list. If you don't * specify GSO or CSUM features, you can simply ignore the header. @@ -143,6 +156,12 @@ struct virtio_net_hdr_v1 { #define rsc_ext_num_packets csum_start #define rsc_ext_num_dupacks csum_offset +struct virtio_net_hdr_v1_hash { + struct virtio_net_hdr_v1 h; + __virtio32 hash_value; + __virtio16 hash_report; + __virtio16 reserved; +}; #ifndef VIRTIO_NET_NO_LEGACY /* This header comes first in the scatter-gather list. @@ -267,6 +286,7 @@ struct virtio_net_ctrl_mac { #define VIRTIO_NET_CTRL_MQ 4 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 #define VIRTIO_NET_CTRL_MQ_RSS_CONFIG 1 + #define VIRTIO_NET_CTRL_MQ_HASH_CONFIG 2 /* for VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET */ struct virtio_net_ctrl_mq { diff --git a/NetKVM/wlh/ParaNdis6-RSS.cpp b/NetKVM/wlh/ParaNdis6-RSS.cpp index f507321f..dc1b06cc 100644 --- a/NetKVM/wlh/ParaNdis6-RSS.cpp +++ b/NetKVM/wlh/ParaNdis6-RSS.cpp @@ -119,17 +119,31 @@ static VOID InitRSSCapabilities(PARANDIS_ADAPTER *pContext) #endif } -BOOLEAN ParaNdis6_IsDeviceRSSCapable(PARANDIS_ADAPTER *pContext) +void ParaNdis6_CheckDeviceRSSCapabilities(PARANDIS_ADAPTER *pContext, bool& bRss, bool& bHash) { + if (bHash || bRss) + { + DPrintf(0, "[%s] Device supports %s %s: key of %d, table of %d, hashes %X\n", __FUNCTION__, + bHash ? "Hash" : " ", bRss ? "RSS" : " ", + pContext->DeviceRSSCapabilities.MaxKeySize, + pContext->DeviceRSSCapabilities.MaxIndirectEntries, + pContext->DeviceRSSCapabilities.SupportedHashes); + } BOOLEAN bResult = (pContext->DeviceRSSCapabilities.SupportedHashes & VIRTIO_NET_RSS_HASH_TYPE_IPv4) && - pContext->DeviceRSSCapabilities.MaxIndirectEntries >= NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 / sizeof(PROCESSOR_NUMBER) && pContext->DeviceRSSCapabilities.MaxKeySize >= NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2; - DPrintf(0, "[%s] Device RSS support: key of %d, table of %d, hashes %X = %s\n", __FUNCTION__, - pContext->DeviceRSSCapabilities.MaxKeySize, - pContext->DeviceRSSCapabilities.MaxIndirectEntries, - pContext->DeviceRSSCapabilities.SupportedHashes, - bResult ? "OK" : "Not enough"); - return bResult; + + if (!bResult) + { + bRss = false; + bHash = false; + } + + bResult = bResult && pContext->DeviceRSSCapabilities.MaxIndirectEntries >= NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 / sizeof(PROCESSOR_NUMBER); + if (!bResult) + { + bRss = false; + } + DPrintf(0, "[%s] Driver will use: %s %s\n", __FUNCTION__, bHash ? "Hash" : " ", bRss ? "RSS" : " "); } NDIS_RECEIVE_SCALE_CAPABILITIES* ParaNdis6_RSSCreateConfiguration(PARANDIS_ADAPTER *pContext)