Patchwork Fix TAP networking on host kernels without IFF_VNET_HDR support

login
register
mail settings
Submitter Pierre Riteau
Date Nov. 24, 2009, 9:06 a.m.
Message ID <1259053593-15362-1-git-send-email-Pierre.Riteau@irisa.fr>
Download mbox | patch
Permalink /patch/39191/
State New
Headers show

Comments

Pierre Riteau - Nov. 24, 2009, 9:06 a.m.
vnet_hdr is initialized at 1 by default. We need to reset it to 0 if
the kernel doesn't support IFF_VNET_HDR.

Signed-off-by: Pierre Riteau <Pierre.Riteau@irisa.fr>
---
 net/tap-linux.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
Mark McLoughlin - Nov. 24, 2009, 10:28 a.m.
On Tue, 2009-11-24 at 10:06 +0100, Pierre Riteau wrote:
> vnet_hdr is initialized at 1 by default. We need to reset it to 0 if
> the kernel doesn't support IFF_VNET_HDR.
> 
> Signed-off-by: Pierre Riteau <Pierre.Riteau@irisa.fr>

Thanks Pierre, I see why this is needed now

Acked-by: Mark McLoughlin <markmc@redhat.com>

Cheers,
Mark.
Pierre Riteau - Nov. 24, 2009, 11:17 a.m.
On 24 nov. 2009, at 11:28, Mark McLoughlin wrote:

> On Tue, 2009-11-24 at 10:06 +0100, Pierre Riteau wrote:
>> vnet_hdr is initialized at 1 by default. We need to reset it to 0 if
>> the kernel doesn't support IFF_VNET_HDR.
>> 
>> Signed-off-by: Pierre Riteau <Pierre.Riteau@irisa.fr>
> 
> Thanks Pierre, I see why this is needed now
> 
> Acked-by: Mark McLoughlin <markmc@redhat.com>
> 
> Cheers,
> Mark.


Thanks for your rapid answer!

BTW, every time I run qemu I see this error message:

    TUNSETOFFLOAD ioctl() failed: Invalid argument

It is caused by the piece of code at the end of net/tap-linux.c:

    if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
        offload &= ~TUN_F_UFO;
        if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
            fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n",
                    strerror(errno));
        }
    }

Isn't there a way to detect whether the kernel supports the TUNSETOFFLOAD ioctl at all?
Mark McLoughlin - Nov. 24, 2009, 11:22 a.m.
On Tue, 2009-11-24 at 12:17 +0100, Pierre Riteau wrote:
> On 24 nov. 2009, at 11:28, Mark McLoughlin wrote:
> 
> > On Tue, 2009-11-24 at 10:06 +0100, Pierre Riteau wrote:
> >> vnet_hdr is initialized at 1 by default. We need to reset it to 0 if
> >> the kernel doesn't support IFF_VNET_HDR.
> >> 
> >> Signed-off-by: Pierre Riteau <Pierre.Riteau@irisa.fr>
> > 
> > Thanks Pierre, I see why this is needed now
> > 
> > Acked-by: Mark McLoughlin <markmc@redhat.com>
> > 
> > Cheers,
> > Mark.
> 
> 
> Thanks for your rapid answer!
> 
> BTW, every time I run qemu I see this error message:
> 
>     TUNSETOFFLOAD ioctl() failed: Invalid argument
> 
> It is caused by the piece of code at the end of net/tap-linux.c:
> 
>     if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
>         offload &= ~TUN_F_UFO;
>         if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
>             fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n",
>                     strerror(errno));
>         }
>     }
> 
> Isn't there a way to detect whether the kernel supports the
> TUNSETOFFLOAD ioctl at all?

The kernel will set errno to EINVAL if TUNSETOFFLOAD isn't supported, so
we could just ignore that case:

     if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
          offload &= ~TUN_F_UFO;
          if (ioctl(fd, TUNSETOFFLOAD, offload) != 0 && errno != EINVAL) {
              fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n",
                      strerror(errno));
          }
      }

The only concern is that we'll also miss out on an error message if
EINVAL is set for another reason. Currently, the only other reason if we
pass a offload flag not supported by the kernel, but that should never
happen.

Feel free to send a patch with that change and I'll ack it

Thanks,
Mark.

Patch

diff --git a/net/tap-linux.c b/net/tap-linux.c
index 0f621a2..e4f7e27 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -52,6 +52,8 @@  int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
             features & IFF_VNET_HDR) {
             *vnet_hdr = 1;
             ifr.ifr_flags |= IFF_VNET_HDR;
+        } else {
+            *vnet_hdr = 0;
         }
 
         if (vnet_hdr_required && !*vnet_hdr) {