From a5efd47244bd0d2468ca5bbeda0dda097c8284a0 Mon Sep 17 00:00:00 2001
From: Xiao Wang <jasowang@redhat.com>
Date: Mon, 13 Dec 2010 13:52:29 -0200
Subject: [RHEL6 qemu-kvm PATCH 2/5] tap: generalize code for different vnet header len

RH-Author: Xiao Wang <jasowang@redhat.com>
Message-id: <20101213135229.20882.42103.stgit@dhcp-91-158.nay.redhat.com>
Patchwork-id: 14614
O-Subject: [RHEL6.1 PATCH 1/3] tap: generalize code for different vnet header len
Bugzilla: 616659
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>

From: Michael S. Tsirkin <mst@redhat.com>

Bugzilla: 616659
Brew build: https://brewweb.devel.redhat.com/taskinfo?taskID=2969665
Test status:
Pass autotest network related tests.

Make host vnet header length a structure field in
preparation for using this support in linux kernel.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked form ef4252b149cf238480c45c06dcbd567d41ee7d76)
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 net/tap-linux.h |    6 ++++++
 net/tap.c       |   28 ++++++++++++++--------------
 2 files changed, 20 insertions(+), 14 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 net/tap-linux.h |    6 ++++++
 net/tap.c       |   28 ++++++++++++++--------------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/net/tap-linux.h b/net/tap-linux.h
index 9f94358..727fcf5 100644
--- a/net/tap-linux.h
+++ b/net/tap-linux.h
@@ -52,4 +52,10 @@ struct virtio_net_hdr
     uint16_t csum_offset;
 };
 
+struct virtio_net_hdr_mrg_rxbuf
+{
+    struct virtio_net_hdr hdr;
+    uint16_t num_buffers;   /* Number of merged rx buffers */
+};
+
 #endif /* QEMU_TAP_H */
diff --git a/net/tap.c b/net/tap.c
index bec19ce..3657202 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -57,10 +57,10 @@ typedef struct TAPState {
     uint8_t buf[TAP_BUFSIZE];
     unsigned int read_poll : 1;
     unsigned int write_poll : 1;
-    unsigned int has_vnet_hdr : 1;
     unsigned int using_vnet_hdr : 1;
     unsigned int has_ufo: 1;
     VHostNetState *vhost_net;
+    unsigned host_vnet_hdr_len;
 } TAPState;
 
 static int launch_script(const char *setup_script, const char *ifname, int fd);
@@ -121,11 +121,11 @@ static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov,
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     const struct iovec *iovp = iov;
     struct iovec iov_copy[iovcnt + 1];
-    struct virtio_net_hdr hdr = { 0, };
+    struct virtio_net_hdr_mrg_rxbuf hdr = { };
 
-    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
+    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
         iov_copy[0].iov_base = &hdr;
-        iov_copy[0].iov_len =  sizeof(hdr);
+        iov_copy[0].iov_len =  s->host_vnet_hdr_len;
         memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
         iovp = iov_copy;
         iovcnt++;
@@ -139,11 +139,11 @@ static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t s
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     struct iovec iov[2];
     int iovcnt = 0;
-    struct virtio_net_hdr hdr = { 0, };
+    struct virtio_net_hdr_mrg_rxbuf hdr = { };
 
-    if (s->has_vnet_hdr) {
+    if (s->host_vnet_hdr_len) {
         iov[iovcnt].iov_base = &hdr;
-        iov[iovcnt].iov_len  = sizeof(hdr);
+        iov[iovcnt].iov_len  = s->host_vnet_hdr_len;
         iovcnt++;
     }
 
@@ -159,7 +159,7 @@ static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     struct iovec iov[1];
 
-    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
+    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
         return tap_receive_raw(nc, buf, size);
     }
 
@@ -202,9 +202,9 @@ static void tap_send(void *opaque)
             break;
         }
 
-        if (s->has_vnet_hdr && !s->using_vnet_hdr) {
-            buf  += sizeof(struct virtio_net_hdr);
-            size -= sizeof(struct virtio_net_hdr);
+        if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
+            buf  += s->host_vnet_hdr_len;
+            size -= s->host_vnet_hdr_len;
         }
 
         size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
@@ -229,7 +229,7 @@ int tap_has_vnet_hdr(VLANClientState *nc)
 
     assert(nc->info->type == NET_CLIENT_TYPE_TAP);
 
-    return s->has_vnet_hdr;
+    return !!s->host_vnet_hdr_len;
 }
 
 void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr)
@@ -239,7 +239,7 @@ void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr)
     using_vnet_hdr = using_vnet_hdr != 0;
 
     assert(nc->info->type == NET_CLIENT_TYPE_TAP);
-    assert(s->has_vnet_hdr == using_vnet_hdr);
+    assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
 
     s->using_vnet_hdr = using_vnet_hdr;
 }
@@ -315,7 +315,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
     s = DO_UPCAST(TAPState, nc, nc);
 
     s->fd = fd;
-    s->has_vnet_hdr = vnet_hdr != 0;
+    s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
     s->using_vnet_hdr = 0;
     s->has_ufo = tap_probe_has_ufo(s->fd);
     tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
-- 
1.7.3.2

