While discussing an issue we are seeing in field, Jonathan pointed out another issue where snd_wnd can underflow and he created a review for it with a possible fix: https://reviews.freebsd.org/D5625
But he also raised a valid point of whether that specific logic is
correct/needed or not. I.e. should we decrement snd_wnd by number of bytes
acked when we are anyhow going to get window information from the
client?
Send window update happens at 2 places in our code right now inside
tcp_do_segment() in tcp_input.c
Block1 In "process_ACK:"
if (acked > sbavail(&so->so_snd)) {
tp->snd_wnd -= sbavail(&so->so_snd);
mfree = sbcut_locked(&so->so_snd,
(int)sbavail(&so->so_snd));
ourfinisacked = 1;
} else {
mfree = sbcut_locked(&so->so_snd, acked);
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
Block2 In "step6:"
if ((thflags & TH_ACK) &&
(SEQ_LT(tp->snd_wl1, th->th_seq) ||
(tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) ||
(tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) {
Logic in plain english:
snd_wl1; last seg that updated window
snd_wl2; last ack that updated window
snd_wl1 <= th_seq || seq is newer
snd_wl1 == th_seq && snd_wl2 <= th_ack || seq is same but ack is newer
snd_wl2 == th_ack && tiwin > snd_wnd ack is same but window is larger
So, in Block1, we more or less decrement snd_wnd by number of bytes
acked. Later in Block2, we use that (changed) value in making decision
of whether we'd accept window update from a certain ack or not.
What is the importance of that logic/code in Block1? I didn't find any
specific reference of that in RFCs though TCP/IP Illustrated Vol.2 has
that without specific explanation.
NetBSD is same as FreeBSD but I don't think Linux subtracts acked bytes
from snd_wnd based on my cursory look at their code.
(Differences of Block2 between different implementations is another can
of worms but I'll leave that to another day. :-))
Cheers,
Hiren
pgpiqUo5oacnR.pgp
Description: PGP signature
