Update various comments mainly related to retransmit/FIN that I
documented while working on a previous bug. Fix a PERSIST bug. Properly account for a FIN sent during a PERSIST. MFC after: 7 days
This commit is contained in:
parent
b2aa8b2a98
commit
28257b5ccc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=104815
@ -215,6 +215,18 @@ tcp_output(struct tcpcb *tp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If snd_nxt == snd_max and we have transmitted a FIN, the
|
||||
* offset will be > 0 even if so_snd.sb_cc is 0, resulting in
|
||||
* a negative length. This can also occur when tcp opens up
|
||||
* its congestion window while receiving additional duplicate
|
||||
* acks after fast-retransmit because TCP will reset snd_nxt
|
||||
* to snd_max after the fast-retransmit.
|
||||
*
|
||||
* In the normal retransmit-FIN-only case, however, snd_nxt will
|
||||
* be set to snd_una, the offset will be 0, and the length may
|
||||
* wind up 0.
|
||||
*/
|
||||
len = (long)ulmin(so->so_snd.sb_cc, win) - off;
|
||||
|
||||
if ((taop = tcp_gettaocache(&tp->t_inpcb->inp_inc)) == NULL) {
|
||||
@ -252,7 +264,7 @@ tcp_output(struct tcpcb *tp)
|
||||
/*
|
||||
* If FIN has been sent but not acked,
|
||||
* but we haven't been called to retransmit,
|
||||
* len will be -1. Otherwise, window shrank
|
||||
* len will be < 0. Otherwise, window shrank
|
||||
* after we sent into it. If window shrank to 0,
|
||||
* cancel pending retransmit, pull snd_nxt back
|
||||
* to (closed) window, and set the persist timer
|
||||
@ -268,6 +280,12 @@ tcp_output(struct tcpcb *tp)
|
||||
tcp_setpersist(tp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* len will be >= 0 after this point. Truncate to the maximum
|
||||
* segment length and ensure that FIN is removed if the length
|
||||
* no longer contains the last data byte.
|
||||
*/
|
||||
if (len > tp->t_maxseg) {
|
||||
len = tp->t_maxseg;
|
||||
sendalot = 1;
|
||||
@ -336,7 +354,8 @@ tcp_output(struct tcpcb *tp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Send if we owe peer an ACK.
|
||||
* Send if we owe the peer an ACK, RST, SYN, or urgent data. ACKNOW
|
||||
* is also a catch-all for the retransmit timer timeout case.
|
||||
*/
|
||||
if (tp->t_flags & TF_ACKNOW)
|
||||
goto send;
|
||||
@ -347,8 +366,7 @@ tcp_output(struct tcpcb *tp)
|
||||
goto send;
|
||||
/*
|
||||
* If our state indicates that FIN should be sent
|
||||
* and we have not yet done so, or we're retransmitting the FIN,
|
||||
* then we need to send.
|
||||
* and we have not yet done so, then we need to send.
|
||||
*/
|
||||
if (flags & TH_FIN &&
|
||||
((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
|
||||
@ -794,7 +812,7 @@ tcp_output(struct tcpcb *tp)
|
||||
|
||||
/*
|
||||
* Set retransmit timer if not currently set,
|
||||
* and not doing an ack or a keep-alive probe.
|
||||
* and not doing a pure ack or a keep-alive probe.
|
||||
* Initial value for retransmit timer is smoothed
|
||||
* round-trip time + 2 * round-trip time variance.
|
||||
* Initialize shift counter which is used for backoff
|
||||
@ -809,9 +827,21 @@ tcp_output(struct tcpcb *tp)
|
||||
callout_reset(tp->tt_rexmt, tp->t_rxtcur,
|
||||
tcp_timer_rexmt, tp);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
/*
|
||||
* Persist case, update snd_max but since we are in
|
||||
* persist mode (no window) we do not update snd_nxt.
|
||||
*/
|
||||
int xlen = len;
|
||||
if (flags & TH_SYN)
|
||||
++xlen;
|
||||
if (flags & TH_FIN) {
|
||||
++xlen;
|
||||
tp->t_flags |= TF_SENTFIN;
|
||||
}
|
||||
if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
|
||||
tp->snd_max = tp->snd_nxt + len;
|
||||
}
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user