qrap: Strip network devices from command line, set them up according to machine
The previous approach wasn't really robust: adding a -netdev option without libvirt knowing could result in clashes with other devices. Drop network devices from command line, check the available busses and addresses from all -device options according to the -machine parameter, and add a virtio-net device using an available address or bus. Then, add a corresponding -netdev socket option. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
7503332a1e
commit
5307faa059
1 changed files with 95 additions and 28 deletions
115
qrap.c
115
qrap.c
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
#include "passt.h"
|
#include "passt.h"
|
||||||
|
|
||||||
|
#define STRINGIFY(x) #x
|
||||||
|
#define STR(x) STRINGIFY(x)
|
||||||
|
|
||||||
static char *qemu_names[] = {
|
static char *qemu_names[] = {
|
||||||
"kvm",
|
"kvm",
|
||||||
"qemu-kvm",
|
"qemu-kvm",
|
||||||
|
@ -37,6 +40,36 @@ static char *qemu_names[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct drop_arg {
|
||||||
|
char *name;
|
||||||
|
char *val;
|
||||||
|
} drop_args[] = {
|
||||||
|
{ "-netdev", NULL },
|
||||||
|
{ "-net", NULL },
|
||||||
|
{ "-device", "virtio-net-pci," },
|
||||||
|
{ "-device", "virtio-net-ccw," },
|
||||||
|
{ "-device", "e1000," },
|
||||||
|
{ "-device", "rtl8139," },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pci_dev {
|
||||||
|
char *mach;
|
||||||
|
char *name;
|
||||||
|
char *template;
|
||||||
|
char *template_post;
|
||||||
|
int first;
|
||||||
|
int last;
|
||||||
|
} pci_devs[] = {
|
||||||
|
{ "pc-q35", "virtio-net-pci",
|
||||||
|
"bus=pci.", ",addr=0x0", 3, 16 },
|
||||||
|
{ "pc-", "virtio-net-pci",
|
||||||
|
"bus=pci.0,addr=0x", "", 2, /* 1: ISA bridge */ 16 },
|
||||||
|
{ "s390-ccw", "virtio-net-ccw",
|
||||||
|
"devno=fe.0.", "", 1, 16 },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
#define DEFAULT_FD 5
|
#define DEFAULT_FD 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,13 +96,13 @@ void usage(const char *name)
|
||||||
*/
|
*/
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *qemu_argv[ARG_MAX], net_id[ARG_MAX] = { 0 }, *net_id_end;
|
char *qemu_argv[ARG_MAX], dev_str[ARG_MAX];
|
||||||
int i, s, qemu_argc = 0, in_netdev = 0, has_socket = 0;
|
int i, s, qemu_argc = 0, addr_map = 0, has_dev = 0;
|
||||||
struct sockaddr_un addr = {
|
struct sockaddr_un addr = {
|
||||||
.sun_family = AF_UNIX,
|
.sun_family = AF_UNIX,
|
||||||
.sun_path = UNIX_SOCK_PATH,
|
.sun_path = UNIX_SOCK_PATH,
|
||||||
};
|
};
|
||||||
char fd_str[ARG_MAX];
|
const struct pci_dev *dev = NULL;
|
||||||
long fd;
|
long fd;
|
||||||
|
|
||||||
if (argc >= 3) {
|
if (argc >= 3) {
|
||||||
|
@ -90,39 +123,73 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = DEFAULT_FD;
|
fd = DEFAULT_FD;
|
||||||
for (qemu_argc = 1, i = 1; i < argc; i++) {
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (in_netdev) {
|
for (i = 1; i < argc - 1; i++) {
|
||||||
in_netdev = 0;
|
if (strcmp(argv[i], "-machine"))
|
||||||
if (strstr(argv[i], ",socket") ||
|
continue;
|
||||||
strstr(argv[i], "socket,"))
|
|
||||||
has_socket = 1;
|
for (dev = pci_devs; dev->mach; dev++) {
|
||||||
} else if (!strcmp(argv[i], "-net") ||
|
if (strstr(argv[i + 1], dev->mach) == argv[i + 1])
|
||||||
!strcmp(argv[i], "-netdev")) {
|
break;
|
||||||
in_netdev = 1;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*net_id && (p = strstr(argv[i], ",netdev=")))
|
if (!dev || !dev->mach)
|
||||||
strncpy(net_id, p + strlen(",netdev="), ARG_MAX);
|
dev = pci_devs;
|
||||||
|
|
||||||
|
for (qemu_argc = 1, i = 1; i < argc; i++) {
|
||||||
|
const struct drop_arg *a;
|
||||||
|
|
||||||
|
for (a = drop_args; a->name; a++) {
|
||||||
|
if (!strcmp(argv[i], a->name)) {
|
||||||
|
if (!a->val)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i + 1 < argc &&
|
||||||
|
strstr(argv[i + 1], a->val) == argv[i + 1])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (a->name) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[i], "-device") && i + 1 < argc) {
|
||||||
|
char *p;
|
||||||
|
long n;
|
||||||
|
|
||||||
|
has_dev = 1;
|
||||||
|
|
||||||
|
if ((p = strstr(argv[i + 1], dev->template))) {
|
||||||
|
n = strtol(p + strlen(dev->template), NULL, 16);
|
||||||
|
if (!errno)
|
||||||
|
addr_map |= (1 << n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qemu_argv[qemu_argc++] = argv[i];
|
qemu_argv[qemu_argc++] = argv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = dev->first; i < dev->last; i++) {
|
||||||
|
if (!(addr_map & (1 << i)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == dev->last) {
|
||||||
|
fprintf(stderr, "Couldn't find free address for device\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!has_socket) {
|
if (has_dev) {
|
||||||
if (*net_id) {
|
qemu_argv[qemu_argc++] = "-device";
|
||||||
net_id_end = strpbrk(net_id, ", ");
|
snprintf(dev_str, ARG_MAX, "%s,%s%x%s,netdev=hostnet0",
|
||||||
if (net_id_end)
|
dev->name, dev->template, i, dev->template_post);
|
||||||
*net_id_end = 0;
|
qemu_argv[qemu_argc++] = dev_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_argv[qemu_argc++] = "-netdev";
|
qemu_argv[qemu_argc++] = "-netdev";
|
||||||
snprintf(fd_str, ARG_MAX, "socket,fd=%u,id=%s", DEFAULT_FD,
|
qemu_argv[qemu_argc++] = "socket,fd=" STR(DEFAULT_FD) ",id=hostnet0";
|
||||||
*net_id ? net_id : "hostnet0");
|
|
||||||
qemu_argv[qemu_argc++] = fd_str;
|
|
||||||
qemu_argv[qemu_argc] = NULL;
|
qemu_argv[qemu_argc] = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
valid_args:
|
valid_args:
|
||||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
Loading…
Reference in a new issue