In order to overcome the fact that a TAP interface can only be created by root, allow the use of an interface that has already been created, configured, made persistent and owned by a specific user/group (such as done with tunctl). In this case, any kind of configuration can be skipped (IP, up and running mode), and the TAP is assumed to be ready for use. This is done by introducing the "tapif" option, as used here: --network trans=mmio,mode=tap,tapif=blah where "blah" is a TAP interface. This allow the creation/configuration of the interface to be controlled by root, and lkvm to be run as a normal user. Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> --- tools/kvm/include/kvm/virtio-net.h | 1 + tools/kvm/virtio/net.c | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/kvm/include/kvm/virtio-net.h b/tools/kvm/include/kvm/virtio-net.h index 0f4d1e5..f435cc3 100644 --- a/tools/kvm/include/kvm/virtio-net.h +++ b/tools/kvm/include/kvm/virtio-net.h @@ -10,6 +10,7 @@ struct virtio_net_params { const char *host_ip; const char *script; const char *trans; + const char *tapif; char guest_mac[6]; char host_mac[6]; struct kvm *kvm; diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c index dbb4431..82dbb88 100644 --- a/tools/kvm/virtio/net.c +++ b/tools/kvm/virtio/net.c @@ -257,6 +257,7 @@ static bool virtio_net__tap_init(struct net_dev *ndev) struct sockaddr_in sin = {0}; struct ifreq ifr; const struct virtio_net_params *params = ndev->params; + bool skipconf = !!params->tapif; /* Did the user already gave us the FD? */ if (params->fd) { @@ -272,6 +273,8 @@ static bool virtio_net__tap_init(struct net_dev *ndev) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; + if (params->tapif) + strncpy(ifr.ifr_name, params->tapif, sizeof(ifr.ifr_name)); if (ioctl(ndev->tap_fd, TUNSETIFF, &ifr) < 0) { pr_warning("Config tap device error. Are you root?"); goto fail; @@ -308,7 +311,7 @@ static bool virtio_net__tap_init(struct net_dev *ndev) goto fail; } } - } else { + } else if (!skipconf) { memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name)); sin.sin_addr.s_addr = inet_addr(params->host_ip); @@ -320,12 +323,14 @@ static bool virtio_net__tap_init(struct net_dev *ndev) } } - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name)); - ioctl(sock, SIOCGIFFLAGS, &ifr); - ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) - pr_warning("Could not bring tap device up"); + if (!skipconf) { + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name)); + ioctl(sock, SIOCGIFFLAGS, &ifr); + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) + pr_warning("Could not bring tap device up"); + } close(sock); @@ -650,6 +655,8 @@ static int set_net_param(struct kvm *kvm, struct virtio_net_params *p, p->host_ip = strdup(val); } else if (strcmp(param, "trans") == 0) { p->trans = strdup(val); + } else if (strcmp(param, "tapif") == 0) { + p->tapif = strdup(val); } else if (strcmp(param, "vhost") == 0) { p->vhost = atoi(val); } else if (strcmp(param, "fd") == 0) { -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html