VIRTIO_NET_F_HASH_REPORT allows to report hash values calculated on the
host. When VHOST_NET_F_VIRTIO_NET_HDR is employed, it will report no
hash values (i.e., the hash_report member is always set to
VIRTIO_NET_HASH_REPORT_NONE). Otherwise, the values reported by the
underlying socket will be reported.

VIRTIO_NET_F_HASH_REPORT requires VIRTIO_F_VERSION_1.

Signed-off-by: Akihiko Odaki <akihiko.od...@daynix.com>
Tested-by: Lei Yang <leiy...@redhat.com>
---
 drivers/vhost/net.c | 68 +++++++++++++++++++++++++++--------------------------
 1 file changed, 35 insertions(+), 33 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index b9b9e9d40951..fc5b43e43a06 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -73,6 +73,7 @@ enum {
        VHOST_NET_FEATURES = VHOST_FEATURES |
                         (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) |
                         (1ULL << VIRTIO_NET_F_MRG_RXBUF) |
+                        (1ULL << VIRTIO_NET_F_HASH_REPORT) |
                         (1ULL << VIRTIO_F_ACCESS_PLATFORM) |
                         (1ULL << VIRTIO_F_RING_RESET)
 };
@@ -1097,10 +1098,6 @@ 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
-       };
        size_t total_len = 0;
        int err, mergeable;
        s16 headcount;
@@ -1174,11 +1171,15 @@ static void handle_rx(struct vhost_net *net)
                /* We don't need to be notified again. */
                iov_iter_init(&msg.msg_iter, ITER_DEST, vq->iov, in, vhost_len);
                fixup = msg.msg_iter;
-               if (unlikely((vhost_hlen))) {
-                       /* We will supply the header ourselves
-                        * TODO: support TSO.
-                        */
-                       iov_iter_advance(&msg.msg_iter, vhost_hlen);
+               /*
+                * Supply virtio_net_hdr if VHOST_NET_F_VIRTIO_NET_HDR
+                * TODO: support TSO.
+                */
+               if (unlikely(vhost_hlen) &&
+                   iov_iter_zero(vhost_hlen, &msg.msg_iter) != vhost_hlen) {
+                       vq_err(vq, "Unable to write vnet_hdr at addr %p\n",
+                              vq->iov->iov_base);
+                       goto out;
                }
                err = sock->ops->recvmsg(sock, &msg,
                                         sock_len, MSG_DONTWAIT | MSG_TRUNC);
@@ -1191,30 +1192,24 @@ static void handle_rx(struct vhost_net *net)
                        vhost_discard_vq_desc(vq, headcount);
                        continue;
                }
-               /* 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)) {
-                               vq_err(vq, "Unable to write vnet_hdr "
-                                      "at addr %p\n", vq->iov->iov_base);
-                               goto out;
-                       }
-               } else {
-                       /* Header came from socket; we'll need to patch
-                        * ->num_buffers over if VIRTIO_NET_F_MRG_RXBUF
-                        */
-                       iov_iter_advance(&fixup, sizeof(hdr));
-               }
                /* TODO: Should check and handle checksum. */
 
+               /*
+                * We'll need to patch ->num_buffers over if
+                * VIRTIO_NET_F_MRG_RXBUF or VIRTIO_F_VERSION_1
+                */
                num_buffers = cpu_to_vhost16(vq, headcount);
-               if (likely(set_num_buffers) &&
-                   copy_to_iter(&num_buffers, sizeof num_buffers,
-                                &fixup) != sizeof num_buffers) {
-                       vq_err(vq, "Failed num_buffers write");
-                       vhost_discard_vq_desc(vq, headcount);
-                       goto out;
+               if (likely(set_num_buffers)) {
+                       iov_iter_advance(&fixup, offsetof(struct 
virtio_net_hdr_v1, num_buffers));
+
+                       if (copy_to_iter(&num_buffers, sizeof(num_buffers),
+                                        &fixup) != sizeof(num_buffers)) {
+                               vq_err(vq, "Failed num_buffers write");
+                               vhost_discard_vq_desc(vq, headcount);
+                               goto out;
+                       }
                }
+
                nvq->done_idx += headcount;
                if (nvq->done_idx > VHOST_NET_BATCH)
                        vhost_net_signal_used(nvq);
@@ -1607,10 +1602,13 @@ static int vhost_net_set_features(struct vhost_net *n, 
u64 features)
        size_t vhost_hlen, sock_hlen, hdr_len;
        int i;
 
-       hdr_len = (features & ((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
-                              (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);
+       else if (features & ((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
+                            (1ULL << VIRTIO_F_VERSION_1)))
+               hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+       else
+               hdr_len = sizeof(struct virtio_net_hdr);
        if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR)) {
                /* vhost provides vnet_hdr */
                vhost_hlen = hdr_len;
@@ -1691,6 +1689,10 @@ static long vhost_net_ioctl(struct file *f, unsigned int 
ioctl,
                        return -EFAULT;
                if (features & ~VHOST_NET_FEATURES)
                        return -EOPNOTSUPP;
+               if ((features & ((1ULL << VIRTIO_F_VERSION_1) |
+                                (1ULL << VIRTIO_NET_F_HASH_REPORT))) ==
+                   (1ULL << VIRTIO_NET_F_HASH_REPORT))
+                       return -EINVAL;
                return vhost_net_set_features(n, features);
        case VHOST_GET_BACKEND_FEATURES:
                features = VHOST_NET_BACKEND_FEATURES;

-- 
2.48.1


Reply via email to