-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1
 
 iQEcBAABAgAGBQJanLRTAAoJEO8Ells5jWIRAxsH/3wX62o+msLjJHakjcu2OTMG
 vdhnB8GfjC5HgMYbovG7TJ95KXg7VRodwru9zgJheTK7DG8fG0nFRuzr8L2tSAph
 3s0YTFYDXJ6MBYD//ubdX+jNnchIvMlTX6yheAzcXvQb+nCcN2efN0XpSlGR+g4D
 wGi1lWKurGEJE6RUfYPpbbUkjXjbbKyclE0RL+WBmmyruerXI8OxuXQ3GuHK75fb
 cZLiToyP9+qnnDyT4lceG5vGRjYLtL8t1nB01M4UTr+tlCkMMsoOjufzGB/CDUdm
 oGi1OuKRw06xTLroUJ/uiwSKQH6dMbrv6sLvk92dHnL9k2ZAjv2bVAgz8eAG7o0=
 =pPIZ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging

# gpg: Signature made Mon 05 Mar 2018 03:06:59 GMT
# gpg:                using RSA key EF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 215D 46F4 8246 689E C77F  3562 EF04 965B 398D 6211

* remotes/jasowang/tags/net-pull-request:
  tap: setting error appropriately when calling net_init_tap_one()
  hw/net: Remove unnecessary header includes
  net: Add a new convenience option "--nic" to configure default/on-board NICs
  net: Remove the deprecated 'host_net_add' and 'host_net_remove' HMP commands
  net: Remove the deprecated way of dumping network packets
  net: Make net_client_init() static
  net: Only show vhost-user in the help text if CONFIG_POSIX is defined
  net: List available netdevs with "-netdev help"
  net: Move error reporting from net_init_client/netdev to the calling site

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-03-05 14:27:24 +00:00
commit 41dfc0dc55
21 changed files with 190 additions and 391 deletions

View file

@ -1288,36 +1288,6 @@ STEXI
@item pcie_aer_inject_error @item pcie_aer_inject_error
@findex pcie_aer_inject_error @findex pcie_aer_inject_error
Inject PCIe AER error Inject PCIe AER error
ETEXI
{
.name = "host_net_add",
.args_type = "device:s,opts:s?",
.params = "tap|user|socket|vde|netmap|bridge|vhost-user|dump [options]",
.help = "add host VLAN client (deprecated, use netdev_add instead)",
.cmd = hmp_host_net_add,
.command_completion = host_net_add_completion,
},
STEXI
@item host_net_add
@findex host_net_add
Add host VLAN client. Deprecated, please use @code{netdev_add} instead.
ETEXI
{
.name = "host_net_remove",
.args_type = "vlan_id:i,device:s",
.params = "vlan_id name",
.help = "remove host VLAN client (deprecated, use netdev_del instead)",
.cmd = hmp_host_net_remove,
.command_completion = host_net_remove_completion,
},
STEXI
@item host_net_remove
@findex host_net_remove
Remove host VLAN client. Deprecated, please use @code{netdev_del} instead.
ETEXI ETEXI
{ {

3
hmp.h
View file

@ -132,9 +132,6 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
const char *str); const char *str);
void migrate_set_parameter_completion(ReadLineState *rs, int nb_args, void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
const char *str); const char *str);
void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str);
void host_net_remove_completion(ReadLineState *rs, int nb_args,
const char *str);
void delvm_completion(ReadLineState *rs, int nb_args, const char *str); void delvm_completion(ReadLineState *rs, int nb_args, const char *str);
void loadvm_completion(ReadLineState *rs, int nb_args, const char *str); void loadvm_completion(ReadLineState *rs, int nb_args, const char *str);
void hmp_rocker(Monitor *mon, const QDict *qdict); void hmp_rocker(Monitor *mon, const QDict *qdict);

View file

@ -30,7 +30,6 @@
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "net/net.h" #include "net/net.h"
#include "net/checksum.h" #include "net/checksum.h"
#include "hw/loader.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "qemu/iov.h" #include "qemu/iov.h"

View file

@ -36,10 +36,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "net/net.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qemu/sockets.h"
#include "hw/sparc/sparc32_dma.h" #include "hw/sparc/sparc32_dma.h"
#include "hw/net/lance.h" #include "hw/net/lance.h"
#include "trace.h" #include "trace.h"

