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

Version: GnuPG v1
 
 iQEcBAABAgAGBQJVZZZPAAoJEJykq7OBq3PIlY8H/jssSf1iBbV6B8oySzcPpNyC
 asTxOxwhkcydgVFzF3xy2H+YUJEfCyRLU4rGTvhIAdawjnCYQBWSyKDz4omWlJ4w
 4gc3Cyw7ZOK1V0wTs21h071roC+vMJIODXfcO8JuYGtJzKrOLVrPILdLEkhl/uLN
 YPLj89gvMcatF6hC3BUYkltBlp42fJIP+9Jhc9OBdxmAyGJFcUZPkyoKaF3FnhTT
 cdE3n75uf3jAIuG14NT6WK8wbKjUX4OQ/alo/gg87fUHaVZduZnAAb1XozyJ/e5o
 nuS9uKmuM/2QN/kb7As4cY3haRtAERO/bAiGhI5i2tahwn+o4uQ7ohfu7fC+RX0=
 =bVyU
 -----END PGP SIGNATURE-----

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

# gpg: Signature made Wed May 27 11:02:55 2015 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/net-pull-request:
  net/net: Record usage status of mac address
  tap: Improve -netdev/netdev_add/-net/... tap error reporting
  tap: Finish conversion of tap_open() to Error
  tap-solaris: Convert tap_open() to Error
  tap-bsd: Convert tap_open() to Error
  tap-linux: Convert tap_open() to Error
  tap: Permit incremental conversion of tap_open() to Error
  tap: Convert launch_script() to Error
  tap: Convert net_init_tap_one() to Error
  tap: Convert tap_set_sndbuf() to Error
  tap: Improve -netdev/netdev_add/-net/... bridge error reporting
  tap: net_tap_fd_init() can't fail, drop dead error handling
  net/dump: Improve -net/host_net_add dump error reporting
  net: Improve -net nic error reporting
  net: Permit incremental conversion of init functions to Error
  net: Improve error message for -net hubport a bit
  net: Change help text to list -netdev instead of -net by default

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-05-28 11:03:02 +01:00
commit bc3004f0bb
19 changed files with 331 additions and 239 deletions

View File

