From 34f708b0b6bef9ac1e371879a47df5b5fb95726f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:30 +0100 Subject: [PATCH 1/9] net: Move error reporting from net_init_client/netdev to the calling site It looks strange that net_init_client() and net_init_netdev() both take an "Error **errp" parameter, but then do the error reporting with "error_report_err(local_err)" on their own. Let's move the error reporting to the calling site instead to simplify this code a little bit. Reviewed-by: Eric Blake Reviewed-by: Paolo Bonzini Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- include/net/net.h | 2 +- net/net.c | 29 +++++------------------------ vl.c | 3 ++- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index 3fc48e4f51a0..bdd4d9ffe436 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -206,7 +206,7 @@ extern const char *legacy_bootp_filename; int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp); int net_client_parse(QemuOptsList *opts_list, const char *str); -int net_init_clients(void); +int net_init_clients(Error **errp); void net_check_clients(void); void net_cleanup(void); void hmp_host_net_add(Monitor *mon, const QDict *qdict); diff --git a/net/net.c b/net/net.c index 7d429252586f..e213a619754a 100644 --- a/net/net.c +++ b/net/net.c @@ -1520,46 +1520,27 @@ void net_check_clients(void) static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) { - Error *local_err = NULL; - - net_client_init(opts, false, &local_err); - if (local_err) { - error_report_err(local_err); - return -1; - } - - return 0; + return net_client_init(opts, false, errp); } static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) { - Error *local_err = NULL; - int ret; - - ret = net_client_init(opts, true, &local_err); - if (local_err) { - error_report_err(local_err); - return -1; - } - - return ret; + return net_client_init(opts, true, errp); } -int net_init_clients(void) +int net_init_clients(Error **errp) { - QemuOptsList *net = qemu_find_opts("net"); - net_change_state_entry = qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL); QTAILQ_INIT(&net_clients); if (qemu_opts_foreach(qemu_find_opts("netdev"), - net_init_netdev, NULL, NULL)) { + net_init_netdev, NULL, errp)) { return -1; } - if (qemu_opts_foreach(net, net_init_client, NULL, NULL)) { + if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, errp)) { return -1; } diff --git a/vl.c b/vl.c index a33ac008fb5e..19316214260a 100644 --- a/vl.c +++ b/vl.c @@ -4489,7 +4489,8 @@ int main(int argc, char **argv, char **envp) colo_info_init(); - if (net_init_clients() < 0) { + if (net_init_clients(&err) < 0) { + error_report_err(err); exit(1); } From 547203ead4327b353c25753a3ebb0acdc0ed2cf5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:31 +0100 Subject: [PATCH 2/9] net: List available netdevs with "-netdev help" Other options like "-chardev" or "-device" feature a nice help text with the available devices when being called with "help" or "?". Since it is quite useful, especially if you want to see which network backends have been compiled into the QEMU binary, let's provide such a help text for "-netdev", too. Reviewed-by: Paolo Bonzini Reviewed-by: Eric Blake Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- net/net.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/net/net.c b/net/net.c index e213a619754a..cf07e15cd467 100644 --- a/net/net.c +++ b/net/net.c @@ -1086,6 +1086,38 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) return 0; } +static void show_netdevs(void) +{ + int idx; + const char *available_netdevs[] = { + "socket", + "hubport", + "tap", +#ifdef CONFIG_SLIRP + "user", +#endif +#ifdef CONFIG_L2TPV3 + "l2tpv3", +#endif +#ifdef CONFIG_VDE + "vde", +#endif +#ifdef CONFIG_NET_BRIDGE + "bridge", +#endif +#ifdef CONFIG_NETMAP + "netmap", +#endif +#ifdef CONFIG_POSIX + "vhost-user", +#endif + }; + + printf("Available netdev backend types:\n"); + for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) { + puts(available_netdevs[idx]); + } +} int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { @@ -1094,7 +1126,10 @@ int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) int ret = -1; Visitor *v = opts_visitor_new(opts); - { + if (is_netdev && is_help_option(qemu_opt_get(opts, "type"))) { + show_netdevs(); + exit(0); + } else { /* Parse convenience option format ip6-net=fec0::0[/64] */ const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); From 253dc14cadd00a3131b5a933e172236dd365f4bc Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:32 +0100 Subject: [PATCH 3/9] net: Only show vhost-user in the help text if CONFIG_POSIX is defined According to net/Makefile.objs we only link in the vhost-user code if CONFIG_POSIX has been set. So the help screen should also only show this information if CONFIG_POSIX has been defined. Reviewed-by: Paolo Bonzini Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- qemu-options.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index fea949dd561f..57815998f106 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1998,8 +1998,10 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " VALE port (created on the fly) called 'name' ('nmname' is name of the \n" " netmap device, defaults to '/dev/netmap')\n" #endif +#ifdef CONFIG_POSIX "-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n" " configure a vhost-user network, backed by a chardev 'dev'\n" +#endif "-netdev hubport,id=str,hubid=n[,netdev=nd]\n" " configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL) DEF("net", HAS_ARG, QEMU_OPTION_net, From aa09a485c239b163701a70b8da257537c663f71f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:33 +0100 Subject: [PATCH 4/9] net: Make net_client_init() static The function is only used within net.c, so there's no need that this is a global function. While we're at it, also remove the unused prototype compute_mcast_idx() (the function has been removed in commit d9caeb09b107e91122d10ba4a08a). Reviewed-by: Paolo Bonzini Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- include/net/net.h | 2 -- net/net.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/net/net.h b/include/net/net.h index bdd4d9ffe436..cd1708c18b32 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -204,7 +204,6 @@ extern const char *host_net_devices[]; extern const char *legacy_tftp_prefix; extern const char *legacy_bootp_filename; -int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp); int net_client_parse(QemuOptsList *opts_list, const char *str); int net_init_clients(Error **errp); void net_check_clients(void); @@ -228,7 +227,6 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd); #define POLYNOMIAL_LE 0xedb88320 uint32_t net_crc32(const uint8_t *p, int len); uint32_t net_crc32_le(const uint8_t *p, int len); -unsigned compute_mcast_idx(const uint8_t *ep); #define vmstate_offset_macaddr(_state, _field) \ vmstate_offset_array(_state, _field.a, uint8_t, \ diff --git a/net/net.c b/net/net.c index cf07e15cd467..dd80f1be989f 100644 --- a/net/net.c +++ b/net/net.c @@ -1119,7 +1119,7 @@ static void show_netdevs(void) } } -int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) +static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { void *object = NULL; Error *err = NULL; From 857d20873d18b3e90c7e7141fe7822f25b707159 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:34 +0100 Subject: [PATCH 5/9] net: Remove the deprecated way of dumping network packets "-net dump" has been marked as deprecated since QEMU v2.10, since it only works with the deprecated 'vlan' parameter (or hubs). Network dumping should be done with "-object filter-dump" nowadays instead. Since nobody complained so far about the deprecation message, let's finally get rid of "-net dump" now. Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- net/dump.c | 102 +----------------------------------------------- net/net.c | 9 +---- qapi/net.json | 29 +++----------- qemu-doc.texi | 6 --- qemu-options.hx | 8 ---- 5 files changed, 9 insertions(+), 145 deletions(-) diff --git a/net/dump.c b/net/dump.c index 15df9a497303..f16c3545e9de 100644 --- a/net/dump.c +++ b/net/dump.c @@ -109,7 +109,7 @@ static int net_dump_state_init(DumpState *s, const char *filename, fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644); if (fd < 0) { - error_setg_errno(errp, errno, "-net dump: can't open %s", filename); + error_setg_errno(errp, errno, "net dump: can't open %s", filename); return -1; } @@ -122,7 +122,7 @@ static int net_dump_state_init(DumpState *s, const char *filename, hdr.linktype = 1; if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { - error_setg_errno(errp, errno, "-net dump write error"); + error_setg_errno(errp, errno, "net dump write error"); close(fd); return -1; } @@ -136,104 +136,6 @@ static int net_dump_state_init(DumpState *s, const char *filename, return 0; } -/* Dumping via VLAN netclient */ - -struct DumpNetClient { - NetClientState nc; - DumpState ds; -}; -typedef struct DumpNetClient DumpNetClient; - -static ssize_t dumpclient_receive(NetClientState *nc, const uint8_t *buf, - size_t size) -{ - DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc); - struct iovec iov = { - .iov_base = (void *)buf, - .iov_len = size - }; - - return dump_receive_iov(&dc->ds, &iov, 1); -} - -static ssize_t dumpclient_receive_iov(NetClientState *nc, - const struct iovec *iov, int cnt) -{ - DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc); - - return dump_receive_iov(&dc->ds, iov, cnt); -} - -static void dumpclient_cleanup(NetClientState *nc) -{ - DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc); - - dump_cleanup(&dc->ds); -} - -static NetClientInfo net_dump_info = { - .type = NET_CLIENT_DRIVER_DUMP, - .size = sizeof(DumpNetClient), - .receive = dumpclient_receive, - .receive_iov = dumpclient_receive_iov, - .cleanup = dumpclient_cleanup, -}; - -int net_init_dump(const Netdev *netdev, const char *name, - NetClientState *peer, Error **errp) -{ - int len, rc; - const char *file; - char def_file[128]; - const NetdevDumpOptions *dump; - NetClientState *nc; - DumpNetClient *dnc; - - assert(netdev->type == NET_CLIENT_DRIVER_DUMP); - dump = &netdev->u.dump; - - assert(peer); - - error_report("'-net dump' is deprecated. " - "Please use '-object filter-dump' instead."); - - if (dump->has_file) { - file = dump->file; - } else { - int id; - int ret; - - ret = net_hub_id_for_client(peer, &id); - assert(ret == 0); /* peer must be on a hub */ - - snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", id); - file = def_file; - } - - if (dump->has_len) { - if (dump->len > INT_MAX) { - error_setg(errp, "invalid length: %"PRIu64, dump->len); - return -1; - } - len = dump->len; - } else { - len = 65536; - } - - nc = qemu_new_net_client(&net_dump_info, peer, "dump", name); - snprintf(nc->info_str, sizeof(nc->info_str), - "dump to %s (len=%d)", file, len); - - dnc = DO_UPCAST(DumpNetClient, nc, nc); - rc = net_dump_state_init(&dnc->ds, file, len, errp); - if (rc) { - qemu_del_net_client(nc); - } - return rc; -} - -/* Dumping via filter */ - #define TYPE_FILTER_DUMP "filter-dump" #define FILTER_DUMP(obj) \ diff --git a/net/net.c b/net/net.c index dd80f1be989f..cbd553df84b9 100644 --- a/net/net.c +++ b/net/net.c @@ -63,7 +63,6 @@ static QTAILQ_HEAD(, NetClientState) net_clients; const char *host_net_devices[] = { "tap", "socket", - "dump", #ifdef CONFIG_NET_BRIDGE "bridge", #endif @@ -967,7 +966,6 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( #ifdef CONFIG_NETMAP [NET_CLIENT_DRIVER_NETMAP] = net_init_netmap, #endif - [NET_CLIENT_DRIVER_DUMP] = net_init_dump, #ifdef CONFIG_NET_BRIDGE [NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge, #endif @@ -993,8 +991,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) netdev = object; name = netdev->id; - if (netdev->type == NET_CLIENT_DRIVER_DUMP || - netdev->type == NET_CLIENT_DRIVER_NIC || + if (netdev->type == NET_CLIENT_DRIVER_NIC || !net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a netdev backend type"); @@ -1036,10 +1033,6 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) legacy.type = NET_CLIENT_DRIVER_VDE; legacy.u.vde = opts->u.vde; break; - case NET_LEGACY_OPTIONS_TYPE_DUMP: - legacy.type = NET_CLIENT_DRIVER_DUMP; - legacy.u.dump = opts->u.dump; - break; case NET_LEGACY_OPTIONS_TYPE_BRIDGE: legacy.type = NET_CLIENT_DRIVER_BRIDGE; legacy.u.bridge = opts->u.bridge; diff --git a/qapi/net.json b/qapi/net.json index 1238ba5de1eb..9117c569723b 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -39,8 +39,8 @@ # # Add a network backend. # -# @type: the type of network backend. Current valid values are 'user', 'tap', -# 'vde', 'socket', 'dump' and 'bridge' +# @type: the type of network backend. Possible values are listed in +# NetClientDriver (excluding 'none' and 'nic') # # @id: the name of the new network backend # @@ -371,23 +371,6 @@ '*group': 'str', '*mode': 'uint16' } } -## -# @NetdevDumpOptions: -# -# Dump VLAN network traffic to a file. -# -# @len: per-packet size limit (64k default). Understands [TGMKkb] -# suffixes. -# -# @file: dump file path (default is qemu-vlan0.pcap) -# -# Since: 1.2 -## -{ 'struct': 'NetdevDumpOptions', - 'data': { - '*len': 'size', - '*file': 'str' } } - ## # @NetdevBridgeOptions: # @@ -466,9 +449,11 @@ # Available netdev drivers. # # Since: 2.7 +# +# 'dump' - removed with 2.12 ## { 'enum': 'NetClientDriver', - 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump', + 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'bridge', 'hubport', 'netmap', 'vhost-user' ] } ## @@ -495,7 +480,6 @@ 'l2tpv3': 'NetdevL2TPv3Options', 'socket': 'NetdevSocketOptions', 'vde': 'NetdevVdeOptions', - 'dump': 'NetdevDumpOptions', 'bridge': 'NetdevBridgeOptions', 'hubport': 'NetdevHubPortOptions', 'netmap': 'NetdevNetmapOptions', @@ -530,7 +514,7 @@ ## { 'enum': 'NetLegacyOptionsType', 'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', - 'dump', 'bridge', 'netmap', 'vhost-user'] } + 'bridge', 'netmap', 'vhost-user'] } ## # @NetLegacyOptions: @@ -550,7 +534,6 @@ 'l2tpv3': 'NetdevL2TPv3Options', 'socket': 'NetdevSocketOptions', 'vde': 'NetdevVdeOptions', - 'dump': 'NetdevDumpOptions', 'bridge': 'NetdevBridgeOptions', 'netmap': 'NetdevNetmapOptions', 'vhost-user': 'NetdevVhostUserOptions' } } diff --git a/qemu-doc.texi b/qemu-doc.texi index b3c276362447..0453ad9f5feb 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2707,12 +2707,6 @@ that can be specified with the ``-device'' parameter. The drive addr argument is replaced by the the addr argument that can be specified with the ``-device'' parameter. -@subsection -net dump (since 2.10.0) - -The ``--net dump'' argument is now replaced with the -``-object filter-dump'' argument which works in combination -with the modern ``-netdev`` backends instead. - @subsection -usbdevice (since 2.10.0) The ``-usbdevice DEV'' argument is now a synonym for setting diff --git a/qemu-options.hx b/qemu-options.hx index 57815998f106..9ce0cfe2c5e4 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2009,8 +2009,6 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, " configure or create an on-board (or machine default) NIC and\n" " connect it either to VLAN 'n' or the netdev 'nd' (for pluggable\n" " NICs please use '-device devtype,netdev=nd' instead)\n" - "-net dump[,vlan=n][,file=f][,len=n]\n" - " dump traffic on vlan 'n' to file 'f' (max n bytes per packet)\n" "-net none use it alone to have zero network devices. If no -net option\n" " is provided, the default is '-net nic -net user'\n" "-net [" @@ -2458,12 +2456,6 @@ qemu -m 512 -object memory-backend-file,id=mem,size=512M,mem-path=/hugetlbfs,sha -device virtio-net-pci,netdev=net0 @end example -@item -net dump[,vlan=@var{n}][,file=@var{file}][,len=@var{len}] -Dump network traffic on VLAN @var{n} to file @var{file} (@file{qemu-vlan0.pcap} by default). -At most @var{len} bytes (64k by default) per packet are stored. The file format is -libpcap, so it can be analyzed with tools such as tcpdump or Wireshark. -Note: For devices created with '-netdev', use '-object filter-dump,...' instead. - @item -net none Indicate that no network devices should be configured. It is used to override the default configuration (@option{-net nic -net user}) which From 7cc28cb061040cb089d29de2d9a73f404b94bc66 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:35 +0100 Subject: [PATCH 6/9] net: Remove the deprecated 'host_net_add' and 'host_net_remove' HMP commands They are deprecated since QEMU v2.10, and so far nobody complained that these commands are still necessary for any reason - and since you can use 'netdev_add' and 'netdev_remove' instead, there also should not be any real reason. Since they are also standing in the way for the upcoming 'vlan' clean-up, it's now time to remove them. Reviewed-by: Paolo Bonzini Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- hmp-commands.hx | 30 ---------------- hmp.h | 3 -- monitor.c | 61 ------------------------------- net/net.c | 94 ------------------------------------------------ qemu-doc.texi | 10 ------ tests/test-hmp.c | 2 -- 6 files changed, 200 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index d26eb4119b9d..964eb515cf6c 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1288,36 +1288,6 @@ STEXI @item pcie_aer_inject_error @findex pcie_aer_inject_error Inject PCIe AER error -ETEXI - - { - .name = "host_net_add", - .args_type = "device:s,opts:s?", - .params = "tap|user|socket|vde|netmap|bridge|vhost-user|dump [options]", - .help = "add host VLAN client (deprecated, use netdev_add instead)", - .cmd = hmp_host_net_add, - .command_completion = host_net_add_completion, - }, - -STEXI -@item host_net_add -@findex host_net_add -Add host VLAN client. Deprecated, please use @code{netdev_add} instead. -ETEXI - - { - .name = "host_net_remove", - .args_type = "vlan_id:i,device:s", - .params = "vlan_id name", - .help = "remove host VLAN client (deprecated, use netdev_del instead)", - .cmd = hmp_host_net_remove, - .command_completion = host_net_remove_completion, - }, - -STEXI -@item host_net_remove -@findex host_net_remove -Remove host VLAN client. Deprecated, please use @code{netdev_del} instead. ETEXI { diff --git a/hmp.h b/hmp.h index 1143db44a760..b89733876de1 100644 --- a/hmp.h +++ b/hmp.h @@ -132,9 +132,6 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args, const char *str); void migrate_set_parameter_completion(ReadLineState *rs, int nb_args, const char *str); -void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str); -void host_net_remove_completion(ReadLineState *rs, int nb_args, - const char *str); void delvm_completion(ReadLineState *rs, int nb_args, const char *str); void loadvm_completion(ReadLineState *rs, int nb_args, const char *str); void hmp_rocker(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 308a3d9b7873..70eb1b95225a 100644 --- a/monitor.c +++ b/monitor.c @@ -3581,67 +3581,6 @@ void migrate_set_parameter_completion(ReadLineState *rs, int nb_args, } } -void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str) -{ - int i; - size_t len; - if (nb_args != 2) { - return; - } - len = strlen(str); - readline_set_completion_index(rs, len); - for (i = 0; host_net_devices[i]; i++) { - if (!strncmp(host_net_devices[i], str, len)) { - readline_add_completion(rs, host_net_devices[i]); - } - } -} - -void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) -{ - NetClientState *ncs[MAX_QUEUE_NUM]; - int count, i, len; - - len = strlen(str); - readline_set_completion_index(rs, len); - if (nb_args == 2) { - count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_DRIVER_NONE, - MAX_QUEUE_NUM); - for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { - int id; - char name[16]; - - if (net_hub_id_for_client(ncs[i], &id)) { - continue; - } - snprintf(name, sizeof(name), "%d", id); - if (!strncmp(str, name, len)) { - readline_add_completion(rs, name); - } - } - return; - } else if (nb_args == 3) { - count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_DRIVER_NIC, - MAX_QUEUE_NUM); - for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { - int id; - const char *name; - - if (ncs[i]->info->type == NET_CLIENT_DRIVER_HUBPORT || - net_hub_id_for_client(ncs[i], &id)) { - continue; - } - name = ncs[i]->name; - if (!strncmp(str, name, len)) { - readline_add_completion(rs, name); - } - } - return; - } -} - static void vm_completion(ReadLineState *rs, const char *str) { size_t len; diff --git a/net/net.c b/net/net.c index cbd553df84b9..2d05808d64a6 100644 --- a/net/net.c +++ b/net/net.c @@ -60,25 +60,6 @@ static VMChangeStateEntry *net_change_state_entry; static QTAILQ_HEAD(, NetClientState) net_clients; -const char *host_net_devices[] = { - "tap", - "socket", -#ifdef CONFIG_NET_BRIDGE - "bridge", -#endif -#ifdef CONFIG_NETMAP - "netmap", -#endif -#ifdef CONFIG_SLIRP - "user", -#endif -#ifdef CONFIG_VDE - "vde", -#endif - "vhost-user", - NULL, -}; - /***********************************************************/ /* network device redirectors */ @@ -1174,81 +1155,6 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) return ret; } - -static int net_host_check_device(const char *device) -{ - int i; - for (i = 0; host_net_devices[i]; i++) { - if (!strncmp(host_net_devices[i], device, - strlen(host_net_devices[i]))) { - return 1; - } - } - - return 0; -} - -void hmp_host_net_add(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *opts_str = qdict_get_try_str(qdict, "opts"); - Error *local_err = NULL; - QemuOpts *opts; - static bool warned; - - if (!warned && !qtest_enabled()) { - error_report("host_net_add is deprecated, use netdev_add instead"); - warned = true; - } - - if (!net_host_check_device(device)) { - monitor_printf(mon, "invalid host network device %s\n", device); - return; - } - - opts = qemu_opts_parse_noisily(qemu_find_opts("net"), - opts_str ? opts_str : "", false); - if (!opts) { - return; - } - - qemu_opt_set(opts, "type", device, &error_abort); - - net_client_init(opts, false, &local_err); - if (local_err) { - error_report_err(local_err); - monitor_printf(mon, "adding host network device %s failed\n", device); - } -} - -void hmp_host_net_remove(Monitor *mon, const QDict *qdict) -{ - NetClientState *nc; - int vlan_id = qdict_get_int(qdict, "vlan_id"); - const char *device = qdict_get_str(qdict, "device"); - static bool warned; - - if (!warned && !qtest_enabled()) { - error_report("host_net_remove is deprecated, use netdev_del instead"); - warned = true; - } - - nc = net_hub_find_client_by_name(vlan_id, device); - if (!nc) { - error_report("Host network device '%s' on hub '%d' not found", - device, vlan_id); - return; - } - if (nc->info->type == NET_CLIENT_DRIVER_NIC) { - error_report("invalid host network device '%s'", device); - return; - } - - qemu_del_net_client(nc->peer); - qemu_del_net_client(nc); - qemu_opts_del(qemu_opts_find(qemu_find_opts("net"), device)); -} - void netdev_add(QemuOpts *opts, Error **errp) { net_client_init(opts, true, errp); diff --git a/qemu-doc.texi b/qemu-doc.texi index 0453ad9f5feb..4fcc85acc7e8 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2760,16 +2760,6 @@ from qcow2 images. The ``query-cpus'' command is replaced by the ``query-cpus-fast'' command. -@section System emulator human monitor commands - -@subsection host_net_add (since 2.10.0) - -The ``host_net_add'' command is replaced by the ``netdev_add'' command. - -@subsection host_net_remove (since 2.10.0) - -The ``host_net_remove'' command is replaced by the ``netdev_del'' command. - @section System emulator devices @subsection ivshmem (since 2.6.0) diff --git a/tests/test-hmp.c b/tests/test-hmp.c index 5b7e447b6af2..5352c9c088ee 100644 --- a/tests/test-hmp.c +++ b/tests/test-hmp.c @@ -37,10 +37,8 @@ static const char *hmp_cmds[] = { "dump-guest-memory /dev/null 0 4096", "dump-guest-memory /dev/null", "gdbserver", - "host_net_add user id=net0", "hostfwd_add tcp::43210-:43210", "hostfwd_remove tcp::43210-:43210", - "host_net_remove 0 net0", "i /w 0", "log all", "log none", From 78cd6f7bf6b196a96388a37e730706cf0c497fda Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 21 Feb 2018 11:18:36 +0100 Subject: [PATCH 7/9] net: Add a new convenience option "--nic" to configure default/on-board NICs The legacy "-net" option can be quite confusing for the users since most people do not expect to get a "vlan" hub between their emulated guest hardware and the host backend. But so far, we are also not able to get rid of "-net" completely, since it is the only way to configure on-board NICs that can not be instantiated via "-device" yet. It's also a little bit shorter to type "-net nic -net tap" instead of "-device xyz,netdev=n1 -netdev tap,id=n1". So what we need is a new convenience option that is shorter to type than the full -device + -netdev stuff, and which can be used to configure the on-board NICs that can not be handled via -device yet. Thus this patch now provides such a new option "--nic": It adds an entry in the nd_table to configure a on-board / default NIC, creates a host backend and connects the two directly, without a confusing "vlan" hub inbetween. Reviewed-by: Paolo Bonzini Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- include/sysemu/sysemu.h | 1 + net/net.c | 78 +++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 40 +++++++++++++++++---- vl.c | 7 ++++ 4 files changed, 120 insertions(+), 6 deletions(-) diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 77bb3da5828e..66f07616d54e 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -197,6 +197,7 @@ extern QemuOptsList bdrv_runtime_opts; extern QemuOptsList qemu_chardev_opts; extern QemuOptsList qemu_device_opts; extern QemuOptsList qemu_netdev_opts; +extern QemuOptsList qemu_nic_opts; extern QemuOptsList qemu_net_opts; extern QemuOptsList qemu_global_opts; extern QemuOptsList qemu_mon_opts; diff --git a/net/net.c b/net/net.c index 2d05808d64a6..0bab2695142a 100644 --- a/net/net.c +++ b/net/net.c @@ -1462,6 +1462,67 @@ static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) return net_client_init(opts, true, errp); } +/* For the convenience "--nic" parameter */ +static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp) +{ + char *mac, *nd_id; + int idx, ret; + NICInfo *ni; + const char *type; + + type = qemu_opt_get(opts, "type"); + if (type && g_str_equal(type, "none")) { + return 0; /* Nothing to do, default_net is cleared in vl.c */ + } + + idx = nic_get_free_idx(); + if (idx == -1 || nb_nics >= MAX_NICS) { + error_setg(errp, "no more on-board/default NIC slots available"); + return -1; + } + + if (!type) { + qemu_opt_set(opts, "type", "user", &error_abort); + } + + ni = &nd_table[idx]; + memset(ni, 0, sizeof(*ni)); + ni->model = qemu_opt_get_del(opts, "model"); + + /* Create an ID if the user did not specify one */ + nd_id = g_strdup(qemu_opts_id(opts)); + if (!nd_id) { + nd_id = g_strdup_printf("__org.qemu.nic%i\n", idx); + qemu_opts_set_id(opts, nd_id); + } + + /* Handle MAC address */ + mac = qemu_opt_get_del(opts, "mac"); + if (mac) { + ret = net_parse_macaddr(ni->macaddr.a, mac); + g_free(mac); + if (ret) { + error_setg(errp, "invalid syntax for ethernet address"); + return -1; + } + if (is_multicast_ether_addr(ni->macaddr.a)) { + error_setg(errp, "NIC cannot have multicast MAC address"); + return -1; + } + } + qemu_macaddr_default_if_unset(&ni->macaddr); + + ret = net_client_init(opts, true, errp); + if (ret == 0) { + ni->netdev = qemu_find_netdev(nd_id); + ni->used = true; + nb_nics++; + } + + g_free(nd_id); + return ret; +} + int net_init_clients(Error **errp) { net_change_state_entry = @@ -1474,6 +1535,10 @@ int net_init_clients(Error **errp) return -1; } + if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) { + return -1; + } + if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, errp)) { return -1; } @@ -1549,6 +1614,19 @@ QemuOptsList qemu_netdev_opts = { }, }; +QemuOptsList qemu_nic_opts = { + .name = "nic", + .implied_opt_name = "type", + .head = QTAILQ_HEAD_INITIALIZER(qemu_nic_opts.head), + .desc = { + /* + * no elements => accept any params + * validation will happen later + */ + { /* end of list */ } + }, +}; + QemuOptsList qemu_net_opts = { .name = "net", .implied_opt_name = "type", diff --git a/qemu-options.hx b/qemu-options.hx index 9ce0cfe2c5e4..2a22a62f743b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2004,13 +2004,34 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #endif "-netdev hubport,id=str,hubid=n[,netdev=nd]\n" " configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL) +DEF("nic", HAS_ARG, QEMU_OPTION_nic, + "--nic [tap|bridge|" +#ifdef CONFIG_SLIRP + "user|" +#endif +#ifdef __linux__ + "l2tpv3|" +#endif +#ifdef CONFIG_VDE + "vde|" +#endif +#ifdef CONFIG_NETMAP + "netmap|" +#endif +#ifdef CONFIG_POSIX + "vhost-user|" +#endif + "socket][,option][,...][mac=macaddr]\n" + " initialize an on-board / default host NIC (using MAC address\n" + " macaddr) and connect it to the given host network backend\n" + "--nic none use it alone to have zero network devices (the default is to\n" + " provided a 'user' network connection)\n", + QEMU_ARCH_ALL) DEF("net", HAS_ARG, QEMU_OPTION_net, "-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n" " configure or create an on-board (or machine default) NIC and\n" " connect it either to VLAN 'n' or the netdev 'nd' (for pluggable\n" " NICs please use '-device devtype,netdev=nd' instead)\n" - "-net none use it alone to have zero network devices. If no -net option\n" - " is provided, the default is '-net nic -net user'\n" "-net [" #ifdef CONFIG_SLIRP "user|" @@ -2456,10 +2477,17 @@ qemu -m 512 -object memory-backend-file,id=mem,size=512M,mem-path=/hugetlbfs,sha -device virtio-net-pci,netdev=net0 @end example -@item -net none -Indicate that no network devices should be configured. It is used to -override the default configuration (@option{-net nic -net user}) which -is activated if no @option{-net} options are provided. +@item --nic [tap|bridge|user|l2tpv3|vde|netmap|vhost-user|socket][,...][,mac=macaddr] + +This option is a shortcut for setting both, the on-board (default) guest NIC +hardware and the host network backend in one go. The host backend options are +the same as with the corresponding @option{--netdev} option. The guest NIC +hardware MAC address can be set with @option{mac=@var{macaddr}}. + +@item --nic none +Indicate that no network devices should be configured. It is used to override +the default configuration (default NIC with @option{--net user} backend) which +is activated if no other networking options are provided. ETEXI STEXI diff --git a/vl.c b/vl.c index 19316214260a..d15985ddac55 100644 --- a/vl.c +++ b/vl.c @@ -3091,6 +3091,7 @@ int main(int argc, char **argv, char **envp) qemu_add_opts(&qemu_chardev_opts); qemu_add_opts(&qemu_device_opts); qemu_add_opts(&qemu_netdev_opts); + qemu_add_opts(&qemu_nic_opts); qemu_add_opts(&qemu_net_opts); qemu_add_opts(&qemu_rtc_opts); qemu_add_opts(&qemu_global_opts); @@ -3311,6 +3312,12 @@ int main(int argc, char **argv, char **envp) exit(1); } break; + case QEMU_OPTION_nic: + default_net = 0; + if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) { + exit(1); + } + break; case QEMU_OPTION_net: default_net = 0; if (net_client_parse(qemu_find_opts("net"), optarg) == -1) { From b20219b6451546b9664ceae471b2622b54f0a4bd Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 22 Feb 2018 10:58:37 +0100 Subject: [PATCH 8/9] hw/net: Remove unnecessary header includes Headers like "hw/loader.h" and "qemu/sockets.h" are not needed in the hw/net/*.c files. And Some other headers are included via other headers already, so we can drop them, too. Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- hw/net/e1000.c | 1 - hw/net/lance.c | 3 --- hw/net/ne2000.c | 2 -- hw/net/pcnet-pci.c | 1 - hw/net/pcnet.c | 1 - hw/net/rtl8139.c | 2 -- hw/net/xgmac.c | 1 - 7 files changed, 11 deletions(-) diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 804ec0872165..c7f1695f57a3 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -30,7 +30,6 @@ #include "hw/pci/pci.h" #include "net/net.h" #include "net/checksum.h" -#include "hw/loader.h" #include "sysemu/sysemu.h" #include "sysemu/dma.h" #include "qemu/iov.h" diff --git a/hw/net/lance.c b/hw/net/lance.c index 0028bc525d30..a08d5ac6a848 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -36,10 +36,7 @@ */ #include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "net/net.h" #include "qemu/timer.h" -#include "qemu/sockets.h" #include "hw/sparc/sparc32_dma.h" #include "hw/net/lance.h" #include "trace.h" diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index 687ef84aaca7..3a9fc89e484b 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -23,10 +23,8 @@ */ #include "qemu/osdep.h" #include "hw/pci/pci.h" -#include "net/net.h" #include "net/eth.h" #include "ne2000.h" -#include "hw/loader.h" #include "sysemu/sysemu.h" /* debug NE2000 card */ diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 0ae5ca470191..70dc8b3f0cdb 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -30,7 +30,6 @@ #include "qemu/osdep.h" #include "hw/pci/pci.h" #include "net/net.h" -#include "hw/loader.h" #include "qemu/timer.h" #include "sysemu/dma.h" #include "sysemu/sysemu.h" diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 606b05c09fc3..0c44554168a6 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -40,7 +40,6 @@ #include "net/net.h" #include "net/eth.h" #include "qemu/timer.h" -#include "qemu/sockets.h" #include "sysemu/sysemu.h" #include "trace.h" diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 1cc95b8cba86..46daa16202c3 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -58,9 +58,7 @@ #include "qemu/timer.h" #include "net/net.h" #include "net/eth.h" -#include "hw/loader.h" #include "sysemu/sysemu.h" -#include "qemu/iov.h" /* debug RTL8139 card */ //#define DEBUG_RTL8139 1 diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 0843bf185c14..fa001563d3de 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -28,7 +28,6 @@ #include "hw/sysbus.h" #include "qemu/log.h" #include "net/net.h" -#include "net/checksum.h" #ifdef DEBUG_XGMAC #define DEBUGF_BRK(message, args...) do { \ From 46d4d36d0bf2b24b205f2f604f0905db80264eef Mon Sep 17 00:00:00 2001 From: Jay Zhou Date: Fri, 2 Mar 2018 17:04:44 +0800 Subject: [PATCH 9/9] tap: setting error appropriately when calling net_init_tap_one() If netdev_add tap,id=net0,...,vhost=on failed in net_init_tap_one(), the followed up device_add virtio-net-pci,netdev=net0 will fail too, prints: TUNSETOFFLOAD ioctl() failed: Bad file descriptor TUNSETOFFLOAD ioctl() failed: Bad file descriptor The reason is that the fd of tap is closed when error occured after calling net_init_tap_one(). The fd should be closed when calling net_init_tap_one failed: - if tap_set_sndbuf() failed - if tap_set_sndbuf() succeeded but vhost failed to open or initialize with vhostforce flag on - with wrong vhost command line parameter The fd should not be closed just because vhost failed to open or initialize but without vhostforce flag. So the followed up device_add can fall back to userspace virtio successfully. Suggested-by: Michael S. Tsirkin Suggested-by: Igor Mammedov Suggested-by: Jason Wang Signed-off-by: Jay Zhou Signed-off-by: Jason Wang --- include/net/vhost_net.h | 3 +++ net/tap.c | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index afc1499eb998..77e47398c4ae 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -4,6 +4,9 @@ #include "net/net.h" #include "hw/virtio/vhost-backend.h" +#define VHOST_NET_INIT_FAILED \ + "vhost-net requested but could not be initialized" + struct vhost_net; typedef struct vhost_net VHostNetState; diff --git a/net/tap.c b/net/tap.c index 979e622e6078..2b3a36f9b50d 100644 --- a/net/tap.c +++ b/net/tap.c @@ -686,14 +686,23 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, if (vhostfdname) { vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err); if (vhostfd == -1) { - error_propagate(errp, err); + if (tap->has_vhostforce && tap->vhostforce) { + error_propagate(errp, err); + } else { + warn_report_err(err); + } return; } } else { vhostfd = open("/dev/vhost-net", O_RDWR); if (vhostfd < 0) { - error_setg_errno(errp, errno, - "tap: open vhost char device failed"); + if (tap->has_vhostforce && tap->vhostforce) { + error_setg_errno(errp, errno, + "tap: open vhost char device failed"); + } else { + warn_report("tap: open vhost char device failed: %s", + strerror(errno)); + } return; } fcntl(vhostfd, F_SETFL, O_NONBLOCK); @@ -702,8 +711,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, s->vhost_net = vhost_net_init(&options); if (!s->vhost_net) { - error_setg(errp, - "vhost-net requested but could not be initialized"); + if (tap->has_vhostforce && tap->vhostforce) { + error_setg(errp, VHOST_NET_INIT_FAILED); + } else { + warn_report(VHOST_NET_INIT_FAILED); + } return; } } else if (vhostfdname) {