View file

@ -23,10 +23,8 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "net/net.h"
#include "net/eth.h" #include "net/eth.h"
#include "ne2000.h" #include "ne2000.h"
#include "hw/loader.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
/* debug NE2000 card */ /* debug NE2000 card */

View file

@ -30,7 +30,6 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "net/net.h" #include "net/net.h"
#include "hw/loader.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"

View file

@ -40,7 +40,6 @@
#include "net/net.h" #include "net/net.h"
#include "net/eth.h" #include "net/eth.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qemu/sockets.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "trace.h" #include "trace.h"

View file

@ -58,9 +58,7 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "net/net.h" #include "net/net.h"
#include "net/eth.h" #include "net/eth.h"
#include "hw/loader.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "qemu/iov.h"
/* debug RTL8139 card */ /* debug RTL8139 card */
//#define DEBUG_RTL8139 1 //#define DEBUG_RTL8139 1

View file

@ -28,7 +28,6 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "net/net.h" #include "net/net.h"
#include "net/checksum.h"
#ifdef DEBUG_XGMAC #ifdef DEBUG_XGMAC
#define DEBUGF_BRK(message, args...) do { \ #define DEBUGF_BRK(message, args...) do { \

View file

@ -204,9 +204,8 @@ extern const char *host_net_devices[];
extern const char *legacy_tftp_prefix; extern const char *legacy_tftp_prefix;
extern const char *legacy_bootp_filename; extern const char *legacy_bootp_filename;
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp);
int net_client_parse(QemuOptsList *opts_list, const char *str); int net_client_parse(QemuOptsList *opts_list, const char *str);
int net_init_clients(void); int net_init_clients(Error **errp);
void net_check_clients(void); void net_check_clients(void);
void net_cleanup(void); void net_cleanup(void);
void hmp_host_net_add(Monitor *mon, const QDict *qdict); void hmp_host_net_add(Monitor *mon, const QDict *qdict);
@ -228,7 +227,6 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd);
#define POLYNOMIAL_LE 0xedb88320 #define POLYNOMIAL_LE 0xedb88320
uint32_t net_crc32(const uint8_t *p, int len); uint32_t net_crc32(const uint8_t *p, int len);
uint32_t net_crc32_le(const uint8_t *p, int len); uint32_t net_crc32_le(const uint8_t *p, int len);
unsigned compute_mcast_idx(const uint8_t *ep);
#define vmstate_offset_macaddr(_state, _field) \ #define vmstate_offset_macaddr(_state, _field) \
vmstate_offset_array(_state, _field.a, uint8_t, \ vmstate_offset_array(_state, _field.a, uint8_t, \

View file

@ -4,6 +4,9 @@
#include "net/net.h" #include "net/net.h"
#include "hw/virtio/vhost-backend.h" #include "hw/virtio/vhost-backend.h"
#define VHOST_NET_INIT_FAILED \
"vhost-net requested but could not be initialized"
struct vhost_net; struct vhost_net;
typedef struct vhost_net VHostNetState; typedef struct vhost_net VHostNetState;

View file

@ -198,6 +198,7 @@ extern QemuOptsList bdrv_runtime_opts;
extern QemuOptsList qemu_chardev_opts; extern QemuOptsList qemu_chardev_opts;
extern QemuOptsList qemu_device_opts; extern QemuOptsList qemu_device_opts;
extern QemuOptsList qemu_netdev_opts; extern QemuOptsList qemu_netdev_opts;
extern QemuOptsList qemu_nic_opts;
extern QemuOptsList qemu_net_opts; extern QemuOptsList qemu_net_opts;
extern QemuOptsList qemu_global_opts; extern QemuOptsList qemu_global_opts;
extern QemuOptsList qemu_mon_opts; extern QemuOptsList qemu_mon_opts;

View file

@ -3581,67 +3581,6 @@ void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
} }
} }
void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str)
{
int i;
size_t len;
if (nb_args != 2) {
return;
}
len = strlen(str);
readline_set_completion_index(rs, len);
for (i = 0; host_net_devices[i]; i++) {
if (!strncmp(host_net_devices[i], str, len)) {
readline_add_completion(rs, host_net_devices[i]);
}
}
}
void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
{
NetClientState *ncs[MAX_QUEUE_NUM];
int count, i, len;
len = strlen(str);
readline_set_completion_index(rs, len);
if (nb_args == 2) {
count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_DRIVER_NONE,
MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
int id;
char name[16];
if (net_hub_id_for_client(ncs[i], &id)) {
continue;
}
snprintf(name, sizeof(name), "%d", id);
if (!strncmp(str, name, len)) {
readline_add_completion(rs, name);
}
}
return;
} else if (nb_args == 3) {
count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_DRIVER_NIC,
MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
int id;
const char *name;
if (ncs[i]->info->type == NET_CLIENT_DRIVER_HUBPORT ||
net_hub_id_for_client(ncs[i], &id)) {
continue;
}
name = ncs[i]->name;
if (!strncmp(str, name, len)) {
readline_add_completion(rs, name);
}
}
return;
}
}
static void vm_completion(ReadLineState *rs, const char *str) static void vm_completion(ReadLineState *rs, const char *str)
{ {
size_t len; size_t len;

View file

@ -109,7 +109,7 @@ static int net_dump_state_init(DumpState *s, const char *filename,
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644); fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
if (fd < 0) { if (fd < 0) {
error_setg_errno(errp, errno, "-net dump: can't open %s", filename); error_setg_errno(errp, errno, "net dump: can't open %s", filename);
return -1; return -1;
} }
@ -122,7 +122,7 @@ static int net_dump_state_init(DumpState *s, const char *filename,
hdr.linktype = 1; hdr.linktype = 1;
if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
error_setg_errno(errp, errno, "-net dump write error"); error_setg_errno(errp, errno, "net dump write error");
close(fd); close(fd);
return -1; return -1;
} }
@ -136,104 +136,6 @@ static int net_dump_state_init(DumpState *s, const char *filename,
return 0; return 0;
} }
/* Dumping via VLAN netclient */
struct DumpNetClient {
NetClientState nc;
DumpState ds;
};
typedef struct DumpNetClient DumpNetClient;
static ssize_t dumpclient_receive(NetClientState *nc, const uint8_t *buf,
size_t size)
{
DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
struct iovec iov = {
.iov_base = (void *)buf,
.iov_len = size
};
return dump_receive_iov(&dc->ds, &iov, 1);
}
static ssize_t dumpclient_receive_iov(NetClientState *nc,
const struct iovec *iov, int cnt)
{
DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
return dump_receive_iov(&dc->ds, iov, cnt);
}
static void dumpclient_cleanup(NetClientState *nc)
{
DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
dump_cleanup(&dc->ds);
}
static NetClientInfo net_dump_info = {
.type = NET_CLIENT_DRIVER_DUMP,
.size = sizeof(DumpNetClient),
.receive = dumpclient_receive,
.receive_iov = dumpclient_receive_iov,
.cleanup = dumpclient_cleanup,
};
int net_init_dump(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp)
{
int len, rc;
const char *file;
char def_file[128];
const NetdevDumpOptions *dump;
NetClientState *nc;
DumpNetClient *dnc;
assert(netdev->type == NET_CLIENT_DRIVER_DUMP);
dump = &netdev->u.dump;
assert(peer);
error_report("'-net dump' is deprecated. "
"Please use '-object filter-dump' instead.");
if (dump->has_file) {
file = dump->file;
} else {
int id;
int ret;
ret = net_hub_id_for_client(peer, &id);
assert(ret == 0); /* peer must be on a hub */
snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", id);
file = def_file;
}
if (dump->has_len) {
if (dump->len > INT_MAX) {
error_setg(errp, "invalid length: %"PRIu64, dump->len);
return -1;
}
len = dump->len;
} else {
len = 65536;
}
nc = qemu_new_net_client(&net_dump_info, peer, "dump", name);
snprintf(nc->info_str, sizeof(nc->info_str),
"dump to %s (len=%d)", file, len);
dnc = DO_UPCAST(DumpNetClient, nc, nc);
rc = net_dump_state_init(&dnc->ds, file, len, errp);
if (rc) {
qemu_del_net_client(nc);
}
return rc;
}
/* Dumping via filter */
#define TYPE_FILTER_DUMP "filter-dump" #define TYPE_FILTER_DUMP "filter-dump"
#define FILTER_DUMP(obj) \ #define FILTER_DUMP(obj) \

