Handle local-incoming option: Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@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