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"
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define STR(x) STRINGIFY(x)
|
||||
|
||||
static char *qemu_names[] = {
|
||||
"kvm",
|
||||
"qemu-kvm",
|
||||
|
@ -37,6 +40,36 @@ static char *qemu_names[] = {
|
|||
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
|
||||
|
||||
/**
|
||||
|
@ -63,13 +96,13 @@ void usage(const char *name)
|
|||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *qemu_argv[ARG_MAX], net_id[ARG_MAX] = { 0 }, *net_id_end;
|
||||
int i, s, qemu_argc = 0, in_netdev = 0, has_socket = 0;
|
||||
char *qemu_argv[ARG_MAX], dev_str[ARG_MAX];
|
||||
int i, s, qemu_argc = 0, addr_map = 0, has_dev = 0;
|
||||
struct sockaddr_un addr = {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = UNIX_SOCK_PATH,
|
||||
};
|
||||
char fd_str[ARG_MAX];
|
||||
const struct pci_dev *dev = NULL;
|
||||
long fd;
|
||||
|
||||
if (argc >= 3) {
|
||||
|
@ -90,39 +123,73 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
fd = DEFAULT_FD;
|
||||
for (qemu_argc = 1, i = 1; i < argc; i++) {
|
||||
char *p;
|
||||
|
||||
if (in_netdev) {
|
||||
in_netdev = 0;
|
||||
if (strstr(argv[i], ",socket") ||
|
||||
strstr(argv[i], "socket,"))
|
||||
has_socket = 1;
|
||||
} else if (!strcmp(argv[i], "-net") ||
|
||||
!strcmp(argv[i], "-netdev")) {
|
||||
in_netdev = 1;
|
||||
for (i = 1; i < argc - 1; i++) {
|
||||
if (strcmp(argv[i], "-machine"))
|
||||
continue;
|
||||
|
||||
for (dev = pci_devs; dev->mach; dev++) {
|
||||
if (strstr(argv[i + 1], dev->mach) == argv[i + 1])
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*net_id && (p = strstr(argv[i], ",netdev=")))
|
||||
strncpy(net_id, p + strlen(",netdev="), ARG_MAX);
|
||||
if (!dev || !dev->mach)
|
||||
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];
|
||||
}
|
||||
|
||||
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 (*net_id) {
|
||||
net_id_end = strpbrk(net_id, ", ");
|
||||
if (net_id_end)
|
||||
*net_id_end = 0;
|
||||
if (has_dev) {
|
||||
qemu_argv[qemu_argc++] = "-device";
|
||||
snprintf(dev_str, ARG_MAX, "%s,%s%x%s,netdev=hostnet0",
|
||||
dev->name, dev->template, i, dev->template_post);
|
||||
qemu_argv[qemu_argc++] = dev_str;
|
||||
}
|
||||
|
||||
qemu_argv[qemu_argc++] = "-netdev";
|
||||
snprintf(fd_str, ARG_MAX, "socket,fd=%u,id=%s", DEFAULT_FD,
|
||||
*net_id ? net_id : "hostnet0");
|
||||
qemu_argv[qemu_argc++] = fd_str;
|
||||
qemu_argv[qemu_argc++] = "socket,fd=" STR(DEFAULT_FD) ",id=hostnet0";
|
||||
qemu_argv[qemu_argc] = NULL;
|
||||
}
|
||||
|
||||
valid_args:
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
|
Loading…
Reference in a new issue