@ -28,38 +28,38 @@
#include "qapi-types.h"
int net_init_dump(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
#ifdef CONFIG_SLIRP
int net_init_slirp(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
#endif
int net_init_hubport(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
int net_init_socket(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
int net_init_tap(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
int net_init_bridge(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
int net_init_l2tpv3(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
#ifdef CONFIG_VDE
int net_init_vde(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
#endif
#ifdef CONFIG_NETMAP
int net_init_netmap(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
#endif
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
NetClientState *peer);
NetClientState *peer, Error **errp);
#endif /* QEMU_NET_CLIENTS_H */

View File

@ -101,7 +101,8 @@ static NetClientInfo net_dump_info = {
};
static int net_dump_init(NetClientState *peer, const char *device,
const char *name, const char *filename, int len)
const char *name, const char *filename, int len,
Error **errp)
{
struct pcap_file_hdr hdr;
NetClientState *nc;
@ -111,7 +112,7 @@ static int net_dump_init(NetClientState *peer, const char *device,
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
if (fd < 0) {
error_report("-net dump: can't open %s", filename);
error_setg_errno(errp, errno, "-net dump: can't open %s", filename);
return -1;
}
@ -124,7 +125,7 @@ static int net_dump_init(NetClientState *peer, const char *device,
hdr.linktype = 1;
if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
error_report("-net dump write error: %s", strerror(errno));
error_setg_errno(errp, errno, "-net dump write error");
close(fd);
return -1;
}
@ -146,7 +147,7 @@ static int net_dump_init(NetClientState *peer, const char *device,
}
int net_init_dump(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
int len;
const char *file;
@ -173,7 +174,7 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
if (dump->has_len) {
if (dump->len > INT_MAX) {
error_report("invalid length: %"PRIu64, dump->len);
error_setg(errp, "invalid length: %"PRIu64, dump->len);
return -1;
}
len = dump->len;
@ -181,5 +182,5 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
len = 65536;
}
return net_dump_init(peer, "dump", name, file, len);
return net_dump_init(peer, "dump", name, file, len, errp);
}

View File

@ -281,17 +281,14 @@ int net_hub_id_for_client(NetClientState *nc, int *id)
}
int net_init_hubport(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
const NetdevHubPortOptions *hubport;
assert(opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT);
assert(!peer);
hubport = opts->hubport;
if (peer) {
return -EINVAL;
}
net_hub_add_port(hubport->hubid, name);
return 0;
}

View File

@ -536,10 +536,9 @@ static NetClientInfo net_l2tpv3_info = {
int net_init_l2tpv3(const NetClientOptions *opts,
const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
const NetdevL2TPv3Options *l2tpv3;
NetL2TPV3State *s;
NetClientState *nc;

View File

@ -167,19 +167,68 @@ void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
macaddr[3], macaddr[4], macaddr[5]);
}
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;
}
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
{
static int index = 0;
static const MACAddr zero = { .a = { 0,0,0,0,0,0 } };
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;
}
}
if (memcmp(macaddr, &zero, sizeof(zero)) != 0)
return;
macaddr->a[0] = 0x52;
macaddr->a[1] = 0x54;
macaddr->a[2] = 0x00;
macaddr->a[3] = 0x12;
macaddr->a[4] = 0x34;
macaddr->a[5] = 0x56 + index++;
macaddr->a[5] = qemu_macaddr_get_free();
qemu_macaddr_set_used(macaddr);
}
/**
@ -374,6 +423,8 @@ void qemu_del_nic(NICState *nic)
{
int i, queues = MAX(nic->conf->peers.queues, 1);
qemu_macaddr_set_free(&nic->conf->macaddr);
/* If this is a peer NIC and peer has already been deleted, free it now. */
if (nic->peer_deleted) {
for (i = 0; i < queues; i++) {
@ -740,7 +791,7 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
}
static int net_init_nic(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
int idx;
NICInfo *nd;
@ -751,7 +802,7 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
error_report("Too Many NICs");
error_setg(errp, "too many NICs");
return -1;
}
@ -762,7 +813,7 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
if (nic->has_netdev) {
nd->netdev = qemu_find_netdev(nic->netdev);
if (!nd->netdev) {
error_report("netdev '%s' not found", nic->netdev);
error_setg(errp, "netdev '%s' not found", nic->netdev);
return -1;
}
} else {
@ -779,19 +830,20 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
if (nic->has_macaddr &&
net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) {
error_report("invalid syntax for ethernet address");
error_setg(errp, "invalid syntax for ethernet address");
return -1;
}
if (nic->has_macaddr &&
is_multicast_ether_addr(nd->macaddr.a)) {
error_report("NIC cannot have multicast MAC address (odd 1st byte)");
error_setg(errp,
"NIC cannot have multicast MAC address (odd 1st byte)");
return -1;
}
qemu_macaddr_default_if_unset(&nd->macaddr);
if (nic->has_vectors) {
if (nic->vectors > 0x7ffffff) {
error_report("invalid # of vectors: %"PRIu32, nic->vectors);
error_setg(errp, "invalid # of vectors: %"PRIu32, nic->vectors);
return -1;
}
nd->nvectors = nic->vectors;
@ -809,7 +861,7 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
const NetClientOptions *opts,
const char *name,
NetClientState *peer) = {
NetClientState *peer, Error **errp) = {
[NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic,
#ifdef CONFIG_SLIRP
[NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp,
@ -882,6 +934,11 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
} else {
u.net = object;
opts = u.net->opts;
if (opts->kind == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
"a net type");
return -1;
}
/* missing optional values have been initialized to "all bits zero" */
name = u.net->has_id ? u.net->id : u.net->name;
}
@ -897,10 +954,12 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL);
}
if (net_client_init_fun[opts->kind](opts, name, peer) < 0) {
/* TODO push error reporting into init() methods */
error_set(errp, QERR_DEVICE_INIT_FAILED,
NetClientOptionsKind_lookup[opts->kind]);
if (net_client_init_fun[opts->kind](opts, name, peer, errp) < 0) {
/* FIXME drop when all init functions store an Error */
if (errp && !*errp) {
error_set(errp, QERR_DEVICE_INIT_FAILED,
NetClientOptionsKind_lookup[opts->kind]);
}
return -1;
}
}

View File

@ -446,8 +446,9 @@ static NetClientInfo net_netmap_info = {
* ... -net netmap,ifname="..."
*/
int net_init_netmap(const NetClientOptions *opts,
const char *name, NetClientState *peer)
const char *name, NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
const NetdevNetmapOptions *netmap_opts = opts->netmap;
NetClientState *nc;
NetmapPriv me;

View File

@ -737,8 +737,9 @@ static const char **slirp_dnssearch(const StringList *dnsname)
}
int net_init_slirp(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
struct slirp_config_str *config;
char *vnet;
int ret;

View File

@ -693,8 +693,9 @@ static int net_socket_udp_init(NetClientState *peer,
}
int net_init_socket(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
Error *err = NULL;
const NetdevSocketOptions *sock;

View File

@ -26,15 +26,14 @@
#include <stdio.h>
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
int vnet_hdr_required, int mq_required, Error **errp)
{
fprintf(stderr, "no tap on AIX\n");
error_setg(errp, "no tap on AIX");
return -1;
}
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
{
return 0;
}
int tap_probe_vnet_hdr(int fd)

View File

@ -35,7 +35,7 @@
#ifndef __FreeBSD__
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
int vnet_hdr_required, int mq_required, Error **errp)
{
int fd;
#ifdef TAPGIFNAME
@ -71,23 +71,19 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
}
}
if (fd < 0) {
error_report("warning: could not open %s (%s): no virtual network emulation",
dname, strerror(errno));
error_setg_errno(errp, errno, "could not open %s", dname);
return -1;
}
#ifdef TAPGIFNAME
if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) {
fprintf(stderr, "warning: could not get tap name: %s\n",
strerror(errno));
error_setg_errno(errp, errno, "could not get tap name");
return -1;
}
pstrcpy(ifname, ifname_size, ifr.ifr_name);
#else
if (fstat(fd, &s) < 0) {
fprintf(stderr,
"warning: could not stat /dev/tap: no virtual network emulation: %s\n",
strerror(errno));
error_setg_errno(errp, errno, "could not stat %s", dname);
return -1;
}
dev = devname(s.st_rdev, S_IFCHR);
@ -99,8 +95,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
*vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) {
error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
error_setg(errp, "vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
close(fd);
return -1;
}
@ -114,14 +110,14 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
#define PATH_NET_TAP "/dev/tap"
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
int vnet_hdr_required, int mq_required, Error **errp)
{
int fd, s, ret;
struct ifreq ifr;
TFR(fd = open(PATH_NET_TAP, O_RDWR));
if (fd < 0) {
error_report("could not open %s: %s", PATH_NET_TAP, strerror(errno));
error_setg_errno(errp, errno, "could not open %s", PATH_NET_TAP);
return -1;
}
@ -129,7 +125,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
ret = ioctl(fd, TAPGIFNAME, (void *)&ifr);
if (ret < 0) {
error_report("could not get tap interface name");
error_setg_errno(errp, errno, "could not get tap interface name");
goto error;
}
@ -137,14 +133,15 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
/* User requested the interface to have a specific name */
s = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (s < 0) {
error_report("could not open socket to set interface name");
error_setg_errno(errp, errno,
"could not open socket to set interface name");
goto error;
}
ifr.ifr_data = ifname;
ret = ioctl(s, SIOCSIFNAME, (void *)&ifr);
close(s);
if (ret < 0) {
error_report("could not set tap interface name");
error_setg(errp, "could not set tap interface name");
goto error;
}
} else {
@ -156,14 +153,14 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
*vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) {
error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
error_setg(errp, "vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
goto error;
}
}
if (mq_required) {
error_report("mq_required requested, but not kernel support"
"for IFF_MULTI_QUEUE available");
error_setg(errp, "mq_required requested, but no kernel support"
" for IFF_MULTI_QUEUE available");
goto error;
}
@ -176,9 +173,8 @@ error:
}
#endif /* __FreeBSD__ */
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
{
return 0;
}
int tap_probe_vnet_hdr(int fd)

View File

@ -26,15 +26,14 @@
#include <stdio.h>
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
int vnet_hdr_required, int mq_required, Error **errp)
{
fprintf(stderr, "no tap on Haiku\n");
error_setg(errp, "no tap on Haiku");
return -1;
}
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
{
return 0;
}
int tap_probe_vnet_hdr(int fd)

