mirror of
https://github.com/openbsd/src.git
synced 2025-01-10 06:47:55 -08:00
correctly calculate mss
This commit is contained in:
parent
2f86f6636b
commit
39b94094a2
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tcp_input.c,v 1.73 2000/09/19 18:10:59 deraadt Exp $ */
|
||||
/* $OpenBSD: tcp_input.c,v 1.74 2000/09/20 17:00:22 provos Exp $ */
|
||||
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
@ -1764,7 +1764,7 @@ trimthenstep6:
|
||||
#if defined (TCP_SACK)
|
||||
if (tp->t_dupacks < tcprexmtthresh)
|
||||
#endif
|
||||
tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
|
||||
tp->snd_cwnd = ulmin(cw + incr, TCP_MAXWIN<<tp->snd_scale);
|
||||
}
|
||||
ND6_HINT(tp);
|
||||
if (acked > so->so_snd.sb_cc) {
|
||||
@ -2220,8 +2220,12 @@ tcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr)
|
||||
}
|
||||
}
|
||||
/* Update t_maxopd and t_maxseg after all options are processed */
|
||||
if (th->th_flags & TH_SYN)
|
||||
if (th->th_flags & TH_SYN) {
|
||||
(void) tcp_mss(tp, mss); /* sets t_maxseg */
|
||||
|
||||
if (mss)
|
||||
tcp_mss_update(tp);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TCP_SACK)
|
||||
@ -2769,69 +2773,35 @@ tcp_xmit_timer(tp, rtt)
|
||||
* 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.
|
||||
*
|
||||
* NOTE: offer == -1 indicates that the maxseg size changed due to
|
||||
* Path MTU discovery.
|
||||
*/
|
||||
int
|
||||
tcp_mss(tp, offer)
|
||||
register struct tcpcb *tp;
|
||||
int offer;
|
||||
{
|
||||
struct route *ro;
|
||||
register struct rtentry *rt;
|
||||
struct rtentry *rt;
|
||||
struct ifnet *ifp;
|
||||
register int rtt, mss, mssopt;
|
||||
u_long bufsize;
|
||||
int mss, mssopt;
|
||||
int iphlen;
|
||||
#ifdef INET6
|
||||
int is_ipv6 = 0;
|
||||
#endif
|
||||
struct inpcb *inp;
|
||||
struct socket *so;
|
||||
|
||||
inp = tp->t_inpcb;
|
||||
ro = &inp->inp_route;
|
||||
so = inp->inp_socket;
|
||||
|
||||
if ((rt = ro->ro_rt) == (struct rtentry *)0) {
|
||||
/* No route yet, so try to acquire one */
|
||||
#ifdef INET6
|
||||
bzero(ro, sizeof(struct route_in6));
|
||||
#else
|
||||
bzero(ro, sizeof(struct route));
|
||||
#endif
|
||||
/*
|
||||
* Get a new IPv6 route if an IPv6 destination, otherwise, get
|
||||
* and IPv4 route (including those pesky IPv4-mapped addresses).
|
||||
*/
|
||||
switch (sotopf(so)) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
|
||||
break;
|
||||
ro->ro_dst.sa_family = AF_INET6;
|
||||
ro->ro_dst.sa_len = sizeof(struct sockaddr_in6);
|
||||
((struct sockaddr_in6 *) &ro->ro_dst)->sin6_addr =
|
||||
inp->inp_faddr6;
|
||||
rtalloc(ro);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
case AF_INET:
|
||||
if (inp->inp_faddr.s_addr == INADDR_ANY)
|
||||
break;
|
||||
ro->ro_dst.sa_family = AF_INET;
|
||||
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
|
||||
satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
|
||||
rtalloc(ro);
|
||||
break;
|
||||
}
|
||||
if ((rt = ro->ro_rt) == (struct rtentry *)0) {
|
||||
tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
|
||||
return (tcp_mssdflt);
|
||||
}
|
||||
}
|
||||
ifp = rt->rt_ifp;
|
||||
|
||||
mssopt = mss = tcp_mssdflt;
|
||||
|
||||
rt = in_pcbrtentry(inp);
|
||||
|
||||
if (rt == NULL)
|
||||
goto out;
|
||||
|
||||
ifp = rt->rt_ifp;
|
||||
|
||||
switch (tp->pf) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
@ -2847,34 +2817,7 @@ tcp_mss(tp, offer)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef RTV_MTU /* if route characteristics exist ... */
|
||||
/*
|
||||
* While we're here, check if there's an initial rtt
|
||||
* or rttvar. Convert from the route-table units
|
||||
* to scaled multiples of the slow timeout timer.
|
||||
*/
|
||||
if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
|
||||
/*
|
||||
* XXX the lock bit for MTU indicates that the value
|
||||
* is also a minimum value; this is subject to time.
|
||||
*/
|
||||
if (rt->rt_rmx.rmx_locks & RTV_RTT)
|
||||
TCPT_RANGESET(tp->t_rttmin,
|
||||
rtt / (RTM_RTTUNIT / PR_SLOWHZ),
|
||||
TCPTV_MIN, TCPTV_REXMTMAX);
|
||||
tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
|
||||
if (rt->rt_rmx.rmx_rttvar)
|
||||
tp->t_rttvar = rt->rt_rmx.rmx_rttvar /
|
||||
(RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
|
||||
else
|
||||
/* default variation is +- 1 rtt */
|
||||
tp->t_rttvar =
|
||||
tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
|
||||
TCPT_RANGESET((long) tp->t_rxtcur,
|
||||
((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
|
||||
tp->t_rttmin, TCPTV_REXMTMAX);
|
||||
}
|
||||
|
||||
#ifdef RTV_MTU
|
||||
/*
|
||||
* if there's an mtu associated with the route and we support
|
||||
* path MTU discovery for the underlying protocol family, use it.
|
||||
@ -2920,17 +2863,6 @@ tcp_mss(tp, offer)
|
||||
}
|
||||
|
||||
out:
|
||||
/*
|
||||
* The current mss, t_maxseg, is initialized to the default value.
|
||||
* If we compute a smaller value, reduce the current mss.
|
||||
* If we compute a larger value, return it for use in sending
|
||||
* a max seg size option, but don't store it for use
|
||||
* unless we received an offer at least that large from peer.
|
||||
* However, do not accept offers under 32 bytes.
|
||||
*/
|
||||
if (offer && offer != -1)
|
||||
mss = min(mss, offer);
|
||||
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
|
||||
@ -2944,13 +2876,93 @@ tcp_mss(tp, offer)
|
||||
(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;
|
||||
/*
|
||||
* The current mss, t_maxseg, is initialized to the default value.
|
||||
* If we compute a smaller value, reduce the current mss.
|
||||
* If we compute a larger value, return it for use in sending
|
||||
* a max seg size option, but don't store it for use
|
||||
* unless we received an offer at least that large from peer.
|
||||
* However, do not accept offers under 32 bytes.
|
||||
*/
|
||||
if (offer && offer != -1)
|
||||
mss = min(mss, offer);
|
||||
mss = max(mss, 64); /* sanity - at least max opt. space */
|
||||
|
||||
if (offer == -1) {
|
||||
/* mss changed due to Path MTU discovery */
|
||||
if (mss < tp->t_maxseg) {
|
||||
/*
|
||||
* Follow suggestion in RFC 2414 to reduce the
|
||||
* congestion window by the ratio of the old
|
||||
* segment size to the new segment size.
|
||||
*/
|
||||
tp->snd_cwnd = ulmax((tp->snd_cwnd / tp->t_maxseg) *
|
||||
mss, mss);
|
||||
}
|
||||
} else
|
||||
tp->snd_cwnd = mss;
|
||||
|
||||
tp->t_maxseg = mss;
|
||||
|
||||
return (offer != -1 ? mssopt : mss);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set connection variables based on the effective MSS.
|
||||
* We are passed the TCPCB for the actual connection. If we
|
||||
* are the server, we are called by the compressed state engine
|
||||
* when the 3-way handshake is complete. If we are the client,
|
||||
* we are called when we recieve the SYN,ACK from the server.
|
||||
*
|
||||
* NOTE: The t_maxseg value must be initialized in the TCPCB
|
||||
* before this routine is called!
|
||||
*/
|
||||
void
|
||||
tcp_mss_update(tp)
|
||||
struct tcpcb *tp;
|
||||
{
|
||||
int mss, rtt;
|
||||
u_long bufsize;
|
||||
struct rtentry *rt;
|
||||
struct socket *so;
|
||||
|
||||
so = tp->t_inpcb->inp_socket;
|
||||
mss = tp->t_maxseg;
|
||||
|
||||
rt = in_pcbrtentry(tp->t_inpcb);
|
||||
|
||||
if (rt == NULL)
|
||||
return;
|
||||
|
||||
#ifdef RTV_MTU /* if route characteristics exist ... */
|
||||
/*
|
||||
* While we're here, check if there's an initial rtt
|
||||
* or rttvar. Convert from the route-table units
|
||||
* to scaled multiples of the slow timeout timer.
|
||||
*/
|
||||
if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
|
||||
/*
|
||||
* XXX the lock bit for MTU indicates that the value
|
||||
* is also a minimum value; this is subject to time.
|
||||
*/
|
||||
if (rt->rt_rmx.rmx_locks & RTV_RTT)
|
||||
TCPT_RANGESET(tp->t_rttmin,
|
||||
rtt / (RTM_RTTUNIT / PR_SLOWHZ),
|
||||
TCPTV_MIN, TCPTV_REXMTMAX);
|
||||
tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
|
||||
if (rt->rt_rmx.rmx_rttvar)
|
||||
tp->t_rttvar = rt->rt_rmx.rmx_rttvar /
|
||||
(RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
|
||||
else
|
||||
/* default variation is +- 1 rtt */
|
||||
tp->t_rttvar =
|
||||
tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
|
||||
TCPT_RANGESET((long) tp->t_rxtcur,
|
||||
((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
|
||||
tp->t_rttmin, TCPTV_REXMTMAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If there's a pipesize, change the socket buffer
|
||||
* to that size. Make the socket buffers an integral
|
||||
@ -2961,15 +2973,16 @@ tcp_mss(tp, offer)
|
||||
if ((bufsize = rt->rt_rmx.rmx_sendpipe) == 0)
|
||||
#endif
|
||||
bufsize = so->so_snd.sb_hiwat;
|
||||
if (bufsize < mss)
|
||||
if (bufsize < mss) {
|
||||
mss = bufsize;
|
||||
else {
|
||||
/* Update t_maxseg and t_maxopd */
|
||||
tcp_mss(tp, mss);
|
||||
} else {
|
||||
bufsize = roundup(bufsize, mss);
|
||||
if (bufsize > sb_max)
|
||||
bufsize = sb_max;
|
||||
(void)sbreserve(&so->so_snd, bufsize);
|
||||
}
|
||||
tp->t_maxseg = mss;
|
||||
|
||||
#ifdef RTV_RPIPE
|
||||
if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0)
|
||||
@ -2985,7 +2998,6 @@ tcp_mss(tp, offer)
|
||||
tcp_rscale(tp, so->so_rcv.sb_hiwat);
|
||||
#endif
|
||||
}
|
||||
tp->snd_cwnd = mss;
|
||||
|
||||
#ifdef RTV_SSTHRESH
|
||||
if (rt->rt_rmx.rmx_ssthresh) {
|
||||
@ -2998,8 +3010,6 @@ tcp_mss(tp, offer)
|
||||
tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh);
|
||||
}
|
||||
#endif /* RTV_MTU */
|
||||
|
||||
return (offer != -1 ? mssopt : mss);
|
||||
}
|
||||
#endif /* TUBA_INCLUDE */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tcp_output.c,v 1.32 2000/09/18 22:06:38 provos Exp $ */
|
||||
/* $OpenBSD: tcp_output.c,v 1.33 2000/09/20 17:00:22 provos Exp $ */
|
||||
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
|
||||
|
||||
/*
|
||||
@ -512,9 +512,13 @@ send:
|
||||
|
||||
opt[0] = TCPOPT_MAXSEG;
|
||||
opt[1] = 4;
|
||||
mss = htons((u_int16_t) tcp_mss(tp, 0));
|
||||
mss = htons((u_int16_t) tcp_mss(tp, flags & TH_ACK ?
|
||||
tp->t_maxopd : 0));
|
||||
bcopy((caddr_t)&mss, (caddr_t)(opt + 2), sizeof(mss));
|
||||
optlen = 4;
|
||||
|
||||
if (flags & TH_ACK)
|
||||
tcp_mss_update(tp);
|
||||
#ifdef TCP_SACK
|
||||
/*
|
||||
* If this is the first SYN of connection (not a SYN
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tcp_subr.c,v 1.31 2000/09/18 22:06:38 provos Exp $ */
|
||||
/* $OpenBSD: tcp_subr.c,v 1.32 2000/09/20 17:00:23 provos Exp $ */
|
||||
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
|
||||
|
||||
/*
|
||||
@ -427,8 +427,9 @@ tcp_newtcpcb(inp)
|
||||
return ((struct tcpcb *)0);
|
||||
bzero((char *) tp, sizeof(struct tcpcb));
|
||||
LIST_INIT(&tp->segq);
|
||||
tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
|
||||
|
||||
tp->t_maxseg = tcp_mssdflt;
|
||||
tp->t_maxopd = 0;
|
||||
|
||||
#ifdef TCP_SACK
|
||||
tp->sack_disable = tcp_do_sack ? 0 : 1;
|
||||
#endif
|
||||
@ -864,17 +865,9 @@ tcp_mtudisc(inp, errno)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slow start out of the error condition. We
|
||||
* use the MTU because we know it's smaller
|
||||
* than the previously transmitted segment.
|
||||
*
|
||||
* Note: This is more conservative than the
|
||||
* suggestion in RFC 2414
|
||||
*/
|
||||
if (rt->rt_rmx.rmx_mtu != 0) {
|
||||
/* also takes care of congestion window */
|
||||
tcp_mss(tp, -1);
|
||||
tp->snd_cwnd = rt->rt_rmx.rmx_mtu;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tcp_var.h,v 1.30 2000/09/18 22:06:38 provos Exp $ */
|
||||
/* $OpenBSD: tcp_var.h,v 1.31 2000/09/20 17:00:23 provos Exp $ */
|
||||
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
|
||||
|
||||
/*
|
||||
@ -343,6 +343,7 @@ int tcp6_input __P((struct mbuf **, int *, int));
|
||||
#endif
|
||||
void tcp_input __P((struct mbuf *, ...));
|
||||
int tcp_mss __P((struct tcpcb *, int));
|
||||
void tcp_mss_update __P((struct tcpcb *));
|
||||
void tcp_mtudisc __P((struct inpcb *, int));
|
||||
struct tcpcb *
|
||||
tcp_newtcpcb __P((struct inpcb *));
|
||||
|
Loading…
Reference in New Issue
Block a user