From: Jason Wang <jasowang@redhat.com>
To: peter.maydell@linaro.org, qemu-devel@nongnu.org
Cc: Yuri Benditovich <yuri.benditovich@daynix.com>,
Jason Wang <jasowang@redhat.com>
Subject: [PULL V2 04/33] virtio-net: reference implementation of hash report
Date: Thu, 18 Jun 2020 21:21:19 +0800 [thread overview]
Message-ID: <1592486508-6135-5-git-send-email-jasowang@redhat.com> (raw)
In-Reply-To: <1592486508-6135-1-git-send-email-jasowang@redhat.com>
From: Yuri Benditovich <yuri.benditovich@daynix.com>
Suggest VIRTIO_NET_F_HASH_REPORT if specified in device
parameters.
If the VIRTIO_NET_F_HASH_REPORT is set,
the device extends configuration space. If the feature
is negotiated, the packet layout is extended to
accomodate the hash information. In this case deliver
packet's hash value and report type in virtio header
extension.
Use for configuration the same procedure as already
used for RSS. We add two fields in rss_data that
controls what the device does with the calculated hash
if rss_data.enabled is set. If field 'populate' is set
the hash is set in the packet, if field 'redirect' is
set the hash is used to decide the queue to place the
packet to.
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/net/virtio-net.c | 99 +++++++++++++++++++++++++++++++++---------
include/hw/virtio/virtio-net.h | 2 +
2 files changed, 81 insertions(+), 20 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 556f221..6ff3cc3 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -119,7 +119,7 @@ static VirtIOFeature feature_sizes[] = {
.end = endof(struct virtio_net_config, mtu)},
{.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
.end = endof(struct virtio_net_config, duplex)},
- {.flags = 1ULL << VIRTIO_NET_F_RSS,
+ {.flags = (1ULL << VIRTIO_NET_F_RSS) | (1ULL << VIRTIO_NET_F_HASH_REPORT),
.end = endof(struct virtio_net_config, supported_hash_types)},
{}
};
@@ -153,7 +153,8 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
netcfg.duplex = n->net_conf.duplex;
netcfg.rss_max_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE;
virtio_stw_p(vdev, &netcfg.rss_max_indirection_table_length,
- VIRTIO_NET_RSS_MAX_TABLE_LEN);
+ virtio_host_has_feature(vdev, VIRTIO_NET_F_RSS) ?
+ VIRTIO_NET_RSS_MAX_TABLE_LEN : 1);
virtio_stl_p(vdev, &netcfg.supported_hash_types,
VIRTIO_NET_RSS_SUPPORTED_HASHES);
memcpy(config, &netcfg, n->config_size);
@@ -579,7 +580,7 @@ static int peer_has_ufo(VirtIONet *n)
}
static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
- int version_1)
+ int version_1, int hash_report)
{
int i;
NetClientState *nc;
@@ -587,7 +588,10 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
n->mergeable_rx_bufs = mergeable_rx_bufs;
if (version_1) {
- n->guest_hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+ n->guest_hdr_len = hash_report ?
+ sizeof(struct virtio_net_hdr_v1_hash) :
+ sizeof(struct virtio_net_hdr_mrg_rxbuf);
+ n->rss_data.populate_hash = !!hash_report;
} else {
n->guest_hdr_len = n->mergeable_rx_bufs ?
sizeof(struct virtio_net_hdr_mrg_rxbuf) :
@@ -708,6 +712,8 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4);
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6);
virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN);
+
+ virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
}
if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
@@ -720,6 +726,7 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
}
virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
+ virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
features = vhost_net_get_features(get_vhost_net(nc->peer), features);
vdev->backend_features = features;
@@ -886,12 +893,15 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
virtio_has_feature(features,
VIRTIO_NET_F_MRG_RXBUF),
virtio_has_feature(features,
- VIRTIO_F_VERSION_1));
+ VIRTIO_F_VERSION_1),
+ virtio_has_feature(features,
+ VIRTIO_NET_F_HASH_REPORT));
n->rsc4_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO4);
n->rsc6_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO6);
+ n->rss_data.redirect = virtio_has_feature(features, VIRTIO_NET_F_RSS);
if (n->has_vnet_hdr) {
n->curr_guest_offloads =
@@ -1165,7 +1175,9 @@ static void virtio_net_disable_rss(VirtIONet *n)
}
static uint16_t virtio_net_handle_rss(VirtIONet *n,
- struct iovec *iov, unsigned int iov_cnt)
+ struct iovec *iov,
+ unsigned int iov_cnt,
+ bool do_rss)
{
VirtIODevice *vdev = VIRTIO_DEVICE(n);
struct virtio_net_rss_config cfg;
@@ -1178,10 +1190,14 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
const char *err_msg = "";
uint32_t err_value = 0;
- if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
+ if (do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
err_msg = "RSS is not negotiated";
goto error;
}
+ if (!do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) {
+ err_msg = "Hash report is not negotiated";
+ goto error;
+ }
size_get = offsetof(struct virtio_net_rss_config, indirection_table);
s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get);
if (s != size_get) {
@@ -1193,6 +1209,9 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
n->rss_data.indirections_len =
virtio_lduw_p(vdev, &cfg.indirection_table_mask);
n->rss_data.indirections_len++;
+ if (!do_rss) {
+ n->rss_data.indirections_len = 1;
+ }
if (!is_power_of_2(n->rss_data.indirections_len)) {
err_msg = "Invalid size of indirection table";
err_value = n->rss_data.indirections_len;
@@ -1203,8 +1222,8 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
err_value = n->rss_data.indirections_len;
goto error;
}
- n->rss_data.default_queue =
- virtio_lduw_p(vdev, &cfg.unclassified_queue);
+ n->rss_data.default_queue = do_rss ?
+ virtio_lduw_p(vdev, &cfg.unclassified_queue) : 0;
if (n->rss_data.default_queue >= n->max_queues) {
err_msg = "Invalid default queue";
err_value = n->rss_data.default_queue;
@@ -1238,7 +1257,7 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
err_value = (uint32_t)s;
goto error;
}
- queues = virtio_lduw_p(vdev, &temp.us);
+ queues = do_rss ? virtio_lduw_p(vdev, &temp.us) : n->curr_queues;
if (queues == 0 || queues > n->max_queues) {
err_msg = "Invalid number of queues";
err_value = queues;
@@ -1284,8 +1303,12 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
uint16_t queues;
virtio_net_disable_rss(n);
+ if (cmd == VIRTIO_NET_CTRL_MQ_HASH_CONFIG) {
+ queues = virtio_net_handle_rss(n, iov, iov_cnt, false);
+ return queues ? VIRTIO_NET_OK : VIRTIO_NET_ERR;
+ }
if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) {
- queues = virtio_net_handle_rss(n, iov, iov_cnt);
+ queues = virtio_net_handle_rss(n, iov, iov_cnt, true);
} else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
struct virtio_net_ctrl_mq mq;
size_t s;
@@ -1572,15 +1595,34 @@ static uint8_t virtio_net_get_hash_type(bool isip4,
return 0xff;
}
+static void virtio_set_packet_hash(const uint8_t *buf, uint8_t report,
+ uint32_t hash)
+{
+ struct virtio_net_hdr_v1_hash *hdr = (void *)buf;
+ hdr->hash_value = hash;
+ hdr->hash_report = report;
+}
+
static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
size_t size)
{
VirtIONet *n = qemu_get_nic_opaque(nc);
- unsigned int index = nc->queue_index, new_index;
+ unsigned int index = nc->queue_index, new_index = index;
struct NetRxPkt *pkt = n->rx_pkt;
uint8_t net_hash_type;
uint32_t hash;
bool isip4, isip6, isudp, istcp;
+ static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = {
+ VIRTIO_NET_HASH_REPORT_IPv4,
+ VIRTIO_NET_HASH_REPORT_TCPv4,
+ VIRTIO_NET_HASH_REPORT_TCPv6,
+ VIRTIO_NET_HASH_REPORT_IPv6,
+ VIRTIO_NET_HASH_REPORT_IPv6_EX,
+ VIRTIO_NET_HASH_REPORT_TCPv6_EX,
+ VIRTIO_NET_HASH_REPORT_UDPv4,
+ VIRTIO_NET_HASH_REPORT_UDPv6,
+ VIRTIO_NET_HASH_REPORT_UDPv6_EX
+ };
net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
size - n->host_hdr_len);
@@ -1594,16 +1636,24 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
n->rss_data.hash_types);
if (net_hash_type > NetPktRssIpV6UdpEx) {
- return n->rss_data.default_queue;
+ if (n->rss_data.populate_hash) {
+ virtio_set_packet_hash(buf, VIRTIO_NET_HASH_REPORT_NONE, 0);
+ }
+ return n->rss_data.redirect ? n->rss_data.default_queue : -1;
}
hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
- new_index = hash & (n->rss_data.indirections_len - 1);
- new_index = n->rss_data.indirections_table[new_index];
- if (index == new_index) {
- return -1;
+
+ if (n->rss_data.populate_hash) {
+ virtio_set_packet_hash(buf, reports[net_hash_type], hash);
}
- return new_index;
+
+ if (n->rss_data.redirect) {
+ new_index = hash & (n->rss_data.indirections_len - 1);
+ new_index = n->rss_data.indirections_table[new_index];
+ }
+
+ return (index == new_index) ? -1 : new_index;
}
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
@@ -1679,6 +1729,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
}
receive_header(n, sg, elem->in_num, buf, size);
+ if (n->rss_data.populate_hash) {
+ offset = sizeof(mhdr);
+ iov_from_buf(sg, elem->in_num, offset,
+ buf + offset, n->host_hdr_len - sizeof(mhdr));
+ }
offset = n->host_hdr_len;
total += n->guest_hdr_len;
guest_offset = n->guest_hdr_len;
@@ -2671,7 +2726,9 @@ static int virtio_net_post_load_device(void *opaque, int version_id)
trace_virtio_net_post_load_device();
virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
virtio_vdev_has_feature(vdev,
- VIRTIO_F_VERSION_1));
+ VIRTIO_F_VERSION_1),
+ virtio_vdev_has_feature(vdev,
+ VIRTIO_NET_F_HASH_REPORT));
/* MAC_TABLE_ENTRIES may be different from the saved image */
if (n->mac_table.in_use > MAC_TABLE_ENTRIES) {
@@ -3290,7 +3347,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
n->vqs[0].tx_waiting = 0;
n->tx_burst = n->net_conf.txburst;
- virtio_net_set_mrg_rx_bufs(n, 0, 0);
+ virtio_net_set_mrg_rx_bufs(n, 0, 0, 0);
n->promisc = 1; /* for compatibility */
n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
@@ -3445,6 +3502,8 @@ static Property virtio_net_properties[] = {
DEFINE_PROP_BIT64("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false),
DEFINE_PROP_BIT64("rss", VirtIONet, host_features,
VIRTIO_NET_F_RSS, false),
+ DEFINE_PROP_BIT64("hash", VirtIONet, host_features,
+ VIRTIO_NET_F_HASH_REPORT, false),
DEFINE_PROP_BIT64("guest_rsc_ext", VirtIONet, host_features,
VIRTIO_NET_F_RSC_EXT, false),
DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout,
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index 5081f3c..a45ef82 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -131,6 +131,8 @@ typedef struct VirtioNetRscChain {
typedef struct VirtioNetRssData {
bool enabled;
+ bool redirect;
+ bool populate_hash;
uint32_t hash_types;
uint8_t key[VIRTIO_NET_RSS_MAX_KEY_SIZE];
uint16_t indirections_len;
--
2.5.0
next prev parent reply other threads:[~2020-06-18 13:23 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-18 13:21 [PULL V2 00/33] Net patches Jason Wang
2020-06-18 13:21 ` [PULL V2 01/33] virtio-net: implement RSS configuration command Jason Wang
2020-06-18 13:21 ` [PULL V2 02/33] virtio-net: implement RX RSS processing Jason Wang
2020-06-18 13:21 ` [PULL V2 03/33] tap: allow extended virtio header with hash info Jason Wang
2020-06-18 13:21 ` Jason Wang [this message]
2020-06-18 13:21 ` [PULL V2 05/33] vmstate.h: provide VMSTATE_VARRAY_UINT16_ALLOC macro Jason Wang
2020-06-18 13:21 ` [PULL V2 06/33] virtio-net: add migration support for RSS and hash report Jason Wang
2020-06-18 13:21 ` [PULL V2 07/33] virtio-net: align RSC fields with updated virtio-net header Jason Wang
2020-06-18 13:21 ` [PULL V2 08/33] Fix tulip breakage Jason Wang
2020-06-18 13:21 ` [PULL V2 09/33] hw/net/tulip: Fix 'Descriptor Error' definition Jason Wang
2020-06-18 13:21 ` [PULL V2 10/33] hw/net/tulip: Log descriptor overflows Jason Wang
2020-06-18 13:21 ` [PULL V2 11/33] net: cadence_gem: Fix debug statements Jason Wang
2020-06-18 13:21 ` [PULL V2 12/33] net: cadence_gem: Fix the queue address update during wrap around Jason Wang
2020-06-18 13:21 ` [PULL V2 13/33] net: cadence_gem: Fix irq update w.r.t queue Jason Wang
2020-06-18 13:21 ` [PULL V2 14/33] net: cadence_gem: Define access permission for interrupt registers Jason Wang
2020-06-18 13:21 ` [PULL V2 15/33] net: cadence_gem: Set ISR according to queue in use Jason Wang
2020-06-18 13:21 ` [PULL V2 16/33] net: cadence_gem: Move tx/rx packet buffert to CadenceGEMState Jason Wang
2020-06-18 13:21 ` [PULL V2 17/33] net: cadence_gem: Fix up code style Jason Wang
2020-06-18 13:21 ` [PULL V2 18/33] net: cadence_gem: Add support for jumbo frames Jason Wang
2020-06-18 13:21 ` [PULL V2 19/33] net: cadnece_gem: Update irq_read_clear field of designcfg_debug1 reg Jason Wang
2020-06-18 13:21 ` [PULL V2 20/33] net: cadence_gem: Update the reset value for interrupt mask register Jason Wang
2020-06-18 13:21 ` [PULL V2 21/33] net: cadence_gem: TX_LAST bit should be set by guest Jason Wang
2020-06-18 13:21 ` [PULL V2 22/33] net: cadence_gem: Fix RX address filtering Jason Wang
2020-06-18 13:21 ` [PULL V2 23/33] net: use peer when purging queue in qemu_flush_or_purge_queue_packets() Jason Wang
2020-06-18 13:21 ` [PULL V2 24/33] net/colo-compare.c: Create event_bh with the right AioContext Jason Wang
2020-06-18 13:21 ` [PULL V2 25/33] chardev/char.c: Use qemu_co_sleep_ns if in coroutine Jason Wang
2020-06-18 13:21 ` [PULL V2 26/33] net/colo-compare.c: Fix deadlock in compare_chr_send Jason Wang
2020-06-18 13:21 ` [PULL V2 27/33] net/colo-compare.c: Only hexdump packets if tracing is enabled Jason Wang
2020-06-18 13:21 ` [PULL V2 28/33] net/colo-compare.c: Check that colo-compare is active Jason Wang
2020-06-18 13:21 ` [PULL V2 29/33] net/colo-compare.c: Correct ordering in complete and finalize Jason Wang
2020-06-25 9:30 ` Peter Maydell
2020-07-03 16:10 ` Lukas Straub
2020-07-23 17:51 ` Peter Maydell
2020-06-18 13:21 ` [PULL V2 30/33] colo-compare: Fix memory leak in packet_enqueue() Jason Wang
2020-06-18 13:21 ` [PULL V2 31/33] hw/net/e1000e: Do not abort() on invalid PSRCTL register value Jason Wang
2020-06-18 13:21 ` [PULL V2 32/33] net: Drop the legacy "name" parameter from the -net option Jason Wang
2020-06-18 13:21 ` [PULL V2 33/33] net: Drop the NetLegacy structure, always use Netdev instead Jason Wang
2020-06-18 14:05 ` [PULL V2 00/33] Net patches no-reply
2020-06-19 3:19 ` Jason Wang
2020-06-19 10:45 ` Peter Maydell
2020-06-19 10:43 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1592486508-6135-5-git-send-email-jasowang@redhat.com \
--to=jasowang@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=yuri.benditovich@daynix.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).