Fix previous bug. Thanks to Enami for spotting the (obvious) error, and

to other people with much help with bug reports etc.
While fixing, change some of the code I added last time to make it
cleaner and simpler.
This commit is contained in:
ragge 2003-07-02 19:33:20 +00:00
parent 918c07021f
commit c6308a0598
2 changed files with 57 additions and 49 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_input.c,v 1.171 2003/06/29 22:31:58 fvdl Exp $ */
/* $NetBSD: tcp_input.c,v 1.172 2003/07/02 19:33:20 ragge Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -152,7 +152,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.171 2003/06/29 22:31:58 fvdl Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.172 2003/07/02 19:33:20 ragge Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -1441,6 +1441,8 @@ after_listen:
SEQ_LEQ(th->th_ack, tp->snd_max) &&
tp->snd_cwnd >= tp->snd_wnd &&
tp->t_dupacks < tcprexmtthresh) {
int slen;
/*
* this is a pure ack for outstanding data.
*/
@ -1456,9 +1458,15 @@ after_listen:
tcpstat.tcps_rcvackpack++;
tcpstat.tcps_rcvackbyte += acked;
ND6_HINT(tp);
slen = tp->t_lastm->m_len;
sbdrop(&so->so_snd, acked);
if (tp->t_lastm != NULL)
if (so->so_snd.sb_cc != 0) {
tp->t_lastoff -= acked;
if (tp->t_lastm->m_len < slen)
tp->t_inoff -=
(slen - tp->t_lastm->m_len);
}
/*
* We want snd_recover to track snd_una to
@ -2072,15 +2080,20 @@ after_listen:
ND6_HINT(tp);
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
tp->t_lastm = NULL;
sbdrop(&so->so_snd, (int)so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
int slen;
slen = tp->t_lastm->m_len;
sbdrop(&so->so_snd, acked);
tp->snd_wnd -= acked;
tp->t_lastoff -= acked;
if (tp->t_lastoff <= 0)
tp->t_lastm = NULL;
if (so->so_snd.sb_cc != 0) {
tp->t_lastoff -= acked;
if (tp->t_lastm->m_len != slen)
tp->t_inoff -=
(slen - tp->t_lastm->m_len);
}
ourfinisacked = 0;
}
sowwakeup(so);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_output.c,v 1.94 2003/06/30 14:51:06 ragge Exp $ */
/* $NetBSD: tcp_output.c,v 1.95 2003/07/02 19:33:20 ragge Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -142,7 +142,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.94 2003/06/30 14:51:06 ragge Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.95 2003/07/02 19:33:20 ragge Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -397,7 +397,7 @@ int
tcp_build_datapkt(struct tcpcb *tp, struct socket *so, int off,
long len, int hdrlen, struct mbuf **mp)
{
struct mbuf *m;
struct mbuf *m, *m0;
if (tp->t_force && len == 1)
tcpstat.tcps_sndprobe++;
@ -440,49 +440,44 @@ tcp_build_datapkt(struct tcpcb *tp, struct socket *so, int off,
m->m_data += max_linkhdr;
m->m_len = hdrlen;
/*
* To avoid traversing the whole sb_mb chain for correct
* data to send, remember last sent mbuf, its offset and
* the sent size. When called the next time, see if the
* data to send is the directly following the previous
* transfer. This is important for large TCP windows.
*/
if (off == 0 || (tp->t_lastoff + tp->t_lastlen) != off) {
/*
* Either a new packet or a retransmit.
* Start from the beginning.
*/
tp->t_lastm = so->so_snd.sb_mb;
tp->t_inoff = off;
} else
tp->t_inoff += tp->t_lastlen;
/* Traverse forward to next packet */
while (tp->t_inoff > 0) {
if (tp->t_lastm == NULL)
panic("tp->t_lastm == NULL");
if (tp->t_inoff < tp->t_lastm->m_len)
break;
tp->t_inoff -= tp->t_lastm->m_len;
tp->t_lastm = tp->t_lastm->m_next;
}
tp->t_lastoff = off;
tp->t_lastlen = len;
m0 = tp->t_lastm;
off = tp->t_inoff;
if (len <= M_TRAILINGSPACE(m)) {
m_copydata(so->so_snd.sb_mb, off, (int) len,
mtod(m, caddr_t) + hdrlen);
m_copydata(m0, off, (int) len, mtod(m, caddr_t) + hdrlen);
m->m_len += len;
TCP_OUTPUT_COUNTER_INCR(&tcp_output_copysmall);
} else {
struct mbuf *m0;
/*
* To avoid traversing the whole sb_mb chain for correct
* data to send, remember last sent mbuf, its offset and
* the sent size. When called the next time, see if the
* data to send is the directly following the previous
* transfer. This is important for large TCP windows.
*/
if (0 && off > 8*1024) { /* Only for long chains */
if (tp->t_lastm == NULL ||
(tp->t_lastoff + tp->t_lastlen) != off) {
/* Prediction failed */
tp->t_lastm = so->so_snd.sb_mb;
tp->t_inoff = off;
} else {
tp->t_inoff += tp->t_lastlen;
tp->t_lastoff = off - tp->t_lastoff;
}
/* Traverse forward to next packet */
while (tp->t_inoff > 0) {
if (tp->t_lastm == NULL)
panic("tp->t_lastm == NULL");
if (tp->t_inoff < tp->t_lastm->m_len)
break;
tp->t_inoff -= tp->t_lastm->m_len;
tp->t_lastm = tp->t_lastm->m_next;
}
tp->t_lastoff = off;
tp->t_lastlen = len;
m0 = tp->t_lastm;
off = tp->t_inoff;
} else
m0 = so->so_snd.sb_mb;
m->m_next = m_copy(m0, off, (int) len);
if (m->m_next == NULL) {
m_freem(m);