View File

@ -37,7 +37,7 @@
#define PATH_NET_TUN "/dev/net/tun"
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
int vnet_hdr_required, int mq_required, Error **errp)
{
struct ifreq ifr;
int fd, ret;
@ -46,7 +46,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
TFR(fd = open(PATH_NET_TUN, O_RDWR));
if (fd < 0) {
error_report("could not open %s: %m", PATH_NET_TUN);
error_setg_errno(errp, errno, "could not open %s", PATH_NET_TUN);
return -1;
}
memset(&ifr, 0, sizeof(ifr));
@ -70,8 +70,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
}
if (vnet_hdr_required && !*vnet_hdr) {
error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
error_setg(errp, "vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
close(fd);
return -1;
}
@ -86,8 +86,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
if (mq_required) {
if (!(features & IFF_MULTI_QUEUE)) {
error_report("multiqueue required, but no kernel "
"support for IFF_MULTI_QUEUE available");
error_setg(errp, "multiqueue required, but no kernel "
"support for IFF_MULTI_QUEUE available");
close(fd);
return -1;
} else {
@ -102,9 +102,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
if (ret != 0) {
if (ifname[0] != '\0') {
error_report("could not configure %s (%s): %m", PATH_NET_TUN, ifr.ifr_name);
error_setg_errno(errp, errno, "could not configure %s (%s)",
PATH_NET_TUN, ifr.ifr_name);
} else {
error_report("could not configure %s: %m", PATH_NET_TUN);
error_setg_errno(errp, errno, "could not configure %s",
PATH_NET_TUN);
}
close(fd);
return -1;
@ -126,7 +128,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
*/
#define TAP_DEFAULT_SNDBUF 0
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
{
int sndbuf;
@ -139,10 +141,8 @@ int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
}
if (ioctl(fd, TUNSETSNDBUF, &sndbuf) == -1 && tap->has_sndbuf) {
error_report("TUNSETSNDBUF ioctl failed: %s", strerror(errno));
return -1;
error_setg_errno(errp, errno, "TUNSETSNDBUF ioctl failed");
}
return 0;
}
int tap_probe_vnet_hdr(int fd)

View File

@ -36,7 +36,6 @@
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <syslog.h>
#include <stropts.h>
#include "qemu/error-report.h"
@ -56,8 +55,10 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
* Allocate TAP device, returns opened fd.
* Stores dev name in the first arg(must be large enough).
*/
static int tap_alloc(char *dev, size_t dev_size)
static int tap_alloc(char *dev, size_t dev_size, Error **errp)
{
/* FIXME leaks like a sieve on error paths */
/* FIXME suspicious: many errors are reported, then ignored */
int tap_fd, if_fd, ppa = -1;
static int ip_fd = 0;
char *ptr;
@ -83,14 +84,14 @@ static int tap_alloc(char *dev, size_t dev_size)
TFR(ip_fd = open("/dev/udp", O_RDWR, 0));
if (ip_fd < 0) {
syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)");
return -1;
error_setg(errp, "Can't open /dev/ip (actually /dev/udp)");
return -1;
}
TFR(tap_fd = open("/dev/tap", O_RDWR, 0));
if (tap_fd < 0) {
syslog(LOG_ERR, "Can't open /dev/tap");
return -1;
error_setg(errp, "Can't open /dev/tap");
return -1;
}
/* Assign a new PPA and get its unit number. */
@ -99,20 +100,20 @@ static int tap_alloc(char *dev, size_t dev_size)
strioc_ppa.ic_len = sizeof(ppa);
strioc_ppa.ic_dp = (char *)&ppa;
if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
syslog (LOG_ERR, "Can't assign new interface");
error_report("Can't assign new interface");
TFR(if_fd = open("/dev/tap", O_RDWR, 0));
if (if_fd < 0) {
syslog(LOG_ERR, "Can't open /dev/tap (2)");
return -1;
error_setg(errp, "Can't open /dev/tap (2)");
return -1;
}
if(ioctl(if_fd, I_PUSH, "ip") < 0){
syslog(LOG_ERR, "Can't push IP module");
return -1;
error_setg(errp, "Can't push IP module");
return -1;
}
if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
syslog(LOG_ERR, "Can't get flags\n");
error_report("Can't get flags");
snprintf (actual_name, 32, "tap%d", ppa);
pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
@ -121,22 +122,22 @@ static int tap_alloc(char *dev, size_t dev_size)
/* Assign ppa according to the unit number returned by tun device */
if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
syslog (LOG_ERR, "Can't set PPA %d", ppa);
error_report("Can't set PPA %d", ppa);
if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
syslog (LOG_ERR, "Can't get flags\n");
error_report("Can't get flags");
/* Push arp module to if_fd */
if (ioctl (if_fd, I_PUSH, "arp") < 0)
syslog (LOG_ERR, "Can't push ARP module (2)");
error_report("Can't push ARP module (2)");
/* Push arp module to ip_fd */
if (ioctl (ip_fd, I_POP, NULL) < 0)
syslog (LOG_ERR, "I_POP failed\n");
error_report("I_POP failed");
if (ioctl (ip_fd, I_PUSH, "arp") < 0)
syslog (LOG_ERR, "Can't push ARP module (3)\n");
error_report("Can't push ARP module (3)");
/* Open arp_fd */
TFR(arp_fd = open ("/dev/tap", O_RDWR, 0));
if (arp_fd < 0)
syslog (LOG_ERR, "Can't open %s\n", "/dev/tap");
error_report("Can't open %s", "/dev/tap");
/* Set ifname to arp */
strioc_if.ic_cmd = SIOCSLIFNAME;
@ -144,16 +145,16 @@ static int tap_alloc(char *dev, size_t dev_size)
strioc_if.ic_len = sizeof(ifr);
strioc_if.ic_dp = (char *)&ifr;
if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
syslog (LOG_ERR, "Can't set ifname to arp\n");
error_report("Can't set ifname to arp");
}
if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
syslog(LOG_ERR, "Can't link TAP device to IP");
return -1;
error_setg(errp, "Can't link TAP device to IP");
return -1;
}
if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
syslog (LOG_ERR, "Can't link TAP device to ARP");
error_report("Can't link TAP device to ARP");
close (if_fd);
@ -166,7 +167,7 @@ static int tap_alloc(char *dev, size_t dev_size)
{
ioctl (ip_fd, I_PUNLINK , arp_muxid);
ioctl (ip_fd, I_PUNLINK, ip_muxid);
syslog (LOG_ERR, "Can't set multiplexor id");
error_report("Can't set multiplexor id");
}
snprintf(dev, dev_size, "tap%d", ppa);
@ -174,13 +175,14 @@ static int tap_alloc(char *dev, size_t dev_size)
}
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
int vnet_hdr_required, int mq_required, Error **errp)
{
char dev[10]="";
int fd;
if( (fd = tap_alloc(dev, sizeof(dev))) < 0 ){
fprintf(stderr, "Cannot allocate TAP device\n");
return -1;
fd = tap_alloc(dev, sizeof(dev), errp);
if (fd < 0) {
return -1;
}
pstrcpy(ifname, ifname_size, dev);
if (*vnet_hdr) {
@ -188,8 +190,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
*vnet_hdr = 0;
if (vnet_hdr_required && !*vnet_hdr) {
error_report("vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
error_setg(errp, "vnet_hdr=1 requested, but no kernel "
"support for IFF_VNET_HDR available");
close(fd);
return -1;
}
@ -198,9 +200,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return fd;
}
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
{
return 0;
}
int tap_probe_vnet_hdr(int fd)

View File

@ -752,8 +752,9 @@ static int tap_win32_init(NetClientState *peer, const char *model,
}
int net_init_tap(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
const NetdevTapOptions *tap;
assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP);

198
net/tap.c
View File

@ -59,7 +59,8 @@ typedef struct TAPState {
unsigned host_vnet_hdr_len;
} TAPState;
static int launch_script(const char *setup_script, const char *ifname, int fd);
static void launch_script(const char *setup_script, const char *ifname,
int fd, Error **errp);
static int tap_can_send(void *opaque);
static void tap_send(void *opaque);
@ -288,6 +289,7 @@ static void tap_set_offload(NetClientState *nc, int csum, int tso4,
static void tap_cleanup(NetClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
Error *err = NULL;
if (s->vhost_net) {
vhost_net_cleanup(s->vhost_net);
@ -296,8 +298,12 @@ static void tap_cleanup(NetClientState *nc)
qemu_purge_queued_packets(nc);
if (s->down_script[0])
launch_script(s->down_script, s->down_script_arg, s->fd);
if (s->down_script[0]) {
launch_script(s->down_script, s->down_script_arg, s->fd, &err);
if (err) {
error_report_err(err);
}
}
tap_read_poll(s, false);
tap_write_poll(s, false);
@ -368,7 +374,8 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
return s;
}
static int launch_script(const char *setup_script, const char *ifname, int fd)
static void launch_script(const char *setup_script, const char *ifname,
int fd, Error **errp)
{
int pid, status;
char *args[3];
@ -376,6 +383,11 @@ static int launch_script(const char *setup_script, const char *ifname, int fd)
/* try to launch network script */
pid = fork();
if (pid < 0) {
error_setg_errno(errp, errno, "could not launch network script %s",
setup_script);
return;
}
if (pid == 0) {
int open_max = sysconf(_SC_OPEN_MAX), i;
@ -390,17 +402,17 @@ static int launch_script(const char *setup_script, const char *ifname, int fd)
*parg = NULL;
execv(setup_script, args);
_exit(1);
} else if (pid > 0) {
} else {
while (waitpid(pid, &status, 0) != pid) {
/* loop */
}
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
return 0;
return;
}
error_setg(errp, "network script %s failed with status %d",
setup_script, status);
}
fprintf(stderr, "%s: could not launch network script\n", setup_script);
return -1;
}
static int recv_fd(int c)
@ -437,7 +449,8 @@ static int recv_fd(int c)
return len;
}
static int net_bridge_run_helper(const char *helper, const char *bridge)
static int net_bridge_run_helper(const char *helper, const char *bridge,
Error **errp)
{
sigset_t oldmask, mask;
int pid, status;
@ -450,11 +463,16 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
sigprocmask(SIG_BLOCK, &mask, &oldmask);
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
error_setg_errno(errp, errno, "socketpair() failed");
return -1;
}
/* try to launch bridge helper */
pid = fork();
if (pid < 0) {
error_setg_errno(errp, errno, "Can't fork bridge helper");
return -1;
}
if (pid == 0) {
int open_max = sysconf(_SC_OPEN_MAX), i;
char fd_buf[6+10];
@ -502,14 +520,16 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
}
_exit(1);
} else if (pid > 0) {
} else {
int fd;
int saved_errno;
close(sv[1]);
do {
fd = recv_fd(sv[0]);
} while (fd == -1 && errno == EINTR);
saved_errno = errno;
close(sv[0]);
@ -518,24 +538,23 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
}
sigprocmask(SIG_SETMASK, &oldmask, NULL);
if (fd < 0) {
fprintf(stderr, "failed to recv file descriptor\n");
error_setg_errno(errp, saved_errno,
"failed to recv file descriptor");
return -1;
}
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
return fd;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
error_setg(errp, "bridge helper failed");
return -1;
}
return fd;
}
fprintf(stderr, "failed to launch bridge helper\n");
return -1;
}
int net_init_bridge(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
const NetdevBridgeOptions *bridge;
const char *helper, *br;
TAPState *s;
int fd, vnet_hdr;
@ -545,20 +564,14 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
fd = net_bridge_run_helper(helper, br);
fd = net_bridge_run_helper(helper, br, errp);
if (fd == -1) {
return -1;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
vnet_hdr = tap_probe_vnet_hdr(fd);
s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
if (!s) {
close(fd);
return -1;
}
snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper,
br);
@ -568,8 +581,9 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr,
const char *setup_script, char *ifname,
size_t ifname_sz, int mq_required)
size_t ifname_sz, int mq_required, Error **errp)
{
Error *err = NULL;
int fd, vnet_hdr_required;
if (tap->has_vnet_hdr) {
@ -581,17 +595,20 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr,
}
TFR(fd = tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required,
mq_required));
mq_required, errp));
if (fd < 0) {
return -1;
}
if (setup_script &&
setup_script[0] != '\0' &&
strcmp(setup_script, "no") != 0 &&
launch_script(setup_script, ifname, fd)) {
close(fd);
return -1;
strcmp(setup_script, "no") != 0) {
launch_script(setup_script, ifname, fd, &err);
if (err) {
error_propagate(errp, err);
close(fd);
return -1;
}
}
return fd;
@ -599,23 +616,20 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr,
#define MAX_TAP_QUEUES 1024
static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
const char *model, const char *name,
const char *ifname, const char *script,
const char *downscript, const char *vhostfdname,
int vnet_hdr, int fd)
static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
const char *model, const char *name,
const char *ifname, const char *script,
const char *downscript, const char *vhostfdname,
int vnet_hdr, int fd, Error **errp)
{
Error *err = NULL;
TAPState *s;
TAPState *s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
int vhostfd;
s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
if (!s) {
return -1;
}
if (tap_set_sndbuf(s->fd, tap) < 0) {
return -1;
tap_set_sndbuf(s->fd, tap, &err);
if (err) {
error_propagate(errp, err);
return;
}
if (tap->has_fd || tap->has_fds) {
@ -646,30 +660,28 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
if (tap->has_vhostfd || tap->has_vhostfds) {
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
if (vhostfd == -1) {
error_report_err(err);
return -1;
error_propagate(errp, err);
return;
}
} else {
vhostfd = open("/dev/vhost-net", O_RDWR);
if (vhostfd < 0) {
error_report("tap: open vhost char device failed: %s",
strerror(errno));
return -1;
error_setg_errno(errp, errno,
"tap: open vhost char device failed");
return;
}
}
options.opaque = (void *)(uintptr_t)vhostfd;
s->vhost_net = vhost_net_init(&options);
if (!s->vhost_net) {
error_report("vhost-net requested but could not be initialized");
return -1;
error_setg(errp,
"vhost-net requested but could not be initialized");
return;
}
} else if (tap->has_vhostfd || tap->has_vhostfds) {
error_report("vhostfd= is not valid without vhost");
return -1;
error_setg(errp, "vhostfd= is not valid without vhost");
}
return 0;
}
static int get_fds(char *str, char *fds[], int max)
@ -699,7 +711,7 @@ static int get_fds(char *str, char *fds[], int max)
}
int net_init_tap(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
const NetdevTapOptions *tap;
int fd, vnet_hdr = 0, i = 0, queues;
@ -718,7 +730,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
/* QEMU vlans does not support multiqueue tap, in this case peer is set.
* For -netdev, peer is always NULL. */
if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) {
error_report("Multiqueue tap cannot be used with QEMU vlans");
error_setg(errp, "Multiqueue tap cannot be used with QEMU vlans");
return -1;
}
@ -726,15 +738,15 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
tap->has_fds || tap->has_vhostfds) {
error_report("ifname=, script=, downscript=, vnet_hdr=, "
"helper=, queues=, fds=, and vhostfds= "
"are invalid with fd=");
error_setg(errp, "ifname=, script=, downscript=, vnet_hdr=, "
"helper=, queues=, fds=, and vhostfds= "
"are invalid with fd=");
return -1;
}
fd = monitor_fd_param(cur_mon, tap->fd, &err);
if (fd == -1) {
error_report_err(err);
error_propagate(errp, err);
return -1;
}
@ -742,9 +754,11 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
vnet_hdr = tap_probe_vnet_hdr(fd);
if (net_init_tap_one(tap, peer, "tap", name, NULL,
script, downscript,
vhostfdname, vnet_hdr, fd)) {
net_init_tap_one(tap, peer, "tap", name, NULL,
script, downscript,
vhostfdname, vnet_hdr, fd, &err);
if (err) {
error_propagate(errp, err);
return -1;
}
} else if (tap->has_fds) {
@ -755,9 +769,9 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
tap->has_vhostfd) {
error_report("ifname=, script=, downscript=, vnet_hdr=, "
"helper=, queues=, and vhostfd= "
"are invalid with fds=");
error_setg(errp, "ifname=, script=, downscript=, vnet_hdr=, "
"helper=, queues=, and vhostfd= "
"are invalid with fds=");
return -1;
}
@ -765,8 +779,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (tap->has_vhostfds) {
nvhosts = get_fds(tap->vhostfds, vhost_fds, MAX_TAP_QUEUES);
if (nfds != nvhosts) {
error_report("The number of fds passed does not match the "
"number of vhostfds passed");
error_setg(errp, "The number of fds passed does not match "
"the number of vhostfds passed");
return -1;
}
}
@ -774,7 +788,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
for (i = 0; i < nfds; i++) {
fd = monitor_fd_param(cur_mon, fds[i], &err);
if (fd == -1) {
error_report_err(err);
error_propagate(errp, err);
return -1;
}
@ -783,26 +797,30 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (i == 0) {
vnet_hdr = tap_probe_vnet_hdr(fd);
} else if (vnet_hdr != tap_probe_vnet_hdr(fd)) {
error_report("vnet_hdr not consistent across given tap fds");
error_setg(errp,
"vnet_hdr not consistent across given tap fds");
return -1;
}
if (net_init_tap_one(tap, peer, "tap", name, ifname,
script, downscript,
tap->has_vhostfds ? vhost_fds[i] : NULL,
vnet_hdr, fd)) {
net_init_tap_one(tap, peer, "tap", name, ifname,
script, downscript,
tap->has_vhostfds ? vhost_fds[i] : NULL,
vnet_hdr, fd, &err);
if (err) {
error_propagate(errp, err);
return -1;
}
}
} else if (tap->has_helper) {
if (tap->has_ifname || tap->has_script || tap->has_downscript ||
tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) {
error_report("ifname=, script=, downscript=, and vnet_hdr= "
"queues=, and vhostfds= are invalid with helper=");
error_setg(errp, "ifname=, script=, downscript=, vnet_hdr=, "
"queues=, and vhostfds= are invalid with helper=");
return -1;
}
fd = net_bridge_run_helper(tap->helper, DEFAULT_BRIDGE_INTERFACE);
fd = net_bridge_run_helper(tap->helper, DEFAULT_BRIDGE_INTERFACE,
errp);
if (fd == -1) {
return -1;
}
@ -810,15 +828,17 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
fcntl(fd, F_SETFL, O_NONBLOCK);
vnet_hdr = tap_probe_vnet_hdr(fd);
if (net_init_tap_one(tap, peer, "bridge", name, ifname,
script, downscript, vhostfdname,
vnet_hdr, fd)) {
net_init_tap_one(tap, peer, "bridge", name, ifname,
script, downscript, vhostfdname,
vnet_hdr, fd, &err);
if (err) {
error_propagate(errp, err);
close(fd);
return -1;
}
} else {
if (tap->has_vhostfds) {
error_report("vhostfds= is invalid if fds= wasn't specified");
error_setg(errp, "vhostfds= is invalid if fds= wasn't specified");
return -1;
}
script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT;
@ -833,23 +853,25 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
for (i = 0; i < queues; i++) {
fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script,
ifname, sizeof ifname, queues > 1);
ifname, sizeof ifname, queues > 1, errp);
if (fd == -1) {
return -1;
}
if (queues > 1 && i == 0 && !tap->has_ifname) {
if (tap_fd_get_ifname(fd, ifname)) {
error_report("Fail to get ifname");
error_setg(errp, "Fail to get ifname");
close(fd);
return -1;
}
}
if (net_init_tap_one(tap, peer, "tap", name, ifname,
i >= 1 ? "no" : script,
i >= 1 ? "no" : downscript,
vhostfdname, vnet_hdr, fd)) {
net_init_tap_one(tap, peer, "tap", name, ifname,
i >= 1 ? "no" : script,
i >= 1 ? "no" : downscript,
vhostfdname, vnet_hdr, fd, &err);
if (err) {
error_propagate(errp, err);
close(fd);
return -1;
}

View File

@ -30,11 +30,11 @@
#include "qapi-types.h"
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required);
int vnet_hdr_required, int mq_required, Error **errp);
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen);
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap);
void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp);
int tap_probe_vnet_hdr(int fd);
int tap_probe_vnet_hdr_len(int fd, int len);
int tap_probe_has_ufo(int fd);

