Polling when VM is stopped doesn't make real sense, as stopped VM can't handle incoming traffic anyway.
And it's critical for introduction of local TAP migration feature in the next commit: the TAP device will be transferred to the target (open fd will be passed through migration channel), and if we continue polling on source, we may get a package, which we'll never handle on source (already stopped), it will be lost. Better is save this package for target VM to handle. Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]> --- net/tap.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/net/tap.c b/net/tap.c index b5be456936d..605e5867b01 100644 --- a/net/tap.c +++ b/net/tap.c @@ -36,6 +36,7 @@ #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" +#include "system/runstate.h" #include "system/system.h" #include "qapi/error.h" #include "qemu/cutils.h" @@ -92,6 +93,8 @@ struct TAPState { Notifier exit; int queue_index; + bool read_poll_detached; + VMChangeStateEntry *vmstate; }; static void launch_script(const char *setup_script, const char *ifname, @@ -146,6 +149,23 @@ static void tap_read_poll(TAPState *s, bool enable) tap_update_fd_handler(s); } +static void tap_vm_state_change(void *opaque, bool running, RunState state) +{ + TAPState *s = opaque; + + if (running) { + if (s->read_poll_detached) { + tap_read_poll(s, true); + s->read_poll_detached = false; + } + } else if (state == RUN_STATE_FINISH_MIGRATE) { + if (s->read_poll) { + s->read_poll_detached = true; + tap_read_poll(s, false); + } + } +} + static void tap_write_poll(TAPState *s, bool enable) { s->write_poll = enable; @@ -376,6 +396,11 @@ static void tap_cleanup(NetClientState *nc) s->exit.notify = NULL; } + if (s->vmstate) { + qemu_del_vm_change_state_handler(s->vmstate); + s->vmstate = NULL; + } + tap_read_poll(s, false); tap_write_poll(s, false); close(s->fd); @@ -815,6 +840,9 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, int sndbuf = (tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT_MAX; + s->read_poll_detached = false; + s->vmstate = qemu_add_vm_change_state_handler(tap_vm_state_change, s); + if (!tap_set_sndbuf(fd, sndbuf, sndbuf_required ? errp : NULL) && sndbuf_required) { goto failed; -- 2.43.0
