diff options
author | jayanth <jayanth@FreeBSD.org> | 2004-07-28 02:15:14 +0000 |
---|---|---|
committer | jayanth <jayanth@FreeBSD.org> | 2004-07-28 02:15:14 +0000 |
commit | b754d213ab76dee1e7bcd5acb4becd5658c0ca99 (patch) | |
tree | 3b799630bf83139bd6292b793a65a64582e070b7 /sys | |
parent | ac2fecdcf2ab22abbc2181ae2023eefe7389adf5 (diff) | |
download | FreeBSD-src-b754d213ab76dee1e7bcd5acb4becd5658c0ca99.zip FreeBSD-src-b754d213ab76dee1e7bcd5acb4becd5658c0ca99.tar.gz |
Fix a bug in the sack code that was causing data to be retransmitted
with the FIN bit set for all segments, if a FIN has already been sent before.
The fix will allow the FIN bit to be set for only the last segment, in case
it has to be retransmitted.
Fix another bug that would have caused snd_nxt to be pulled by len if
there was an error from ip_output. snd_nxt should not be touched
during sack retransmissions.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/tcp_output.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index c69b90a..5d71887 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -356,8 +356,13 @@ after_sack_rexmit: len = tp->t_maxseg; sendalot = 1; } - if (off + len < so->so_snd.sb_cc) - flags &= ~TH_FIN; + if (sack_rxmit) { + if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc)) + flags &= ~TH_FIN; + } else { + if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) + flags &= ~TH_FIN; + } recwin = sbspace(&so->so_rcv); @@ -1088,8 +1093,12 @@ timer: * No need to check for TH_FIN here because * the TF_SENTFIN flag handles that case. */ - if ((flags & TH_SYN) == 0) - tp->snd_nxt -= len; + if ((flags & TH_SYN) == 0) { + if (sack_rxmit) + p->rxmit -= len; + else + tp->snd_nxt -= len; + } } out: |