Hi, I have seen some stalling TCP connections while doing unidirectional throughput tests. The sending machine is doing zero window probes, but is not sending more data although the other machine announced that it has space again.
I guess this commit in tcp_input.c triggered it: ---------------------------- revision 1.362 date: 2019/11/11 21:17:21; author: bluhm; state: Exp; lines: +9 -3; commitid: wXndkYTLO9jvCPdW; 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. from FreeBSD; via markus@; OK sashan@ tobhe@ ---------------------------- There we fixed an integer underflow. So we no longer have uint32 max in the send window, but 0. I see this in my test case. Now we need the machanism that writes the correct send window size. There is a commit in FreeBSD from 2002: https://github.com/freebsd/freebsd-src/commit/1645d0903ef7162f5c4516373f0c9df0501ac893 The header prediction code did not update snd_wl2. If there is a sequence number wrap, the send window update is not reached. Although I did not obverve it, there seems to be the same problem for snd_wl1 and rcv_up. For rcv_up I copied the comparison with rcv_nxt from urgent processing to keep future urgent data. ok? bluhm Index: netinet/tcp_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.368 diff -u -p -r1.368 tcp_input.c --- netinet/tcp_input.c 16 Apr 2021 12:08:25 -0000 1.368 +++ netinet/tcp_input.c 5 Aug 2021 21:51:50 -0000 @@ -966,6 +966,8 @@ findpcb: tp->t_pmtud_mss_acked = acked; tp->snd_una = th->th_ack; + /* Pull snd_wl2 up to prevent seq wrap. */ + tp->snd_wl2 = th->th_ack; /* * We want snd_last to track snd_una so * as to avoid sequence wraparound problems @@ -1015,6 +1017,10 @@ findpcb: tcp_clean_sackreport(tp); tcpstat_inc(tcps_preddat); tp->rcv_nxt += tlen; + /* Pull snd_wl1 and rcv_up up to prevent seq wrap. */ + tp->snd_wl1 = th->th_seq; + if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) + tp->rcv_up = tp->rcv_nxt; tcpstat_pkt(tcps_rcvpack, tcps_rcvbyte, tlen); ND6_HINT(tp);