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:
Matthew Dillon 2002-10-10 19:21:50 +00:00
parent b2aa8b2a98
commit 28257b5ccc

View File

@ -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
/*