2008-10-31 22:10:00 +03:00
|
|
|
/*
|
|
|
|
* QEMU System Emulator
|
|
|
|
*
|
|
|
|
* Copyright (c) 2003-2008 Fabrice Bellard
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
2018-02-01 14:18:31 +03:00
|
|
|
|
2016-01-29 20:50:00 +03:00
|
|
|
#include "qemu/osdep.h"
|
2009-03-07 19:52:02 +03:00
|
|
|
|
2012-10-24 10:43:34 +04:00
|
|
|
#include "net/net.h"
|
2012-10-24 13:27:28 +04:00
|
|
|
#include "clients.h"
|
|
|
|
#include "hub.h"
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-properties.h"
|
2012-10-24 10:43:34 +04:00
|
|
|
#include "net/slirp.h"
|
2013-10-21 12:08:44 +04:00
|
|
|
#include "net/eth.h"
|
2012-10-24 13:27:28 +04:00
|
|
|
#include "util.h"
|
2012-09-17 20:43:51 +04:00
|
|
|
|
2012-12-17 21:19:49 +04:00
|
|
|
#include "monitor/monitor.h"
|
2016-03-20 20:16:19 +03:00
|
|
|
#include "qemu/help_option.h"
|
2018-02-11 12:36:01 +03:00
|
|
|
#include "qapi/qapi-commands-net.h"
|
2021-04-02 06:05:20 +03:00
|
|
|
#include "qapi/qapi-visit-net.h"
|
2018-02-01 14:18:39 +03:00
|
|
|
#include "qapi/qmp/qdict.h"
|
2015-03-17 19:22:46 +03:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2015-03-17 20:29:20 +03:00
|
|
|
#include "qemu/error-report.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/sockets.h"
|
2016-03-20 20:16:19 +03:00
|
|
|
#include "qemu/cutils.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/config-file.h"
|
2019-05-23 17:35:06 +03:00
|
|
|
#include "qemu/ctype.h"
|
2021-02-15 12:02:25 +03:00
|
|
|
#include "qemu/id.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/iov.h"
|
2020-11-11 13:52:22 +03:00
|
|
|
#include "qemu/qemu-print.h"
|
2013-08-21 19:02:47 +04:00
|
|
|
#include "qemu/main-loop.h"
|
2018-02-01 14:18:46 +03:00
|
|
|
#include "qemu/option.h"
|
qapi: net: add stream and dgram netdevs
Copied from socket netdev file and modified to use SocketAddress
to be able to introduce new features like unix socket.
"udp" and "mcast" are squashed into dgram netdev, multicast is detected
according to the IP address type.
"listen" and "connect" modes are managed by stream netdev. An optional
parameter "server" defines the mode (off by default)
The two new types need to be parsed the modern way with -netdev, because
with the traditional way, the "type" field of netdev structure collides with
the "type" field of SocketAddress and prevents the correct evaluation of the
command line option. Moreover the traditional way doesn't allow to use
the same type (SocketAddress) several times with the -netdev option
(needed to specify "local" and "remote" addresses).
The previous commit paved the way for parsing the modern way, but
omitted one detail: how to pick modern vs. traditional, in
netdev_is_modern().
We want to pick based on the value of parameter "type". But how to
extract it from the option argument?
Parsing the option argument, either the modern or the traditional way,
extracts it for us, but only if parsing succeeds.
If parsing fails, there is no good option. No matter which parser we
pick, it'll be the wrong one for some arguments, and the error
reporting will be confusing.
Fortunately, the traditional parser accepts *anything* when called in
a certain way. This maximizes our chance to extract the value of
"type", and in turn minimizes the risk of confusing error reporting.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:11 +03:00
|
|
|
#include "qemu/keyval.h"
|
2018-02-01 14:18:31 +03:00
|
|
|
#include "qapi/error.h"
|
2012-07-17 18:17:13 +04:00
|
|
|
#include "qapi/opts-visitor.h"
|
2019-08-12 08:23:59 +03:00
|
|
|
#include "sysemu/runstate.h"
|
Add the function of colo_compare_cleanup
This patch fixes the following:
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007f6ae4559859 in __GI_abort () at abort.c:79
#2 0x0000559aaa386720 in error_exit (err=16, msg=0x559aaa5973d0 <__func__.16227> "qemu_mutex_destroy") at util/qemu-thread-posix.c:36
#3 0x0000559aaa3868c5 in qemu_mutex_destroy (mutex=0x559aabffe828) at util/qemu-thread-posix.c:69
#4 0x0000559aaa2f93a8 in char_finalize (obj=0x559aabffe800) at chardev/char.c:285
#5 0x0000559aaa23318a in object_deinit (obj=0x559aabffe800, type=0x559aabfd7d20) at qom/object.c:606
#6 0x0000559aaa2331b8 in object_deinit (obj=0x559aabffe800, type=0x559aabfd9060) at qom/object.c:610
#7 0x0000559aaa233200 in object_finalize (data=0x559aabffe800) at qom/object.c:620
#8 0x0000559aaa234202 in object_unref (obj=0x559aabffe800) at qom/object.c:1074
#9 0x0000559aaa2356b6 in object_finalize_child_property (obj=0x559aac0dac10, name=0x559aac778760 "compare0-0", opaque=0x559aabffe800) at qom/object.c:1584
#10 0x0000559aaa232f70 in object_property_del_all (obj=0x559aac0dac10) at qom/object.c:557
#11 0x0000559aaa2331ed in object_finalize (data=0x559aac0dac10) at qom/object.c:619
#12 0x0000559aaa234202 in object_unref (obj=0x559aac0dac10) at qom/object.c:1074
#13 0x0000559aaa2356b6 in object_finalize_child_property (obj=0x559aac0c75c0, name=0x559aac0dadc0 "chardevs", opaque=0x559aac0dac10) at qom/object.c:1584
#14 0x0000559aaa233071 in object_property_del_child (obj=0x559aac0c75c0, child=0x559aac0dac10, errp=0x0) at qom/object.c:580
#15 0x0000559aaa233155 in object_unparent (obj=0x559aac0dac10) at qom/object.c:599
#16 0x0000559aaa2fb721 in qemu_chr_cleanup () at chardev/char.c:1159
#17 0x0000559aa9f9b110 in main (argc=54, argv=0x7ffeb62fa998, envp=0x7ffeb62fab50) at vl.c:4539
When chardev is cleaned up, chr_write_lock needs to be destroyed. But
the colo-compare module is not cleaned up normally before it when the
guest poweroff. It is holding chr_write_lock at this time. This will
cause qemu crash.So we add the function of colo_compare_cleanup() before
qemu_chr_cleanup() to fix the bug.
Signed-off-by: Lei Rao <lei.rao@intel.com>
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
Reviewed-by: Lukas Straub <lukasstraub2@web.de>
Tested-by: Lukas Straub <lukasstraub2@web.de>
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2021-06-08 11:23:30 +03:00
|
|
|
#include "net/colo-compare.h"
|
2015-10-07 06:52:14 +03:00
|
|
|
#include "net/filter.h"
|
2016-01-26 09:43:33 +03:00
|
|
|
#include "qapi/string-output-visitor.h"
|
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.
More details from Markus:
qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().
net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net. Their desc[] are all empty, which means any
keys are accepted. The result of the parse (a QemuOpts) is stored in
the QemuOptsList.
Note that QemuOpts is flat by design. In some places, we layer non-flat
on top using dotted keys convention, but not here.
net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.
These functions pass the QemuOpts to net_client_init(). They also do
other things with the QemuOpts, which we can ignore here.
net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP
command netdev_add.
The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".
A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax. The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.
This commit paves the way to use of the modern way instead.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:09 +03:00
|
|
|
#include "qapi/qobject-input-visitor.h"
|
2009-03-07 18:32:56 +03:00
|
|
|
|
2012-02-04 12:24:46 +04:00
|
|
|
/* Net bridge is currently not supported for W32. */
|
|
|
|
#if !defined(_WIN32)
|
|
|
|
# define CONFIG_NET_BRIDGE
|
|
|
|
#endif
|
|
|
|
|
2014-09-04 12:39:13 +04:00
|
|
|
static VMChangeStateEntry *net_change_state_entry;
|
2023-01-24 15:19:30 +03:00
|
|
|
NetClientStateList net_clients;
|
2008-10-31 22:10:00 +03:00
|
|
|
|
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.
More details from Markus:
qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().
net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net. Their desc[] are all empty, which means any
keys are accepted. The result of the parse (a QemuOpts) is stored in
the QemuOptsList.
Note that QemuOpts is flat by design. In some places, we layer non-flat
on top using dotted keys convention, but not here.
net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.
These functions pass the QemuOpts to net_client_init(). They also do
other things with the QemuOpts, which we can ignore here.
net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP
command netdev_add.
The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".
A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax. The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.
This commit paves the way to use of the modern way instead.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:09 +03:00
|
|
|
typedef struct NetdevQueueEntry {
|
|
|
|
Netdev *nd;
|
|
|
|
Location loc;
|
|
|
|
QSIMPLEQ_ENTRY(NetdevQueueEntry) entry;
|
|
|
|
} NetdevQueueEntry;
|
|
|
|
|
|
|
|
typedef QSIMPLEQ_HEAD(, NetdevQueueEntry) NetdevQueue;
|
|
|
|
|
|
|
|
static NetdevQueue nd_queue = QSIMPLEQ_HEAD_INITIALIZER(nd_queue);
|
|
|
|
|
2008-10-31 22:10:00 +03:00
|
|
|
/***********************************************************/
|
|
|
|
/* network device redirectors */
|
|
|
|
|
2022-10-21 12:09:06 +03:00
|
|
|
int convert_host_port(struct sockaddr_in *saddr, const char *host,
|
|
|
|
const char *port, Error **errp)
|
2008-10-31 22:10:00 +03:00
|
|
|
{
|
|
|
|
struct hostent *he;
|
2022-10-21 12:09:06 +03:00
|
|
|
const char *r;
|
|
|
|
long p;
|
2008-10-31 22:10:00 +03:00
|
|
|
|
2021-08-13 18:05:03 +03:00
|
|
|
memset(saddr, 0, sizeof(*saddr));
|
|
|
|
|
2008-10-31 22:10:00 +03:00
|
|
|
saddr->sin_family = AF_INET;
|
2022-10-21 12:09:06 +03:00
|
|
|
if (host[0] == '\0') {
|
2008-10-31 22:10:00 +03:00
|
|
|
saddr->sin_addr.s_addr = 0;
|
|
|
|
} else {
|
2022-10-21 12:09:06 +03:00
|
|
|
if (qemu_isdigit(host[0])) {
|
|
|
|
if (!inet_aton(host, &saddr->sin_addr)) {
|
2017-09-04 17:35:39 +03:00
|
|
|
error_setg(errp, "host address '%s' is not a valid "
|
2022-10-21 12:09:06 +03:00
|
|
|
"IPv4 address", host);
|
|
|
|
return -1;
|
2017-09-04 17:35:39 +03:00
|
|
|
}
|
2008-10-31 22:10:00 +03:00
|
|
|
} else {
|
2022-10-21 12:09:06 +03:00
|
|
|
he = gethostbyname(host);
|
2017-09-04 17:35:39 +03:00
|
|
|
if (he == NULL) {
|
2022-10-21 12:09:06 +03:00
|
|
|
error_setg(errp, "can't resolve host address '%s'", host);
|
|
|
|
return -1;
|
2017-09-04 17:35:39 +03:00
|
|
|
}
|
2008-10-31 22:10:00 +03:00
|
|
|
saddr->sin_addr = *(struct in_addr *)he->h_addr;
|
|
|
|
}
|
|
|
|
}
|
2022-10-21 12:09:06 +03:00
|
|
|
if (qemu_strtol(port, &r, 0, &p) != 0) {
|
|
|
|
error_setg(errp, "port number '%s' is invalid", port);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
saddr->sin_port = htons(p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parse_host_port(struct sockaddr_in *saddr, const char *str,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
gchar **substrings;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
substrings = g_strsplit(str, ":", 2);
|
|
|
|
if (!substrings || !substrings[0] || !substrings[1]) {
|
|
|
|
error_setg(errp, "host address '%s' doesn't contain ':' "
|
|
|
|
"separating host from port", str);
|
2019-05-17 16:47:47 +03:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
2017-09-04 17:35:39 +03:00
|
|
|
}
|
2022-10-21 12:09:06 +03:00
|
|
|
|
|
|
|
ret = convert_host_port(saddr, substrings[0], substrings[1], errp);
|
2019-05-17 16:47:47 +03:00
|
|
|
|
|
|
|
out:
|
|
|
|
g_strfreev(substrings);
|
|
|
|
return ret;
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2015-03-14 07:09:25 +03:00
|
|
|
char *qemu_mac_strdup_printf(const uint8_t *macaddr)
|
|
|
|
{
|
|
|
|
return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
|
|
|
|
macaddr[0], macaddr[1], macaddr[2],
|
|
|
|
macaddr[3], macaddr[4], macaddr[5]);
|
|
|
|
}
|
|
|
|
|
2022-10-21 12:09:10 +03:00
|
|
|
void qemu_set_info_str(NetClientState *nc, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(nc->info_str, sizeof(nc->info_str), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
|
2009-01-07 20:46:21 +03:00
|
|
|
{
|
2022-10-21 12:09:10 +03:00
|
|
|
qemu_set_info_str(nc, "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
nc->model, macaddr[0], macaddr[1], macaddr[2],
|
|
|
|
macaddr[3], macaddr[4], macaddr[5]);
|
2009-01-07 20:46:21 +03:00
|
|
|
}
|
|
|
|
|
2015-05-21 12:44:48 +03:00
|
|
|
static int mac_table[256] = {0};
|
|
|
|
|
|
|
|
static void qemu_macaddr_set_used(MACAddr *macaddr)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = 0x56; index < 0xFF; index++) {
|
|
|
|
if (macaddr->a[5] == index) {
|
|
|
|
mac_table[index]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qemu_macaddr_set_free(MACAddr *macaddr)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } };
|
|
|
|
|
|
|
|
if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (index = 0x56; index < 0xFF; index++) {
|
|
|
|
if (macaddr->a[5] == index) {
|
|
|
|
mac_table[index]--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int qemu_macaddr_get_free(void)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = 0x56; index < 0xFF; index++) {
|
|
|
|
if (mac_table[index] == 0) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-10-21 17:25:22 +04:00
|
|
|
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
|
|
|
|
{
|
|
|
|
static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
|
2015-05-21 12:44:48 +03:00
|
|
|
static const MACAddr base = { .a = { 0x52, 0x54, 0x00, 0x12, 0x34, 0 } };
|
|
|
|
|
|
|
|
if (memcmp(macaddr, &zero, sizeof(zero)) != 0) {
|
|
|
|
if (memcmp(macaddr->a, &base.a, (sizeof(base.a) - 1)) != 0) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
qemu_macaddr_set_used(macaddr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-10-21 17:25:22 +04:00
|
|
|
|
|
|
|
macaddr->a[0] = 0x52;
|
|
|
|
macaddr->a[1] = 0x54;
|
|
|
|
macaddr->a[2] = 0x00;
|
|
|
|
macaddr->a[3] = 0x12;
|
|
|
|
macaddr->a[4] = 0x34;
|
2015-05-21 12:44:48 +03:00
|
|
|
macaddr->a[5] = qemu_macaddr_get_free();
|
|
|
|
qemu_macaddr_set_used(macaddr);
|
2009-10-21 17:25:22 +04:00
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:05 +04:00
|
|
|
/**
|
|
|
|
* Generate a name for net client
|
|
|
|
*
|
net: make network client name unique
assign_name() creates a name MODEL.NUM, where MODEL is the client's model,
and NUM is the number of MODELs that already exist.
Markus added NIC naming for non-VLAN clients in commit 53e51d85.
commit d33d93b2 incorrectly added a judgement of net-hub. It caused
net clients created with -netdev get same names.
eg:
# qemu-upstream -device virtio-net-pci,netdev=h1 -netdev tap,id=h1 \
-device virtio-net-pci,netdev=h2 -netdev tap,id=h2 ..
(qemu) info network
virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
\ h1: index=0,type=tap,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:57
\ h2: index=0,type=tap,ifname=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
This patch removed the check of nic-hub, and created unique names for
all net clients that have same model.
v2: update commitlog & comments
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2013-04-15 14:55:19 +04:00
|
|
|
* Only net clients created with the legacy -net option and NICs need this.
|
2012-07-24 19:35:05 +04:00
|
|
|
*/
|
2012-07-24 19:35:14 +04:00
|
|
|
static char *assign_name(NetClientState *nc1, const char *model)
|
2009-01-07 20:43:44 +03:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
NetClientState *nc;
|
2009-01-07 20:43:44 +03:00
|
|
|
int id = 0;
|
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
|
|
|
if (nc == nc1) {
|
2012-07-24 19:35:05 +04:00
|
|
|
continue;
|
2009-10-08 22:58:23 +04:00
|
|
|
}
|
net: make network client name unique
assign_name() creates a name MODEL.NUM, where MODEL is the client's model,
and NUM is the number of MODELs that already exist.
Markus added NIC naming for non-VLAN clients in commit 53e51d85.
commit d33d93b2 incorrectly added a judgement of net-hub. It caused
net clients created with -netdev get same names.
eg:
# qemu-upstream -device virtio-net-pci,netdev=h1 -netdev tap,id=h1 \
-device virtio-net-pci,netdev=h2 -netdev tap,id=h2 ..
(qemu) info network
virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
\ h1: index=0,type=tap,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:57
\ h2: index=0,type=tap,ifname=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
This patch removed the check of nic-hub, and created unique names for
all net clients that have same model.
v2: update commitlog & comments
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2013-04-15 14:55:19 +04:00
|
|
|
if (strcmp(nc->model, model) == 0) {
|
Fix automatically assigned network names for netdev
If a network client doesn't have a name, we make one up, with
assign_name(). assign_name() creates a name MODEL.NUM, where MODEL is
the client's model, and NUM is the number of MODELs that already
exist.
Bug: it misses clients that are not on a VLAN, i.e. netdevs and the
NICs using them:
$ qemu-system-x86_64 -nodefaults -vnc :0 -S -monitor stdio -netdev user,id=hostnet0 -net nic,netdev=hostnet0 -netdev user,id=hostnet1 -net nic,netdev=hostnet1
QEMU 0.14.50 monitor - type 'help' for more information
(qemu) info network
Devices not on any VLAN:
hostnet0: net=10.0.2.0, restricted=n peer=e1000.0
hostnet1: net=10.0.2.0, restricted=n peer=e1000.0
e1000.0: model=e1000,macaddr=52:54:00:12:34:56 peer=hostnet0
e1000.0: model=e1000,macaddr=52:54:00:12:34:57 peer=hostnet1
Fix that.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2011-06-16 20:45:36 +04:00
|
|
|
id++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-09 22:34:27 +04:00
|
|
|
return g_strdup_printf("%s.%d", model, id);
|
2009-01-07 20:43:44 +03:00
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:27 +04:00
|
|
|
static void qemu_net_client_destructor(NetClientState *nc)
|
|
|
|
{
|
|
|
|
g_free(nc);
|
|
|
|
}
|
2018-12-04 06:53:43 +03:00
|
|
|
static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
|
|
|
unsigned flags,
|
|
|
|
const struct iovec *iov,
|
|
|
|
int iovcnt,
|
|
|
|
void *opaque);
|
2013-01-30 15:12:27 +04:00
|
|
|
|
2013-01-30 15:12:26 +04:00
|
|
|
static void qemu_net_client_setup(NetClientState *nc,
|
|
|
|
NetClientInfo *info,
|
|
|
|
NetClientState *peer,
|
|
|
|
const char *model,
|
2013-01-30 15:12:27 +04:00
|
|
|
const char *name,
|
2021-10-20 07:55:55 +03:00
|
|
|
NetClientDestructor *destructor,
|
|
|
|
bool is_datapath)
|
2008-10-31 22:10:00 +03:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
nc->info = info;
|
|
|
|
nc->model = g_strdup(model);
|
2009-11-25 21:49:02 +03:00
|
|
|
if (name) {
|
2012-07-24 19:35:14 +04:00
|
|
|
nc->name = g_strdup(name);
|
2009-11-25 21:49:02 +03:00
|
|
|
} else {
|
2012-07-24 19:35:14 +04:00
|
|
|
nc->name = assign_name(nc, model);
|
2009-11-25 21:49:02 +03:00
|
|
|
}
|
2009-10-08 22:58:23 +04:00
|
|
|
|
2012-07-24 19:35:08 +04:00
|
|
|
if (peer) {
|
|
|
|
assert(!peer->peer);
|
2012-07-24 19:35:14 +04:00
|
|
|
nc->peer = peer;
|
|
|
|
peer->peer = nc;
|
2009-10-08 22:58:24 +04:00
|
|
|
}
|
2012-07-24 19:35:14 +04:00
|
|
|
QTAILQ_INSERT_TAIL(&net_clients, nc, next);
|
2008-10-31 22:10:00 +03:00
|
|
|
|
2015-10-07 06:52:17 +03:00
|
|
|
nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
|
2013-01-30 15:12:27 +04:00
|
|
|
nc->destructor = destructor;
|
2021-10-20 07:55:55 +03:00
|
|
|
nc->is_datapath = is_datapath;
|
2015-10-07 06:52:14 +03:00
|
|
|
QTAILQ_INIT(&nc->filters);
|
2013-01-30 15:12:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NetClientState *qemu_new_net_client(NetClientInfo *info,
|
|
|
|
NetClientState *peer,
|
|
|
|
const char *model,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
NetClientState *nc;
|
|
|
|
|
|
|
|
assert(info->size >= sizeof(NetClientState));
|
|
|
|
|
|
|
|
nc = g_malloc0(info->size);
|
2013-01-30 15:12:27 +04:00
|
|
|
qemu_net_client_setup(nc, info, peer, model, name,
|
2021-10-20 07:55:55 +03:00
|
|
|
qemu_net_client_destructor, true);
|
|
|
|
|
|
|
|
return nc;
|
|
|
|
}
|
|
|
|
|
|
|
|
NetClientState *qemu_new_net_control_client(NetClientInfo *info,
|
|
|
|
NetClientState *peer,
|
|
|
|
const char *model,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
NetClientState *nc;
|
|
|
|
|
|
|
|
assert(info->size >= sizeof(NetClientState));
|
|
|
|
|
|
|
|
nc = g_malloc0(info->size);
|
|
|
|
qemu_net_client_setup(nc, info, peer, model, name,
|
|
|
|
qemu_net_client_destructor, false);
|
2013-01-30 15:12:26 +04:00
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
return nc;
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2009-11-25 21:49:10 +03:00
|
|
|
NICState *qemu_new_nic(NetClientInfo *info,
|
|
|
|
NICConf *conf,
|
|
|
|
const char *model,
|
|
|
|
const char *name,
|
|
|
|
void *opaque)
|
|
|
|
{
|
2013-01-30 15:12:28 +04:00
|
|
|
NetClientState **peers = conf->peers.ncs;
|
2009-11-25 21:49:10 +03:00
|
|
|
NICState *nic;
|
2014-05-26 14:04:08 +04:00
|
|
|
int i, queues = MAX(1, conf->peers.queues);
|
2009-11-25 21:49:10 +03:00
|
|
|
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
assert(info->type == NET_CLIENT_DRIVER_NIC);
|
2009-11-25 21:49:10 +03:00
|
|
|
assert(info->size >= sizeof(NICState));
|
|
|
|
|
2013-02-22 19:15:06 +04:00
|
|
|
nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
|
|
|
|
nic->ncs = (void *)nic + info->size;
|
2009-11-25 21:49:10 +03:00
|
|
|
nic->conf = conf;
|
|
|
|
nic->opaque = opaque;
|
|
|
|
|
2013-02-22 19:15:06 +04:00
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
|
2021-10-20 07:55:55 +03:00
|
|
|
NULL, true);
|
2013-01-30 15:12:28 +04:00
|
|
|
nic->ncs[i].queue_index = i;
|
|
|
|
}
|
|
|
|
|
2009-11-25 21:49:10 +03:00
|
|
|
return nic;
|
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
|
|
|
|
{
|
2013-02-22 19:15:06 +04:00
|
|
|
return nic->ncs + queue_index;
|
2013-01-30 15:12:28 +04:00
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:22 +04:00
|
|
|
NetClientState *qemu_get_queue(NICState *nic)
|
|
|
|
{
|
2013-01-30 15:12:28 +04:00
|
|
|
return qemu_get_subqueue(nic, 0);
|
2013-01-30 15:12:22 +04:00
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:23 +04:00
|
|
|
NICState *qemu_get_nic(NetClientState *nc)
|
|
|
|
{
|
2013-01-30 15:12:28 +04:00
|
|
|
NetClientState *nc0 = nc - nc->queue_index;
|
|
|
|
|
2013-02-22 19:15:06 +04:00
|
|
|
return (NICState *)((void *)nc0 - nc->info->size);
|
2013-01-30 15:12:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void *qemu_get_nic_opaque(NetClientState *nc)
|
|
|
|
{
|
|
|
|
NICState *nic = qemu_get_nic(nc);
|
|
|
|
|
|
|
|
return nic->opaque;
|
|
|
|
}
|
|
|
|
|
2020-07-01 17:55:25 +03:00
|
|
|
NetClientState *qemu_get_peer(NetClientState *nc, int queue_index)
|
|
|
|
{
|
|
|
|
assert(nc != NULL);
|
|
|
|
NetClientState *ncs = nc + queue_index;
|
|
|
|
return ncs->peer;
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:15 +04:00
|
|
|
static void qemu_cleanup_net_client(NetClientState *nc)
|
2008-10-31 22:10:00 +03:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
QTAILQ_REMOVE(&net_clients, nc, next);
|
2008-10-31 22:10:00 +03:00
|
|
|
|
2013-02-13 02:16:06 +04:00
|
|
|
if (nc->info->cleanup) {
|
|
|
|
nc->info->cleanup(nc);
|
|
|
|
}
|
2010-09-20 20:08:41 +04:00
|
|
|
}
|
2009-10-08 22:58:23 +04:00
|
|
|
|
2012-07-24 19:35:15 +04:00
|
|
|
static void qemu_free_net_client(NetClientState *nc)
|
2010-09-20 20:08:41 +04:00
|
|
|
{
|
2013-08-02 23:47:08 +04:00
|
|
|
if (nc->incoming_queue) {
|
|
|
|
qemu_del_net_queue(nc->incoming_queue);
|
2012-07-24 19:35:11 +04:00
|
|
|
}
|
2012-07-24 19:35:14 +04:00
|
|
|
if (nc->peer) {
|
|
|
|
nc->peer->peer = NULL;
|
2010-09-20 20:08:41 +04:00
|
|
|
}
|
2012-07-24 19:35:14 +04:00
|
|
|
g_free(nc->name);
|
|
|
|
g_free(nc->model);
|
2013-01-30 15:12:27 +04:00
|
|
|
if (nc->destructor) {
|
|
|
|
nc->destructor(nc);
|
|
|
|
}
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:15 +04:00
|
|
|
void qemu_del_net_client(NetClientState *nc)
|
2010-09-20 20:08:41 +04:00
|
|
|
{
|
2013-01-30 15:12:28 +04:00
|
|
|
NetClientState *ncs[MAX_QUEUE_NUM];
|
|
|
|
int queues, i;
|
2015-10-07 06:52:14 +03:00
|
|
|
NetFilterState *nf, *next;
|
2013-01-30 15:12:28 +04:00
|
|
|
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
assert(nc->info->type != NET_CLIENT_DRIVER_NIC);
|
2014-12-23 19:53:20 +03:00
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
/* If the NetClientState belongs to a multiqueue backend, we will change all
|
|
|
|
* other NetClientStates also.
|
|
|
|
*/
|
|
|
|
queues = qemu_find_net_clients_except(nc->name, ncs,
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
NET_CLIENT_DRIVER_NIC,
|
2013-01-30 15:12:28 +04:00
|
|
|
MAX_QUEUE_NUM);
|
|
|
|
assert(queues != 0);
|
|
|
|
|
2015-10-07 06:52:14 +03:00
|
|
|
QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
|
|
|
|
object_unparent(OBJECT(nf));
|
|
|
|
}
|
|
|
|
|
2010-09-20 20:08:41 +04:00
|
|
|
/* If there is a peer NIC, delete and cleanup client, but do not free. */
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
|
2013-01-30 15:12:23 +04:00
|
|
|
NICState *nic = qemu_get_nic(nc->peer);
|
2010-09-20 20:08:41 +04:00
|
|
|
if (nic->peer_deleted) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nic->peer_deleted = true;
|
2013-01-30 15:12:28 +04:00
|
|
|
|
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
ncs[i]->peer->link_down = true;
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
if (nc->peer->info->link_status_changed) {
|
|
|
|
nc->peer->info->link_status_changed(nc->peer);
|
2010-09-20 20:08:41 +04:00
|
|
|
}
|
2013-01-30 15:12:28 +04:00
|
|
|
|
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
qemu_cleanup_net_client(ncs[i]);
|
|
|
|
}
|
|
|
|
|
2010-09-20 20:08:41 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
qemu_cleanup_net_client(ncs[i]);
|
|
|
|
qemu_free_net_client(ncs[i]);
|
|
|
|
}
|
2013-01-30 15:12:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void qemu_del_nic(NICState *nic)
|
|
|
|
{
|
2014-05-26 14:04:08 +04:00
|
|
|
int i, queues = MAX(nic->conf->peers.queues, 1);
|
2013-01-30 15:12:28 +04:00
|
|
|
|
2015-05-21 12:44:48 +03:00
|
|
|
qemu_macaddr_set_free(&nic->conf->macaddr);
|
|
|
|
|
2020-11-12 12:46:53 +03:00
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
NetClientState *nc = qemu_get_subqueue(nic, i);
|
|
|
|
/* If this is a peer NIC and peer has already been deleted, free it now. */
|
|
|
|
if (nic->peer_deleted) {
|
|
|
|
qemu_free_net_client(nc->peer);
|
|
|
|
} else if (nc->peer) {
|
|
|
|
/* if there are RX packets pending, complete them */
|
|
|
|
qemu_purge_queued_packets(nc->peer);
|
2009-06-24 16:42:31 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
for (i = queues - 1; i >= 0; i--) {
|
|
|
|
NetClientState *nc = qemu_get_subqueue(nic, i);
|
|
|
|
|
|
|
|
qemu_cleanup_net_client(nc);
|
|
|
|
qemu_free_net_client(nc);
|
|
|
|
}
|
2013-02-22 19:15:06 +04:00
|
|
|
|
|
|
|
g_free(nic);
|
2009-06-24 16:42:31 +04:00
|
|
|
}
|
|
|
|
|
2009-11-25 21:49:31 +03:00
|
|
|
void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
|
|
|
|
{
|
2012-07-24 19:35:13 +04:00
|
|
|
NetClientState *nc;
|
2009-11-25 21:49:31 +03:00
|
|
|
|
2012-07-24 19:35:12 +04:00
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
|
2013-01-30 15:12:28 +04:00
|
|
|
if (nc->queue_index == 0) {
|
|
|
|
func(qemu_get_nic(nc), opaque);
|
|
|
|
}
|
2009-11-25 21:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
bool qemu_has_ufo(NetClientState *nc)
|
2014-02-06 20:02:16 +04:00
|
|
|
{
|
2014-02-20 15:14:07 +04:00
|
|
|
if (!nc || !nc->info->has_ufo) {
|
2014-02-06 20:02:16 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
return nc->info->has_ufo(nc);
|
2014-02-06 20:02:16 +04:00
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
bool qemu_has_vnet_hdr(NetClientState *nc)
|
2014-02-06 20:02:16 +04:00
|
|
|
{
|
2014-02-20 15:14:07 +04:00
|
|
|
if (!nc || !nc->info->has_vnet_hdr) {
|
2014-02-06 20:02:16 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
return nc->info->has_vnet_hdr(nc);
|
2014-02-06 20:02:16 +04:00
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
|
2014-02-06 20:02:16 +04:00
|
|
|
{
|
2014-02-20 15:14:07 +04:00
|
|
|
if (!nc || !nc->info->has_vnet_hdr_len) {
|
2014-02-06 20:02:16 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
return nc->info->has_vnet_hdr_len(nc, len);
|
2014-02-06 20:02:16 +04:00
|
|
|
}
|
|
|
|
|
2023-02-23 13:20:05 +03:00
|
|
|
bool qemu_get_using_vnet_hdr(NetClientState *nc)
|
|
|
|
{
|
|
|
|
if (!nc || !nc->info->get_using_vnet_hdr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nc->info->get_using_vnet_hdr(nc);
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
|
2014-02-06 20:02:16 +04:00
|
|
|
{
|
2014-02-20 15:14:07 +04:00
|
|
|
if (!nc || !nc->info->using_vnet_hdr) {
|
2014-02-06 20:02:16 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
nc->info->using_vnet_hdr(nc, enable);
|
2014-02-06 20:02:16 +04:00
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
2014-02-06 20:02:16 +04:00
|
|
|
int ecn, int ufo)
|
|
|
|
{
|
2014-02-20 15:14:07 +04:00
|
|
|
if (!nc || !nc->info->set_offload) {
|
2014-02-06 20:02:16 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
|
2014-02-06 20:02:16 +04:00
|
|
|
}
|
|
|
|
|
2023-02-23 13:20:05 +03:00
|
|
|
int qemu_get_vnet_hdr_len(NetClientState *nc)
|
|
|
|
{
|
|
|
|
if (!nc || !nc->info->get_vnet_hdr_len) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nc->info->get_vnet_hdr_len(nc);
|
|
|
|
}
|
|
|
|
|
2014-02-20 15:14:07 +04:00
|
|
|
void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
|
2014-02-06 20:02:16 +04:00
|
|
|
{
|
2014-02-20 15:14:07 +04:00
|
|
|
if (!nc || !nc->info->set_vnet_hdr_len) {
|
2014-02-06 20:02:16 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-04 09:53:45 +03:00
|
|
|
nc->vnet_hdr_len = len;
|
2014-02-20 15:14:07 +04:00
|
|
|
nc->info->set_vnet_hdr_len(nc, len);
|
2014-02-06 20:02:16 +04:00
|
|
|
}
|
|
|
|
|
2015-06-17 16:23:44 +03:00
|
|
|
int qemu_set_vnet_le(NetClientState *nc, bool is_le)
|
|
|
|
{
|
2022-03-23 18:57:17 +03:00
|
|
|
#if HOST_BIG_ENDIAN
|
2015-06-17 16:23:44 +03:00
|
|
|
if (!nc || !nc->info->set_vnet_le) {
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nc->info->set_vnet_le(nc, is_le);
|
2015-10-14 12:11:27 +03:00
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
2015-06-17 16:23:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int qemu_set_vnet_be(NetClientState *nc, bool is_be)
|
|
|
|
{
|
2022-03-23 18:57:17 +03:00
|
|
|
#if HOST_BIG_ENDIAN
|
2015-10-14 12:11:27 +03:00
|
|
|
return 0;
|
|
|
|
#else
|
2015-06-17 16:23:44 +03:00
|
|
|
if (!nc || !nc->info->set_vnet_be) {
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nc->info->set_vnet_be(nc, is_be);
|
2015-10-14 12:11:27 +03:00
|
|
|
#endif
|
2015-06-17 16:23:44 +03:00
|
|
|
}
|
|
|
|
|
2021-02-24 06:44:36 +03:00
|
|
|
int qemu_can_receive_packet(NetClientState *nc)
|
|
|
|
{
|
|
|
|
if (nc->receive_disabled) {
|
|
|
|
return 0;
|
|
|
|
} else if (nc->info->can_receive &&
|
|
|
|
!nc->info->can_receive(nc)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:13 +04:00
|
|
|
int qemu_can_send_packet(NetClientState *sender)
|
2008-10-31 22:10:00 +03:00
|
|
|
{
|
2014-08-26 12:06:17 +04:00
|
|
|
int vm_running = runstate_is_running();
|
|
|
|
|
|
|
|
if (!vm_running) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:11 +04:00
|
|
|
if (!sender->peer) {
|
2009-10-08 22:58:24 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-02-24 06:44:36 +03:00
|
|
|
return qemu_can_receive_packet(sender->peer);
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2015-10-07 06:52:15 +03:00
|
|
|
static ssize_t filter_receive_iov(NetClientState *nc,
|
|
|
|
NetFilterDirection direction,
|
|
|
|
NetClientState *sender,
|
|
|
|
unsigned flags,
|
|
|
|
const struct iovec *iov,
|
|
|
|
int iovcnt,
|
|
|
|
NetPacketSent *sent_cb)
|
|
|
|
{
|
|
|
|
ssize_t ret = 0;
|
|
|
|
NetFilterState *nf = NULL;
|
|
|
|
|
2016-01-26 08:00:22 +03:00
|
|
|
if (direction == NET_FILTER_DIRECTION_TX) {
|
|
|
|
QTAILQ_FOREACH(nf, &nc->filters, next) {
|
|
|
|
ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
|
|
|
|
iovcnt, sent_cb);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2018-12-06 15:10:34 +03:00
|
|
|
QTAILQ_FOREACH_REVERSE(nf, &nc->filters, next) {
|
2016-01-26 08:00:22 +03:00
|
|
|
ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
|
|
|
|
iovcnt, sent_cb);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
2015-10-07 06:52:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t filter_receive(NetClientState *nc,
|
|
|
|
NetFilterDirection direction,
|
|
|
|
NetClientState *sender,
|
|
|
|
unsigned flags,
|
|
|
|
const uint8_t *data,
|
|
|
|
size_t size,
|
|
|
|
NetPacketSent *sent_cb)
|
|
|
|
{
|
|
|
|
struct iovec iov = {
|
|
|
|
.iov_base = (void *)data,
|
|
|
|
.iov_len = size
|
|
|
|
};
|
|
|
|
|
|
|
|
return filter_receive_iov(nc, direction, sender, flags, &iov, 1, sent_cb);
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
void qemu_purge_queued_packets(NetClientState *nc)
|
2009-06-18 21:21:29 +04:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
if (!nc->peer) {
|
2009-10-08 22:58:24 +04:00
|
|
|
return;
|
2009-10-08 22:58:32 +04:00
|
|
|
}
|
2009-10-08 22:58:24 +04:00
|
|
|
|
2013-08-02 23:47:08 +04:00
|
|
|
qemu_net_queue_purge(nc->peer->incoming_queue, nc);
|
2009-06-18 21:21:29 +04:00
|
|
|
}
|
|
|
|
|
2014-09-04 12:39:13 +04:00
|
|
|
void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
|
2009-04-29 14:48:12 +04:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
nc->receive_disabled = 0;
|
2009-10-08 22:58:32 +04:00
|
|
|
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_HUBPORT) {
|
2013-02-05 20:53:31 +04:00
|
|
|
if (net_hub_flush(nc->peer)) {
|
|
|
|
qemu_notify_event();
|
|
|
|
}
|
|
|
|
}
|
2013-08-02 23:47:08 +04:00
|
|
|
if (qemu_net_queue_flush(nc->incoming_queue)) {
|
2012-08-09 18:45:55 +04:00
|
|
|
/* We emptied the queue successfully, signal to the IO thread to repoll
|
|
|
|
* the file descriptor (for tap, for example).
|
|
|
|
*/
|
|
|
|
qemu_notify_event();
|
2014-09-04 12:39:13 +04:00
|
|
|
} else if (purge) {
|
|
|
|
/* Unable to empty the queue, purge remaining packets */
|
2020-05-11 07:04:53 +03:00
|
|
|
qemu_net_queue_purge(nc->incoming_queue, nc->peer);
|
2012-08-09 18:45:55 +04:00
|
|
|
}
|
2009-04-29 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2014-09-04 12:39:13 +04:00
|
|
|
void qemu_flush_queued_packets(NetClientState *nc)
|
|
|
|
{
|
|
|
|
qemu_flush_or_purge_queued_packets(nc, false);
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:13 +04:00
|
|
|
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
|
2009-10-22 20:43:41 +04:00
|
|
|
unsigned flags,
|
|
|
|
const uint8_t *buf, int size,
|
|
|
|
NetPacketSent *sent_cb)
|
2009-04-21 23:56:41 +04:00
|
|
|
{
|
2009-10-08 22:58:32 +04:00
|
|
|
NetQueue *queue;
|
2015-10-07 06:52:15 +03:00
|
|
|
int ret;
|
2009-01-08 22:44:06 +03:00
|
|
|
|
2008-10-31 22:10:00 +03:00
|
|
|
#ifdef DEBUG_NET
|
2009-10-08 22:58:24 +04:00
|
|
|
printf("qemu_send_packet_async:\n");
|
2020-08-22 21:09:50 +03:00
|
|
|
qemu_hexdump(stdout, "net", buf, size);
|
2008-10-31 22:10:00 +03:00
|
|
|
#endif
|
2009-04-29 15:15:26 +04:00
|
|
|
|
2012-07-24 19:35:11 +04:00
|
|
|
if (sender->link_down || !sender->peer) {
|
2009-10-08 22:58:32 +04:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2015-10-07 06:52:15 +03:00
|
|
|
/* Let filters handle the packet first */
|
|
|
|
ret = filter_receive(sender, NET_FILTER_DIRECTION_TX,
|
|
|
|
sender, flags, buf, size, sent_cb);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX,
|
|
|
|
sender, flags, buf, size, sent_cb);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-08-02 23:47:08 +04:00
|
|
|
queue = sender->peer->incoming_queue;
|
2009-10-08 22:58:32 +04:00
|
|
|
|
2009-10-22 20:43:41 +04:00
|
|
|
return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:13 +04:00
|
|
|
ssize_t qemu_send_packet_async(NetClientState *sender,
|
2009-10-22 20:43:41 +04:00
|
|
|
const uint8_t *buf, int size,
|
|
|
|
NetPacketSent *sent_cb)
|
|
|
|
{
|
|
|
|
return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
|
|
|
|
buf, size, sent_cb);
|
2009-04-29 15:15:26 +04:00
|
|
|
}
|
|
|
|
|
2019-01-17 14:43:54 +03:00
|
|
|
ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
|
2009-04-29 15:15:26 +04:00
|
|
|
{
|
2019-01-17 14:43:54 +03:00
|
|
|
return qemu_send_packet_async(nc, buf, size, NULL);
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2021-02-24 06:44:36 +03:00
|
|
|
ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
|
|
|
|
{
|
|
|
|
if (!qemu_can_receive_packet(nc)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qemu_net_queue_receive(nc->incoming_queue, buf, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov,
|
|
|
|
int iovcnt)
|
|
|
|
{
|
|
|
|
if (!qemu_can_receive_packet(nc)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qemu_net_queue_receive_iov(nc->incoming_queue, iov, iovcnt);
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
|
2009-10-22 20:43:41 +04:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
|
2009-10-22 20:43:41 +04:00
|
|
|
buf, size, NULL);
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
|
2015-10-07 06:52:16 +03:00
|
|
|
int iovcnt, unsigned flags)
|
2008-12-17 22:13:11 +03:00
|
|
|
{
|
2016-03-28 15:34:11 +03:00
|
|
|
uint8_t *buf = NULL;
|
2015-10-07 06:52:16 +03:00
|
|
|
uint8_t *buffer;
|
2011-02-24 03:57:21 +03:00
|
|
|
size_t offset;
|
2016-03-28 15:34:11 +03:00
|
|
|
ssize_t ret;
|
2008-12-17 22:13:11 +03:00
|
|
|
|
2015-10-07 06:52:16 +03:00
|
|
|
if (iovcnt == 1) {
|
|
|
|
buffer = iov[0].iov_base;
|
|
|
|
offset = iov[0].iov_len;
|
|
|
|
} else {
|
2016-06-30 12:49:40 +03:00
|
|
|
offset = iov_size(iov, iovcnt);
|
|
|
|
if (offset > NET_BUFSIZE) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
buf = g_malloc(offset);
|
2015-10-07 06:52:16 +03:00
|
|
|
buffer = buf;
|
2016-06-30 12:49:40 +03:00
|
|
|
offset = iov_to_buf(iov, iovcnt, 0, buf, offset);
|
2015-10-07 06:52:16 +03:00
|
|
|
}
|
2008-12-17 22:13:11 +03:00
|
|
|
|
2015-10-07 06:52:16 +03:00
|
|
|
if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
|
2016-03-28 15:34:11 +03:00
|
|
|
ret = nc->info->receive_raw(nc, buffer, offset);
|
2015-10-07 06:52:16 +03:00
|
|
|
} else {
|
2016-03-28 15:34:11 +03:00
|
|
|
ret = nc->info->receive(nc, buffer, offset);
|
2015-10-07 06:52:16 +03:00
|
|
|
}
|
2016-03-28 15:34:11 +03:00
|
|
|
|
|
|
|
g_free(buf);
|
|
|
|
return ret;
|
2008-12-17 22:13:11 +03:00
|
|
|
}
|
|
|
|
|
2018-12-04 06:53:43 +03:00
|
|
|
static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
|
|
|
|
unsigned flags,
|
|
|
|
const struct iovec *iov,
|
|
|
|
int iovcnt,
|
|
|
|
void *opaque)
|
2009-10-08 22:58:32 +04:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
NetClientState *nc = opaque;
|
2012-08-18 00:16:42 +04:00
|
|
|
int ret;
|
2009-10-08 22:58:32 +04:00
|
|
|
|
2018-05-30 08:16:36 +03:00
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
if (nc->link_down) {
|
2018-12-04 06:53:43 +03:00
|
|
|
return iov_size(iov, iovcnt);
|
2009-10-08 22:58:32 +04:00
|
|
|
}
|
|
|
|
|
2012-08-18 00:16:42 +04:00
|
|
|
if (nc->receive_disabled) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-09 12:39:27 +03:00
|
|
|
if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
|
2012-08-18 00:16:42 +04:00
|
|
|
ret = nc->info->receive_iov(nc, iov, iovcnt);
|
2009-10-08 22:58:32 +04:00
|
|
|
} else {
|
2015-10-07 06:52:16 +03:00
|
|
|
ret = nc_sendv_compat(nc, iov, iovcnt, flags);
|
2012-08-18 00:16:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
nc->receive_disabled = 1;
|
2009-04-29 14:48:12 +04:00
|
|
|
}
|
2012-08-18 00:16:42 +04:00
|
|
|
|
|
|
|
return ret;
|
2009-04-29 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:13 +04:00
|
|
|
ssize_t qemu_sendv_packet_async(NetClientState *sender,
|
2009-04-29 15:15:26 +04:00
|
|
|
const struct iovec *iov, int iovcnt,
|
|
|
|
NetPacketSent *sent_cb)
|
2009-04-29 14:48:12 +04:00
|
|
|
{
|
2009-10-08 22:58:32 +04:00
|
|
|
NetQueue *queue;
|
2018-12-04 06:53:43 +03:00
|
|
|
size_t size = iov_size(iov, iovcnt);
|
2015-10-07 06:52:15 +03:00
|
|
|
int ret;
|
2009-10-08 22:58:32 +04:00
|
|
|
|
2018-12-04 06:53:43 +03:00
|
|
|
if (size > NET_BUFSIZE) {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:11 +04:00
|
|
|
if (sender->link_down || !sender->peer) {
|
2018-12-04 06:53:43 +03:00
|
|
|
return size;
|
2009-04-29 14:48:12 +04:00
|
|
|
}
|
|
|
|
|
2015-10-07 06:52:15 +03:00
|
|
|
/* Let filters handle the packet first */
|
|
|
|
ret = filter_receive_iov(sender, NET_FILTER_DIRECTION_TX, sender,
|
|
|
|
QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, sender,
|
|
|
|
QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-08-02 23:47:08 +04:00
|
|
|
queue = sender->peer->incoming_queue;
|
2009-10-08 22:58:32 +04:00
|
|
|
|
2009-10-22 20:43:40 +04:00
|
|
|
return qemu_net_queue_send_iov(queue, sender,
|
|
|
|
QEMU_NET_PACKET_FLAG_NONE,
|
|
|
|
iov, iovcnt, sent_cb);
|
2008-12-17 22:13:11 +03:00
|
|
|
}
|
|
|
|
|
2009-04-29 15:15:26 +04:00
|
|
|
ssize_t
|
2012-07-24 19:35:14 +04:00
|
|
|
qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
|
2009-04-29 15:15:26 +04:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:13 +04:00
|
|
|
NetClientState *qemu_find_netdev(const char *id)
|
2009-10-08 22:58:29 +04:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
NetClientState *nc;
|
2009-10-08 22:58:29 +04:00
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->info->type == NET_CLIENT_DRIVER_NIC)
|
Fix netdev name lookup in -device, device_add, netdev_del
qemu_find_netdev() looks up members of non_vlan_clients by name. It
happily returns the first match. Trouble is the names need not be
unique.
non_vlan_clients contains host parts (netdevs) and guest parts (NICs).
Netdevs have unique names: a netdev's name is a (mandatory)
qemu_netdev_opts ID, and these are unique.
NIC names are not unique. If a NIC has a qdev ID (which is unique),
that's its name. Else, we make up a name. The made-up names are
unique, but they can clash with qdev IDs. Even if NICs had unique
names, they could still clash with netdev names.
Callers of qemu_find_netdev():
* net_init_nic() wants a netdev. It happens to work because it runs
before NICs get added to non_vlan_clients.
* do_netdev_del() wants a netdev. If it gets a NIC, it complains and
fails. Bug: a netdev with the same name that comes later in
non_vlan_clients can't be deleted:
$ qemu-system-x86_64 -nodefaults -vnc :0 -S -monitor stdio -netdev user,id=hostnet0 -device virtio-net-pci,netdev=hostnet0,id=virtio1
[...]
(qemu) netdev_add user,id=virtio1
(qemu) info network
Devices not on any VLAN:
hostnet0: net=10.0.2.0, restricted=n peer=virtio1
virtio1: model=virtio-net-pci,macaddr=52:54:00:12:34:56 peer=hostnet0
virtio1: net=10.0.2.0, restricted=n
(qemu) netdev_del virtio1
Device 'virtio1' not found
* parse_netdev() wants a netdev. If it gets a NIC, it gets confused.
With the test setup above:
(qemu) device_add virtio-net-pci,netdev=virtio1
Property 'virtio-net-pci.netdev' can't take value 'virtio1', it's in use
You can even connect two NICs to each other:
$ qemu-system-x86_64 -nodefaults -vnc :0 -S -monitor stdio -device virtio-net-pci,id=virtio1 -device e1000,netdev=virtio1
[...]
Devices not on any VLAN:
virtio1: model=virtio-net-pci,macaddr=52:54:00:12:34:56 peer=e1000.0
e1000.0: model=e1000,macaddr=52:54:00:12:34:57 peer=virtio1
(qemu) q
Segmentation fault (core dumped)
* do_set_link() works fine for both netdevs and NICs. Whether it
really makes sense for netdevs is debatable, but that's outside this
patch's scope.
Change qemu_find_netdev() to return only netdevs. This fixes the
netdev_del and device_add/-device bugs demonstrated above.
To avoid changing set_link, make do_set_link() search non_vlan_clients
by hand instead of calling qemu_find_netdev().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2011-06-16 20:45:37 +04:00
|
|
|
continue;
|
2012-07-24 19:35:14 +04:00
|
|
|
if (!strcmp(nc->name, id)) {
|
|
|
|
return nc;
|
2009-10-08 22:58:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-01-30 15:12:25 +04:00
|
|
|
int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
NetClientDriver type, int max)
|
2013-01-30 15:12:25 +04:00
|
|
|
{
|
|
|
|
NetClientState *nc;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
|
|
|
if (nc->info->type == type) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-05-08 02:41:30 +04:00
|
|
|
if (!id || !strcmp(nc->name, id)) {
|
2013-01-30 15:12:25 +04:00
|
|
|
if (ret < max) {
|
|
|
|
ncs[ret] = nc;
|
|
|
|
}
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-02-11 18:20:03 +03:00
|
|
|
static int nic_get_free_idx(void)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = 0; index < MAX_NICS; index++)
|
|
|
|
if (!nd_table[index].used)
|
|
|
|
return index;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-11-10 15:52:22 +03:00
|
|
|
GPtrArray *qemu_get_nic_models(const char *device_type)
|
|
|
|
{
|
|
|
|
GPtrArray *nic_models = g_ptr_array_new();
|
|
|
|
GSList *list = object_class_get_list_sorted(device_type, false);
|
|
|
|
|
|
|
|
while (list) {
|
|
|
|
DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, list->data,
|
|
|
|
TYPE_DEVICE);
|
|
|
|
GSList *next;
|
|
|
|
if (test_bit(DEVICE_CATEGORY_NETWORK, dc->categories) &&
|
|
|
|
dc->user_creatable) {
|
|
|
|
const char *name = object_class_get_name(list->data);
|
|
|
|
/*
|
|
|
|
* A network device might also be something else than a NIC, see
|
|
|
|
* e.g. the "rocker" device. Thus we have to look for the "netdev"
|
|
|
|
* property, too. Unfortunately, some devices like virtio-net only
|
|
|
|
* create this property during instance_init, so we have to create
|
|
|
|
* a temporary instance here to be able to check it.
|
|
|
|
*/
|
|
|
|
Object *obj = object_new_with_class(OBJECT_CLASS(dc));
|
|
|
|
if (object_property_find(obj, "netdev")) {
|
|
|
|
g_ptr_array_add(nic_models, (gpointer)name);
|
|
|
|
}
|
|
|
|
object_unref(obj);
|
|
|
|
}
|
|
|
|
next = list->next;
|
|
|
|
g_slist_free_1(list);
|
|
|
|
list = next;
|
|
|
|
}
|
|
|
|
g_ptr_array_add(nic_models, NULL);
|
|
|
|
|
|
|
|
return nic_models;
|
|
|
|
}
|
|
|
|
|
2009-09-25 05:53:51 +04:00
|
|
|
int qemu_show_nic_models(const char *arg, const char *const *models)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-08-02 16:45:54 +04:00
|
|
|
if (!arg || !is_help_option(arg)) {
|
2009-09-25 05:53:51 +04:00
|
|
|
return 0;
|
2012-08-02 16:45:54 +04:00
|
|
|
}
|
2009-09-25 05:53:51 +04:00
|
|
|
|
2022-11-10 15:52:24 +03:00
|
|
|
printf("Available NIC models:\n");
|
2019-04-23 19:06:08 +03:00
|
|
|
for (i = 0 ; models[i]; i++) {
|
|
|
|
printf("%s\n", models[i]);
|
|
|
|
}
|
2009-09-25 05:53:51 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-01-13 22:03:57 +03:00
|
|
|
void qemu_check_nic_model(NICInfo *nd, const char *model)
|
|
|
|
{
|
|
|
|
const char *models[2];
|
|
|
|
|
|
|
|
models[0] = model;
|
|
|
|
models[1] = NULL;
|
|
|
|
|
2009-09-25 05:53:51 +04:00
|
|
|
if (qemu_show_nic_models(nd->model, models))
|
|
|
|
exit(0);
|
|
|
|
if (qemu_find_nic_model(nd, models, model) < 0)
|
|
|
|
exit(1);
|
2009-01-13 22:03:57 +03:00
|
|
|
}
|
|
|
|
|
2009-09-25 05:53:51 +04:00
|
|
|
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
|
|
|
|
const char *default_model)
|
2009-01-13 22:03:57 +03:00
|
|
|
{
|
2009-09-25 05:53:51 +04:00
|
|
|
int i;
|
2009-01-13 22:03:57 +03:00
|
|
|
|
|
|
|
if (!nd->model)
|
2011-08-21 07:09:37 +04:00
|
|
|
nd->model = g_strdup(default_model);
|
2009-01-13 22:03:57 +03:00
|
|
|
|
2009-09-25 05:53:51 +04:00
|
|
|
for (i = 0 ; models[i]; i++) {
|
|
|
|
if (strcmp(nd->model, models[i]) == 0)
|
|
|
|
return i;
|
2009-01-13 22:03:57 +03:00
|
|
|
}
|
|
|
|
|
2011-06-22 16:03:54 +04:00
|
|
|
error_report("Unsupported NIC model: %s", nd->model);
|
2009-09-25 05:53:51 +04:00
|
|
|
return -1;
|
2009-01-13 22:03:57 +03:00
|
|
|
}
|
|
|
|
|
2016-07-14 06:50:12 +03:00
|
|
|
static int net_init_nic(const Netdev *netdev, const char *name,
|
2015-05-15 14:58:50 +03:00
|
|
|
NetClientState *peer, Error **errp)
|
2009-10-06 15:17:06 +04:00
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
NICInfo *nd;
|
2012-07-17 18:17:14 +04:00
|
|
|
const NetLegacyNicOptions *nic;
|
|
|
|
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
assert(netdev->type == NET_CLIENT_DRIVER_NIC);
|
|
|
|
nic = &netdev->u.nic;
|
2009-10-06 15:17:06 +04:00
|
|
|
|
|
|
|
idx = nic_get_free_idx();
|
|
|
|
if (idx == -1 || nb_nics >= MAX_NICS) {
|
2015-05-15 14:58:51 +03:00
|
|
|
error_setg(errp, "too many NICs");
|
2009-10-06 15:17:06 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nd = &nd_table[idx];
|
|
|
|
|
|
|
|
memset(nd, 0, sizeof(*nd));
|
|
|
|
|
2022-11-04 19:07:00 +03:00
|
|
|
if (nic->netdev) {
|
2012-07-17 18:17:14 +04:00
|
|
|
nd->netdev = qemu_find_netdev(nic->netdev);
|
2009-10-08 22:58:29 +04:00
|
|
|
if (!nd->netdev) {
|
2015-05-15 14:58:51 +03:00
|
|
|
error_setg(errp, "netdev '%s' not found", nic->netdev);
|
2009-10-08 22:58:29 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-24 19:35:05 +04:00
|
|
|
assert(peer);
|
|
|
|
nd->netdev = peer;
|
2009-10-08 22:58:29 +04:00
|
|
|
}
|
2013-01-22 14:07:57 +04:00
|
|
|
nd->name = g_strdup(name);
|
2022-11-04 19:07:00 +03:00
|
|
|
if (nic->model) {
|
2012-07-17 18:17:14 +04:00
|
|
|
nd->model = g_strdup(nic->model);
|
2009-10-06 15:17:06 +04:00
|
|
|
}
|
2022-11-04 19:07:00 +03:00
|
|
|
if (nic->addr) {
|
2012-07-17 18:17:14 +04:00
|
|
|
nd->devaddr = g_strdup(nic->addr);
|
2009-10-06 15:17:06 +04:00
|
|
|
}
|
|
|
|
|
2022-11-04 19:07:00 +03:00
|
|
|
if (nic->macaddr &&
|
2012-07-17 18:17:14 +04:00
|
|
|
net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
|
2015-05-15 14:58:51 +03:00
|
|
|
error_setg(errp, "invalid syntax for ethernet address");
|
2009-10-06 15:17:06 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2022-11-04 19:07:00 +03:00
|
|
|
if (nic->macaddr &&
|
2013-10-21 12:08:44 +04:00
|
|
|
is_multicast_ether_addr(nd->macaddr.a)) {
|
2015-05-15 14:58:51 +03:00
|
|
|
error_setg(errp,
|
|
|
|
"NIC cannot have multicast MAC address (odd 1st byte)");
|
2013-10-21 12:08:44 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2011-07-20 14:20:22 +04:00
|
|
|
qemu_macaddr_default_if_unset(&nd->macaddr);
|
2009-10-06 15:17:06 +04:00
|
|
|
|
2012-07-17 18:17:14 +04:00
|
|
|
if (nic->has_vectors) {
|
|
|
|
if (nic->vectors > 0x7ffffff) {
|
2015-05-15 14:58:51 +03:00
|
|
|
error_setg(errp, "invalid # of vectors: %"PRIu32, nic->vectors);
|
2012-07-17 18:17:14 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
nd->nvectors = nic->vectors;
|
|
|
|
} else {
|
|
|
|
nd->nvectors = DEV_NVECTORS_UNSPECIFIED;
|
2009-10-06 15:17:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nd->used = 1;
|
|
|
|
nb_nics++;
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2012-07-17 18:17:13 +04:00
|
|
|
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
|
2016-07-14 06:50:12 +03:00
|
|
|
const Netdev *netdev,
|
2012-07-17 18:17:13 +04:00
|
|
|
const char *name,
|
2015-05-15 14:58:50 +03:00
|
|
|
NetClientState *peer, Error **errp) = {
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_NIC] = net_init_nic,
|
2009-10-06 15:17:07 +04:00
|
|
|
#ifdef CONFIG_SLIRP
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_USER] = net_init_slirp,
|
2012-02-04 12:24:46 +04:00
|
|
|
#endif
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_TAP] = net_init_tap,
|
|
|
|
[NET_CLIENT_DRIVER_SOCKET] = net_init_socket,
|
qapi: net: add stream and dgram netdevs
Copied from socket netdev file and modified to use SocketAddress
to be able to introduce new features like unix socket.
"udp" and "mcast" are squashed into dgram netdev, multicast is detected
according to the IP address type.
"listen" and "connect" modes are managed by stream netdev. An optional
parameter "server" defines the mode (off by default)
The two new types need to be parsed the modern way with -netdev, because
with the traditional way, the "type" field of netdev structure collides with
the "type" field of SocketAddress and prevents the correct evaluation of the
command line option. Moreover the traditional way doesn't allow to use
the same type (SocketAddress) several times with the -netdev option
(needed to specify "local" and "remote" addresses).
The previous commit paved the way for parsing the modern way, but
omitted one detail: how to pick modern vs. traditional, in
netdev_is_modern().
We want to pick based on the value of parameter "type". But how to
extract it from the option argument?
Parsing the option argument, either the modern or the traditional way,
extracts it for us, but only if parsing succeeds.
If parsing fails, there is no good option. No matter which parser we
pick, it'll be the wrong one for some arguments, and the error
reporting will be confusing.
Fortunately, the traditional parser accepts *anything* when called in
a certain way. This maximizes our chance to extract the value of
"type", and in turn minimizes the risk of confusing error reporting.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:11 +03:00
|
|
|
[NET_CLIENT_DRIVER_STREAM] = net_init_stream,
|
|
|
|
[NET_CLIENT_DRIVER_DGRAM] = net_init_dgram,
|
2009-10-06 15:17:10 +04:00
|
|
|
#ifdef CONFIG_VDE
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_VDE] = net_init_vde,
|
2013-11-06 14:44:06 +04:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_NETMAP
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_NETMAP] = net_init_netmap,
|
2009-10-06 15:17:10 +04:00
|
|
|
#endif
|
2012-02-04 12:24:46 +04:00
|
|
|
#ifdef CONFIG_NET_BRIDGE
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
|
2012-07-17 18:17:13 +04:00
|
|
|
#endif
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
|
2019-02-14 20:35:49 +03:00
|
|
|
#ifdef CONFIG_VHOST_NET_USER
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
|
2014-06-10 14:02:16 +04:00
|
|
|
#endif
|
2020-07-01 17:55:38 +03:00
|
|
|
#ifdef CONFIG_VHOST_NET_VDPA
|
|
|
|
[NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa,
|
|
|
|
#endif
|
2014-07-01 16:58:08 +04:00
|
|
|
#ifdef CONFIG_L2TPV3
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
|
2014-06-20 13:34:41 +04:00
|
|
|
#endif
|
2022-03-17 20:28:34 +03:00
|
|
|
#ifdef CONFIG_VMNET
|
|
|
|
[NET_CLIENT_DRIVER_VMNET_HOST] = net_init_vmnet_host,
|
|
|
|
[NET_CLIENT_DRIVER_VMNET_SHARED] = net_init_vmnet_shared,
|
|
|
|
[NET_CLIENT_DRIVER_VMNET_BRIDGED] = net_init_vmnet_bridged,
|
|
|
|
#endif /* CONFIG_VMNET */
|
2009-10-06 15:17:06 +04:00
|
|
|
};
|
|
|
|
|
2012-07-17 18:17:13 +04:00
|
|
|
|
2020-05-18 21:01:03 +03:00
|
|
|
static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
|
2009-10-06 15:17:06 +04:00
|
|
|
{
|
2015-05-27 19:16:51 +03:00
|
|
|
NetClientState *peer = NULL;
|
net: Fix handling of id in netdev_add and netdev_del
CLI -netdev accumulates in option group "netdev".
Before commit 08712fcb85 "net: Track netdevs in NetClientState rather
than QemuOpt", netdev_add added to the option group, and netdev_del
removed from it, both HMP and QMP. Thus, every netdev had a
corresponding QemuOpts in this option group.
Commit 08712fcb85 dropped this for QMP netdev_add and both netdev_del.
Now a netdev has a corresponding QemuOpts only when it was created
with CLI or HMP. Two issues:
* QMP and HMP netdev_del can leave QemuOpts behind, breaking HMP
netdev_add. Reproducer:
$ qemu-system-x86_64 -S -display none -nodefaults -monitor stdio
QEMU 5.1.92 monitor - type 'help' for more information
(qemu) netdev_add user,id=net0
(qemu) info network
net0: index=0,type=user,net=10.0.2.0,restrict=off
(qemu) netdev_del net0
(qemu) info network
(qemu) netdev_add user,id=net0
upstream-qemu: Duplicate ID 'net0' for netdev
Try "help netdev_add" for more information
Fix by restoring the QemuOpts deletion in qmp_netdev_del(), but with
a guard, because the QemuOpts need not exist.
* QMP netdev_add loses its "no duplicate ID" check. Reproducer:
$ qemu-system-x86_64 -S -display none -qmp stdio
{"QMP": {"version": {"qemu": {"micro": 92, "minor": 1, "major": 5}, "package": "v5.2.0-rc2-1-g02c1f0142c"}, "capabilities": ["oob"]}}
{"execute": "qmp_capabilities"}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
Fix by adding a duplicate ID check to net_client_init1() to replace
the lost one. The check is redundant for callers where QemuOpts
still checks, i.e. for CLI and HMP.
Reported-by: Andrew Melnichenko <andrew@daynix.com>
Fixes: 08712fcb851034228b61f75bd922863a984a4f60
Cc: qemu-stable@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2020-11-25 13:02:20 +03:00
|
|
|
NetClientState *nc;
|
2009-10-06 15:17:06 +04:00
|
|
|
|
2010-03-25 19:22:38 +03:00
|
|
|
if (is_netdev) {
|
2018-02-21 13:18:34 +03:00
|
|
|
if (netdev->type == NET_CLIENT_DRIVER_NIC ||
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
!net_client_init_fun[netdev->type]) {
|
2022-10-03 13:06:12 +03:00
|
|
|
error_setg(errp, "network backend '%s' is not compiled into this binary",
|
|
|
|
NetClientDriver_str(netdev->type));
|
2009-10-08 22:58:27 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-07-17 18:17:13 +04:00
|
|
|
} else {
|
2020-05-18 21:01:03 +03:00
|
|
|
if (netdev->type == NET_CLIENT_DRIVER_NONE) {
|
2015-05-27 19:16:50 +03:00
|
|
|
return 0; /* nothing to do */
|
2015-05-27 19:16:52 +03:00
|
|
|
}
|
2022-10-03 13:06:12 +03:00
|
|
|
if (netdev->type == NET_CLIENT_DRIVER_HUBPORT) {
|
|
|
|
error_setg(errp, "network backend '%s' is only supported with -netdev/-nic",
|
|
|
|
NetClientDriver_str(netdev->type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!net_client_init_fun[netdev->type]) {
|
|
|
|
error_setg(errp, "network backend '%s' is not compiled into this binary",
|
|
|
|
NetClientDriver_str(netdev->type));
|
2015-05-27 19:16:50 +03:00
|
|
|
return -1;
|
|
|
|
}
|
2009-10-08 22:58:27 +04:00
|
|
|
|
2018-04-30 21:02:23 +03:00
|
|
|
/* Do not add to a hub if it's a nic with a netdev= parameter. */
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (netdev->type != NET_CLIENT_DRIVER_NIC ||
|
2022-11-04 19:07:00 +03:00
|
|
|
!netdev->u.nic.netdev) {
|
2018-04-30 21:02:23 +03:00
|
|
|
peer = net_hub_add_port(0, NULL, NULL);
|
2017-01-24 12:42:49 +03:00
|
|
|
}
|
2015-05-27 19:16:51 +03:00
|
|
|
}
|
2012-07-17 18:17:13 +04:00
|
|
|
|
net: Fix handling of id in netdev_add and netdev_del
CLI -netdev accumulates in option group "netdev".
Before commit 08712fcb85 "net: Track netdevs in NetClientState rather
than QemuOpt", netdev_add added to the option group, and netdev_del
removed from it, both HMP and QMP. Thus, every netdev had a
corresponding QemuOpts in this option group.
Commit 08712fcb85 dropped this for QMP netdev_add and both netdev_del.
Now a netdev has a corresponding QemuOpts only when it was created
with CLI or HMP. Two issues:
* QMP and HMP netdev_del can leave QemuOpts behind, breaking HMP
netdev_add. Reproducer:
$ qemu-system-x86_64 -S -display none -nodefaults -monitor stdio
QEMU 5.1.92 monitor - type 'help' for more information
(qemu) netdev_add user,id=net0
(qemu) info network
net0: index=0,type=user,net=10.0.2.0,restrict=off
(qemu) netdev_del net0
(qemu) info network
(qemu) netdev_add user,id=net0
upstream-qemu: Duplicate ID 'net0' for netdev
Try "help netdev_add" for more information
Fix by restoring the QemuOpts deletion in qmp_netdev_del(), but with
a guard, because the QemuOpts need not exist.
* QMP netdev_add loses its "no duplicate ID" check. Reproducer:
$ qemu-system-x86_64 -S -display none -qmp stdio
{"QMP": {"version": {"qemu": {"micro": 92, "minor": 1, "major": 5}, "package": "v5.2.0-rc2-1-g02c1f0142c"}, "capabilities": ["oob"]}}
{"execute": "qmp_capabilities"}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
Fix by adding a duplicate ID check to net_client_init1() to replace
the lost one. The check is redundant for callers where QemuOpts
still checks, i.e. for CLI and HMP.
Reported-by: Andrew Melnichenko <andrew@daynix.com>
Fixes: 08712fcb851034228b61f75bd922863a984a4f60
Cc: qemu-stable@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2020-11-25 13:02:20 +03:00
|
|
|
nc = qemu_find_netdev(netdev->id);
|
|
|
|
if (nc) {
|
|
|
|
error_setg(errp, "Duplicate ID '%s'", netdev->id);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-05-18 21:01:02 +03:00
|
|
|
if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
|
2015-05-27 19:16:51 +03:00
|
|
|
/* FIXME drop when all init functions store an Error */
|
|
|
|
if (errp && !*errp) {
|
2020-11-13 11:26:18 +03:00
|
|
|
error_setg(errp, "Device '%s' could not be initialized",
|
2017-08-24 11:46:08 +03:00
|
|
|
NetClientDriver_str(netdev->type));
|
2009-10-08 22:58:27 +04:00
|
|
|
}
|
2015-05-27 19:16:51 +03:00
|
|
|
return -1;
|
2009-10-08 22:58:27 +04:00
|
|
|
}
|
2020-03-17 23:17:11 +03:00
|
|
|
|
|
|
|
if (is_netdev) {
|
|
|
|
nc = qemu_find_netdev(netdev->id);
|
|
|
|
assert(nc);
|
|
|
|
nc->is_netdev = true;
|
|
|
|
}
|
|
|
|
|
2012-07-17 18:17:13 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
void show_netdevs(void)
|
2018-02-21 13:18:31 +03:00
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
const char *available_netdevs[] = {
|
|
|
|
"socket",
|
qapi: net: add stream and dgram netdevs
Copied from socket netdev file and modified to use SocketAddress
to be able to introduce new features like unix socket.
"udp" and "mcast" are squashed into dgram netdev, multicast is detected
according to the IP address type.
"listen" and "connect" modes are managed by stream netdev. An optional
parameter "server" defines the mode (off by default)
The two new types need to be parsed the modern way with -netdev, because
with the traditional way, the "type" field of netdev structure collides with
the "type" field of SocketAddress and prevents the correct evaluation of the
command line option. Moreover the traditional way doesn't allow to use
the same type (SocketAddress) several times with the -netdev option
(needed to specify "local" and "remote" addresses).
The previous commit paved the way for parsing the modern way, but
omitted one detail: how to pick modern vs. traditional, in
netdev_is_modern().
We want to pick based on the value of parameter "type". But how to
extract it from the option argument?
Parsing the option argument, either the modern or the traditional way,
extracts it for us, but only if parsing succeeds.
If parsing fails, there is no good option. No matter which parser we
pick, it'll be the wrong one for some arguments, and the error
reporting will be confusing.
Fortunately, the traditional parser accepts *anything* when called in
a certain way. This maximizes our chance to extract the value of
"type", and in turn minimizes the risk of confusing error reporting.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:11 +03:00
|
|
|
"stream",
|
|
|
|
"dgram",
|
2018-02-21 13:18:31 +03:00
|
|
|
"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",
|
2020-10-16 06:09:09 +03:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_VHOST_VDPA
|
|
|
|
"vhost-vdpa",
|
2022-03-17 20:28:34 +03:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_VMNET
|
|
|
|
"vmnet-host",
|
|
|
|
"vmnet-shared",
|
|
|
|
"vmnet-bridged",
|
2018-02-21 13:18:31 +03:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
qemu_printf("Available netdev backend types:\n");
|
2018-02-21 13:18:31 +03:00
|
|
|
for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
|
2020-11-11 13:52:22 +03:00
|
|
|
qemu_printf("%s\n", available_netdevs[idx]);
|
2018-02-21 13:18:31 +03:00
|
|
|
}
|
|
|
|
}
|
2009-10-08 22:58:27 +04:00
|
|
|
|
2018-02-21 13:18:33 +03:00
|
|
|
static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
|
2012-07-17 18:17:13 +04:00
|
|
|
{
|
2019-05-17 16:47:46 +03:00
|
|
|
gchar **substrings = NULL;
|
2020-05-18 21:01:03 +03:00
|
|
|
Netdev *object = NULL;
|
2012-07-17 18:17:13 +04:00
|
|
|
int ret = -1;
|
2016-06-09 19:48:36 +03:00
|
|
|
Visitor *v = opts_visitor_new(opts);
|
2009-10-06 15:17:06 +04:00
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
/* Parse convenience option format ip6-net=fec0::0[/64] */
|
|
|
|
const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
|
2016-03-15 12:31:22 +03:00
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
if (ip6_net) {
|
|
|
|
char *prefix_addr;
|
|
|
|
unsigned long prefix_len = 64; /* Default 64bit prefix length. */
|
2019-05-17 16:47:46 +03:00
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
substrings = g_strsplit(ip6_net, "/", 2);
|
|
|
|
if (!substrings || !substrings[0]) {
|
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
|
|
|
|
"a valid IPv6 prefix");
|
|
|
|
goto out;
|
|
|
|
}
|
2019-05-17 16:47:46 +03:00
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
prefix_addr = substrings[0];
|
2016-03-15 12:31:22 +03:00
|
|
|
|
2020-11-11 13:52:22 +03:00
|
|
|
/* Handle user-specified prefix length. */
|
|
|
|
if (substrings[1] &&
|
|
|
|
qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
|
|
|
|
{
|
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
|
|
|
|
"ipv6-prefixlen", "a number");
|
|
|
|
goto out;
|
2016-03-15 12:31:22 +03:00
|
|
|
}
|
2020-11-11 13:52:22 +03:00
|
|
|
|
|
|
|
qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
|
|
|
|
qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
|
|
|
|
&error_abort);
|
|
|
|
qemu_opt_unset(opts, "ipv6-net");
|
2016-03-15 12:31:22 +03:00
|
|
|
}
|
|
|
|
|
2020-05-18 21:01:03 +03:00
|
|
|
/* Create an ID for -net if the user did not specify one */
|
|
|
|
if (!is_netdev && !qemu_opts_id(opts)) {
|
2021-02-15 12:02:25 +03:00
|
|
|
qemu_opts_set_id(opts, id_generate(ID_NET));
|
2009-10-06 15:17:06 +04:00
|
|
|
}
|
|
|
|
|
2020-07-07 19:05:47 +03:00
|
|
|
if (visit_type_Netdev(v, NULL, &object, errp)) {
|
|
|
|
ret = net_client_init1(object, is_netdev, errp);
|
2012-07-17 18:17:13 +04:00
|
|
|
}
|
|
|
|
|
2020-05-18 21:01:03 +03:00
|
|
|
qapi_free_Netdev(object);
|
2012-07-17 18:17:13 +04:00
|
|
|
|
2019-05-17 16:47:45 +03:00
|
|
|
out:
|
2019-05-17 16:47:46 +03:00
|
|
|
g_strfreev(substrings);
|
2016-06-09 19:48:36 +03:00
|
|
|
visit_free(v);
|
2012-07-17 18:17:13 +04:00
|
|
|
return ret;
|
2009-10-06 15:17:06 +04:00
|
|
|
}
|
|
|
|
|
2012-04-19 00:34:15 +04:00
|
|
|
void netdev_add(QemuOpts *opts, Error **errp)
|
|
|
|
{
|
2016-07-14 06:50:24 +03:00
|
|
|
net_client_init(opts, true, errp);
|
2012-04-19 00:34:15 +04:00
|
|
|
}
|
|
|
|
|
net: Complete qapi-fication of netdev_add
We've had all the required pieces for doing a type-safe representation
of netdev_add as a flat union for quite some time now (since
0e55c381f6 in v2.7.0, released in 2016), but did not make the final
switch to using it because of concern about whether a command-line
regression in accepting "1" in place of 1 for integer arguments would
be problematic. Back then, we did not have the deprecation cycle to
allow us to make progress. But now that we have waited so long, other
problems have crept in: for example, our desire to add
qemu-storage-daemon is hampered by the inability to express net
objects, and we are unable to introspect what we actually accept.
Additionally, our round-trip through QemuOpts silently eats any
argument that expands to an array, rendering dnssearch, hostfwd, and
guestfwd useless through QMP:
{"execute": "netdev_add", "arguments": { "id": "netdev0",
"type": "user", "dnssearch": [
{ "str": "8.8.8.8" }, { "str": "8.8.4.4" }
]}}
So without further ado, let's turn on proper QAPI. netdev_add() was a
trivial wrapper around net_client_init(), which did a few steps prior
to calling net_client_init1(); with this patch, we now skip directly
to net_client_init1(). In addition to fixing array parameters, the
following additional differences occur:
- {"execute": "netdev_add", "arguments": {"type": "help"}}
no longer attempts to print help to stdout and exit. Bug fix, broken
in 547203ead4 'net: List available netdevs with "-netdev help"',
v2.12.0.
- {"execute": "netdev_add", "arguments': {... "ipv6-net": "..." }}
no longer attempts to desugar the undocumented ipv6-net magic string
into the proper "ipv6-prefix" and "ipv6-prefixlen". Undocumented
misfeature, introduced in commit 7aac531ef2 "qapi-schema, qemu-options
& slirp: Adding Qemu options for IPv6 addresses", v2.6.0.
- {'execute':'netdev_add',
'arguments':{'id':'net2', 'type':'hubport', 'hubid':"2"}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'hubid', expected: integer"}}
Used to succeed: since our command line treats everything as strings,
our not-so-round-trip conversion from QAPI -> QemuOpts -> QAPI lost
the original typing and turned everything into a string; now that we
skip the QemuOpts, the JSON input has to match the exact QAPI type.
But this stricter QMP is desirable, and introspection is sufficient
for any affected applications to make sure they use it correctly.
In qmp_netdev_add(), we still have to create a QemuOpts object so that
qmp_netdev_del() will be able to remove a hotplugged network device;
but the opts->head remains empty since we now manage all parsing
through the QAPI object rather than QemuOpts; a separate patch will
address the abuse of QemuOpts as a witness for whether a
NetClientState is a netdev. In the meantime, our argument that we are
okay requires auditing all uses of option group "netdev":
- qemu_netdev_opts: option group definition, empty .desc[]
- CLI (CLI netdev parsing ends before monitors start, so while
monitors can mess with CLI netdevs, CLI cannot mess with
monitor netdevs):
- main() case QEMU_OPTION_netdev: store CLI definition
- main() case QEMU_OPTION_readconfig, case QEMU_OPTION_writeconfig:
similar, dealing only with CLI
- net_init_clients(): Pass CLI to net_client_init()
- Monitor:
- hmp_netdev_add(): straightforward parse into net_client_init()
- qmp_netdev_add(): subject of this patch, used to add full
object to option group, now just adds bare-bones id
- qmp_netdev_del(), netdev_del_completion(): check the option group
solely for id, as a 'is this a netdev' predicate
Reported-by: Alex Kirillov <lekiravi@yandex-team.ru>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200317201711.322764-2-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Commit message typo fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2020-03-17 23:17:10 +03:00
|
|
|
void qmp_netdev_add(Netdev *netdev, Error **errp)
|
2010-03-25 19:22:40 +03:00
|
|
|
{
|
net: validate that ids are well formed
When a network or network device is created from the command line or HMP,
QemuOpts ensures that the id passes the id_wellformed check. However,
QMP skips this:
$ qemu-system-x86_64 -qmp stdio -S -nic user,id=123/456
qemu-system-x86_64: -nic user,id=123/456: Parameter id expects an identifier
Identifiers consist of letters, digits, -, ., _, starting with a letter.
$ qemu-system-x86_64 -qmp stdio -S
{"execute":"qmp_capabilities"}
{"return": {}}
{"execute":"netdev_add", "arguments": {"type": "user", "id": "123/456"}}
{"return": {}}
After:
$ qemu-system-x86_64 -qmp stdio -S
{"execute":"qmp_capabilities"}
{"return": {}}
{"execute":"netdev_add", "arguments": {"type": "user", "id": "123/456"}}
{"error": {"class": "GenericError", "desc": "Parameter "id" expects an identifier"}}
Validity checks should be performed always at the bottom of the call chain,
because QMP skips all the steps above. At the same time we know that every
call chain should go through either QMP or (for legacy) through QemuOpts.
Because the id for -net and -nic is automatically generated and not
well-formed by design, just add the check to QMP.
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2021-03-12 17:51:38 +03:00
|
|
|
if (!id_wellformed(netdev->id)) {
|
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-17 23:17:11 +03:00
|
|
|
net_client_init1(netdev, true, errp);
|
2010-03-25 19:22:40 +03:00
|
|
|
}
|
|
|
|
|
2012-04-16 21:36:32 +04:00
|
|
|
void qmp_netdev_del(const char *id, Error **errp)
|
2010-03-25 19:22:40 +03:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
NetClientState *nc;
|
net: Fix handling of id in netdev_add and netdev_del
CLI -netdev accumulates in option group "netdev".
Before commit 08712fcb85 "net: Track netdevs in NetClientState rather
than QemuOpt", netdev_add added to the option group, and netdev_del
removed from it, both HMP and QMP. Thus, every netdev had a
corresponding QemuOpts in this option group.
Commit 08712fcb85 dropped this for QMP netdev_add and both netdev_del.
Now a netdev has a corresponding QemuOpts only when it was created
with CLI or HMP. Two issues:
* QMP and HMP netdev_del can leave QemuOpts behind, breaking HMP
netdev_add. Reproducer:
$ qemu-system-x86_64 -S -display none -nodefaults -monitor stdio
QEMU 5.1.92 monitor - type 'help' for more information
(qemu) netdev_add user,id=net0
(qemu) info network
net0: index=0,type=user,net=10.0.2.0,restrict=off
(qemu) netdev_del net0
(qemu) info network
(qemu) netdev_add user,id=net0
upstream-qemu: Duplicate ID 'net0' for netdev
Try "help netdev_add" for more information
Fix by restoring the QemuOpts deletion in qmp_netdev_del(), but with
a guard, because the QemuOpts need not exist.
* QMP netdev_add loses its "no duplicate ID" check. Reproducer:
$ qemu-system-x86_64 -S -display none -qmp stdio
{"QMP": {"version": {"qemu": {"micro": 92, "minor": 1, "major": 5}, "package": "v5.2.0-rc2-1-g02c1f0142c"}, "capabilities": ["oob"]}}
{"execute": "qmp_capabilities"}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
Fix by adding a duplicate ID check to net_client_init1() to replace
the lost one. The check is redundant for callers where QemuOpts
still checks, i.e. for CLI and HMP.
Reported-by: Andrew Melnichenko <andrew@daynix.com>
Fixes: 08712fcb851034228b61f75bd922863a984a4f60
Cc: qemu-stable@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2020-11-25 13:02:20 +03:00
|
|
|
QemuOpts *opts;
|
2010-03-25 19:22:40 +03:00
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
nc = qemu_find_netdev(id);
|
|
|
|
if (!nc) {
|
2015-03-16 10:57:47 +03:00
|
|
|
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
|
|
"Device '%s' not found", id);
|
2012-04-16 21:36:32 +04:00
|
|
|
return;
|
2010-03-25 19:22:40 +03:00
|
|
|
}
|
2012-04-16 21:36:32 +04:00
|
|
|
|
2020-03-17 23:17:11 +03:00
|
|
|
if (!nc->is_netdev) {
|
2012-10-24 16:34:12 +04:00
|
|
|
error_setg(errp, "Device '%s' is not a netdev", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:15 +04:00
|
|
|
qemu_del_net_client(nc);
|
net: Fix handling of id in netdev_add and netdev_del
CLI -netdev accumulates in option group "netdev".
Before commit 08712fcb85 "net: Track netdevs in NetClientState rather
than QemuOpt", netdev_add added to the option group, and netdev_del
removed from it, both HMP and QMP. Thus, every netdev had a
corresponding QemuOpts in this option group.
Commit 08712fcb85 dropped this for QMP netdev_add and both netdev_del.
Now a netdev has a corresponding QemuOpts only when it was created
with CLI or HMP. Two issues:
* QMP and HMP netdev_del can leave QemuOpts behind, breaking HMP
netdev_add. Reproducer:
$ qemu-system-x86_64 -S -display none -nodefaults -monitor stdio
QEMU 5.1.92 monitor - type 'help' for more information
(qemu) netdev_add user,id=net0
(qemu) info network
net0: index=0,type=user,net=10.0.2.0,restrict=off
(qemu) netdev_del net0
(qemu) info network
(qemu) netdev_add user,id=net0
upstream-qemu: Duplicate ID 'net0' for netdev
Try "help netdev_add" for more information
Fix by restoring the QemuOpts deletion in qmp_netdev_del(), but with
a guard, because the QemuOpts need not exist.
* QMP netdev_add loses its "no duplicate ID" check. Reproducer:
$ qemu-system-x86_64 -S -display none -qmp stdio
{"QMP": {"version": {"qemu": {"micro": 92, "minor": 1, "major": 5}, "package": "v5.2.0-rc2-1-g02c1f0142c"}, "capabilities": ["oob"]}}
{"execute": "qmp_capabilities"}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
{"execute": "netdev_add", "arguments": {"type": "user", "id":"net0"}}
{"return": {}}
Fix by adding a duplicate ID check to net_client_init1() to replace
the lost one. The check is redundant for callers where QemuOpts
still checks, i.e. for CLI and HMP.
Reported-by: Andrew Melnichenko <andrew@daynix.com>
Fixes: 08712fcb851034228b61f75bd922863a984a4f60
Cc: qemu-stable@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2020-11-25 13:02:20 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Wart: we need to delete the QemuOpts associated with netdevs
|
|
|
|
* created via CLI or HMP, to avoid bogus "Duplicate ID" errors in
|
|
|
|
* HMP netdev_add.
|
|
|
|
*/
|
|
|
|
opts = qemu_opts_find(qemu_find_opts("netdev"), id);
|
|
|
|
if (opts) {
|
|
|
|
qemu_opts_del(opts);
|
|
|
|
}
|
2010-03-25 19:22:40 +03:00
|
|
|
}
|
|
|
|
|
2016-01-26 09:43:33 +03:00
|
|
|
static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
ObjectProperty *prop;
|
|
|
|
ObjectPropertyIterator iter;
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 19:48:43 +03:00
|
|
|
Visitor *v;
|
2016-01-26 09:43:33 +03:00
|
|
|
|
|
|
|
/* generate info str */
|
|
|
|
object_property_iter_init(&iter, OBJECT(nf));
|
|
|
|
while ((prop = object_property_iter_next(&iter))) {
|
|
|
|
if (!strcmp(prop->name, "type")) {
|
|
|
|
continue;
|
|
|
|
}
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 19:48:43 +03:00
|
|
|
v = string_output_visitor_new(false, &str);
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
object_property_get(OBJECT(nf), prop->name, v, NULL);
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 19:48:43 +03:00
|
|
|
visit_complete(v, &str);
|
|
|
|
visit_free(v);
|
2016-01-26 09:43:33 +03:00
|
|
|
monitor_printf(mon, ",%s=%s", prop->name, str);
|
|
|
|
g_free(str);
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
2012-07-24 19:35:16 +04:00
|
|
|
void print_net_client(Monitor *mon, NetClientState *nc)
|
2011-07-20 14:20:21 +04:00
|
|
|
{
|
2015-10-07 06:52:19 +03:00
|
|
|
NetFilterState *nf;
|
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
|
|
|
|
nc->queue_index,
|
2017-08-24 11:46:08 +03:00
|
|
|
NetClientDriver_str(nc->info->type),
|
2021-04-02 06:03:33 +03:00
|
|
|
nc->info_str);
|
2015-10-07 06:52:19 +03:00
|
|
|
if (!QTAILQ_EMPTY(&nc->filters)) {
|
|
|
|
monitor_printf(mon, "filters:\n");
|
|
|
|
}
|
|
|
|
QTAILQ_FOREACH(nf, &nc->filters, next) {
|
2020-07-14 19:02:00 +03:00
|
|
|
monitor_printf(mon, " - %s: type=%s",
|
|
|
|
object_get_canonical_path_component(OBJECT(nf)),
|
2016-01-26 09:43:33 +03:00
|
|
|
object_get_typename(OBJECT(nf)));
|
|
|
|
netfilter_print_info(mon, nf);
|
2015-10-07 06:52:19 +03:00
|
|
|
}
|
2011-07-20 14:20:21 +04:00
|
|
|
}
|
|
|
|
|
2022-11-04 19:07:00 +03:00
|
|
|
RxFilterInfoList *qmp_query_rx_filter(const char *name, Error **errp)
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
{
|
|
|
|
NetClientState *nc;
|
2021-01-14 01:10:13 +03:00
|
|
|
RxFilterInfoList *filter_list = NULL, **tail = &filter_list;
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
|
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
|
|
|
RxFilterInfo *info;
|
|
|
|
|
2022-11-04 19:07:00 +03:00
|
|
|
if (name && strcmp(nc->name, name) != 0) {
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* only query rx-filter information of NIC */
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
|
2022-11-04 19:07:00 +03:00
|
|
|
if (name) {
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
error_setg(errp, "net client(%s) isn't a NIC", name);
|
2021-01-14 01:10:09 +03:00
|
|
|
assert(!filter_list);
|
2014-04-24 17:44:18 +04:00
|
|
|
return NULL;
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-10-19 16:04:38 +03:00
|
|
|
/* only query information on queue 0 since the info is per nic,
|
|
|
|
* not per queue
|
|
|
|
*/
|
|
|
|
if (nc->queue_index != 0)
|
|
|
|
continue;
|
|
|
|
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
if (nc->info->query_rx_filter) {
|
|
|
|
info = nc->info->query_rx_filter(nc);
|
2021-01-14 01:10:13 +03:00
|
|
|
QAPI_LIST_APPEND(tail, info);
|
2022-11-04 19:07:00 +03:00
|
|
|
} else if (name) {
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
error_setg(errp, "net client(%s) doesn't support"
|
|
|
|
" rx-filter querying", name);
|
2021-01-14 01:10:09 +03:00
|
|
|
assert(!filter_list);
|
2014-04-24 17:44:18 +04:00
|
|
|
return NULL;
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
}
|
2014-04-24 17:44:17 +04:00
|
|
|
|
2022-11-04 19:07:00 +03:00
|
|
|
if (name) {
|
2014-04-24 17:44:17 +04:00
|
|
|
break;
|
|
|
|
}
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
}
|
|
|
|
|
2022-11-04 19:07:00 +03:00
|
|
|
if (filter_list == NULL && name) {
|
net: add support of mac-programming over macvtap in QEMU side
Currently macvtap based macvlan device is working in promiscuous
mode, we want to implement mac-programming over macvtap through
Libvirt for better performance.
Design:
QEMU notifies Libvirt when rx-filter config is changed in guest,
then Libvirt query the rx-filter information by a monitor command,
and sync the change to macvtap device. Related rx-filter config
of the nic contains main mac, rx-mode items and vlan table.
This patch adds a QMP event to notify management of rx-filter change,
and adds a monitor command for management to query rx-filter
information.
Test:
If we repeatedly add/remove vlan, and change macaddr of vlan
interfaces in guest by a loop script.
Result:
The events will flood the QMP client(management), management takes
too much resource to process the events.
Event_throttle API (set rate to 1 ms) can avoid the events to flood
QMP client, but it could cause an unexpected delay (~1ms), guests
guests normally expect rx-filter updates immediately.
So we use a flag for each nic to avoid events flooding, the event
is emitted once until the query command is executed. The flag
implementation could not introduce unexpected delay.
There maybe exist an uncontrollable delay if we let Libvirt do the
real change, guests normally expect rx-filter updates immediately.
But it's another separate issue, we can investigate it when the
work in Libvirt side is done.
Michael S. Tsirkin: tweaked to enable events on start
Michael S. Tsirkin: fixed not to crash when no id
Michael S. Tsirkin: fold in patch:
"additional fixes for mac-programming feature"
Amos Kong: always notify QMP client if mactable is changed
Amos Kong: return NULL list if no net client supports rx-filter query
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2013-06-14 11:45:52 +04:00
|
|
|
error_setg(errp, "invalid net client name: %s", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return filter_list;
|
|
|
|
}
|
|
|
|
|
2018-09-03 07:38:56 +03:00
|
|
|
void colo_notify_filters_event(int event, Error **errp)
|
|
|
|
{
|
|
|
|
NetClientState *nc;
|
|
|
|
NetFilterState *nf;
|
|
|
|
NetFilterClass *nfc = NULL;
|
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
|
|
|
QTAILQ_FOREACH(nf, &nc->filters, next) {
|
|
|
|
nfc = NETFILTER_GET_CLASS(OBJECT(nf));
|
|
|
|
nfc->handle_event(nf, event, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-23 19:11:55 +04:00
|
|
|
void qmp_set_link(const char *name, bool up, Error **errp)
|
2009-01-08 22:44:06 +03:00
|
|
|
{
|
2013-01-30 15:12:28 +04:00
|
|
|
NetClientState *ncs[MAX_QUEUE_NUM];
|
|
|
|
NetClientState *nc;
|
|
|
|
int queues, i;
|
2009-01-08 22:44:06 +03:00
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
queues = qemu_find_net_clients_except(name, ncs,
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
NET_CLIENT_DRIVER__MAX,
|
2013-01-30 15:12:28 +04:00
|
|
|
MAX_QUEUE_NUM);
|
|
|
|
|
|
|
|
if (queues == 0) {
|
2015-03-16 10:57:47 +03:00
|
|
|
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
|
|
"Device '%s' not found", name);
|
2011-11-23 19:11:55 +04:00
|
|
|
return;
|
2009-01-08 22:44:06 +03:00
|
|
|
}
|
2013-01-30 15:12:28 +04:00
|
|
|
nc = ncs[0];
|
2009-01-08 22:44:06 +03:00
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
ncs[i]->link_down = !up;
|
|
|
|
}
|
2009-01-08 22:44:06 +03:00
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
if (nc->info->link_status_changed) {
|
|
|
|
nc->info->link_status_changed(nc);
|
2009-11-25 21:49:30 +03:00
|
|
|
}
|
2011-02-09 19:45:04 +03:00
|
|
|
|
net: Update netdev peer on link change
When a link change occurs on a backend (like tap), we currently do
not propage such change to the nic. As a result, when someone turns
off a link on a tap device, for instance, then a guest doesn't see
that change and continues to try to send traffic or run DHCP even
though the lower-layer is disconnected. This is OK when the network
is set up as a HUB since the the guest may be connected to other HUB
ports too, but when it's set up as a netdev, it makes thinkgs worse.
The patch addresses this by setting the peers link down only when the
peer is not a HUBPORT device. With this patch, in the following config
-netdev tap,id=net0 -device e1000,mac=XXXXX,netdev=net0
when net0 link is turned off, the guest e1000 shows lower-layer link
down. This allows guests to boot much faster in such configurations.
With windows guest, it also allows the network to recover properly
since windows will not configure the link-local IPv4 address, and
when the link is turned on, the proper address address is configured.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2013-11-22 06:05:51 +04:00
|
|
|
if (nc->peer) {
|
|
|
|
/* Change peer link only if the peer is NIC and then notify peer.
|
|
|
|
* If the peer is a HUBPORT or a backend, we do not change the
|
|
|
|
* link status.
|
|
|
|
*
|
2018-04-30 21:02:23 +03:00
|
|
|
* This behavior is compatible with qemu hubs where there could be
|
net: Update netdev peer on link change
When a link change occurs on a backend (like tap), we currently do
not propage such change to the nic. As a result, when someone turns
off a link on a tap device, for instance, then a guest doesn't see
that change and continues to try to send traffic or run DHCP even
though the lower-layer is disconnected. This is OK when the network
is set up as a HUB since the the guest may be connected to other HUB
ports too, but when it's set up as a netdev, it makes thinkgs worse.
The patch addresses this by setting the peers link down only when the
peer is not a HUBPORT device. With this patch, in the following config
-netdev tap,id=net0 -device e1000,mac=XXXXX,netdev=net0
when net0 link is turned off, the guest e1000 shows lower-layer link
down. This allows guests to boot much faster in such configurations.
With windows guest, it also allows the network to recover properly
since windows will not configure the link-local IPv4 address, and
when the link is turned on, the proper address address is configured.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2013-11-22 06:05:51 +04:00
|
|
|
* multiple clients that can still communicate with each other in
|
|
|
|
* disconnected mode. For now maintain this compatibility.
|
|
|
|
*/
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
|
net: Update netdev peer on link change
When a link change occurs on a backend (like tap), we currently do
not propage such change to the nic. As a result, when someone turns
off a link on a tap device, for instance, then a guest doesn't see
that change and continues to try to send traffic or run DHCP even
though the lower-layer is disconnected. This is OK when the network
is set up as a HUB since the the guest may be connected to other HUB
ports too, but when it's set up as a netdev, it makes thinkgs worse.
The patch addresses this by setting the peers link down only when the
peer is not a HUBPORT device. With this patch, in the following config
-netdev tap,id=net0 -device e1000,mac=XXXXX,netdev=net0
when net0 link is turned off, the guest e1000 shows lower-layer link
down. This allows guests to boot much faster in such configurations.
With windows guest, it also allows the network to recover properly
since windows will not configure the link-local IPv4 address, and
when the link is turned on, the proper address address is configured.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2013-11-22 06:05:51 +04:00
|
|
|
for (i = 0; i < queues; i++) {
|
|
|
|
ncs[i]->peer->link_down = !up;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nc->peer->info->link_status_changed) {
|
|
|
|
nc->peer->info->link_status_changed(nc->peer);
|
|
|
|
}
|
2011-02-09 19:45:04 +03:00
|
|
|
}
|
2009-01-08 22:44:06 +03:00
|
|
|
}
|
|
|
|
|
2021-01-11 18:20:20 +03:00
|
|
|
static void net_vm_change_state_handler(void *opaque, bool running,
|
2014-09-04 12:39:13 +04:00
|
|
|
RunState state)
|
|
|
|
{
|
2015-07-07 04:21:07 +03:00
|
|
|
NetClientState *nc;
|
|
|
|
NetClientState *tmp;
|
2014-09-04 12:39:13 +04:00
|
|
|
|
2015-07-07 04:21:07 +03:00
|
|
|
QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
|
|
|
|
if (running) {
|
|
|
|
/* Flush queued packets and wake up backends. */
|
|
|
|
if (nc->peer && qemu_can_send_packet(nc)) {
|
|
|
|
qemu_flush_queued_packets(nc->peer);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Complete all queued packets, to guarantee we don't modify
|
|
|
|
* state later when VM is not running.
|
|
|
|
*/
|
2014-09-04 12:39:13 +04:00
|
|
|
qemu_flush_or_purge_queued_packets(nc, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-31 22:10:00 +03:00
|
|
|
void net_cleanup(void)
|
|
|
|
{
|
2013-01-30 15:12:28 +04:00
|
|
|
NetClientState *nc;
|
2009-10-08 22:58:28 +04:00
|
|
|
|
Add the function of colo_compare_cleanup
This patch fixes the following:
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007f6ae4559859 in __GI_abort () at abort.c:79
#2 0x0000559aaa386720 in error_exit (err=16, msg=0x559aaa5973d0 <__func__.16227> "qemu_mutex_destroy") at util/qemu-thread-posix.c:36
#3 0x0000559aaa3868c5 in qemu_mutex_destroy (mutex=0x559aabffe828) at util/qemu-thread-posix.c:69
#4 0x0000559aaa2f93a8 in char_finalize (obj=0x559aabffe800) at chardev/char.c:285
#5 0x0000559aaa23318a in object_deinit (obj=0x559aabffe800, type=0x559aabfd7d20) at qom/object.c:606
#6 0x0000559aaa2331b8 in object_deinit (obj=0x559aabffe800, type=0x559aabfd9060) at qom/object.c:610
#7 0x0000559aaa233200 in object_finalize (data=0x559aabffe800) at qom/object.c:620
#8 0x0000559aaa234202 in object_unref (obj=0x559aabffe800) at qom/object.c:1074
#9 0x0000559aaa2356b6 in object_finalize_child_property (obj=0x559aac0dac10, name=0x559aac778760 "compare0-0", opaque=0x559aabffe800) at qom/object.c:1584
#10 0x0000559aaa232f70 in object_property_del_all (obj=0x559aac0dac10) at qom/object.c:557
#11 0x0000559aaa2331ed in object_finalize (data=0x559aac0dac10) at qom/object.c:619
#12 0x0000559aaa234202 in object_unref (obj=0x559aac0dac10) at qom/object.c:1074
#13 0x0000559aaa2356b6 in object_finalize_child_property (obj=0x559aac0c75c0, name=0x559aac0dadc0 "chardevs", opaque=0x559aac0dac10) at qom/object.c:1584
#14 0x0000559aaa233071 in object_property_del_child (obj=0x559aac0c75c0, child=0x559aac0dac10, errp=0x0) at qom/object.c:580
#15 0x0000559aaa233155 in object_unparent (obj=0x559aac0dac10) at qom/object.c:599
#16 0x0000559aaa2fb721 in qemu_chr_cleanup () at chardev/char.c:1159
#17 0x0000559aa9f9b110 in main (argc=54, argv=0x7ffeb62fa998, envp=0x7ffeb62fab50) at vl.c:4539
When chardev is cleaned up, chr_write_lock needs to be destroyed. But
the colo-compare module is not cleaned up normally before it when the
guest poweroff. It is holding chr_write_lock at this time. This will
cause qemu crash.So we add the function of colo_compare_cleanup() before
qemu_chr_cleanup() to fix the bug.
Signed-off-by: Lei Rao <lei.rao@intel.com>
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
Reviewed-by: Lukas Straub <lukasstraub2@web.de>
Tested-by: Lukas Straub <lukasstraub2@web.de>
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2021-06-08 11:23:30 +03:00
|
|
|
/*cleanup colo compare module for COLO*/
|
|
|
|
colo_compare_cleanup();
|
|
|
|
|
2013-01-30 15:12:28 +04:00
|
|
|
/* We may del multiple entries during qemu_del_net_client(),
|
|
|
|
* so QTAILQ_FOREACH_SAFE() is also not safe here.
|
|
|
|
*/
|
|
|
|
while (!QTAILQ_EMPTY(&net_clients)) {
|
|
|
|
nc = QTAILQ_FIRST(&net_clients);
|
qapi: Change Netdev into a flat union
This is a mostly-mechanical conversion that creates a new flat
union 'Netdev' QAPI type that covers all the branches of the
former 'NetClientOptions' simple union, where the branches are
now listed in a new 'NetClientDriver' enum rather than generated
from the simple union. The existence of a flat union has no
change to the command line syntax accepted for new code, and
will make it possible for a future patch to switch the QMP
command to parse a boxed union for no change to valid QMP; but
it does have some ripple effect on the C code when dealing with
the new types.
While making the conversion, note that the 'NetLegacy' type
remains unchanged: it applies only to legacy command line options,
and will not be ported to QMP, so it should remain a wrapper
around a simple union; to avoid confusion, the type named
'NetClientOptions' is now gone, and we introduce 'NetLegacyOptions'
in its place. Then, in the C code, we convert from NetLegacy to
Netdev as soon as possible, so that the bulk of the net stack
only has to deal with one QAPI type, not two. Note that since
the old legacy code always rejected 'hubport', we can just omit
that branch from the new 'NetLegacyOptions' simple union.
Based on an idea originally by Zoltán Kővágó <DirtY.iCE.hu@gmail.com>:
Message-Id: <01a527fbf1a5de880091f98cf011616a78adeeee.1441627176.git.DirtY.iCE.hu@gmail.com>
although the sed script in that patch no longer applies due to
other changes in the tree since then, and I also did some manual
cleanups (such as fixing whitespace to keep checkpatch happy).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1468468228-27827-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Fixup from Eric squashed in]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-14 06:50:23 +03:00
|
|
|
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
|
2013-01-30 15:12:24 +04:00
|
|
|
qemu_del_nic(qemu_get_nic(nc));
|
|
|
|
} else {
|
|
|
|
qemu_del_net_client(nc);
|
|
|
|
}
|
2009-10-08 22:58:28 +04:00
|
|
|
}
|
2014-09-04 12:39:13 +04:00
|
|
|
|
|
|
|
qemu_del_vm_change_state_handler(net_change_state_entry);
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
|
|
|
|
2010-02-11 16:44:58 +03:00
|
|
|
void net_check_clients(void)
|
2008-10-31 22:10:00 +03:00
|
|
|
{
|
2012-07-24 19:35:14 +04:00
|
|
|
NetClientState *nc;
|
2011-05-20 19:50:01 +04:00
|
|
|
int i;
|
2008-10-31 22:10:00 +03:00
|
|
|
|
2012-07-24 19:35:07 +04:00
|
|
|
net_hub_check_clients();
|
2011-03-15 16:20:54 +03:00
|
|
|
|
2012-07-24 19:35:14 +04:00
|
|
|
QTAILQ_FOREACH(nc, &net_clients, next) {
|
|
|
|
if (!nc->peer) {
|
2017-09-11 22:52:53 +03:00
|
|
|
warn_report("%s %s has no peer",
|
2017-09-11 22:52:56 +03:00
|
|
|
nc->info->type == NET_CLIENT_DRIVER_NIC
|
|
|
|
? "nic" : "netdev",
|
|
|
|
nc->name);
|
2010-02-11 16:45:00 +03:00
|
|
|
}
|
|
|
|
}
|
2011-05-20 19:50:01 +04:00
|
|
|
|
|
|
|
/* Check that all NICs requested via -net nic actually got created.
|
|
|
|
* NICs created via -device don't need to be checked here because
|
|
|
|
* they are always instantiated.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < MAX_NICS; i++) {
|
|
|
|
NICInfo *nd = &nd_table[i];
|
|
|
|
if (nd->used && !nd->instantiated) {
|
2017-09-11 22:52:53 +03:00
|
|
|
warn_report("requested NIC (%s, model %s) "
|
|
|
|
"was not created (not supported by this machine?)",
|
|
|
|
nd->name ? nd->name : "anonymous",
|
|
|
|
nd->model ? nd->model : "unspecified");
|
2011-05-20 19:50:01 +04:00
|
|
|
}
|
|
|
|
}
|
2008-10-31 22:10:00 +03:00
|
|
|
}
|
2009-10-06 15:17:16 +04:00
|
|
|
|
2015-03-13 15:35:14 +03:00
|
|
|
static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
|
2009-10-06 15:17:16 +04:00
|
|
|
{
|
2018-02-21 13:18:30 +03:00
|
|
|
return net_client_init(opts, false, errp);
|
2009-10-08 22:58:27 +04:00
|
|
|
}
|
|
|
|
|
2015-03-13 15:35:14 +03:00
|
|
|
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
|
2009-10-08 22:58:27 +04:00
|
|
|
{
|
2020-11-11 13:52:22 +03:00
|
|
|
const char *type = qemu_opt_get(opts, "type");
|
|
|
|
|
|
|
|
if (type && is_help_option(type)) {
|
|
|
|
show_netdevs();
|
|
|
|
exit(0);
|
|
|
|
}
|
2018-02-21 13:18:30 +03:00
|
|
|
return net_client_init(opts, true, errp);
|
2009-10-06 15:17:16 +04:00
|
|
|
}
|
2012-04-20 23:50:25 +04:00
|
|
|
|
2018-02-21 13:18:36 +03:00
|
|
|
/* 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");
|
2022-11-10 15:52:23 +03:00
|
|
|
if (type) {
|
|
|
|
if (g_str_equal(type, "none")) {
|
|
|
|
return 0; /* Nothing to do, default_net is cleared in vl.c */
|
|
|
|
}
|
|
|
|
if (is_help_option(type)) {
|
|
|
|
GPtrArray *nic_models = qemu_get_nic_models(TYPE_DEVICE);
|
|
|
|
show_netdevs();
|
|
|
|
printf("\n");
|
|
|
|
qemu_show_nic_models(type, (const char **)nic_models->pdata);
|
|
|
|
g_ptr_array_free(nic_models, true);
|
|
|
|
exit(0);
|
|
|
|
}
|
2018-02-21 13:18:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
idx = nic_get_free_idx();
|
|
|
|
if (idx == -1 || nb_nics >= MAX_NICS) {
|
|
|
|
error_setg(errp, "no more on-board/default NIC slots available");
|
2012-04-20 23:50:25 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-02-21 13:18:36 +03:00
|
|
|
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) {
|
2021-02-15 12:02:25 +03:00
|
|
|
nd_id = id_generate(ID_NET);
|
2018-02-21 13:18:36 +03:00
|
|
|
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");
|
2018-04-30 10:26:45 +03:00
|
|
|
goto out;
|
2018-02-21 13:18:36 +03:00
|
|
|
}
|
|
|
|
if (is_multicast_ether_addr(ni->macaddr.a)) {
|
|
|
|
error_setg(errp, "NIC cannot have multicast MAC address");
|
2018-04-30 10:26:45 +03:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
2018-02-21 13:18:36 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
2018-04-30 10:26:45 +03:00
|
|
|
out:
|
2018-02-21 13:18:36 +03:00
|
|
|
g_free(nd_id);
|
2012-04-20 23:50:25 +04:00
|
|
|
return ret;
|
2009-10-06 15:17:16 +04:00
|
|
|
}
|
|
|
|
|
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.
More details from Markus:
qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().
net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net. Their desc[] are all empty, which means any
keys are accepted. The result of the parse (a QemuOpts) is stored in
the QemuOptsList.
Note that QemuOpts is flat by design. In some places, we layer non-flat
on top using dotted keys convention, but not here.
net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.
These functions pass the QemuOpts to net_client_init(). They also do
other things with the QemuOpts, which we can ignore here.
net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP
command netdev_add.
The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".
A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax. The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.
This commit paves the way to use of the modern way instead.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:09 +03:00
|
|
|
static void netdev_init_modern(void)
|
|
|
|
{
|
|
|
|
while (!QSIMPLEQ_EMPTY(&nd_queue)) {
|
|
|
|
NetdevQueueEntry *nd = QSIMPLEQ_FIRST(&nd_queue);
|
|
|
|
|
|
|
|
QSIMPLEQ_REMOVE_HEAD(&nd_queue, entry);
|
|
|
|
loc_push_restore(&nd->loc);
|
|
|
|
net_client_init1(nd->nd, true, &error_fatal);
|
|
|
|
loc_pop(&nd->loc);
|
|
|
|
qapi_free_Netdev(nd->nd);
|
|
|
|
g_free(nd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-21 12:09:07 +03:00
|
|
|
void net_init_clients(void)
|
2009-10-06 15:17:16 +04:00
|
|
|
{
|
2014-09-04 12:39:13 +04:00
|
|
|
net_change_state_entry =
|
|
|
|
qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
|
|
|
|
|
2012-07-24 19:35:12 +04:00
|
|
|
QTAILQ_INIT(&net_clients);
|
2009-10-08 22:58:23 +04:00
|
|
|
|
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.
More details from Markus:
qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().
net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net. Their desc[] are all empty, which means any
keys are accepted. The result of the parse (a QemuOpts) is stored in
the QemuOptsList.
Note that QemuOpts is flat by design. In some places, we layer non-flat
on top using dotted keys convention, but not here.
net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.
These functions pass the QemuOpts to net_client_init(). They also do
other things with the QemuOpts, which we can ignore here.
net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP
command netdev_add.
The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".
A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax. The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.
This commit paves the way to use of the modern way instead.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:09 +03:00
|
|
|
netdev_init_modern();
|
|
|
|
|
2022-10-21 12:09:07 +03:00
|
|
|
qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
|
|
|
|
&error_fatal);
|
2018-02-21 13:18:36 +03:00
|
|
|
|
2022-10-21 12:09:07 +03:00
|
|
|
qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL,
|
|
|
|
&error_fatal);
|
2009-10-06 15:17:16 +04:00
|
|
|
|
2022-10-21 12:09:07 +03:00
|
|
|
qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL,
|
|
|
|
&error_fatal);
|
2009-10-06 15:17:16 +04:00
|
|
|
}
|
|
|
|
|
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.
More details from Markus:
qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().
net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net. Their desc[] are all empty, which means any
keys are accepted. The result of the parse (a QemuOpts) is stored in
the QemuOptsList.
Note that QemuOpts is flat by design. In some places, we layer non-flat
on top using dotted keys convention, but not here.
net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.
These functions pass the QemuOpts to net_client_init(). They also do
other things with the QemuOpts, which we can ignore here.
net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP
command netdev_add.
The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".
A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax. The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.
This commit paves the way to use of the modern way instead.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:09 +03:00
|
|
|
/*
|
|
|
|
* Does this -netdev argument use modern rather than traditional syntax?
|
|
|
|
* Modern syntax is to be parsed with netdev_parse_modern().
|
|
|
|
* Traditional syntax is to be parsed with net_client_parse().
|
|
|
|
*/
|
|
|
|
bool netdev_is_modern(const char *optarg)
|
|
|
|
{
|
qapi: net: add stream and dgram netdevs
Copied from socket netdev file and modified to use SocketAddress
to be able to introduce new features like unix socket.
"udp" and "mcast" are squashed into dgram netdev, multicast is detected
according to the IP address type.
"listen" and "connect" modes are managed by stream netdev. An optional
parameter "server" defines the mode (off by default)
The two new types need to be parsed the modern way with -netdev, because
with the traditional way, the "type" field of netdev structure collides with
the "type" field of SocketAddress and prevents the correct evaluation of the
command line option. Moreover the traditional way doesn't allow to use
the same type (SocketAddress) several times with the -netdev option
(needed to specify "local" and "remote" addresses).
The previous commit paved the way for parsing the modern way, but
omitted one detail: how to pick modern vs. traditional, in
netdev_is_modern().
We want to pick based on the value of parameter "type". But how to
extract it from the option argument?
Parsing the option argument, either the modern or the traditional way,
extracts it for us, but only if parsing succeeds.
If parsing fails, there is no good option. No matter which parser we
pick, it'll be the wrong one for some arguments, and the error
reporting will be confusing.
Fortunately, the traditional parser accepts *anything* when called in
a certain way. This maximizes our chance to extract the value of
"type", and in turn minimizes the risk of confusing error reporting.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:11 +03:00
|
|
|
QemuOpts *opts;
|
|
|
|
bool is_modern;
|
|
|
|
const char *type;
|
|
|
|
static QemuOptsList dummy_opts = {
|
|
|
|
.name = "netdev",
|
|
|
|
.implied_opt_name = "type",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
|
|
|
|
.desc = { { } },
|
|
|
|
};
|
|
|
|
|
|
|
|
if (optarg[0] == '{') {
|
|
|
|
/* This is JSON, which means it's modern syntax */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
opts = qemu_opts_create(&dummy_opts, NULL, false, &error_abort);
|
|
|
|
qemu_opts_do_parse(opts, optarg, dummy_opts.implied_opt_name,
|
|
|
|
&error_abort);
|
|
|
|
type = qemu_opt_get(opts, "type");
|
|
|
|
is_modern = !g_strcmp0(type, "stream") || !g_strcmp0(type, "dgram");
|
|
|
|
|
|
|
|
qemu_opts_reset(&dummy_opts);
|
|
|
|
|
|
|
|
return is_modern;
|
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
As qemu_opts_parse_noisily() flattens the QAPI structures ("type" field
of Netdev structure can collides with "type" field of SocketAddress),
we introduce a way to bypass qemu_opts_parse_noisily() and use directly
visit_type_Netdev() to parse the backend parameters.
More details from Markus:
qemu_init() passes the argument of -netdev, -nic, and -net to
net_client_parse().
net_client_parse() parses with qemu_opts_parse_noisily(), passing
QemuOptsList qemu_netdev_opts for -netdev, qemu_nic_opts for -nic, and
qemu_net_opts for -net. Their desc[] are all empty, which means any
keys are accepted. The result of the parse (a QemuOpts) is stored in
the QemuOptsList.
Note that QemuOpts is flat by design. In some places, we layer non-flat
on top using dotted keys convention, but not here.
net_init_clients() iterates over the stored QemuOpts, and passes them to
net_init_netdev(), net_param_nic(), or net_init_client(), respectively.
These functions pass the QemuOpts to net_client_init(). They also do
other things with the QemuOpts, which we can ignore here.
net_client_init() uses the opts visitor to convert the (flat) QemOpts to
a (non-flat) QAPI object Netdev. Netdev is also the argument of QMP
command netdev_add.
The opts visitor was an early attempt to support QAPI in
(QemuOpts-based) CLI. It restricts QAPI types to a certain shape; see
commit eb7ee2cbeb "qapi: introduce OptsVisitor".
A more modern way to support QAPI is qobject_input_visitor_new_str().
It uses keyval_parse() instead of QemuOpts for KEY=VALUE,... syntax, and
it also supports JSON syntax. The former isn't quite as expressive as
JSON, but it's a lot closer than QemuOpts + opts visitor.
This commit paves the way to use of the modern way instead.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2022-10-21 12:09:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* netdev_parse_modern() uses modern, more expressive syntax than
|
|
|
|
* net_client_parse(), but supports only the -netdev option.
|
|
|
|
* netdev_parse_modern() appends to @nd_queue, whereas net_client_parse()
|
|
|
|
* appends to @qemu_netdev_opts.
|
|
|
|
*/
|
|
|
|
void netdev_parse_modern(const char *optarg)
|
|
|
|
{
|
|
|
|
Visitor *v;
|
|
|
|
NetdevQueueEntry *nd;
|
|
|
|
|
|
|
|
v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
|
|
|
|
nd = g_new(NetdevQueueEntry, 1);
|
|
|
|
visit_type_Netdev(v, NULL, &nd->nd, &error_fatal);
|
|
|
|
visit_free(v);
|
|
|
|
loc_save(&nd->loc);
|
|
|
|
|
|
|
|
QSIMPLEQ_INSERT_TAIL(&nd_queue, nd, entry);
|
|
|
|
}
|
|
|
|
|
2022-10-21 12:09:08 +03:00
|
|
|
void net_client_parse(QemuOptsList *opts_list, const char *optarg)
|
2009-10-06 15:17:16 +04:00
|
|
|
{
|
QemuOpts: Wean off qerror_report_err()
qerror_report_err() is a transitional interface to help with
converting existing monitor commands to QMP. It should not be used
elsewhere.
The only remaining user in qemu-option.c is qemu_opts_parse(). Is it
used in QMP context? If not, we can simply replace
qerror_report_err() by error_report_err().
The uses in qemu-img.c, qemu-io.c, qemu-nbd.c and under tests/ are
clearly not in QMP context.
The uses in vl.c aren't either, because the only QMP command handlers
there are qmp_query_status() and qmp_query_machines(), and they don't
call it.
Remaining uses:
* drive_def(): Command line -drive and such, HMP drive_add and pci_add
* hmp_chardev_add(): HMP chardev-add
* monitor_parse_command(): HMP core
* tmp_config_parse(): Command line -tpmdev
* net_host_device_add(): HMP host_net_add
* net_client_parse(): Command line -net and -netdev
* qemu_global_option(): Command line -global
* vnc_parse_func(): Command line -display, -vnc, default display, HMP
change, QMP change. Bummer.
* qemu_pci_hot_add_nic(): HMP pci_add
* usb_net_init(): Command line -usbdevice, HMP usb_add
Propagate errors through qemu_opts_parse(). Create a convenience
function qemu_opts_parse_noisily() that passes errors to
error_report_err(). Switch all non-QMP users outside tests to it.
That leaves vnc_parse_func(). Propagate errors through it. Since I'm
touching it anyway, rename it to vnc_parse().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-02-13 14:50:26 +03:00
|
|
|
if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
|
2022-10-21 12:09:08 +03:00
|
|
|
exit(1);
|
2009-10-06 15:17:16 +04:00
|
|
|
}
|
|
|
|
}
|
2012-03-05 07:08:50 +04:00
|
|
|
|
|
|
|
/* From FreeBSD */
|
|
|
|
/* XXX: optimize */
|
2017-12-15 21:41:43 +03:00
|
|
|
uint32_t net_crc32(const uint8_t *p, int len)
|
2012-03-05 07:08:50 +04:00
|
|
|
{
|
|
|
|
uint32_t crc;
|
|
|
|
int carry, i, j;
|
|
|
|
uint8_t b;
|
|
|
|
|
|
|
|
crc = 0xffffffff;
|
2017-12-15 21:41:43 +03:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
b = *p++;
|
2012-03-05 07:08:50 +04:00
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
|
|
|
|
crc <<= 1;
|
|
|
|
b >>= 1;
|
|
|
|
if (carry) {
|
2017-12-15 21:41:43 +03:00
|
|
|
crc = ((crc ^ POLYNOMIAL_BE) | carry);
|
2012-03-05 07:08:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-15 21:41:43 +03:00
|
|
|
|
|
|
|
return crc;
|
|
|
|
}
|
|
|
|
|
2017-12-15 21:41:44 +03:00
|
|
|
uint32_t net_crc32_le(const uint8_t *p, int len)
|
|
|
|
{
|
|
|
|
uint32_t crc;
|
|
|
|
int carry, i, j;
|
|
|
|
uint8_t b;
|
|
|
|
|
|
|
|
crc = 0xffffffff;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
b = *p++;
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
carry = (crc & 0x1) ^ (b & 0x01);
|
|
|
|
crc >>= 1;
|
|
|
|
b >>= 1;
|
|
|
|
if (carry) {
|
|
|
|
crc ^= POLYNOMIAL_LE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return crc;
|
|
|
|
}
|
|
|
|
|
2012-11-26 19:03:42 +04:00
|
|
|
QemuOptsList qemu_netdev_opts = {
|
|
|
|
.name = "netdev",
|
|
|
|
.implied_opt_name = "type",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
|
2018-02-21 13:18:36 +03:00
|
|
|
.desc = {
|
|
|
|
/*
|
|
|
|
* no elements => accept any params
|
|
|
|
* validation will happen later
|
|
|
|
*/
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
QemuOptsList qemu_nic_opts = {
|
|
|
|
.name = "nic",
|
|
|
|
.implied_opt_name = "type",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_nic_opts.head),
|
2012-11-26 19:03:42 +04:00
|
|
|
.desc = {
|
|
|
|
/*
|
|
|
|
* no elements => accept any params
|
|
|
|
* validation will happen later
|
|
|
|
*/
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
QemuOptsList qemu_net_opts = {
|
|
|
|
.name = "net",
|
|
|
|
.implied_opt_name = "type",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
|
|
|
|
.desc = {
|
|
|
|
/*
|
|
|
|
* no elements => accept any params
|
|
|
|
* validation will happen later
|
|
|
|
*/
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
2016-05-13 10:35:19 +03:00
|
|
|
|
|
|
|
void net_socket_rs_init(SocketReadState *rs,
|
2017-07-04 09:53:46 +03:00
|
|
|
SocketReadStateFinalize *finalize,
|
|
|
|
bool vnet_hdr)
|
2016-05-13 10:35:19 +03:00
|
|
|
{
|
|
|
|
rs->state = 0;
|
2017-07-04 09:53:46 +03:00
|
|
|
rs->vnet_hdr = vnet_hdr;
|
2016-05-13 10:35:19 +03:00
|
|
|
rs->index = 0;
|
|
|
|
rs->packet_len = 0;
|
2017-07-04 09:53:46 +03:00
|
|
|
rs->vnet_hdr_len = 0;
|
2016-05-13 10:35:19 +03:00
|
|
|
memset(rs->buf, 0, sizeof(rs->buf));
|
|
|
|
rs->finalize = finalize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns
|
2016-08-18 06:23:25 +03:00
|
|
|
* 0: success
|
|
|
|
* -1: error occurs
|
2016-05-13 10:35:19 +03:00
|
|
|
*/
|
|
|
|
int net_fill_rstate(SocketReadState *rs, const uint8_t *buf, int size)
|
|
|
|
{
|
|
|
|
unsigned int l;
|
|
|
|
|
|
|
|
while (size > 0) {
|
2017-07-04 09:53:46 +03:00
|
|
|
/* Reassemble a packet from the network.
|
|
|
|
* 0 = getting length.
|
|
|
|
* 1 = getting vnet header length.
|
|
|
|
* 2 = getting data.
|
|
|
|
*/
|
|
|
|
switch (rs->state) {
|
2016-05-13 10:35:19 +03:00
|
|
|
case 0:
|
|
|
|
l = 4 - rs->index;
|
|
|
|
if (l > size) {
|
|
|
|
l = size;
|
|
|
|
}
|
|
|
|
memcpy(rs->buf + rs->index, buf, l);
|
|
|
|
buf += l;
|
|
|
|
size -= l;
|
|
|
|
rs->index += l;
|
|
|
|
if (rs->index == 4) {
|
|
|
|
/* got length */
|
|
|
|
rs->packet_len = ntohl(*(uint32_t *)rs->buf);
|
|
|
|
rs->index = 0;
|
2017-07-04 09:53:46 +03:00
|
|
|
if (rs->vnet_hdr) {
|
|
|
|
rs->state = 1;
|
|
|
|
} else {
|
|
|
|
rs->state = 2;
|
|
|
|
rs->vnet_hdr_len = 0;
|
|
|
|
}
|
2016-05-13 10:35:19 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
2017-07-04 09:53:46 +03:00
|
|
|
l = 4 - rs->index;
|
|
|
|
if (l > size) {
|
|
|
|
l = size;
|
|
|
|
}
|
|
|
|
memcpy(rs->buf + rs->index, buf, l);
|
|
|
|
buf += l;
|
|
|
|
size -= l;
|
|
|
|
rs->index += l;
|
|
|
|
if (rs->index == 4) {
|
|
|
|
/* got vnet header length */
|
|
|
|
rs->vnet_hdr_len = ntohl(*(uint32_t *)rs->buf);
|
|
|
|
rs->index = 0;
|
|
|
|
rs->state = 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2016-05-13 10:35:19 +03:00
|
|
|
l = rs->packet_len - rs->index;
|
|
|
|
if (l > size) {
|
|
|
|
l = size;
|
|
|
|
}
|
|
|
|
if (rs->index + l <= sizeof(rs->buf)) {
|
|
|
|
memcpy(rs->buf + rs->index, buf, l);
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "serious error: oversized packet received,"
|
|
|
|
"connection terminated.\n");
|
|
|
|
rs->index = rs->state = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rs->index += l;
|
|
|
|
buf += l;
|
|
|
|
size -= l;
|
|
|
|
if (rs->index >= rs->packet_len) {
|
|
|
|
rs->index = 0;
|
|
|
|
rs->state = 0;
|
2016-11-04 18:46:33 +03:00
|
|
|
assert(rs->finalize);
|
|
|
|
rs->finalize(rs);
|
2016-05-13 10:35:19 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-08-18 06:23:25 +03:00
|
|
|
|
|
|
|
assert(size == 0);
|
2016-05-13 10:35:19 +03:00
|
|
|
return 0;
|
|
|
|
}
|