kvmtool: allow the TAP interface to be specified on the command line

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@arm.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
Marc Zyngier
2014-04-24 18:10:06 +01:00
committed by Will Deacon
parent 3ad9fad44c
commit 1dfc7c243d
2 changed files with 15 additions and 7 deletions
+1
View File
@@ -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;
+14 -7
View File
@@ -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) {