The default Linux TCP retransmission timeout for unacknowledged segments
is on the order of 15+ minutes and can stretch well past an hour with
exponential backoff. For QEMU live migration over TCP that means a
silently disconnected peer (cable pulled, peer host crashed, NAT idle
flush, firewall reset) can leave the source QEMU "migrating" for many
minutes with no diagnosis.
TCP keep-alive options already help, but they only trigger on idle
connections; they do nothing when the connection has unacknowledged
in-flight data, which is the common case during a live migration push.
The Linux TCP_USER_TIMEOUT socket option bounds this: the kernel
forcibly closes the connection and returns ETIMEDOUT after the
configured number of milliseconds of unacknowledged data, regardless of
keep-alive state.
This series adds TCP_USER_TIMEOUT as a new optional InetSocketAddress
member. Two parsing paths feed into InetSocketAddress in QEMU, and
both need separate plumbing to accept a new option:
- the QAPI keyval visitor used by modern syntax such as
-netdev stream, -chardev socket, -incoming <channel>, and any
QMP command that takes a SocketAddress argument. This path
automatically picks up the new member once it is declared in
qapi/sockets.json.
- the legacy URI parser (socket_parse() -> inet_parse()) used by
-incoming tcp:, migrate tcp:, and HMP nbd_server_start, which
has its own option table (inet_opts) and needs an explicit entry
plus a copy into the QAPI struct.
This series adds the qapi/sockets.json declaration and the inet_opts /
inet_parse() plumbing so that user-timeout is available through both
paths.
While preparing it I noticed two pre-existing qemu-options.hx issues
that had never been caught because nothing tested those options'
acceptance through the QAPI path:
- The -netdev stream synopsis listed several InetSocketAddress and
UnixSocketAddress members without the required "addr." prefix
(to, numeric, keep-alive, mptcp, ipv4, ipv6, abstract, tight).
These names are actually rejected by the QAPI input visitor with
"Parameter '...' is unexpected". Broken since bb1326abd9df ("net:
update netdev stream/dgram man page", 2024-07).
- keep-alive-count/idle/interval (added to InetSocketAddress in 10.1)
and keep-alive/numeric/mptcp (older) were never documented in the
-incoming tcp: synopsis, despite inet_opts accepting them.
The series is therefore split into:
1/5 bug-fix only: add the missing "addr." prefix to -netdev stream
inet/unix option docs (separated so it can be considered for
stable backport)
2/5 pure docs: keep-alive-count/idle/interval for -netdev stream
3/5 pure docs: keep-alive*/numeric/mptcp for -incoming tcp:
4/5 the feature itself: meson HAVE_TCP_USER_TIMEOUT check,
qapi/sockets.json schema addition, inet_set_sockopts() and
inet_parse() plumbing, qemu-options.hx user-timeout entries for
both -netdev stream (addr.user-timeout=...) and -incoming tcp:
(user-timeout=...), and test_inet_parse_all_options_good
extension
5/5 new qtest /netdev/stream/inet/options that smoke-tests the
complete optional InetSocketAddress member set on the QAPI
keyval parsing path; catches the class of schema/synopsis drift
described above
Each commit builds and passes test-util-sockets and
qtest-x86_64/netdev-socket independently, verified with
git rebase --exec. checkpatch reports 0 errors / 0 warnings for every
patch.
A companion libvirt change to expose this option through the QEMU
driver's migration parameters is in preparation.
Mitsuru Kariya (5):
qemu-options: fix missing addr. prefix on -netdev stream inet/unix
options
qemu-options: document keep-alive-count/idle/interval for -netdev
stream
qemu-options: document keep-alive*/numeric/mptcp for -incoming tcp:
util/qemu-sockets: add TCP_USER_TIMEOUT support
tests/qtest/netdev-socket: smoke test -netdev stream inet option set
meson.build | 2 +
qapi/sockets.json | 7 ++++
qemu-options.hx | 47 +++++++++++++++-------
tests/qtest/netdev-socket.c | 71 ++++++++++++++++++++++++++++++++++
tests/unit/test-util-sockets.c | 13 +++++++
util/qemu-sockets.c | 24 ++++++++++++
6 files changed, 149 insertions(+), 15 deletions(-)
--
2.43.0