View File

@ -110,8 +110,9 @@ static int net_vde_init(NetClientState *peer, const char *model,
}
int net_init_vde(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
const NetdevVdeOptions *vde;
assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VDE);

View File

@ -223,8 +223,9 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
}
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
NetClientState *peer)
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
const NetdevVhostUserOptions *vhost_user_opts;
CharDriverState *chr;

View File

@ -1449,25 +1449,25 @@ DEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL)
#endif
#endif
DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
" create a new Network Interface Card and connect it to VLAN 'n'\n"
DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
#ifdef CONFIG_SLIRP
"-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=on|off]\n"
"-netdev user,id=str[,net=addr[/mask]][,host=addr][,restrict=on|off]\n"
" [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]\n"
" [,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
#ifndef _WIN32
"[,smb=dir[,smbserver=addr]]\n"
#endif
" connect the user mode network stack to VLAN 'n', configure its\n"
" DHCP server and enabled optional services\n"
" configure a user mode network backend with ID 'str',\n"
" its DHCP server and optional services\n"
#endif
#ifdef _WIN32
"-net tap[,vlan=n][,name=str],ifname=name\n"
" connect the host TAP network interface to VLAN 'n'\n"
"-netdev tap,id=str,ifname=name\n"
" configure a host TAP network backend with ID 'str'\n"
#else
"-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
" connect the host TAP network interface to VLAN 'n'\n"
"-netdev tap,id=str[,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile]\n"
" [,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off]\n"
" [,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
" configure a host TAP network backend with ID 'str'\n"
" use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
" to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
" to deconfigure it\n"
@ -1486,14 +1486,18 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" use 'vhostfd=h' to connect to an already opened vhost net device\n"
" use 'vhostfds=x:y:...:z to connect to multiple already opened vhost net devices\n"
" use 'queues=n' to specify the number of queues to be created for multiqueue TAP\n"
"-net bridge[,vlan=n][,name=str][,br=bridge][,helper=helper]\n"
" connects a host TAP network interface to a host bridge device 'br'\n"
" (default=" DEFAULT_BRIDGE_INTERFACE ") using the program 'helper'\n"
" (default=" DEFAULT_BRIDGE_HELPER ")\n"
"-netdev bridge,id=str[,br=bridge][,helper=helper]\n"
" configure a host TAP network backend with ID 'str' that is\n"
" connected to a bridge (default=" DEFAULT_BRIDGE_INTERFACE ")\n"
" using the program 'helper (default=" DEFAULT_BRIDGE_HELPER ")\n"
#endif
#ifdef __linux__
"-net l2tpv3[,vlan=n][,name=str],src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport],txsession=txsession[,rxsession=rxsession][,ipv6=on/off][,udp=on/off][,cookie64=on/off][,counter][,pincounter][,txcookie=txcookie][,rxcookie=rxcookie][,offset=offset]\n"
" connect the VLAN to an Ethernet over L2TPv3 pseudowire\n"
"-netdev l2tpv3,id=str,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport]\n"
" [,rxsession=rxsession],txsession=txsession[,ipv6=on/off][,udp=on/off]\n"
" [,cookie64=on/off][,counter][,pincounter][,txcookie=txcookie]\n"
" [,rxcookie=rxcookie][,offset=offset]\n"
" configure a network backend with ID 'str' connected to\n"
" an Ethernet over L2TPv3 pseudowire.\n"
" Linux kernel 3.3+ as well as most routers can talk\n"
" L2TPv3. This transport allows connecting a VM to a VM,\n"
" VM to a router and even VM to Host. It is a nearly-universal\n"
@ -1514,32 +1518,41 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" use 'pincounter=on' to work around broken counter handling in peer\n"
" use 'offset=X' to add an extra offset between header and data\n"
#endif
"-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
" connect the vlan 'n' to another VLAN using a socket connection\n"
"-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port[,localaddr=addr]]\n"
" connect the vlan 'n' to multicast maddr and port\n"
"-netdev socket,id=str[,fd=h][,listen=[host]:port][,connect=host:port]\n"
" configure a network backend to connect to another network\n"
" using a socket connection\n"
"-netdev socket,id=str[,fd=h][,mcast=maddr:port[,localaddr=addr]]\n"
" configure a network backend to connect to a multicast maddr and port\n"
" use 'localaddr=addr' to specify the host address to send packets from\n"
"-net socket[,vlan=n][,name=str][,fd=h][,udp=host:port][,localaddr=host:port]\n"
" connect the vlan 'n' to another VLAN using an UDP tunnel\n"
"-netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]\n"
" configure a network backend to connect to another network\n"
" using an UDP tunnel\n"
#ifdef CONFIG_VDE
"-net vde[,vlan=n][,name=str][,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n"
" connect the vlan 'n' to port 'n' of a vde switch running\n"
" on host and listening for incoming connections on 'socketpath'.\n"
"-netdev vde,id=str[,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n"
" configure a network backend to connect to port 'n' of a vde switch\n"
" running on host and listening for incoming connections on 'socketpath'.\n"
" Use group 'groupname' and mode 'octalmode' to change default\n"
" ownership and permissions for communication port.\n"
#endif
#ifdef CONFIG_NETMAP
"-net netmap,ifname=name[,devname=nmname]\n"
"-netdev netmap,id=str,ifname=name[,devname=nmname]\n"
" attach to the existing netmap-enabled network interface 'name', or to a\n"
" VALE port (created on the fly) called 'name' ('nmname' is name of the \n"
" netmap device, defaults to '/dev/netmap')\n"
#endif
"-netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]\n"
" configure a vhost-user network, backed by a chardev 'dev'\n"
"-netdev hubport,id=str,hubid=n\n"
" configure a hub port on QEMU VLAN 'n'\n", QEMU_ARCH_ALL)
DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
" old way to create a new NIC and connect it to VLAN 'n'\n"
" (use the '-device devtype,netdev=str' option if possible 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", QEMU_ARCH_ALL)
DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
"-netdev ["
" is provided, the default is '-net nic -net user'\n"
"-net ["
#ifdef CONFIG_SLIRP
"user|"
#endif
@ -1551,9 +1564,9 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
#ifdef CONFIG_NETMAP
"netmap|"
#endif
"vhost-user|"
"socket|"
"hubport],id=str[,option][,option][,...]\n", QEMU_ARCH_ALL)
"socket][,vlan=n][,option][,option][,...]\n"
" old way to initialize a host network interface\n"
" (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
STEXI
@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
@findex -net