1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-09 22:38:01 -08:00

- fix three bugs pointed out in Stevens, i.a. updating timestamps correctly

- fix a 4.4bsd-lite2 bug, when tcp options are present the maximum segment
size is not updated correctly, so that fast recovery forces out a segment
which is split in two segments by tcp_output(), the fix is adpated from
FreeBSD, the effective mss is recorded after option negotiation in 3way
handshake.
[I was able to fix this on time spent at Center for Information Technology
Integration (citi.umich.edu)]
This commit is contained in:
provos 1998-10-28 21:34:32 +00:00
parent e74bf56f77
commit 5f0eddb4ad
4 changed files with 77 additions and 53 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_input.c,v 1.19 1998/06/27 02:42:40 deraadt Exp $ */
/* $OpenBSD: tcp_input.c,v 1.20 1998/10/28 21:34:32 provos Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@ -641,9 +641,9 @@ findpcb:
/*
* If last ACK falls within this segment's sequence numbers,
* record the timestamp.
* Fix from Braden, see Stevens p. 870
*/
if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {
if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {
tp->ts_recent_age = tcp_now;
tp->ts_recent = ts_val;
}
@ -980,7 +980,8 @@ trimthenstep6:
tiflags &= ~TH_URG;
todrop--;
}
if (todrop >= ti->ti_len) {
if (todrop >= ti->ti_len ||
(todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
/*
* Any valid FIN must be to the left of the
* window. At this point, FIN must be a
@ -1064,10 +1065,10 @@ trimthenstep6:
/*
* If last ACK falls within this segment's sequence numbers,
* record its timestamp.
* Fix from Braden, see Stevens p. 870
*/
if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len +
((tiflags & (TH_SYN|TH_FIN)) != 0))) {
if (ts_present && TSTMP_GEQ(ts_val, tp->ts_recent) &&
SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {
tp->ts_recent_age = tcp_now;
tp->ts_recent = ts_val;
}
@ -1579,7 +1580,7 @@ tcp_dooptions(tp, cp, cnt, ti, ts_present, ts_val, ts_ecr)
int *ts_present;
u_int32_t *ts_val, *ts_ecr;
{
u_int16_t mss;
u_int16_t mss = 0;
int opt, optlen;
for (; cnt > 0; cnt -= optlen, cp += optlen) {
@ -1605,7 +1606,6 @@ tcp_dooptions(tp, cp, cnt, ti, ts_present, ts_val, ts_ecr)
continue;
bcopy((char *) cp + 2, (char *) &mss, sizeof(mss));
NTOHS(mss);
(void) tcp_mss(tp, mss); /* sets t_maxseg */
break;
case TCPOPT_WINDOW:
@ -1638,6 +1638,9 @@ tcp_dooptions(tp, cp, cnt, ti, ts_present, ts_val, ts_ecr)
break;
}
}
/* Update t_maxopd and t_maxseg after all options are processed */
if (ti->ti_flags & TH_SYN)
(void) tcp_mss(tp, mss); /* sets t_maxseg */
}
/*
@ -1762,6 +1765,12 @@ tcp_xmit_timer(tp, rtt)
* window to be a single segment if the destination isn't local.
* While looking at the routing entry, we also initialize other path-dependent
* parameters from pre-set or cached values in the routing entry.
*
* Also take into account the space needed for options that we
* send regularly. Make maxseg shorter by that amount to assure
* that we can send maxseg amount of data even when the options
* are present. Store the upper limit of the length of options plus
* data in maxopd.
*/
int
tcp_mss(tp, offer)
@ -1788,9 +1797,11 @@ tcp_mss(tp, offer)
satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
rtalloc(ro);
}
if ((rt = ro->ro_rt) == (struct rtentry *)0)
if ((rt = ro->ro_rt) == (struct rtentry *)0) {
tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
return (tcp_mssdflt);
}
}
ifp = rt->rt_ifp;
so = inp->inp_socket;
@ -1828,13 +1839,6 @@ tcp_mss(tp, offer)
#endif /* RTV_MTU */
{
mss = ifp->if_mtu - sizeof(struct tcpiphdr);
#if (MCLBYTES & (MCLBYTES - 1)) == 0
if (mss > MCLBYTES)
mss &= ~(MCLBYTES-1);
#else
if (mss > MCLBYTES)
mss = mss / MCLBYTES * MCLBYTES;
#endif
if (!in_localaddr(inp->inp_faddr))
mss = min(mss, tcp_mssdflt);
}
@ -1848,8 +1852,27 @@ tcp_mss(tp, offer)
*/
if (offer)
mss = min(mss, offer);
mss = max(mss, 32); /* sanity */
if (mss < tp->t_maxseg || offer != 0) {
mss = max(mss, 64); /* sanity - at least max opt. space */
/*
* maxopd stores the maximum length of data AND options
* in a segment; maxseg is the amount of data in a normal
* segment. We need to store this value (maxopd) apart
* from maxseg, because now every segment carries options
* and thus we normally have somewhat less data in segments.
*/
tp->t_maxopd = mss;
if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
(tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
mss -= TCPOLEN_TSTAMP_APPA;
#if (MCLBYTES & (MCLBYTES - 1)) == 0
if (mss > MCLBYTES)
mss &= ~(MCLBYTES-1);
#else
if (mss > MCLBYTES)
mss = mss / MCLBYTES * MCLBYTES;
#endif
/*
* If there's a pipesize, change the socket buffer
* to that size. Make the socket buffers an integral
@ -1880,7 +1903,6 @@ tcp_mss(tp, offer)
bufsize = sb_max;
(void)sbreserve(&so->so_rcv, bufsize);
}
}
tp->snd_cwnd = mss;
#ifdef RTV_SSTHRESH

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_output.c,v 1.10 1998/05/18 21:11:06 provos Exp $ */
/* $OpenBSD: tcp_output.c,v 1.11 1998/10/28 21:34:33 provos Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@ -194,7 +194,7 @@ again:
goto send;
if (tp->t_force)
goto send;
if (len >= tp->max_sndwnd / 2)
if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
goto send;
if (SEQ_LT(tp->snd_nxt, tp->snd_max))
goto send;
@ -330,10 +330,10 @@ send:
/*
* Adjust data length if insertion of options will
* bump the packet length beyond the t_maxseg length.
* bump the packet length beyond the t_maxopd length.
*/
if (len > tp->t_maxseg - optlen) {
len = tp->t_maxseg - optlen;
if (len > tp->t_maxopd - optlen) {
len = tp->t_maxopd - optlen;
sendalot = 1;
flags &= ~TH_FIN;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_subr.c,v 1.10 1998/05/18 21:11:07 provos Exp $ */
/* $OpenBSD: tcp_subr.c,v 1.11 1998/10/28 21:34:33 provos Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@ -235,7 +235,7 @@ tcp_newtcpcb(inp)
return ((struct tcpcb *)0);
bzero((char *) tp, sizeof(struct tcpcb));
LIST_INIT(&tp->segq);
tp->t_maxseg = tcp_mssdflt;
tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
tp->t_inpcb = inp;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_var.h,v 1.11 1998/06/10 03:40:05 beck Exp $ */
/* $OpenBSD: tcp_var.h,v 1.12 1998/10/28 21:34:33 provos Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@ -98,6 +98,8 @@ struct tcpcb {
* for slow start exponential to
* linear switch
*/
u_int t_maxopd; /* mss plus options */
/*
* transmit timing stuff. See below for scale of srtt and rttvar.
* "Variance" is actually smoothed difference.