All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@arndb.de>
To: Mark McLoughlin <markmc@redhat.com>
Cc: avi@redhat.com, kvm@vger.kernel.org,
	Jens Osterkamp <Jens.Osterkamp@gmx.de>
Subject: Re: [PATCH 1/1] net: fix vnet_hdr bustage with slirp
Date: Fri, 7 Aug 2009 13:51:01 +0200	[thread overview]
Message-ID: <200908071351.02086.arnd@arndb.de> (raw)
In-Reply-To: <1249634851-24005-1-git-send-email-markmc@redhat.com>

On Friday 07 August 2009, Mark McLoughlin wrote:
> slirp has started using VLANClientState::opaque and this has caused the
> kvm specific tap_has_vnet_hdr() hack to break because we blindly use
> this opaque pointer even if it is not a tap client.
> 
> Add yet another hack to check that we're actually getting called with a
> tap client.
> 
> [Needed on stable-0.11 too]
> 
> Signed-off-by: Mark McLoughlin <markmc@redhat.com>

Jens and I discovered the same bug before, but then we forgot about
sending a fix (sorry). Your patch should work fine as a workaround,
but I wonder if it is the right solution. 

The abstraction of struct VLANClientState is otherwise done through
function pointers taking the VLANClientState pointer as their
first argument. IMHO a cleaner abstraction would be to do the same
for tap_has_vnet_hdr(), like the patch below, and similar for
other functions passing 'opaque' pointers.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 6dfe758..6b34e82 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -123,7 +123,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev)
     VirtIONet *n = to_virtio_net(vdev);
     VLANClientState *host = n->vc->vlan->first_client;
 
-    if (tap_has_vnet_hdr(host)) {
+    if (host->has_vnet_hdr && host->has_vnet_hdr(host)) {
         tap_using_vnet_hdr(host, 1);
         features |= (1 << VIRTIO_NET_F_CSUM);
         features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
@@ -166,7 +166,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
     n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
 
 #ifdef TAP_VNET_HDR
-    if (!tap_has_vnet_hdr(host) || !host->set_offload)
+    if (!(host->has_vnet_hdr && host->has_vnet_hdr(host)) || !host->set_offload)
         return;
 
     host->set_offload(host,
@@ -398,7 +398,7 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
     hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
 
 #ifdef TAP_VNET_HDR
-    if (tap_has_vnet_hdr(n->vc->vlan->first_client)) {
+    if ((host->has_vnet_hdr && host->has_vnet_hdr(n->vc->vlan->first_client))) {
         memcpy(hdr, buf, sizeof(*hdr));
         offset = sizeof(*hdr);
         work_around_broken_dhclient(hdr, buf + offset, size - offset);
@@ -425,7 +425,8 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
         return 1;
 
 #ifdef TAP_VNET_HDR
-    if (tap_has_vnet_hdr(n->vc->vlan->first_client))
+    if ((host->has_vnet_hdr &&
+	    host->has_vnet_hdr(n->vc->vlan->first_client)))
         ptr += sizeof(struct virtio_net_hdr);
 #endif
 
@@ -529,7 +530,8 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
 {
     VirtQueueElement elem;
 #ifdef TAP_VNET_HDR
-    int has_vnet_hdr = tap_has_vnet_hdr(n->vc->vlan->first_client);
+    int has_vnet_hdr = (host->has_vnet_hdr &&
+		    host->has_vnet_hdr(n->vc->vlan->first_client));
 #else
     int has_vnet_hdr = 0;
 #endif
@@ -620,7 +622,7 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
     qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);
 
 #ifdef TAP_VNET_HDR
-    qemu_put_be32(f, tap_has_vnet_hdr(n->vc->vlan->first_client));
+    qemu_put_be32(f, (host->has_vnet_hdr && host->has_vnet_hdr(n->vc->vlan->first_client)));
 #else
     qemu_put_be32(f, 0);
 #endif
diff --git a/net.c b/net.c
index 931def1..b56ae78 100644
--- a/net.c
+++ b/net.c
@@ -754,7 +754,7 @@ static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
 
 #ifdef _WIN32
 
-int tap_has_vnet_hdr(void *opaque)
+static int tap_has_vnet_hdr(struct VLANClientState *vc)
 {
     return 0;
 }
@@ -906,9 +906,8 @@ static void tap_send(void *opaque)
     } while (s->size > 0);
 }
 
-int tap_has_vnet_hdr(void *opaque)
+static int tap_has_vnet_hdr(struct VLANClientState *vc)
 {
-    VLANClientState *vc = opaque;
     TAPState *s = vc->opaque;
 
     return s ? s->has_vnet_hdr : 0;
@@ -991,6 +990,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
     s->has_vnet_hdr = vnet_hdr != 0;
     s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive,
                                  NULL, tap_cleanup, s);
+    s->vc->has_vnet_hdr = tap_has_vnet_hdr;
     s->vc->fd_readv = tap_receive_iov;
 #ifdef TUNSETOFFLOAD
     s->vc->set_offload = tap_set_offload;
diff --git a/net.h b/net.h
index bc42428..7c79734 100644
--- a/net.h
+++ b/net.h
@@ -21,6 +21,7 @@ struct VLANClientState {
     IOCanRWHandler *fd_can_read;
     NetCleanup *cleanup;
     LinkStatusChanged *link_status_changed;
+    int (*has_vnet_hdr)(struct VLANClientState *);
     int link_down;
     SetOffload *set_offload;
     void *opaque;
@@ -72,7 +73,6 @@ void qemu_handler_true(void *opaque);
 void do_info_network(Monitor *mon);
 int do_set_link(Monitor *mon, const char *name, const char *up_or_down);
 
-int tap_has_vnet_hdr(void *opaque);
 void tap_using_vnet_hdr(void *opaque, int using_vnet_hdr);
 
 /* NIC info */

  reply	other threads:[~2009-08-07 11:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-07  8:47 [PATCH 1/1] net: fix vnet_hdr bustage with slirp Mark McLoughlin
2009-08-07 11:51 ` Arnd Bergmann [this message]
2009-08-07 12:19   ` Mark McLoughlin
2009-08-07 13:20     ` Arnd Bergmann
2009-08-09  9:53 ` Avi Kivity

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=200908071351.02086.arnd@arndb.de \
    --to=arnd@arndb.de \
    --cc=Jens.Osterkamp@gmx.de \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=markmc@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.