aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-05-28 11:03:02 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-05-28 11:03:02 +0100
commitbc3004f0bb28d36b97eea5ff48922d16b4df7a1f (patch)
tree24f38de78463888de57d61aa76bac3639e7fc298
parent0915aed5842bd4dbe396b92d4f3b846ae29ad663 (diff)
parent2bc22a58e16f0650e56dccfac9495e5aef58e2ef (diff)
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>
-rw-r--r--net/clients.h20
-rw-r--r--net/dump.c13
-rw-r--r--net/hub.c7
-rw-r--r--net/l2tpv3.c5
-rw-r--r--net/net.c89
-rw-r--r--net/netmap.c3
-rw-r--r--net/slirp.c3
-rw-r--r--net/socket.c3
-rw-r--r--net/tap-aix.c7
-rw-r--r--net/tap-bsd.c38
-rw-r--r--net/tap-haiku.c7
-rw-r--r--net/tap-linux.c24
-rw-r--r--net/tap-solaris.c63
-rw-r--r--net/tap-win32.c3
-rw-r--r--net/tap.c198
-rw-r--r--net/tap_int.h4
-rw-r--r--net/vde.c3
-rw-r--r--net/vhost-user.c3
-rw-r--r--qemu-options.hx77
19 files changed, 331 insertions, 239 deletions
diff --git a/net/clients.h b/net/clients.h
index 2e8fedad8..d47530e82 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -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 */
diff --git a/net/dump.c b/net/dump.c
index 9d3a09e33..02c8064be 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -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);
}
diff --git a/net/hub.c b/net/hub.c
index 2b60ab9a6..3047f1276 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -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;
}
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index 8c598b09b..ed395dc12 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -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;
diff --git a/net/net.c b/net/net.c
index 7427f6a65..db6be12a1 100644
--- a/net/net.c
+++ b/net/net.c
@@ -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;
}
}
diff --git a/net/netmap.c b/net/netmap.c
index 0c1772b03..69300eb1a 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -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;
diff --git a/net/slirp.c b/net/slirp.c
index 9bbed7447..0e15cf675 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -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;
diff --git a/net/socket.c b/net/socket.c
index c30e03f5a..5a19aa188 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -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;
diff --git a/net/tap-aix.c b/net/tap-aix.c
index 804d16448..18fdbf3b2 100644
--- a/net/tap-aix.c
+++ b/net/tap-aix.c
@@ -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)
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index bf91bd03f..5889920ea 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -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)
diff --git a/net/tap-haiku.c b/net/tap-haiku.c
index e5ce436d2..d18590c63 100644
--- a/net/tap-haiku.c
+++ b/net/tap-haiku.c
@@ -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)
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 812bf2dfc..6c3caef21 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -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)
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 9c7278f1b..90b2fd12f 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -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)
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 8aee611f7..f6fc9610a 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -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);
diff --git a/net/tap.c b/net/tap.c
index 968df46c8..d1ca314dc 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -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;
}
diff --git a/net/tap_int.h b/net/tap_int.h
index 79afdf2d5..d12a40996 100644
--- a/net/tap_int.h
+++ b/net/tap_int.h
@@ -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);
diff --git a/net/vde.c b/net/vde.c
index 2a619fbc8..dacaa64b4 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -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);
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 1d86a2be1..11899c53c 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -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;
diff --git a/qemu-options.hx b/qemu-options.hx
index ec356f65c..88d766125 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -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