[libvirt] [PATCH] macvtap IFF_VNET_HDR configuration

Daniel Veillard veillard at redhat.com
Fri Feb 19 10:44:25 UTC 2010


On Thu, Feb 18, 2010 at 05:43:40PM -0500, Stefan Berger wrote:
> This patch sets or unsets the IFF_VNET_HDR flag depending on what device
> is used in the VM. The manipulation of the flag is done in the open
> function and is only fatal if the IFF_VNET_HDR flag could not be cleared
> although it has to be (or if an ioctl generally fails). In that case the
> macvtap tap is closed again and the macvtap interface torn.
> 
> This patch also passes 'make syntax-check' :-).

  Yup, thanks :-)

> Signed-off-by: Stefan Berger <stefanb at us.ibm.com>
> 
> 

> Index: libvirt-macvtap/src/qemu/qemu_conf.c
> ===================================================================
> --- libvirt-macvtap.orig/src/qemu/qemu_conf.c
> +++ libvirt-macvtap/src/qemu/qemu_conf.c
> @@ -1434,14 +1434,20 @@ int
>  qemudPhysIfaceConnect(virConnectPtr conn,
>                        virDomainNetDefPtr net,
>                        char *linkdev,
> -                      int brmode)
> +                      int brmode,
> +                      unsigned long long qemuCmdFlags)
>  {
>      int rc;
>  #if WITH_MACVTAP
>      char *res_ifname = NULL;
> +    int vnet_hdr = 0;
> +
> +    if (qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HDR &&
> +        net->model && STREQ(net->model, "virtio"))
> +        vnet_hdr = 1;
>  
>      rc = openMacvtapTap(conn, net->ifname, net->mac, linkdev, brmode,
> -                        &res_ifname);
> +                        &res_ifname, vnet_hdr);
>      if (rc >= 0) {
>          VIR_FREE(net->ifname);
>          net->ifname = res_ifname;
> @@ -1451,6 +1457,7 @@ qemudPhysIfaceConnect(virConnectPtr conn
>      (void)net;
>      (void)linkdev;
>      (void)brmode;
> +    (void)qemuCmdFlags;
>      qemuReportError(VIR_ERR_INTERNAL_ERROR,
>                      "%s", _("No support for macvtap device"));
>      rc = -1;
> @@ -3752,7 +3759,8 @@ int qemudBuildCommandLine(virConnectPtr 
>              } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
>                  int tapfd = qemudPhysIfaceConnect(conn, net,
>                                                    net->data.direct.linkdev,
> -                                                  net->data.direct.mode);
> +                                                  net->data.direct.mode,
> +                                                  qemuCmdFlags);
>                  if (tapfd < 0)
>                      goto error;
>  
> Index: libvirt-macvtap/src/util/macvtap.c
> ===================================================================
> --- libvirt-macvtap.orig/src/util/macvtap.c
> +++ libvirt-macvtap/src/util/macvtap.c
> @@ -615,6 +615,64 @@ macvtapModeFromInt(enum virDomainNetdevM
>  
>  
>  /**
> + * configMacvtapTap:
> + * @tapfd: file descriptor of the macvtap tap
> + * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
> + *
> + * Returns 0 on success, -1 in case of fatal error, error code otherwise.
> + *
> + * Turn the IFF_VNET_HDR flag, if requested and available, make sure
> + * it's off in the other cases.
> + * A fatal error is defined as the VNET_HDR flag being set but it cannot
> + * be turned off for some reason. This is reported with -1. Other fatal
> + * error is not being able to read the interface flags. In that case the
> + * macvtap device should not be used.
> + */
> +static int
> +configMacvtapTap(int tapfd, int vnet_hdr)
> +{
> +    unsigned int features;
> +    struct ifreq ifreq;
> +    short new_flags = 0;
> +    int rc_on_fail = 0;
> +    const char *errmsg = NULL;
> +
> +    memset(&ifreq, 0, sizeof(ifreq));
> +
> +    if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) {
> +        virReportSystemError(errno, "%s",
> +                             _("cannot get interface flags on macvtap tap"));
> +        return -1;
> +    }
> +
> +    new_flags = ifreq.ifr_flags;
> +
> +    if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) {
> +        new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR;
> +        rc_on_fail = -1;
> +        errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap");
> +    } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) {
> +        if (ioctl(tapfd, TUNGETFEATURES, &features) != 0)
> +            return errno;
> +        if ((features & IFF_VNET_HDR)) {
> +            new_flags = ifreq.ifr_flags | IFF_VNET_HDR;
> +            errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap");
> +        }
> +    }
> +
> +    if (new_flags != ifreq.ifr_flags) {
> +        ifreq.ifr_flags = new_flags;
> +        if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) {
> +            virReportSystemError(errno, "%s", errmsg);
> +            return rc_on_fail;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +
> +/**
>   * openMacvtapTap:
>   * Create an instance of a macvtap device and open its tap character
>   * device.
> @@ -640,7 +698,8 @@ openMacvtapTap(virConnectPtr conn,
>                 const unsigned char *macaddress,
>                 const char *linkdev,
>                 int mode,
> -               char **res_ifname)
> +               char **res_ifname,
> +               int vnet_hdr)
>  {
>      const char *type = "macvtap";
>      int c, rc;
> @@ -699,9 +758,14 @@ create_name:
>  
>      rc = openTap(cr_ifname, 10);
>  
> -    if (rc >= 0)
> +    if (rc >= 0) {
> +        if (configMacvtapTap(rc, vnet_hdr) < 0) {
> +            close(rc);
> +            rc = -1;
> +            goto link_del_exit;
> +        }
>          *res_ifname = strdup(cr_ifname);
> -    else
> +    } else
>          goto link_del_exit;
>  
>      return rc;
> Index: libvirt-macvtap/src/util/macvtap.h
> ===================================================================
> --- libvirt-macvtap.orig/src/util/macvtap.h
> +++ libvirt-macvtap/src/util/macvtap.h
> @@ -33,9 +33,10 @@ int openMacvtapTap(virConnectPtr conn,
>                     const unsigned char *macaddress,
>                     const char *linkdev,
>                     int mode,
> -                   char **res_ifname);
> +                   char **res_ifname,
> +                   int vnet_hdr);
>  
> -void delMacvtap(const char *name);
> +void delMacvtap(const char *ifname);
>  
>  #endif /* WITH_MACVTAP */
>  
> Index: libvirt-macvtap/src/qemu/qemu_conf.h
> ===================================================================
> --- libvirt-macvtap.orig/src/qemu/qemu_conf.h
> +++ libvirt-macvtap/src/qemu/qemu_conf.h
> @@ -253,7 +253,8 @@ int         qemudNetworkIfaceConnect    
>  int qemudPhysIfaceConnect(virConnectPtr conn,
>                            virDomainNetDefPtr net,
>                            char *linkdev,
> -                          int brmode);
> +                          int brmode,
> +                          unsigned long long qemuCmdFlags);
>  
>  int         qemudProbeMachineTypes      (const char *binary,
>                                           virCapsGuestMachinePtr **machines,
> Index: libvirt-macvtap/src/qemu/qemu_driver.c
> ===================================================================
> --- libvirt-macvtap.orig/src/qemu/qemu_driver.c
> +++ libvirt-macvtap/src/qemu/qemu_driver.c
> @@ -5725,7 +5725,8 @@ static int qemudDomainAttachNetDevice(vi
>  
>          if ((tapfd = qemudPhysIfaceConnect(conn, net,
>                                             net->data.direct.linkdev,
> -                                           net->data.direct.mode)) < 0)
> +                                           net->data.direct.mode,
> +                                           qemuCmdFlags)) < 0)
>              return -1;
>      }
>  

  Looks reasonnable, ACK, applied !

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list