diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-03-05 14:27:24 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-05 14:27:24 +0000 |
commit | 41dfc0dc55f0b338ab3c1d29a1721441b76ebd03 (patch) | |
tree | ad63b36baa4dc7bdecef827063cdba2091d1fed7 /net | |
parent | 4a22592e32868db846898831c27fbee8e73e24e3 (diff) | |
parent | 46d4d36d0bf2b24b205f2f604f0905db80264eef (diff) | |
download | qemu-41dfc0dc55f0b338ab3c1d29a1721441b76ebd03.zip qemu-41dfc0dc55f0b338ab3c1d29a1721441b76ebd03.tar.gz qemu-41dfc0dc55f0b338ab3c1d29a1721441b76ebd03.tar.bz2 |
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
# gpg: Signature made Mon 05 Mar 2018 03:06:59 GMT
# gpg: using RSA key EF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211
* remotes/jasowang/tags/net-pull-request:
tap: setting error appropriately when calling net_init_tap_one()
hw/net: Remove unnecessary header includes
net: Add a new convenience option "--nic" to configure default/on-board NICs
net: Remove the deprecated 'host_net_add' and 'host_net_remove' HMP commands
net: Remove the deprecated way of dumping network packets
net: Make net_client_init() static
net: Only show vhost-user in the help text if CONFIG_POSIX is defined
net: List available netdevs with "-netdev help"
net: Move error reporting from net_init_client/netdev to the calling site
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/dump.c | 102 | ||||
-rw-r--r-- | net/net.c | 239 | ||||
-rw-r--r-- | net/tap.c | 22 |
3 files changed, 135 insertions, 228 deletions
@@ -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) \ @@ -60,26 +60,6 @@ static VMChangeStateEntry *net_change_state_entry; static QTAILQ_HEAD(, NetClientState) net_clients; -const char *host_net_devices[] = { - "tap", - "socket", - "dump", -#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 */ @@ -967,7 +947,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 +972,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 +1014,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; @@ -1086,15 +1060,50 @@ 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 + }; -int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) + printf("Available netdev backend types:\n"); + for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) { + puts(available_netdevs[idx]); + } +} + +static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { void *object = NULL; Error *err = NULL; 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"); @@ -1146,81 +1155,6 @@ 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); @@ -1520,46 +1454,92 @@ 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; + return net_client_init(opts, true, errp); +} - ret = net_client_init(opts, true, &local_err); - if (local_err) { - error_report_err(local_err); +/* 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(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(qemu_find_opts("nic"), net_param_nic, 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; } @@ -1634,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", @@ -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) { |