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.benditov...@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

Reply via email to