Hi, FreeBSD has a fix for TCP send window underflow. markus@ has seen that this bug is also triggered in our code.
https://svnweb.freebsd.org/base/head/sys/netinet/tcp_input.c?r1=296935&r2=298408 Prevent underflows in tp->snd_wnd if the remote side ACKs more than tp->snd_wnd. This can happen, for example, when the remote side responds to a window probe by ACKing the one byte it contains. Note that FreeBSD has an additional cast in "if (tp->snd_wnd >= (u_long) acked)". This is not necessary as the compiler will do this conversion anyway. markus@ did put an additional check in his fix "if (tp->snd_wnd > acked && acked >= 0)", but this is also not necessary. The integer variable acked is always positive due to the check "if (SEQ_LEQ(th->th_ack, tp->snd_una))" some lines above. ok? bluhm Index: netinet/tcp_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.361 diff -u -p -r1.361 tcp_input.c --- netinet/tcp_input.c 12 Jul 2019 19:43:51 -0000 1.361 +++ netinet/tcp_input.c 10 Nov 2019 22:00:29 -0000 @@ -1712,12 +1712,18 @@ trimthenstep6: } ND6_HINT(tp); if (acked > so->so_snd.sb_cc) { - tp->snd_wnd -= so->so_snd.sb_cc; + if (tp->snd_wnd > so->so_snd.sb_cc) + tp->snd_wnd -= so->so_snd.sb_cc; + else + tp->snd_wnd = 0; sbdrop(so, &so->so_snd, (int)so->so_snd.sb_cc); ourfinisacked = 1; } else { sbdrop(so, &so->so_snd, acked); - tp->snd_wnd -= acked; + if (tp->snd_wnd > acked) + tp->snd_wnd -= acked; + else + tp->snd_wnd = 0; ourfinisacked = 0; }