From patchwork Wed Sep 5 08:31:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 1406601 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 61696DF264 for ; Wed, 5 Sep 2012 08:36:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758152Ab2IEIgQ (ORCPT ); Wed, 5 Sep 2012 04:36:16 -0400 Received: from mail-wg0-f44.google.com ([74.125.82.44]:58173 "EHLO mail-wg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750990Ab2IEIgO (ORCPT ); Wed, 5 Sep 2012 04:36:14 -0400 Received: by mail-wg0-f44.google.com with SMTP id dr13so393355wgb.1 for ; Wed, 05 Sep 2012 01:36:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=LxHodgQoAsqsyvJuATUPOZDwCcHzHgtvr+YLwr/pkkk=; b=W0G9Fw13mgC8EqSUe71oaMR2wxEv7mgR2y+hLynlzn32SWnn3emnJfaCMeNvI1O0/q xgQDfJNMFQSkRDqR5l/uxDPZW6GRKFMpK5HeGXjQcEU3B7pLcvJggcYVa8OFWwh5kdDl XGSzPfrgHI7Sp4C9hi+FIupNdldBL73ETpv2J4Lh9ELJgmJVBu8c2nMqPQ9n/sVkv+c+ ziAjMz/Jue7HMLHh8P6gIXenAubnJobcb/D5wP/eTuomEvFfPvJ6O4FESEmeXtoBzKLu b31CoWgyiXX76R4ECcWhhmjR6NqDbX8+WxtwiwWpKTkIMAZq+HAIhDhAujWXPI8cRWHR YN2g== Received: by 10.216.132.135 with SMTP id o7mr12270555wei.6.1346834174017; Wed, 05 Sep 2012 01:36:14 -0700 (PDT) Received: from lappy.capriciverd.com (20.Red-80-59-140.staticIP.rima-tde.net. [80.59.140.20]) by mx.google.com with ESMTPS id q4sm27971068wix.9.2012.09.05.01.36.11 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 05 Sep 2012 01:36:13 -0700 (PDT) From: Sasha Levin To: penberg@kernel.org Cc: asias.hejun@gmail.com, mingo@elte.hu, gorcunov@openvz.org, kvm@vger.kernel.org, Sasha Levin Subject: [PATCH 21/33] kvm tools: virtio-net init/exit Date: Wed, 5 Sep 2012 10:31:55 +0200 Message-Id: <1346833927-15740-22-git-send-email-levinsasha928@gmail.com> X-Mailer: git-send-email 1.7.12 In-Reply-To: <1346833927-15740-1-git-send-email-levinsasha928@gmail.com> References: <1346833927-15740-1-git-send-email-levinsasha928@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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 --- 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; }