239
net/net.c
View file

@ -60,26 +60,6 @@
static VMChangeStateEntry *net_change_state_entry; static VMChangeStateEntry *net_change_state_entry;
static QTAILQ_HEAD(, NetClientState) net_clients; static QTAILQ_HEAD(, NetClientState) net_clients;
const char *host_net_devices[] = {
"tap",
"socket",
"dump",
#ifdef CONFIG_NET_BRIDGE
"bridge",
#endif
#ifdef CONFIG_NETMAP
"netmap",
#endif
#ifdef CONFIG_SLIRP
"user",
#endif
#ifdef CONFIG_VDE
"vde",
#endif
"vhost-user",
NULL,
};
/***********************************************************/ /***********************************************************/
/* network device redirectors */ /* network device redirectors */
@ -967,7 +947,6 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
#ifdef CONFIG_NETMAP #ifdef CONFIG_NETMAP
[NET_CLIENT_DRIVER_NETMAP] = net_init_netmap, [NET_CLIENT_DRIVER_NETMAP] = net_init_netmap,
#endif #endif
[NET_CLIENT_DRIVER_DUMP] = net_init_dump,
#ifdef CONFIG_NET_BRIDGE #ifdef CONFIG_NET_BRIDGE
[NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge, [NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
#endif #endif
@ -993,8 +972,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
netdev = object; netdev = object;
name = netdev->id; name = netdev->id;
if (netdev->type == NET_CLIENT_DRIVER_DUMP || if (netdev->type == NET_CLIENT_DRIVER_NIC ||
netdev->type == NET_CLIENT_DRIVER_NIC ||
!net_client_init_fun[netdev->type]) { !net_client_init_fun[netdev->type]) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a netdev backend type"); "a netdev backend type");
@ -1036,10 +1014,6 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
legacy.type = NET_CLIENT_DRIVER_VDE; legacy.type = NET_CLIENT_DRIVER_VDE;
legacy.u.vde = opts->u.vde; legacy.u.vde = opts->u.vde;
break; break;
case NET_LEGACY_OPTIONS_TYPE_DUMP:
legacy.type = NET_CLIENT_DRIVER_DUMP;
legacy.u.dump = opts->u.dump;
break;
case NET_LEGACY_OPTIONS_TYPE_BRIDGE: case NET_LEGACY_OPTIONS_TYPE_BRIDGE:
legacy.type = NET_CLIENT_DRIVER_BRIDGE; legacy.type = NET_CLIENT_DRIVER_BRIDGE;
legacy.u.bridge = opts->u.bridge; legacy.u.bridge = opts->u.bridge;
@ -1086,15 +1060,50 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp)
return 0; return 0;
} }
static void show_netdevs(void)
{
int idx;
const char *available_netdevs[] = {
"socket",
"hubport",
"tap",
#ifdef CONFIG_SLIRP
"user",
#endif
#ifdef CONFIG_L2TPV3
"l2tpv3",
#endif
#ifdef CONFIG_VDE
"vde",
#endif
#ifdef CONFIG_NET_BRIDGE
"bridge",
#endif
#ifdef CONFIG_NETMAP
"netmap",
#endif
#ifdef CONFIG_POSIX
"vhost-user",
#endif
};
int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) printf("Available netdev backend types:\n");
for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
puts(available_netdevs[idx]);
}
}
static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
{ {
void *object = NULL; void *object = NULL;
Error *err = NULL; Error *err = NULL;
int ret = -1; int ret = -1;
Visitor *v = opts_visitor_new(opts); Visitor *v = opts_visitor_new(opts);
{ if (is_netdev && is_help_option(qemu_opt_get(opts, "type"))) {
show_netdevs();
exit(0);
} else {
/* Parse convenience option format ip6-net=fec0::0[/64] */ /* Parse convenience option format ip6-net=fec0::0[/64] */
const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
@ -1146,81 +1155,6 @@ int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
return ret; return ret;
} }
static int net_host_check_device(const char *device)
{
int i;
for (i = 0; host_net_devices[i]; i++) {
if (!strncmp(host_net_devices[i], device,
strlen(host_net_devices[i]))) {
return 1;
}
}
return 0;
}
void hmp_host_net_add(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_str(qdict, "device");
const char *opts_str = qdict_get_try_str(qdict, "opts");
Error *local_err = NULL;
QemuOpts *opts;
static bool warned;
if (!warned && !qtest_enabled()) {
error_report("host_net_add is deprecated, use netdev_add instead");
warned = true;
}
if (!net_host_check_device(device)) {
monitor_printf(mon, "invalid host network device %s\n", device);
return;
}
opts = qemu_opts_parse_noisily(qemu_find_opts("net"),
opts_str ? opts_str : "", false);
if (!opts) {
return;
}
qemu_opt_set(opts, "type", device, &error_abort);
net_client_init(opts, false, &local_err);
if (local_err) {
error_report_err(local_err);
monitor_printf(mon, "adding host network device %s failed\n", device);
}
}
void hmp_host_net_remove(Monitor *mon, const QDict *qdict)
{
NetClientState *nc;
int vlan_id = qdict_get_int(qdict, "vlan_id");
const char *device = qdict_get_str(qdict, "device");
static bool warned;
if (!warned && !qtest_enabled()) {
error_report("host_net_remove is deprecated, use netdev_del instead");
warned = true;
}
nc = net_hub_find_client_by_name(vlan_id, device);
if (!nc) {
error_report("Host network device '%s' on hub '%d' not found",
device, vlan_id);
return;
}
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
error_report("invalid host network device '%s'", device);
return;
}
qemu_del_net_client(nc->peer);
qemu_del_net_client(nc);
qemu_opts_del(qemu_opts_find(qemu_find_opts("net"), device));
}
void netdev_add(QemuOpts *opts, Error **errp) void netdev_add(QemuOpts *opts, Error **errp)
{ {
net_client_init(opts, true, errp); net_client_init(opts, true, errp);
@ -1520,46 +1454,92 @@ void net_check_clients(void)
static int net_init_client(void *dummy, QemuOpts *opts, Error **errp) static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
{ {
Error *local_err = NULL; return net_client_init(opts, false, errp);
net_client_init(opts, false, &local_err);
if (local_err) {
error_report_err(local_err);
return -1;
}
return 0;
} }
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp) static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
{ {
Error *local_err = NULL; return net_client_init(opts, true, errp);
int ret; }
ret = net_client_init(opts, true, &local_err); /* For the convenience "--nic" parameter */
if (local_err) { static int net_param_nic(void *dummy, QemuOpts *opts, Error **errp)
error_report_err(local_err); {
char *mac, *nd_id;
int idx, ret;
NICInfo *ni;
const char *type;
type = qemu_opt_get(opts, "type");
if (type && g_str_equal(type, "none")) {
return 0; /* Nothing to do, default_net is cleared in vl.c */
}
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
error_setg(errp, "no more on-board/default NIC slots available");
return -1; return -1;
} }
if (!type) {
qemu_opt_set(opts, "type", "user", &error_abort);
}
ni = &nd_table[idx];
memset(ni, 0, sizeof(*ni));
ni->model = qemu_opt_get_del(opts, "model");
/* Create an ID if the user did not specify one */
nd_id = g_strdup(qemu_opts_id(opts));
if (!nd_id) {
nd_id = g_strdup_printf("__org.qemu.nic%i\n", idx);
qemu_opts_set_id(opts, nd_id);
}
/* Handle MAC address */
mac = qemu_opt_get_del(opts, "mac");
if (mac) {
ret = net_parse_macaddr(ni->macaddr.a, mac);
g_free(mac);
if (ret) {
error_setg(errp, "invalid syntax for ethernet address");
return -1;
}
if (is_multicast_ether_addr(ni->macaddr.a)) {
error_setg(errp, "NIC cannot have multicast MAC address");
return -1;
}
}
qemu_macaddr_default_if_unset(&ni->macaddr);
ret = net_client_init(opts, true, errp);
if (ret == 0) {
ni->netdev = qemu_find_netdev(nd_id);
ni->used = true;
nb_nics++;
}
g_free(nd_id);
return ret; return ret;
} }
int net_init_clients(void) int net_init_clients(Error **errp)
{ {
QemuOptsList *net = qemu_find_opts("net");
net_change_state_entry = net_change_state_entry =
qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL); qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
QTAILQ_INIT(&net_clients); QTAILQ_INIT(&net_clients);
if (qemu_opts_foreach(qemu_find_opts("netdev"), if (qemu_opts_foreach(qemu_find_opts("netdev"),
net_init_netdev, NULL, NULL)) { net_init_netdev, NULL, errp)) {
return -1; return -1;
} }
if (qemu_opts_foreach(net, net_init_client, NULL, NULL)) { if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) {
return -1;
}
if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, errp)) {
return -1; return -1;
} }
@ -1634,6 +1614,19 @@ QemuOptsList qemu_netdev_opts = {
}, },
}; };
QemuOptsList qemu_nic_opts = {
.name = "nic",
.implied_opt_name = "type",
.head = QTAILQ_HEAD_INITIALIZER(qemu_nic_opts.head),
.desc = {
/*
* no elements => accept any params
* validation will happen later
*/
{ /* end of list */ }
},
};
QemuOptsList qemu_net_opts = { QemuOptsList qemu_net_opts = {
.name = "net", .name = "net",
.implied_opt_name = "type", .implied_opt_name = "type",

View file

@ -686,14 +686,23 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
if (vhostfdname) { if (vhostfdname) {
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err); vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
if (vhostfd == -1) { if (vhostfd == -1) {
if (tap->has_vhostforce && tap->vhostforce) {
error_propagate(errp, err); error_propagate(errp, err);
} else {
warn_report_err(err);
}
return; return;
} }
} else { } else {
vhostfd = open("/dev/vhost-net", O_RDWR); vhostfd = open("/dev/vhost-net", O_RDWR);
if (vhostfd < 0) { if (vhostfd < 0) {
if (tap->has_vhostforce && tap->vhostforce) {
error_setg_errno(errp, errno, error_setg_errno(errp, errno,
"tap: open vhost char device failed"); "tap: open vhost char device failed");
} else {
warn_report("tap: open vhost char device failed: %s",
strerror(errno));
}
return; return;
} }
fcntl(vhostfd, F_SETFL, O_NONBLOCK); fcntl(vhostfd, F_SETFL, O_NONBLOCK);
@ -702,8 +711,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
s->vhost_net = vhost_net_init(&options); s->vhost_net = vhost_net_init(&options);
if (!s->vhost_net) { if (!s->vhost_net) {
error_setg(errp, if (tap->has_vhostforce && tap->vhostforce) {
"vhost-net requested but could not be initialized"); error_setg(errp, VHOST_NET_INIT_FAILED);
} else {
warn_report(VHOST_NET_INIT_FAILED);
}
return; return;
} }
} else if (vhostfdname) { } else if (vhostfdname) {

View file

@ -39,8 +39,8 @@
# #
# Add a network backend. # Add a network backend.
# #
# @type: the type of network backend. Current valid values are 'user', 'tap', # @type: the type of network backend. Possible values are listed in
# 'vde', 'socket', 'dump' and 'bridge' # NetClientDriver (excluding 'none' and 'nic')
# #
# @id: the name of the new network backend # @id: the name of the new network backend
# #
@ -371,23 +371,6 @@
'*group': 'str', '*group': 'str',
'*mode': 'uint16' } } '*mode': 'uint16' } }
##
# @NetdevDumpOptions:
#
# Dump VLAN network traffic to a file.
#
# @len: per-packet size limit (64k default). Understands [TGMKkb]
# suffixes.
#
# @file: dump file path (default is qemu-vlan0.pcap)
#
# Since: 1.2
##
{ 'struct': 'NetdevDumpOptions',
'data': {
'*len': 'size',
'*file': 'str' } }
## ##
# @NetdevBridgeOptions: # @NetdevBridgeOptions:
# #
@ -466,9 +449,11 @@
# Available netdev drivers. # Available netdev drivers.
# #
# Since: 2.7 # Since: 2.7
#
# 'dump' - removed with 2.12
## ##
{ 'enum': 'NetClientDriver', { 'enum': 'NetClientDriver',
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'dump', 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
'bridge', 'hubport', 'netmap', 'vhost-user' ] } 'bridge', 'hubport', 'netmap', 'vhost-user' ] }
## ##
@ -495,7 +480,6 @@
'l2tpv3': 'NetdevL2TPv3Options', 'l2tpv3': 'NetdevL2TPv3Options',
'socket': 'NetdevSocketOptions', 'socket': 'NetdevSocketOptions',
'vde': 'NetdevVdeOptions', 'vde': 'NetdevVdeOptions',
'dump': 'NetdevDumpOptions',
'bridge': 'NetdevBridgeOptions', 'bridge': 'NetdevBridgeOptions',
'hubport': 'NetdevHubPortOptions', 'hubport': 'NetdevHubPortOptions',
'netmap': 'NetdevNetmapOptions', 'netmap': 'NetdevNetmapOptions',
@ -530,7 +514,7 @@
## ##
{ 'enum': 'NetLegacyOptionsType', { 'enum': 'NetLegacyOptionsType',
'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', 'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
'dump', 'bridge', 'netmap', 'vhost-user'] } 'bridge', 'netmap', 'vhost-user'] }
## ##
# @NetLegacyOptions: # @NetLegacyOptions:
@ -550,7 +534,6 @@
'l2tpv3': 'NetdevL2TPv3Options', 'l2tpv3': 'NetdevL2TPv3Options',
'socket': 'NetdevSocketOptions', 'socket': 'NetdevSocketOptions',
'vde': 'NetdevVdeOptions', 'vde': 'NetdevVdeOptions',
'dump': 'NetdevDumpOptions',
'bridge': 'NetdevBridgeOptions', 'bridge': 'NetdevBridgeOptions',
'netmap': 'NetdevNetmapOptions', 'netmap': 'NetdevNetmapOptions',
'vhost-user': 'NetdevVhostUserOptions' } } 'vhost-user': 'NetdevVhostUserOptions' } }

