Yuri Benditovich
2021-Jan-05 12:24 UTC
[RFC PATCH 2/7] vhost: support for hash report virtio-net feature
According to the virtio specification if VIRTIO_NET_F_HASH_REPORT feature acked the virtio-net header is extended to hold the hash value and hash report type. Signed-off-by: Yuri Benditovich <yuri.benditovich at daynix.com> --- drivers/vhost/net.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 531a00d703cd..31a894b9a992 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -73,7 +73,8 @@ enum { VHOST_NET_FEATURES = VHOST_FEATURES | (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | - (1ULL << VIRTIO_F_ACCESS_PLATFORM) + (1ULL << VIRTIO_F_ACCESS_PLATFORM) | + (1ULL << VIRTIO_NET_F_HASH_REPORT) }; enum { @@ -1108,14 +1109,16 @@ static void handle_rx(struct vhost_net *net) .msg_controllen = 0, .msg_flags = MSG_DONTWAIT, }; - struct virtio_net_hdr hdr = { - .flags = 0, - .gso_type = VIRTIO_NET_HDR_GSO_NONE + struct virtio_net_hdr_v1_hash hdrv1 = { + { + .flags = 0, + .gso_type = VIRTIO_NET_HDR_GSO_NONE + } }; size_t total_len = 0; int err, mergeable; s16 headcount; - size_t vhost_hlen, sock_hlen; + size_t vhost_hlen, sock_hlen, extra_hlen; size_t vhost_len, sock_len; bool busyloop_intr = false; struct socket *sock; @@ -1137,9 +1140,12 @@ static void handle_rx(struct vhost_net *net) vhost_hlen = nvq->vhost_hlen; sock_hlen = nvq->sock_hlen; + vq_log = unlikely(vhost_has_feature(vq, VHOST_F_LOG_ALL)) ? vq->log : NULL; mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); + extra_hlen = vhost_has_feature(vq, VIRTIO_NET_F_HASH_REPORT) ? + sizeof(hdrv1) - sizeof(hdrv1.hdr) : 0; do { sock_len = vhost_net_rx_peek_head_len(net, sock->sk, @@ -1201,8 +1207,8 @@ static void handle_rx(struct vhost_net *net) } /* Supply virtio_net_hdr if VHOST_NET_F_VIRTIO_NET_HDR */ if (unlikely(vhost_hlen)) { - if (copy_to_iter(&hdr, sizeof(hdr), - &fixup) != sizeof(hdr)) { + if (copy_to_iter(&hdrv1, sizeof(struct virtio_net_hdr), + &fixup) != sizeof(struct virtio_net_hdr)) { vq_err(vq, "Unable to write vnet_hdr " "at addr %p\n", vq->iov->iov_base); goto out; @@ -1211,7 +1217,7 @@ static void handle_rx(struct vhost_net *net) /* Header came from socket; we'll need to patch * ->num_buffers over if VIRTIO_NET_F_MRG_RXBUF */ - iov_iter_advance(&fixup, sizeof(hdr)); + iov_iter_advance(&fixup, sizeof(struct virtio_net_hdr)); } /* TODO: Should check and handle checksum. */ @@ -1223,6 +1229,18 @@ static void handle_rx(struct vhost_net *net) vhost_discard_vq_desc(vq, headcount); goto out; } + if (unlikely(extra_hlen)) { + if (unlikely(vhost_hlen)) { + if (copy_to_iter(&hdrv1.hash_value, extra_hlen, + &fixup) != extra_hlen) { + vq_err(vq, "Unable to write extra_hdr " + "at addr %p\n", vq->iov->iov_base); + goto out; + } + } else { + iov_iter_advance(&fixup, extra_hlen); + } + } nvq->done_idx += headcount; if (nvq->done_idx > VHOST_NET_BATCH) vhost_net_signal_used(nvq); @@ -1624,6 +1642,9 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features) (1ULL << VIRTIO_F_VERSION_1))) ? sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + if (features & (1ULL << VIRTIO_NET_F_HASH_REPORT)) { + hdr_len = sizeof(struct virtio_net_hdr_v1_hash); + } if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR)) { /* vhost provides vnet_hdr */ vhost_hlen = hdr_len; -- 2.17.1