[libvirt] [ 1/3] autocreate tap device for ethernet network type

Daniel P. Berrange berrange at redhat.com
Wed Mar 23 11:34:12 UTC 2016


On Fri, Mar 18, 2016 at 10:19:41PM +0000, Vasiliy Tolstov wrote:
> If a user specify network type ethernet, then create it via libvirt and run
> script if it provided. After this commit user does not need to
> run external script to create tap device or add root permissions to qemu
> process.
> 
> Signed-off-by: Vasiliy Tolstov <v.tolstov at selfip.ru>
> ---
>  src/qemu/qemu_command.c   |  38 ++++++-----
>  src/qemu/qemu_hotplug.c   |  36 +++++++++--
>  src/qemu/qemu_interface.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_interface.h |   5 ++
>  src/qemu/qemu_process.c   |   6 ++
>  5 files changed, 221 insertions(+), 22 deletions(-)

> diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
> index 08af13358113..bab0ff5b2006 100644
> --- a/src/qemu/qemu_interface.c
> +++ b/src/qemu/qemu_interface.c
> +int
> +qemuInterfaceEthernetConnect(virDomainDefPtr def,
> +                           virQEMUDriverPtr driver,
> +                           virDomainNetDefPtr net,
> +                           int *tapfd,
> +                           size_t tapfdSize)
> +{
> +    virMacAddr tapmac;
> +    size_t j;
> +    int ret = -1;
> +    unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
> +    bool template_ifname = false;
> +    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
> +    const char *tunpath = "/dev/net/tun";
> +
> +    if (net->backend.tap) {
> +        tunpath = net->backend.tap;
> +        if (!(virQEMUDriverIsPrivileged(driver))) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("cannot use custom tap device in session mode"));
> +            goto cleanup;
> +        }
> +    }
> +
> +    if (!net->ifname ||
> +        STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) ||
> +        strchr(net->ifname, '%')) {
> +        VIR_FREE(net->ifname);
> +        if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0)
> +            goto cleanup;
> +        /* avoid exposing vnet%d in getXMLDesc or error outputs */
> +        template_ifname = true;
> +    }
> +
> +    if (net->model && STREQ(net->model, "virtio"))
> +        tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
> +
> +    if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
> +                           tap_create_flags) < 0) {
> +        virDomainAuditNetDevice(def, net, tunpath, false);
> +        goto cleanup;
> +    }
> +
> +    virDomainAuditNetDevice(def, net, tunpath, true);
> +    virMacAddrSet(&tapmac, &net->mac);
> +    tapmac.addr[0] = 0xFE;
> +
> +    if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
> +        goto cleanup;
> +
> +    for (j = 0; j < net->nips; j++) {
> +        virDomainNetIpDefPtr ip = net->ips[j];
> +        unsigned int prefix = (ip->prefix > 0) ? ip->prefix :
> +                              VIR_SOCKET_ADDR_DEFAULT_PREFIX;
> +        char *ipStr = virSocketAddrFormat(&ip->address);
> +
> +        VIR_DEBUG("Adding IP address '%s/%u' to '%s'",
> +                  ipStr, ip->prefix, net->ifname);
> +
> +        if (virNetDevSetIPAddress(net->ifname, &ip->address, &ip->peer, prefix) < 0) {
> +            virReportError(VIR_ERR_SYSTEM_ERROR,
> +                           _("Failed to set IP address '%s' on %s"),
> +                           ipStr, net->ifname);
> +            VIR_FREE(ipStr);
> +            goto cleanup;
> +        }
> +        VIR_FREE(ipStr);
> +    }
> +
> +    if (net->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP ||
> +        net->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT) {
> +        if (virNetDevSetOnline(net->ifname, true) < 0)
> +            goto cleanup;
> +
> +        /* Set the routes */
> +        for (j = 0; j < net->nroutes; j++) {
> +            virNetworkRouteDefPtr route = net->routes[j];
> +
> +            if (virNetDevAddRoute(net->ifname,
> +                                  virNetworkRouteDefGetAddress(route),
> +                                  virNetworkRouteDefGetPrefix(route),
> +                                  virNetworkRouteDefGetGateway(route),
> +                                  virNetworkRouteDefGetMetric(route)) < 0) {
> +                goto cleanup;
> +            }
> +        }
> +    }


This is still doing alot more work than QEMU would do if it crated
the TAP device. In particular the adding of IP addresses & routes
is not something QEMU would do - this is left for the specified
network script todo.

We can have a discussion about whether to support setting of routes
and IP's on this device, vs inventing a new type of device for this
purpose, but that should be in a separate patch.

RAther than have you re-post again, I'll commit just this patch
with this IP & route stuff removed now.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list