View file

@ -2707,12 +2707,6 @@ that can be specified with the ``-device'' parameter.
The drive addr argument is replaced by the the addr argument The drive addr argument is replaced by the the addr argument
that can be specified with the ``-device'' parameter. that can be specified with the ``-device'' parameter.
@subsection -net dump (since 2.10.0)
The ``--net dump'' argument is now replaced with the
``-object filter-dump'' argument which works in combination
with the modern ``-netdev`` backends instead.
@subsection -usbdevice (since 2.10.0) @subsection -usbdevice (since 2.10.0)
The ``-usbdevice DEV'' argument is now a synonym for setting The ``-usbdevice DEV'' argument is now a synonym for setting
@ -2766,16 +2760,6 @@ from qcow2 images.
The ``query-cpus'' command is replaced by the ``query-cpus-fast'' command. The ``query-cpus'' command is replaced by the ``query-cpus-fast'' command.
@section System emulator human monitor commands
@subsection host_net_add (since 2.10.0)
The ``host_net_add'' command is replaced by the ``netdev_add'' command.
@subsection host_net_remove (since 2.10.0)
The ``host_net_remove'' command is replaced by the ``netdev_del'' command.
@section System emulator devices @section System emulator devices
@subsection ivshmem (since 2.6.0) @subsection ivshmem (since 2.6.0)

