Handle local-incoming option:
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
include/net/tap.h | 4 ++
net/tap.c | 129 ++++++++++++++++++++++++++++++++++------------
2 files changed, 99 insertions(+), 34 deletions(-)
diff --git a/include/net/tap.h b/include/net/tap.h
index 6f34f13eae..3ef2e2dbae 100644
--- a/include/net/tap.h
+++ b/include/net/tap.h
@@ -30,7 +30,11 @@
int tap_enable(NetClientState *nc);
int tap_disable(NetClientState *nc);
+bool tap_local_incoming(NetClientState *nc);
int tap_get_fd(NetClientState *nc);
+int tap_load(NetClientState *nc, QEMUFile *f);
+int tap_save(NetClientState *nc, QEMUFile *f);
+
#endif /* QEMU_NET_TAP_H */
diff --git a/net/tap.c b/net/tap.c
index c07af762b0..4d3cdc0662 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -35,6 +35,8 @@
#include "net/eth.h"
#include "net/net.h"
#include "clients.h"
+#include "migration/migration.h"
+#include "migration/qemu-file.h"
#include "monitor/monitor.h"
#include "system/system.h"
#include "qapi/error.h"
@@ -81,6 +83,7 @@ typedef struct TAPState {
VHostNetState *vhost_net;
unsigned host_vnet_hdr_len;
Notifier exit;
+ bool local_incoming;
} TAPState;
static void launch_script(const char *setup_script, const char *ifname,
@@ -727,21 +730,25 @@ static int net_tap_open_one(const Netdev *netdev,
vnet_hdr_required = 0;
}
- fd = RETRY_ON_EINTR(tap_open(ifname, ifname_sz, &vnet_hdr,
- vnet_hdr_required, mq_required, errp));
- if (fd < 0) {
- return -1;
- }
-
- if (script &&
- script[0] != '\0' &&
- strcmp(script, "no") != 0) {
- launch_script(script, ifname, fd, &err);
- if (err) {
- error_propagate(errp, err);
- close(fd);
+ if (tap->local_incoming) {
+ fd = -1;
+ } else {
+ fd = RETRY_ON_EINTR(tap_open(ifname, ifname_sz, &vnet_hdr,
+ vnet_hdr_required, mq_required, errp));
+ if (fd < 0) {
return -1;
}
+
+ if (script &&
+ script[0] != '\0' &&
+ strcmp(script, "no") != 0) {
+ launch_script(script, ifname, fd, &err);
+ if (err) {
+ error_propagate(errp, err);
+ close(fd);
+ return -1;
+ }
+ }
}
ret = net_tap_fd_init_common(netdev, peer, "tap", name, ifname,
@@ -757,6 +764,42 @@ static int net_tap_open_one(const Netdev *netdev,
#define MAX_TAP_QUEUES 1024
+int tap_save(NetClientState *nc, QEMUFile *f)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+ qemu_file_put_fd(f, s->fd);
+ qemu_put_byte(f, s->using_vnet_hdr);
+ qemu_put_byte(f, s->has_ufo);
+ qemu_put_byte(f, s->has_uso);
+ qemu_put_byte(f, s->enabled);
+ qemu_put_be32(f, s->host_vnet_hdr_len);
+
+ return 0;
+}
+
+int tap_load(NetClientState *nc, QEMUFile *f)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+ s->fd = qemu_file_get_fd(f);
+ if (s->fd < 0) {
+ return -1;
+ }
+
+ s->using_vnet_hdr = qemu_get_byte(f);
+ s->has_ufo = qemu_get_byte(f);
+ s->has_uso = qemu_get_byte(f);
+ s->enabled = qemu_get_byte(f);
+ qemu_get_be32s(f, &s->host_vnet_hdr_len);
+
+ tap_read_poll(s, true);
+ s->exit.notify = tap_exit_notify;
+ qemu_add_exit_notifier(&s->exit);
+
+ return 0;
+}
+
static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
const char *model, const char *name,
const char *ifname, const char *script,
@@ -764,30 +807,40 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
const char *vhostfdname,
int vnet_hdr, int fd, Error **errp)
{
- const NetdevTapOptions *tap;
+ const NetdevTapOptions *tap = NULL;
int ret;
NetClientState *nc;
TAPState *s;
+ bool local_incoming = false;
+
+ if (netdev->type == NET_CLIENT_DRIVER_TAP) {
+ tap = &netdev->u.tap;
+ local_incoming = tap->local_incoming;
+ }
nc = qemu_new_net_client(&net_tap_info, peer, model, name);
s = DO_UPCAST(TAPState, nc, nc);
-
- s->fd = fd;
- s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
- s->using_vnet_hdr = false;
- s->has_ufo = tap_probe_has_ufo(s->fd);
- s->has_uso = tap_probe_has_uso(s->fd);
- s->enabled = true;
- tap_set_offload(&s->nc, 0, 0, 0, 0, 0, 0, 0);
- /*
- * Make sure host header length is set correctly in tap:
- * it might have been modified by another instance of qemu.
- */
- if (vnet_hdr) {
- tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
+ s->local_incoming = local_incoming;
+
+ if (!local_incoming) {
+ s->fd = fd;
+ s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
+ s->using_vnet_hdr = false;
+ s->has_ufo = tap_probe_has_ufo(s->fd);
+ s->has_uso = tap_probe_has_uso(s->fd);
+ s->enabled = true;
+ tap_set_offload(&s->nc, 0, 0, 0, 0, 0, 0, 0);
+ /*
+ * Make sure host header length is set correctly in tap:
+ * it might have been modified by another instance of qemu.
+ */
+ if (vnet_hdr) {
+ tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
+ }
+ tap_read_poll(s, true);
}
- tap_read_poll(s, true);
+
s->vhost_net = NULL;
s->exit.notify = NULL;
@@ -799,9 +852,8 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
}
assert(netdev->type == NET_CLIENT_DRIVER_TAP);
- tap = &netdev->u.tap;
- if (tap_set_sndbuf(s->fd, tap, errp) < 0) {
+ if (!local_incoming && tap_set_sndbuf(s->fd, tap, errp) < 0) {
goto failed;
}
@@ -822,9 +874,11 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
}
}
- ret = net_tap_setup_vhost(s, tap, vhostfdname, errp);
- if (ret < 0) {
- goto failed;
+ if (!local_incoming) {
+ ret = net_tap_setup_vhost(s, tap, vhostfdname, errp);
+ if (ret < 0) {
+ goto failed;
+ }
}
return 0;
@@ -1081,3 +1135,10 @@ int tap_disable(NetClientState *nc)
return ret;
}
}
+
+bool tap_local_incoming(NetClientState *nc)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+ return s->local_incoming && runstate_check(RUN_STATE_INMIGRATE);
+}
--
2.48.1
© 2016 - 2025 Red Hat, Inc.