Make the init/exit of virtio-net self-contained, so the global init code won't need to check if it was selected or not. This also moves the bulk of the net-specific initialization code, including the parser, into virtio-net itself. Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> --- tools/kvm/builtin-run.c | 122 +++------------------------------ tools/kvm/include/kvm/virtio-net.h | 6 +- tools/kvm/virtio/net.c | 134 +++++++++++++++++++++++++++++++++++-- 3 files changed, 144 insertions(+), 118 deletions(-) diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c index 9a09376..7c6fe80 100644 --- a/tools/kvm/builtin-run.c +++ b/tools/kvm/builtin-run.c @@ -146,97 +146,6 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i return 0; } -static inline void str_to_mac(const char *str, char *mac) -{ - sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", - mac, mac+1, mac+2, mac+3, mac+4, mac+5); -} -static int set_net_param(struct virtio_net_params *p, const char *param, - const char *val) -{ - if (strcmp(param, "guest_mac") == 0) { - str_to_mac(val, p->guest_mac); - } else if (strcmp(param, "mode") == 0) { - if (!strncmp(val, "user", 4)) { - int i; - - for (i = 0; i < kvm->cfg.num_net_devices; i++) - if (kvm->cfg.net_params[i].mode == NET_MODE_USER) - die("Only one usermode network device allowed at a time"); - p->mode = NET_MODE_USER; - } else if (!strncmp(val, "tap", 3)) { - p->mode = NET_MODE_TAP; - } else if (!strncmp(val, "none", 4)) { - kvm->cfg.no_net = 1; - return -1; - } else - die("Unknown network mode %s, please use user, tap or none", kvm->cfg.network); - } else if (strcmp(param, "script") == 0) { - p->script = strdup(val); - } else if (strcmp(param, "guest_ip") == 0) { - p->guest_ip = strdup(val); - } else if (strcmp(param, "host_ip") == 0) { - p->host_ip = strdup(val); - } else if (strcmp(param, "trans") == 0) { - p->trans = strdup(val); - } else if (strcmp(param, "vhost") == 0) { - p->vhost = atoi(val); - } else if (strcmp(param, "fd") == 0) { - p->fd = atoi(val); - } else - die("Unknown network parameter %s", param); - - return 0; -} - -static int netdev_parser(const struct option *opt, const char *arg, int unset) -{ - struct virtio_net_params p; - char *buf = NULL, *cmd = NULL, *cur = NULL; - bool on_cmd = true; - - if (arg) { - buf = strdup(arg); - if (buf == NULL) - die("Failed allocating new net buffer"); - cur = strtok(buf, ",="); - } - - p = (struct virtio_net_params) { - .guest_ip = DEFAULT_GUEST_ADDR, - .host_ip = DEFAULT_HOST_ADDR, - .script = DEFAULT_SCRIPT, - .mode = NET_MODE_TAP, - }; - - str_to_mac(DEFAULT_GUEST_MAC, p.guest_mac); - p.guest_mac[5] += kvm->cfg.num_net_devices; - - while (cur) { - if (on_cmd) { - cmd = cur; - } else { - if (set_net_param(&p, cmd, cur) < 0) - goto done; - } - on_cmd = !on_cmd; - - cur = strtok(NULL, ",="); - }; - - kvm->cfg.num_net_devices++; - - kvm->cfg.net_params = realloc(kvm->cfg.net_params, kvm->cfg.num_net_devices * sizeof(*kvm->cfg.net_params)); - if (kvm->cfg.net_params == NULL) - die("Failed adding new network device"); - - kvm->cfg.net_params[kvm->cfg.num_net_devices - 1] = p; - -done: - free(buf); - return 0; -} - #define BUILD_OPTIONS(name, cfg, kvm) \ struct option name[] = { \ OPT_GROUP("Basic options:"), \ @@ -287,7 +196,7 @@ done: OPT_GROUP("Networking options:"), \ OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params", \ "Create a new guest NIC", \ - netdev_parser, NULL, NULL), \ + netdev_parser, NULL, kvm), \ OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel DHCP\ in rootfs mode"), \ \ @@ -739,7 +648,7 @@ static int kvm_cmd_run_init(int argc, const char **argv) static char real_cmdline[2048], default_name[20]; struct framebuffer *fb = NULL; unsigned int nr_online_cpus; - int i, r; + int r; kvm = kvm__new(); if (IS_ERR(kvm)) @@ -1023,25 +932,10 @@ static int kvm_cmd_run_init(int argc, const char **argv) virtio_9p__init(kvm); - for (i = 0; i < kvm->cfg.num_net_devices; i++) { - kvm->cfg.net_params[i].kvm = kvm; - virtio_net__init(&kvm->cfg.net_params[i]); - } - - if (kvm->cfg.num_net_devices == 0 && kvm->cfg.no_net == 0) { - struct virtio_net_params net_params; - - net_params = (struct virtio_net_params) { - .guest_ip = kvm->cfg.guest_ip, - .host_ip = kvm->cfg.host_ip, - .kvm = kvm, - .script = kvm->cfg.script, - .mode = NET_MODE_USER, - }; - str_to_mac(kvm->cfg.guest_mac, net_params.guest_mac); - str_to_mac(kvm->cfg.host_mac, net_params.host_mac); - - virtio_net__init(&net_params); + r = virtio_net__init(kvm); + if (r < 0) { + pr_err("virtio_net__init() failed with error %d\n", r); + goto fail; } kvm__init_ram(kvm); @@ -1158,6 +1052,10 @@ static void kvm_cmd_run_exit(int guest_ret) if (r < 0) pr_warning("kvm_timer__exit() failed with error %d\n", r); + r = virtio_net__exit(kvm); + if (r < 0) + pr_warning("virtio_net__exit() failed with error %d\n", r); + r = virtio_scsi_exit(kvm); if (r < 0) pr_warning("virtio_scsi_exit() failed with error %d\n", r); diff --git a/tools/kvm/include/kvm/virtio-net.h b/tools/kvm/include/kvm/virtio-net.h index 737676eb..db43d98 100644 --- a/tools/kvm/include/kvm/virtio-net.h +++ b/tools/kvm/include/kvm/virtio-net.h @@ -1,6 +1,8 @@ #ifndef KVM__VIRTIO_NET_H #define KVM__VIRTIO_NET_H +#include "kvm/parse-options.h" + struct kvm; struct virtio_net_params { @@ -16,7 +18,9 @@ struct virtio_net_params { int fd; }; -void virtio_net__init(const struct virtio_net_params *params); +int virtio_net__init(struct kvm *kvm); +int virtio_net__exit(struct kvm *kvm); +int netdev_parser(const struct option *opt, const char *arg, int unset); enum { NET_MODE_USER, diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c index 25bc3a4..4aca581 100644 --- a/tools/kvm/virtio/net.c +++ b/tools/kvm/virtio/net.c @@ -490,17 +490,106 @@ static void virtio_net__vhost_init(struct kvm *kvm, struct net_dev *ndev) free(mem); } -void virtio_net__init(const struct virtio_net_params *params) +static inline void str_to_mac(const char *str, char *mac) +{ + sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + mac, mac+1, mac+2, mac+3, mac+4, mac+5); +} +static int set_net_param(struct virtio_net_params *p, const char *param, + const char *val) +{ + if (strcmp(param, "guest_mac") == 0) { + str_to_mac(val, p->guest_mac); + } else if (strcmp(param, "mode") == 0) { + if (!strncmp(val, "user", 4)) { + int i; + + for (i = 0; i < kvm->cfg.num_net_devices; i++) + if (kvm->cfg.net_params[i].mode == NET_MODE_USER) + die("Only one usermode network device allowed at a time"); + p->mode = NET_MODE_USER; + } else if (!strncmp(val, "tap", 3)) { + p->mode = NET_MODE_TAP; + } else if (!strncmp(val, "none", 4)) { + kvm->cfg.no_net = 1; + return -1; + } else + die("Unknown network mode %s, please use user, tap or none", kvm->cfg.network); + } else if (strcmp(param, "script") == 0) { + p->script = strdup(val); + } else if (strcmp(param, "guest_ip") == 0) { + p->guest_ip = strdup(val); + } else if (strcmp(param, "host_ip") == 0) { + p->host_ip = strdup(val); + } else if (strcmp(param, "trans") == 0) { + p->trans = strdup(val); + } else if (strcmp(param, "vhost") == 0) { + p->vhost = atoi(val); + } else if (strcmp(param, "fd") == 0) { + p->fd = atoi(val); + } else + die("Unknown network parameter %s", param); + + return 0; +} + +int netdev_parser(const struct option *opt, const char *arg, int unset) +{ + struct virtio_net_params p; + char *buf = NULL, *cmd = NULL, *cur = NULL; + bool on_cmd = true; + struct kvm *kvm = opt->ptr; + + if (arg) { + buf = strdup(arg); + if (buf == NULL) + die("Failed allocating new net buffer"); + cur = strtok(buf, ",="); + } + + p = (struct virtio_net_params) { + .guest_ip = DEFAULT_GUEST_ADDR, + .host_ip = DEFAULT_HOST_ADDR, + .script = DEFAULT_SCRIPT, + .mode = NET_MODE_TAP, + }; + + str_to_mac(DEFAULT_GUEST_MAC, p.guest_mac); + p.guest_mac[5] += kvm->cfg.num_net_devices; + + while (cur) { + if (on_cmd) { + cmd = cur; + } else { + if (set_net_param(&p, cmd, cur) < 0) + goto done; + } + on_cmd = !on_cmd; + + cur = strtok(NULL, ",="); + }; + + kvm->cfg.num_net_devices++; + + kvm->cfg.net_params = realloc(kvm->cfg.net_params, kvm->cfg.num_net_devices * sizeof(*kvm->cfg.net_params)); + if (kvm->cfg.net_params == NULL) + die("Failed adding new network device"); + + kvm->cfg.net_params[kvm->cfg.num_net_devices - 1] = p; + +done: + free(buf); + return 0; +} + +static int virtio_net__init_one(struct virtio_net_params *params) { int i; struct net_dev *ndev; - if (!params) - return; - ndev = calloc(1, sizeof(struct net_dev)); if (ndev == NULL) - die("Failed allocating ndev"); + return -ENOMEM; list_add_tail(&ndev->list, &ndevs); @@ -543,4 +632,39 @@ void virtio_net__init(const struct virtio_net_params *params) if (compat_id == -1) compat_id = virtio_compat_add_message("virtio-net", "CONFIG_VIRTIO_NET"); + + return 0; +} + +int virtio_net__init(struct kvm *kvm) +{ + int i; + + for (i = 0; i < kvm->cfg.num_net_devices; i++) { + kvm->cfg.net_params[i].kvm = kvm; + virtio_net__init_one(&kvm->cfg.net_params[i]); + } + + if (kvm->cfg.num_net_devices == 0 && kvm->cfg.no_net == 0) { + struct virtio_net_params net_params; + + net_params = (struct virtio_net_params) { + .guest_ip = kvm->cfg.guest_ip, + .host_ip = kvm->cfg.host_ip, + .kvm = kvm, + .script = kvm->cfg.script, + .mode = NET_MODE_USER, + }; + str_to_mac(kvm->cfg.guest_mac, net_params.guest_mac); + str_to_mac(kvm->cfg.host_mac, net_params.host_mac); + + virtio_net__init_one(&net_params); + } + + return 0; +} + +int virtio_net__exit(struct kvm *kvm) +{ + return 0; } -- 1.7.12 -- 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