aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/can/can_core.c4
-rw-r--r--net/can/can_host.c4
-rw-r--r--net/can/can_socketcan.c2
-rw-r--r--net/checksum.c4
-rw-r--r--net/colo-compare.c11
-rw-r--r--net/dump.c7
-rw-r--r--net/filter-buffer.c2
-rw-r--r--net/filter-mirror.c4
-rw-r--r--net/filter-replay.c4
-rw-r--r--net/filter-rewriter.c2
-rw-r--r--net/filter.c4
-rw-r--r--net/hub.c27
-rw-r--r--net/meson.build2
-rw-r--r--net/net-hmp-cmds.c2
-rw-r--r--net/net.c65
-rw-r--r--net/queue.c11
-rw-r--r--net/slirp.c29
-rw-r--r--net/socket.c2
-rw-r--r--net/stream.c36
-rw-r--r--net/tap-linux.c17
-rw-r--r--net/tap-win32.c15
-rw-r--r--net/tap.c36
-rw-r--r--net/vhost-user.c3
-rw-r--r--net/vhost-vdpa.c71
-rw-r--r--net/vmnet-common.m27
25 files changed, 204 insertions, 187 deletions
diff --git a/net/can/can_core.c b/net/can/can_core.c
index 0115d78..77fe2b8 100644
--- a/net/can/can_core.c
+++ b/net/can/can_core.c
@@ -149,7 +149,7 @@ static bool can_bus_can_be_deleted(UserCreatable *uc)
}
static void can_bus_class_init(ObjectClass *klass,
- void *class_data G_GNUC_UNUSED)
+ const void *class_data G_GNUC_UNUSED)
{
UserCreatableClass *uc_klass = USER_CREATABLE_CLASS(klass);
@@ -162,7 +162,7 @@ static const TypeInfo can_bus_info = {
.instance_size = sizeof(CanBusState),
.instance_init = can_bus_instance_init,
.class_init = can_bus_class_init,
- .interfaces = (InterfaceInfo[]) {
+ .interfaces = (const InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
diff --git a/net/can/can_host.c b/net/can/can_host.c
index b2fe553..3f9bb33 100644
--- a/net/can/can_host.c
+++ b/net/can/can_host.c
@@ -72,7 +72,7 @@ static void can_host_complete(UserCreatable *uc, Error **errp)
}
static void can_host_class_init(ObjectClass *klass,
- void *class_data G_GNUC_UNUSED)
+ const void *class_data G_GNUC_UNUSED)
{
UserCreatableClass *uc_klass = USER_CREATABLE_CLASS(klass);
@@ -92,7 +92,7 @@ static const TypeInfo can_host_info = {
.class_size = sizeof(CanHostClass),
.abstract = true,
.class_init = can_host_class_init,
- .interfaces = (InterfaceInfo[]) {
+ .interfaces = (const InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c
index c1a1ad0..8a57ae0 100644
--- a/net/can/can_socketcan.c
+++ b/net/can/can_socketcan.c
@@ -308,7 +308,7 @@ static void can_host_socketcan_instance_init(Object *obj)
}
static void can_host_socketcan_class_init(ObjectClass *klass,
- void *class_data G_GNUC_UNUSED)
+ const void *class_data G_GNUC_UNUSED)
{
CanHostClass *chc = CAN_HOST_CLASS(klass);
diff --git a/net/checksum.c b/net/checksum.c
index 1a957e4..537457d 100644
--- a/net/checksum.c
+++ b/net/checksum.c
@@ -57,7 +57,7 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
return net_checksum_finish(sum);
}
-void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
+void net_checksum_calculate(void *data, int length, int csum_flag)
{
int mac_hdr_len, ip_len;
struct ip_header *ip;
@@ -101,7 +101,7 @@ void net_checksum_calculate(uint8_t *data, int length, int csum_flag)
return;
}
- ip = (struct ip_header *)(data + mac_hdr_len);
+ ip = (struct ip_header *)((uint8_t *)data + mac_hdr_len);
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
return; /* not IPv4 */
diff --git a/net/colo-compare.c b/net/colo-compare.c
index c4ad0ab..0e1844e 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -25,7 +25,7 @@
#include "chardev/char-fe.h"
#include "qemu/sockets.h"
#include "colo.h"
-#include "sysemu/iothread.h"
+#include "system/iothread.h"
#include "net/colo-compare.h"
#include "migration/colo.h"
#include "util.h"
@@ -412,8 +412,7 @@ static void colo_compare_tcp(CompareState *s, Connection *conn)
* can ensure that the packet's payload is acknowledged by
* primary and secondary.
*/
- uint32_t min_ack = conn->pack - conn->sack > 0 ?
- conn->sack : conn->pack;
+ uint32_t min_ack = MIN(conn->pack, conn->sack);
pri:
if (g_queue_is_empty(&conn->primary_list)) {
@@ -1329,8 +1328,6 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
}
QTAILQ_INSERT_TAIL(&net_compares, s, next);
qemu_mutex_unlock(&colo_compare_mutex);
-
- return;
}
static void colo_flush_packets(void *opaque, void *user_data)
@@ -1355,7 +1352,7 @@ static void colo_flush_packets(void *opaque, void *user_data)
}
}
-static void colo_compare_class_init(ObjectClass *oc, void *data)
+static void colo_compare_class_init(ObjectClass *oc, const void *data)
{
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
@@ -1479,7 +1476,7 @@ static const TypeInfo colo_compare_info = {
.instance_finalize = colo_compare_finalize,
.class_size = sizeof(CompareClass),
.class_init = colo_compare_class_init,
- .interfaces = (InterfaceInfo[]) {
+ .interfaces = (const InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
diff --git a/net/dump.c b/net/dump.c
index 956e34a..581234b 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -32,7 +32,7 @@
#include "qapi/visitor.h"
#include "net/filter.h"
#include "qom/object.h"
-#include "sysemu/rtc.h"
+#include "system/rtc.h"
typedef struct DumpState {
int64_t start_ts;
@@ -155,7 +155,8 @@ static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
{
NetFilterDumpState *nfds = FILTER_DUMP(nf);
- dump_receive_iov(&nfds->ds, iov, iovcnt, qemu_get_vnet_hdr_len(nf->netdev));
+ dump_receive_iov(&nfds->ds, iov, iovcnt, flags & QEMU_NET_PACKET_FLAG_RAW ?
+ 0 : qemu_get_vnet_hdr_len(nf->netdev));
return 0;
}
@@ -233,7 +234,7 @@ static void filter_dump_instance_finalize(Object *obj)
g_free(nfds->filename);
}
-static void filter_dump_class_init(ObjectClass *oc, void *data)
+static void filter_dump_class_init(ObjectClass *oc, const void *data)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 283dc9c..a36be31 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -172,7 +172,7 @@ static void filter_buffer_set_interval(Object *obj, Visitor *v,
s->interval = value;
}
-static void filter_buffer_class_init(ObjectClass *oc, void *data)
+static void filter_buffer_class_init(ObjectClass *oc, const void *data)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index 34a63b5..27734c9 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -410,7 +410,7 @@ static void filter_redirector_set_vnet_hdr(Object *obj,
s->vnet_hdr = value;
}
-static void filter_mirror_class_init(ObjectClass *oc, void *data)
+static void filter_mirror_class_init(ObjectClass *oc, const void *data)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
@@ -425,7 +425,7 @@ static void filter_mirror_class_init(ObjectClass *oc, void *data)
nfc->receive_iov = filter_mirror_receive_iov;
}
-static void filter_redirector_class_init(ObjectClass *oc, void *data)
+static void filter_redirector_class_init(ObjectClass *oc, const void *data)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
diff --git a/net/filter-replay.c b/net/filter-replay.c
index 5469067..451663c 100644
--- a/net/filter-replay.c
+++ b/net/filter-replay.c
@@ -17,7 +17,7 @@
#include "qemu/timer.h"
#include "qapi/visitor.h"
#include "net/filter.h"
-#include "sysemu/replay.h"
+#include "system/replay.h"
#include "qom/object.h"
#define TYPE_FILTER_REPLAY "filter-replay"
@@ -65,7 +65,7 @@ static void filter_replay_instance_finalize(Object *obj)
replay_unregister_net(nfrs->rns);
}
-static void filter_replay_class_init(ObjectClass *oc, void *data)
+static void filter_replay_class_init(ObjectClass *oc, const void *data)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index c18c4c2..cdf85aa 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -411,7 +411,7 @@ static void filter_rewriter_init(Object *obj)
s->failover_mode = FAILOVER_MODE_OFF;
}
-static void colo_rewriter_class_init(ObjectClass *oc, void *data)
+static void colo_rewriter_class_init(ObjectClass *oc, const void *data)
{
NetFilterClass *nfc = NETFILTER_CLASS(oc);
diff --git a/net/filter.c b/net/filter.c
index 3335908..c7cc661 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -333,7 +333,7 @@ static void default_handle_event(NetFilterState *nf, int event, Error **errp)
}
}
-static void netfilter_class_init(ObjectClass *oc, void *data)
+static void netfilter_class_init(ObjectClass *oc, const void *data)
{
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
NetFilterClass *nfc = NETFILTER_CLASS(oc);
@@ -363,7 +363,7 @@ static const TypeInfo netfilter_info = {
.instance_size = sizeof(NetFilterState),
.instance_init = netfilter_init,
.instance_finalize = netfilter_finalize,
- .interfaces = (InterfaceInfo[]) {
+ .interfaces = (const InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
diff --git a/net/hub.c b/net/hub.c
index 4c8a469..cba20eb 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -20,7 +20,7 @@
#include "hub.h"
#include "qemu/iov.h"
#include "qemu/error-report.h"
-#include "sysemu/qtest.h"
+#include "system/qtest.h"
/*
* A hub broadcasts incoming packets to all its ports except the source port.
@@ -194,31 +194,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name,
}
/**
- * Find a available port on a hub; otherwise create one new port
- */
-NetClientState *net_hub_port_find(int hub_id)
-{
- NetHub *hub;
- NetHubPort *port;
- NetClientState *nc;
-
- QLIST_FOREACH(hub, &hubs, next) {
- if (hub->id == hub_id) {
- QLIST_FOREACH(port, &hub->ports, next) {
- nc = port->nc.peer;
- if (!nc) {
- return &(port->nc);
- }
- }
- break;
- }
- }
-
- nc = net_hub_add_port(hub_id, NULL, NULL);
- return nc;
-}
-
-/**
* Print hub configuration
*/
void net_hub_info(Monitor *mon)
diff --git a/net/meson.build b/net/meson.build
index e0cd714..bb97b4d 100644
--- a/net/meson.build
+++ b/net/meson.build
@@ -39,7 +39,7 @@ if have_netmap
system_ss.add(files('netmap.c'))
endif
-system_ss.add(when: libxdp, if_true: files('af-xdp.c'))
+system_ss.add(when: [libxdp, libbpf], if_true: files('af-xdp.c'))
if have_vhost_net_user
system_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('vhost-user.c'), if_false: files('vhost-user-stub.c'))
diff --git a/net/net-hmp-cmds.c b/net/net-hmp-cmds.c
index 41d326b..e7c55d2 100644
--- a/net/net-hmp-cmds.c
+++ b/net/net-hmp-cmds.c
@@ -22,7 +22,7 @@
#include "qapi/clone-visitor.h"
#include "qapi/qapi-commands-net.h"
#include "qapi/qapi-visit-net.h"
-#include "qapi/qmp/qdict.h"
+#include "qobject/qdict.h"
#include "qemu/config-file.h"
#include "qemu/help_option.h"
#include "qemu/option.h"
diff --git a/net/net.c b/net/net.c
index 2eb8bc9..39d6f28 100644
--- a/net/net.c
+++ b/net/net.c
@@ -36,7 +36,7 @@
#include "qemu/help_option.h"
#include "qapi/qapi-commands-net.h"
#include "qapi/qapi-visit-net.h"
-#include "qapi/qmp/qdict.h"
+#include "qobject/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
#include "qemu/sockets.h"
@@ -51,7 +51,7 @@
#include "qemu/keyval.h"
#include "qapi/error.h"
#include "qapi/opts-visitor.h"
-#include "sysemu/runstate.h"
+#include "system/runstate.h"
#include "net/colo-compare.h"
#include "net/filter.h"
#include "qapi/string-output-visitor.h"
@@ -381,9 +381,12 @@ NetClientState *qemu_get_peer(NetClientState *nc, int queue_index)
return ncs->peer;
}
-static void qemu_cleanup_net_client(NetClientState *nc)
+static void qemu_cleanup_net_client(NetClientState *nc,
+ bool remove_from_net_clients)
{
- QTAILQ_REMOVE(&net_clients, nc, next);
+ if (remove_from_net_clients) {
+ QTAILQ_REMOVE(&net_clients, nc, next);
+ }
if (nc->info->cleanup) {
nc->info->cleanup(nc);
@@ -425,7 +428,13 @@ void qemu_del_net_client(NetClientState *nc)
object_unparent(OBJECT(nf));
}
- /* If there is a peer NIC, delete and cleanup client, but do not free. */
+ /*
+ * If there is a peer NIC, transfer ownership to it. Delete the client
+ * from net_client list but do not cleanup nor free. This way NIC can
+ * still access to members of the backend.
+ *
+ * The cleanup and free will be done when the NIC is free.
+ */
if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
NICState *nic = qemu_get_nic(nc->peer);
if (nic->peer_deleted) {
@@ -435,21 +444,18 @@ void qemu_del_net_client(NetClientState *nc)
for (i = 0; i < queues; i++) {
ncs[i]->peer->link_down = true;
+ QTAILQ_REMOVE(&net_clients, ncs[i], next);
}
if (nc->peer->info->link_status_changed) {
nc->peer->info->link_status_changed(nc->peer);
}
- for (i = 0; i < queues; i++) {
- qemu_cleanup_net_client(ncs[i]);
- }
-
return;
}
for (i = 0; i < queues; i++) {
- qemu_cleanup_net_client(ncs[i]);
+ qemu_cleanup_net_client(ncs[i], true);
qemu_free_net_client(ncs[i]);
}
}
@@ -462,8 +468,12 @@ void qemu_del_nic(NICState *nic)
for (i = 0; i < queues; i++) {
NetClientState *nc = qemu_get_subqueue(nic, i);
- /* If this is a peer NIC and peer has already been deleted, free it now. */
+ /*
+ * If this is a peer NIC and peer has already been deleted, clean it up
+ * and free it now.
+ */
if (nic->peer_deleted) {
+ qemu_cleanup_net_client(nc->peer, false);
qemu_free_net_client(nc->peer);
} else if (nc->peer) {
/* if there are RX packets pending, complete them */
@@ -474,7 +484,7 @@ void qemu_del_nic(NICState *nic)
for (i = queues - 1; i >= 0; i--) {
NetClientState *nc = qemu_get_subqueue(nic, i);
- qemu_cleanup_net_client(nc);
+ qemu_cleanup_net_client(nc, true);
qemu_free_net_client(nc);
}
@@ -542,6 +552,10 @@ void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
int qemu_get_vnet_hdr_len(NetClientState *nc)
{
+ if (!nc) {
+ return 0;
+ }
+
return nc->vnet_hdr_len;
}
@@ -750,16 +764,6 @@ ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
return qemu_net_queue_receive(nc->incoming_queue, buf, size);
}
-ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov,
- int iovcnt)
-{
- if (!qemu_can_receive_packet(nc)) {
- return 0;
- }
-
- return qemu_net_queue_receive_iov(nc->incoming_queue, iov, iovcnt);
-}
-
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
{
return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
@@ -828,6 +832,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
iov_copy[0].iov_len = nc->vnet_hdr_len;
memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
iov = iov_copy;
+ iovcnt++;
}
if (nc->info->receive_iov) {
@@ -1683,6 +1688,9 @@ void net_cleanup(void)
* of the latest NET_CLIENT_DRIVER_NIC, and operate on *p as we walk
* the list.
*
+ * However, the NIC may have peers that trust to be clean beyond this
+ * point. For example, if they have been removed with device_del.
+ *
* The 'nc' variable isn't part of the list traversal; it's purely
* for convenience as too much '(*p)->' has a tendency to make the
* readers' eyes bleed.
@@ -1690,6 +1698,17 @@ void net_cleanup(void)
while (*p) {
nc = *p;
if (nc->info->type == NET_CLIENT_DRIVER_NIC) {
+ NICState *nic = qemu_get_nic(nc);
+
+ if (nic->peer_deleted) {
+ int queues = MAX(nic->conf->peers.queues, 1);
+
+ for (int i = 0; i < queues; i++) {
+ nc = qemu_get_subqueue(nic, i);
+ qemu_cleanup_net_client(nc->peer, false);
+ }
+ }
+
/* Skip NET_CLIENT_DRIVER_NIC entries */
p = &QTAILQ_NEXT(nc, next);
} else {
@@ -1737,7 +1756,7 @@ void net_check_clients(void)
static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
{
- const char *model = qemu_opt_get_del(opts, "model");
+ const char *model = qemu_opt_get(opts, "model");
if (is_nic_model_help_option(model)) {
return 0;
diff --git a/net/queue.c b/net/queue.c
index c872d51..fb33856 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -193,17 +193,6 @@ ssize_t qemu_net_queue_receive(NetQueue *queue,
return qemu_net_queue_deliver(queue, NULL, 0, data, size);
}
-ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
- const struct iovec *iov,
- int iovcnt)
-{
- if (queue->delivering) {
- return 0;
- }
-
- return qemu_net_queue_deliver_iov(queue, NULL, 0, iov, iovcnt);
-}
-
ssize_t qemu_net_queue_send(NetQueue *queue,
NetClientState *sender,
unsigned flags,
diff --git a/net/slirp.c b/net/slirp.c
index eb9a456..9657e86 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -40,10 +40,10 @@
#include "qemu/sockets.h"
#include <libslirp.h>
#include "chardev/char-fe.h"
-#include "sysemu/sysemu.h"
+#include "system/system.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
-#include "qapi/qmp/qdict.h"
+#include "qobject/qdict.h"
#include "util.h"
#include "migration/register.h"
#include "migration/vmstate.h"
@@ -247,7 +247,14 @@ static void net_slirp_timer_mod(void *timer, int64_t expire_timer,
timer_mod(&t->timer, expire_timer);
}
-static void net_slirp_register_poll_fd(int fd, void *opaque)
+#if !SLIRP_CHECK_VERSION(4, 9, 0)
+# define slirp_os_socket int
+# define slirp_pollfds_fill_socket slirp_pollfds_fill
+# define register_poll_socket register_poll_fd
+# define unregister_poll_socket unregister_poll_fd
+#endif
+
+static void net_slirp_register_poll_sock(slirp_os_socket fd, void *opaque)
{
#ifdef WIN32
AioContext *ctxt = qemu_get_aio_context();
@@ -260,7 +267,7 @@ static void net_slirp_register_poll_fd(int fd, void *opaque)
#endif
}
-static void net_slirp_unregister_poll_fd(int fd, void *opaque)
+static void net_slirp_unregister_poll_sock(slirp_os_socket fd, void *opaque)
{
#ifdef WIN32
if (WSAEventSelect(fd, NULL, 0) != 0) {
@@ -286,8 +293,8 @@ static const SlirpCb slirp_cb = {
#endif
.timer_free = net_slirp_timer_free,
.timer_mod = net_slirp_timer_mod,
- .register_poll_fd = net_slirp_register_poll_fd,
- .unregister_poll_fd = net_slirp_unregister_poll_fd,
+ .register_poll_socket = net_slirp_register_poll_sock,
+ .unregister_poll_socket = net_slirp_unregister_poll_sock,
.notify = net_slirp_notify,
};
@@ -314,7 +321,7 @@ static int slirp_poll_to_gio(int events)
return ret;
}
-static int net_slirp_add_poll(int fd, int events, void *opaque)
+static int net_slirp_add_poll(slirp_os_socket fd, int events, void *opaque)
{
GArray *pollfds = opaque;
GPollFD pfd = {
@@ -363,8 +370,8 @@ static void net_slirp_poll_notify(Notifier *notifier, void *data)
switch (poll->state) {
case MAIN_LOOP_POLL_FILL:
- slirp_pollfds_fill(s->slirp, &poll->timeout,
- net_slirp_add_poll, poll->pollfds);
+ slirp_pollfds_fill_socket(s->slirp, &poll->timeout,
+ net_slirp_add_poll, poll->pollfds);
break;
case MAIN_LOOP_POLL_OK:
case MAIN_LOOP_POLL_ERR:
@@ -629,7 +636,9 @@ static int net_slirp_init(NetClientState *peer, const char *model,
s = DO_UPCAST(SlirpState, nc, nc);
- cfg.version = SLIRP_CHECK_VERSION(4,7,0) ? 4 : 1;
+ cfg.version =
+ SLIRP_CHECK_VERSION(4, 9, 0) ? 6 :
+ SLIRP_CHECK_VERSION(4, 7, 0) ? 4 : 1;
cfg.restricted = restricted;
cfg.in_enabled = ipv4;
cfg.vnetwork = net;
diff --git a/net/socket.c b/net/socket.c
index 8e3702e..784dda6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -157,7 +157,7 @@ static void net_socket_send(void *opaque)
NetSocketState *s = opaque;
int size;
int ret;
- uint8_t buf1[NET_BUFSIZE];
+ QEMU_UNINITIALIZED uint8_t buf1[NET_BUFSIZE];
const uint8_t *buf;
size = recv(s->fd, buf1, sizeof(buf1), 0);
diff --git a/net/stream.c b/net/stream.c
index 97e6ec6..6152d2a 100644
--- a/net/stream.c
+++ b/net/stream.c
@@ -51,7 +51,7 @@ typedef struct NetStreamState {
guint ioc_write_tag;
SocketReadState rs;
unsigned int send_index; /* number of bytes sent*/
- uint32_t reconnect;
+ uint32_t reconnect_ms;
guint timer_tag;
SocketAddress *addr;
} NetStreamState;
@@ -148,7 +148,7 @@ static gboolean net_stream_send(QIOChannel *ioc,
NetStreamState *s = data;
int size;
int ret;
- char buf1[NET_BUFSIZE];
+ QEMU_UNINITIALIZED char buf1[NET_BUFSIZE];
const char *buf;
size = qio_channel_read(s->ioc, buf1, sizeof(buf1), NULL);
@@ -387,10 +387,9 @@ static gboolean net_stream_reconnect(gpointer data)
static void net_stream_arm_reconnect(NetStreamState *s)
{
- if (s->reconnect && s->timer_tag == 0) {
+ if (s->reconnect_ms && s->timer_tag == 0) {
qemu_set_info_str(&s->nc, "connecting");
- s->timer_tag = g_timeout_add_seconds(s->reconnect,
- net_stream_reconnect, s);
+ s->timer_tag = g_timeout_add(s->reconnect_ms, net_stream_reconnect, s);
}
}
@@ -398,7 +397,7 @@ static int net_stream_client_init(NetClientState *peer,
const char *model,
const char *name,
SocketAddress *addr,
- uint32_t reconnect,
+ uint32_t reconnect_ms,
Error **errp)
{
NetStreamState *s;
@@ -412,8 +411,8 @@ static int net_stream_client_init(NetClientState *peer,
s->ioc = QIO_CHANNEL(sioc);
s->nc.link_down = true;
- s->reconnect = reconnect;
- if (reconnect) {
+ s->reconnect_ms = reconnect_ms;
+ if (reconnect_ms) {
s->addr = QAPI_CLONE(SocketAddress, addr);
}
qio_channel_socket_connect_async(sioc, addr,
@@ -432,13 +431,24 @@ int net_init_stream(const Netdev *netdev, const char *name,
sock = &netdev->u.stream;
if (!sock->has_server || !sock->server) {
+ uint32_t reconnect_ms = 0;
+
+ if (sock->has_reconnect && sock->has_reconnect_ms) {
+ error_setg(errp, "'reconnect' and 'reconnect-ms' are mutually "
+ "exclusive");
+ return -1;
+ } else if (sock->has_reconnect_ms) {
+ reconnect_ms = sock->reconnect_ms;
+ } else if (sock->has_reconnect) {
+ reconnect_ms = sock->reconnect * 1000u;
+ }
+
return net_stream_client_init(peer, "stream", name, sock->addr,
- sock->has_reconnect ? sock->reconnect : 0,
- errp);
+ reconnect_ms, errp);
}
- if (sock->has_reconnect) {
- error_setg(errp, "'reconnect' option is incompatible with "
- "socket in server mode");
+ if (sock->has_reconnect || sock->has_reconnect_ms) {
+ error_setg(errp, "'reconnect' and 'reconnect-ms' options are "
+ "incompatible with socket in server mode");
return -1;
}
return net_stream_server_init(peer, "stream", name, sock->addr, errp);
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 1226d5f..22ec2f4 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -45,10 +45,21 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int len = sizeof(struct virtio_net_hdr);
unsigned int features;
- fd = RETRY_ON_EINTR(open(PATH_NET_TUN, O_RDWR));
+
+ ret = if_nametoindex(ifname);
+ if (ret) {
+ g_autofree char *file = g_strdup_printf("/dev/tap%d", ret);
+ fd = open(file, O_RDWR);
+ } else {
+ fd = -1;
+ }
+
if (fd < 0) {
- error_setg_errno(errp, errno, "could not open %s", PATH_NET_TUN);
- return -1;
+ fd = RETRY_ON_EINTR(open(PATH_NET_TUN, O_RDWR));
+ if (fd < 0) {
+ error_setg_errno(errp, errno, "could not open %s", PATH_NET_TUN);
+ return -1;
+ }
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 7edbd71..671dee9 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -214,7 +214,7 @@ static int is_tap_win32_dev(const char *guid)
for (;;) {
char enum_name[256];
- char unit_string[256];
+ g_autofree char *unit_string = NULL;
HKEY unit_key;
char component_id_string[] = "ComponentId";
char component_id[256];
@@ -239,8 +239,7 @@ static int is_tap_win32_dev(const char *guid)
return FALSE;
}
- snprintf (unit_string, sizeof(unit_string), "%s\\%s",
- ADAPTER_KEY, enum_name);
+ unit_string = g_strdup_printf("%s\\%s", ADAPTER_KEY, enum_name);
status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
@@ -315,7 +314,7 @@ static int get_device_guid(
while (!stop)
{
char enum_name[256];
- char connection_string[256];
+ g_autofree char *connection_string = NULL;
HKEY connection_key;
char name_data[256];
DWORD name_type;
@@ -338,9 +337,7 @@ static int get_device_guid(
return -1;
}
- snprintf(connection_string,
- sizeof(connection_string),
- "%s\\%s\\Connection",
+ connection_string = g_strdup_printf("%s\\%s\\Connection",
NETWORK_CONNECTIONS_KEY, enum_name);
status = RegOpenKeyEx(
@@ -595,7 +592,7 @@ static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
- char device_path[256];
+ g_autofree char *device_path = NULL;
char device_guid[0x100];
int rc;
HANDLE handle;
@@ -617,7 +614,7 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
if (rc)
return -1;
- snprintf (device_path, sizeof(device_path), "%s%s%s",
+ device_path = g_strdup_printf("%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
diff --git a/net/tap.c b/net/tap.c
index 51f7aec..ae1c7e3 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -36,7 +36,7 @@
#include "net/net.h"
#include "clients.h"
#include "monitor/monitor.h"
-#include "sysemu/sysemu.h"
+#include "system/system.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
@@ -385,6 +385,24 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
return s;
}
+static void close_all_fds_after_fork(int excluded_fd)
+{
+ const int skip_fd[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
+ excluded_fd};
+ unsigned int nskip = ARRAY_SIZE(skip_fd);
+
+ /*
+ * skip_fd must be an ordered array of distinct fds, exclude
+ * excluded_fd if already included in the [STDIN_FILENO - STDERR_FILENO]
+ * range
+ */
+ if (excluded_fd <= STDERR_FILENO) {
+ nskip--;
+ }
+
+ qemu_close_all_open_fd(skip_fd, nskip);
+}
+
static void launch_script(const char *setup_script, const char *ifname,
int fd, Error **errp)
{
@@ -400,13 +418,7 @@ static void launch_script(const char *setup_script, const char *ifname,
return;
}
if (pid == 0) {
- int open_max = sysconf(_SC_OPEN_MAX), i;
-
- for (i = 3; i < open_max; i++) {
- if (i != fd) {
- close(i);
- }
- }
+ close_all_fds_after_fork(fd);
parg = args;
*parg++ = (char *)setup_script;
*parg++ = (char *)ifname;
@@ -490,17 +502,11 @@ static int net_bridge_run_helper(const char *helper, const char *bridge,
return -1;
}
if (pid == 0) {
- int open_max = sysconf(_SC_OPEN_MAX), i;
char *fd_buf = NULL;
char *br_buf = NULL;
char *helper_cmd = NULL;
- for (i = 3; i < open_max; i++) {
- if (i != sv[1]) {
- close(i);
- }
- }
-
+ close_all_fds_after_fork(sv[1]);
fd_buf = g_strdup_printf("%s%d", "--fd=", sv[1]);
if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 1255551..0b235e5 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -16,6 +16,7 @@
#include "chardev/char-fe.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-net.h"
+#include "qapi/qapi-events-net.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
@@ -271,6 +272,7 @@ static void chr_closed_bh(void *opaque)
if (err) {
error_report_err(err);
}
+ qapi_event_send_netdev_vhost_user_disconnected(name);
}
static void net_vhost_user_event(void *opaque, QEMUChrEvent event)
@@ -300,6 +302,7 @@ static void net_vhost_user_event(void *opaque, QEMUChrEvent event)
net_vhost_user_watch, s);
qmp_set_link(name, true, &err);
s->started = true;
+ qapi_event_send_netdev_vhost_user_connected(name, chr->label);
break;
case CHR_EVENT_CLOSED:
/* a close event may happen during a read/write, but vhost
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 03457ea..58d7389 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -88,6 +88,7 @@ const int vdpa_feature_bits[] = {
VIRTIO_NET_F_MQ,
VIRTIO_NET_F_MRG_RXBUF,
VIRTIO_NET_F_MTU,
+ VIRTIO_NET_F_RSC_EXT,
VIRTIO_NET_F_RSS,
VIRTIO_NET_F_STATUS,
VIRTIO_RING_F_EVENT_IDX,
@@ -223,14 +224,6 @@ static void vhost_vdpa_cleanup(NetClientState *nc)
{
VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
- /*
- * If a peer NIC is attached, do not cleanup anything.
- * Cleanup will happen as a part of qemu_cleanup() -> net_cleanup()
- * when the guest is shutting down.
- */
- if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_NIC) {
- return;
- }
munmap(s->cvq_cmd_out_buffer, vhost_vdpa_net_cvq_cmd_page_len());
munmap(s->status, vhost_vdpa_net_cvq_cmd_page_len());
if (s->vhost_net) {
@@ -242,6 +235,7 @@ static void vhost_vdpa_cleanup(NetClientState *nc)
return;
}
qemu_close(s->vhost_vdpa.shared->device_fd);
+ g_clear_pointer(&s->vhost_vdpa.shared->iova_tree, vhost_iova_tree_delete);
g_free(s->vhost_vdpa.shared);
}
@@ -269,6 +263,18 @@ static bool vhost_vdpa_has_ufo(NetClientState *nc)
}
+/*
+ * FIXME: vhost_vdpa doesn't have an API to "set h/w endianness". But it's
+ * reasonable to assume that h/w is LE by default, because LE is what
+ * virtio 1.0 and later ask for. So, this function just says "yes, the h/w is
+ * LE". Otherwise, on a BE machine, higher-level code would mistakely think
+ * the h/w is BE and can't support VDPA for a virtio 1.0 client.
+ */
+static int vhost_vdpa_set_vnet_le(NetClientState *nc, bool enable)
+{
+ return 0;
+}
+
static bool vhost_vdpa_check_peer_type(NetClientState *nc, ObjectClass *oc,
Error **errp)
{
@@ -357,14 +363,8 @@ static int vdpa_net_migration_state_notifier(NotifierWithReturn *notifier,
static void vhost_vdpa_net_data_start_first(VhostVDPAState *s)
{
- struct vhost_vdpa *v = &s->vhost_vdpa;
-
migration_add_notifier(&s->migration_state,
vdpa_net_migration_state_notifier);
- if (v->shadow_vqs_enabled) {
- v->shared->iova_tree = vhost_iova_tree_new(v->shared->iova_range.first,
- v->shared->iova_range.last);
- }
}
static int vhost_vdpa_net_data_start(NetClientState *nc)
@@ -374,8 +374,7 @@ static int vhost_vdpa_net_data_start(NetClientState *nc)
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
- if (s->always_svq ||
- migration_is_setup_or_active()) {
+ if (s->always_svq || migration_is_running()) {
v->shadow_vqs_enabled = true;
} else {
v->shadow_vqs_enabled = false;
@@ -412,19 +411,12 @@ static int vhost_vdpa_net_data_load(NetClientState *nc)
static void vhost_vdpa_net_client_stop(NetClientState *nc)
{
VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
- struct vhost_dev *dev;
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
if (s->vhost_vdpa.index == 0) {
migration_remove_notifier(&s->migration_state);
}
-
- dev = s->vhost_vdpa.dev;
- if (dev->vq_index + dev->nvqs == dev->vq_index_end) {
- g_clear_pointer(&s->vhost_vdpa.shared->iova_tree,
- vhost_iova_tree_delete);
- }
}
static NetClientInfo net_vhost_vdpa_info = {
@@ -437,6 +429,7 @@ static NetClientInfo net_vhost_vdpa_info = {
.cleanup = vhost_vdpa_cleanup,
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
.has_ufo = vhost_vdpa_has_ufo,
+ .set_vnet_le = vhost_vdpa_set_vnet_le,
.check_peer_type = vhost_vdpa_check_peer_type,
.set_steering_ebpf = vhost_vdpa_set_steering_ebpf,
};
@@ -510,14 +503,20 @@ static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size,
bool write)
{
DMAMap map = {};
+ hwaddr taddr = (hwaddr)(uintptr_t)buf;
int r;
- map.translated_addr = (hwaddr)(uintptr_t)buf;
map.size = size - 1;
map.perm = write ? IOMMU_RW : IOMMU_RO,
- r = vhost_iova_tree_map_alloc(v->shared->iova_tree, &map);
+ r = vhost_iova_tree_map_alloc(v->shared->iova_tree, &map, taddr);
if (unlikely(r != IOVA_OK)) {
error_report("Cannot map injected element");
+
+ if (map.translated_addr == taddr) {
+ error_report("Insertion to IOVA->HVA tree failed");
+ /* Remove the mapping from the IOVA-only tree */
+ goto dma_map_err;
+ }
return r;
}
@@ -589,24 +588,6 @@ out:
return 0;
}
- /*
- * If other vhost_vdpa already have an iova_tree, reuse it for simplicity,
- * whether CVQ shares ASID with guest or not, because:
- * - Memory listener need access to guest's memory addresses allocated in
- * the IOVA tree.
- * - There should be plenty of IOVA address space for both ASID not to
- * worry about collisions between them. Guest's translations are still
- * validated with virtio virtqueue_pop so there is no risk for the guest
- * to access memory that it shouldn't.
- *
- * To allocate a iova tree per ASID is doable but it complicates the code
- * and it is not worth it for the moment.
- */
- if (!v->shared->iova_tree) {
- v->shared->iova_tree = vhost_iova_tree_new(v->shared->iova_range.first,
- v->shared->iova_range.last);
- }
-
r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer,
vhost_vdpa_net_cvq_cmd_page_len(), false);
if (unlikely(r < 0)) {
@@ -643,7 +624,7 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s,
VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0);
int r;
- r = vhost_svq_add(svq, out_sg, out_num, in_sg, in_num, NULL);
+ r = vhost_svq_add(svq, out_sg, out_num, NULL, in_sg, in_num, NULL, NULL);
if (unlikely(r != 0)) {
if (unlikely(r == -ENOSPC)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
@@ -1715,6 +1696,8 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
s->vhost_vdpa.shared->device_fd = vdpa_device_fd;
s->vhost_vdpa.shared->iova_range = iova_range;
s->vhost_vdpa.shared->shadow_data = svq;
+ s->vhost_vdpa.shared->iova_tree = vhost_iova_tree_new(iova_range.first,
+ iova_range.last);
} else if (!is_datapath) {
s->cvq_cmd_out_buffer = mmap(NULL, vhost_vdpa_net_cvq_cmd_page_len(),
PROT_READ | PROT_WRITE,
diff --git a/net/vmnet-common.m b/net/vmnet-common.m
index 30c4e53..ab33ce2 100644
--- a/net/vmnet-common.m
+++ b/net/vmnet-common.m
@@ -17,7 +17,8 @@
#include "clients.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
-#include "sysemu/runstate.h"
+#include "system/runstate.h"
+#include "net/eth.h"
#include <vmnet/vmnet.h>
#include <dispatch/dispatch.h>
@@ -93,7 +94,7 @@ ssize_t vmnet_receive_common(NetClientState *nc,
if_status = vmnet_write(s->vmnet_if, &packet, &pkt_cnt);
if (if_status != VMNET_SUCCESS) {
- error_report("vmnet: write error: %s\n",
+ error_report("vmnet: write error: %s",
vmnet_status_map_str(if_status));
return -1;
}
@@ -147,10 +148,26 @@ static int vmnet_read_packets(VmnetState *s)
*/
static void vmnet_write_packets_to_qemu(VmnetState *s)
{
+ uint8_t *pkt;
+ size_t pktsz;
+ uint8_t min_pkt[ETH_ZLEN];
+ size_t min_pktsz;
+ ssize_t size;
+
while (s->packets_send_current_pos < s->packets_send_end_pos) {
- ssize_t size = qemu_send_packet_async(&s->nc,
- s->iov_buf[s->packets_send_current_pos].iov_base,
- s->packets_buf[s->packets_send_current_pos].vm_pkt_size,
+ pkt = s->iov_buf[s->packets_send_current_pos].iov_base;
+ pktsz = s->packets_buf[s->packets_send_current_pos].vm_pkt_size;
+
+ if (net_peer_needs_padding(&s->nc)) {
+ min_pktsz = sizeof(min_pkt);
+
+ if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pktsz)) {
+ pkt = min_pkt;
+ pktsz = min_pktsz;
+ }
+ }
+
+ size = qemu_send_packet_async(&s->nc, pkt, pktsz,
vmnet_send_completed);
if (size == 0) {