View file

@ -1998,19 +1998,40 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
" VALE port (created on the fly) called 'name' ('nmname' is name of the \n" " VALE port (created on the fly) called 'name' ('nmname' is name of the \n"
" netmap device, defaults to '/dev/netmap')\n" " netmap device, defaults to '/dev/netmap')\n"
#endif #endif
#ifdef CONFIG_POSIX
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n" "-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
" configure a vhost-user network, backed by a chardev 'dev'\n" " configure a vhost-user network, backed by a chardev 'dev'\n"
#endif
"-netdev hubport,id=str,hubid=n[,netdev=nd]\n" "-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL) " configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
DEF("nic", HAS_ARG, QEMU_OPTION_nic,
"--nic [tap|bridge|"
#ifdef CONFIG_SLIRP
"user|"
#endif
#ifdef __linux__
"l2tpv3|"
#endif
#ifdef CONFIG_VDE
"vde|"
#endif
#ifdef CONFIG_NETMAP
"netmap|"
#endif
#ifdef CONFIG_POSIX
"vhost-user|"
#endif
"socket][,option][,...][mac=macaddr]\n"
" initialize an on-board / default host NIC (using MAC address\n"
" macaddr) and connect it to the given host network backend\n"
"--nic none use it alone to have zero network devices (the default is to\n"
" provided a 'user' network connection)\n",
QEMU_ARCH_ALL)
DEF("net", HAS_ARG, QEMU_OPTION_net, DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n" "-net nic[,vlan=n][,netdev=nd][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
" configure or create an on-board (or machine default) NIC and\n" " configure or create an on-board (or machine default) NIC and\n"
" connect it either to VLAN 'n' or the netdev 'nd' (for pluggable\n" " connect it either to VLAN 'n' or the netdev 'nd' (for pluggable\n"
" NICs please use '-device devtype,netdev=nd' instead)\n" " NICs please use '-device devtype,netdev=nd' instead)\n"
"-net dump[,vlan=n][,file=f][,len=n]\n"
" dump traffic on vlan 'n' to file 'f' (max n bytes per packet)\n"
"-net none use it alone to have zero network devices. If no -net option\n"
" is provided, the default is '-net nic -net user'\n"
"-net [" "-net ["
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
"user|" "user|"
@ -2456,16 +2477,17 @@ qemu -m 512 -object memory-backend-file,id=mem,size=512M,mem-path=/hugetlbfs,sha
-device virtio-net-pci,netdev=net0 -device virtio-net-pci,netdev=net0
@end example @end example
@item -net dump[,vlan=@var{n}][,file=@var{file}][,len=@var{len}] @item --nic [tap|bridge|user|l2tpv3|vde|netmap|vhost-user|socket][,...][,mac=macaddr]
Dump network traffic on VLAN @var{n} to file @var{file} (@file{qemu-vlan0.pcap} by default).
At most @var{len} bytes (64k by default) per packet are stored. The file format is
libpcap, so it can be analyzed with tools such as tcpdump or Wireshark.
Note: For devices created with '-netdev', use '-object filter-dump,...' instead.
@item -net none This option is a shortcut for setting both, the on-board (default) guest NIC
Indicate that no network devices should be configured. It is used to hardware and the host network backend in one go. The host backend options are
override the default configuration (@option{-net nic -net user}) which the same as with the corresponding @option{--netdev} option. The guest NIC
is activated if no @option{-net} options are provided. hardware MAC address can be set with @option{mac=@var{macaddr}}.
@item --nic none
Indicate that no network devices should be configured. It is used to override
the default configuration (default NIC with @option{--net user} backend) which
is activated if no other networking options are provided.
ETEXI ETEXI
STEXI STEXI

View file

@ -37,10 +37,8 @@ static const char *hmp_cmds[] = {
"dump-guest-memory /dev/null 0 4096", "dump-guest-memory /dev/null 0 4096",
"dump-guest-memory /dev/null", "dump-guest-memory /dev/null",
"gdbserver", "gdbserver",
"host_net_add user id=net0",
"hostfwd_add tcp::43210-:43210", "hostfwd_add tcp::43210-:43210",
"hostfwd_remove tcp::43210-:43210", "hostfwd_remove tcp::43210-:43210",
"host_net_remove 0 net0",
"i /w 0", "i /w 0",
"log all", "log all",
"log none", "log none",

10
vl.c
View file

@ -3093,6 +3093,7 @@ int main(int argc, char **argv, char **envp)
qemu_add_opts(&qemu_chardev_opts); qemu_add_opts(&qemu_chardev_opts);
qemu_add_opts(&qemu_device_opts); qemu_add_opts(&qemu_device_opts);
qemu_add_opts(&qemu_netdev_opts); qemu_add_opts(&qemu_netdev_opts);
qemu_add_opts(&qemu_nic_opts);
qemu_add_opts(&qemu_net_opts); qemu_add_opts(&qemu_net_opts);
qemu_add_opts(&qemu_rtc_opts); qemu_add_opts(&qemu_rtc_opts);
qemu_add_opts(&qemu_global_opts); qemu_add_opts(&qemu_global_opts);
@ -3313,6 +3314,12 @@ int main(int argc, char **argv, char **envp)
exit(1); exit(1);
} }
break; break;
case QEMU_OPTION_nic:
default_net = 0;
if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) {
exit(1);
}
break;
case QEMU_OPTION_net: case QEMU_OPTION_net:
default_net = 0; default_net = 0;
if (net_client_parse(qemu_find_opts("net"), optarg) == -1) { if (net_client_parse(qemu_find_opts("net"), optarg) == -1) {
@ -4491,7 +4498,8 @@ int main(int argc, char **argv, char **envp)
colo_info_init(); colo_info_init();
if (net_init_clients() < 0) { if (net_init_clients(&err) < 0) {
error_report_err(err);
exit(1); exit(1);
} }