diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2025-08-29 22:11:30 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2025-09-11 17:03:44 +0200 |
commit | 25f93545e7232a7dab9a022862514778c18bc85e (patch) | |
tree | 1a02de8334d2a43c22704c979a522d2e168e0e99 | |
parent | c62fb08002ad88079b84d1aa694492746f0d7f22 (diff) | |
download | passt-25f93545e7232a7dab9a022862514778c18bc85e.tar passt-25f93545e7232a7dab9a022862514778c18bc85e.tar.gz passt-25f93545e7232a7dab9a022862514778c18bc85e.tar.bz2 passt-25f93545e7232a7dab9a022862514778c18bc85e.tar.lz passt-25f93545e7232a7dab9a022862514778c18bc85e.tar.xz passt-25f93545e7232a7dab9a022862514778c18bc85e.tar.zst passt-25f93545e7232a7dab9a022862514778c18bc85e.zip |
tcp: Don't try to transmit right after the peer shrank the window to zero
If the peer shrinks the window to zero, we'll skip storing the new
window, as a convenient way to cause window probes (which exceed any
zero-sized window, strictly speaking) if we don't get window updates
in a while.
As we do so, though, we need to ensure we don't try to queue more data
from the socket right after we process this window update, as the
entire point of a zero-window advertisement is to keep us from sending
more data.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: Paul Holzinger <pholzing@redhat.com>
Reviewed-by: Jon Maloy <jmaloy@redhat.com>
-rw-r--r-- | tcp.c | 16 |
1 files changed, 9 insertions, 7 deletions
@@ -1271,8 +1271,10 @@ static void tcp_get_tap_ws(struct tcp_tap_conn *conn, * @c: Execution context * @conn: Connection pointer * @wnd: Window value, host order, unscaled + * + * Return: false on zero window (not stored to wnd_from_tap), true otherwise */ -static void tcp_tap_window_update(const struct ctx *c, +static bool tcp_tap_window_update(const struct ctx *c, struct tcp_tap_conn *conn, unsigned wnd) { wnd = MIN(MAX_WINDOW, wnd << conn->ws_from_tap); @@ -1285,13 +1287,14 @@ static void tcp_tap_window_update(const struct ctx *c, */ if (!wnd && SEQ_LT(conn->seq_ack_from_tap, conn->seq_to_tap)) { tcp_rewind_seq(c, conn); - return; + return false; } conn->wnd_from_tap = MIN(wnd >> conn->ws_from_tap, USHRT_MAX); /* FIXME: reflect the tap-side receiver's window back to the sock-side * sender by adjusting SO_RCVBUF? */ + return true; } /** @@ -2101,9 +2104,8 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af, if (!th->ack) goto reset; - tcp_tap_window_update(c, conn, ntohs(th->window)); - - tcp_data_from_sock(c, conn); + if (tcp_tap_window_update(c, conn, ntohs(th->window))) + tcp_data_from_sock(c, conn); if (p->count - idx == 1) return 1; @@ -2113,8 +2115,8 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af, if (conn->events & TAP_FIN_RCVD) { tcp_sock_consume(conn, ntohl(th->ack_seq)); tcp_update_seqack_from_tap(c, conn, ntohl(th->ack_seq)); - tcp_tap_window_update(c, conn, ntohs(th->window)); - tcp_data_from_sock(c, conn); + if (tcp_tap_window_update(c, conn, ntohs(th->window))) + tcp_data_from_sock(c, conn); if (conn->seq_ack_from_tap == conn->seq_to_tap) { if (th->ack && conn->events & TAP_FIN_SENT) |