diff options
author | 2000-09-18 22:06:36 +0000 | |
---|---|---|
committer | 2000-09-18 22:06:36 +0000 | |
commit | 62c4355e0f896ae5d33dc8e181b593b965dc1a7c (patch) | |
tree | 227ac38b9696134dc2a925911c014f9a9500df85 /sys/netinet/tcp_input.c | |
parent | fix reversed muting; patch from: jason@ (diff) | |
download | wireguard-openbsd-62c4355e0f896ae5d33dc8e181b593b965dc1a7c.tar.xz wireguard-openbsd-62c4355e0f896ae5d33dc8e181b593b965dc1a7c.zip |
Path MTU discovery based on NetBSD but with the decision to use the DF
flag delayed to ip_output(). That halves the code and reduces most of
the route lookups. okay deraadt@
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r-- | sys/netinet/tcp_input.c | 91 |
1 files changed, 52 insertions, 39 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 33a38b7dee4..3762fc8004c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.69 2000/09/05 21:57:41 provos Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.70 2000/09/18 22:06:38 provos Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -2743,13 +2743,14 @@ tcp_xmit_timer(tp, rtt) int tcp_mss(tp, offer) register struct tcpcb *tp; - u_int offer; + int offer; { struct route *ro; register struct rtentry *rt; struct ifnet *ifp; - register int rtt, mss; + register int rtt, mss, mssopt; u_long bufsize; + int iphlen, is_ipv6 = 0; struct inpcb *inp; struct socket *so; @@ -2796,6 +2797,23 @@ tcp_mss(tp, offer) } ifp = rt->rt_ifp; + mssopt = mss = tcp_mssdflt; + + switch (tp->pf) { +#ifdef INET6 + case AF_INET6: + iphlen = sizeof(struct ip6_hdr); + is_ipv6 = 1; + break; +#endif + case AF_INET: + iphlen = sizeof(struct ip); + break; + default: + /* the family does not support path MTU discovery */ + goto out; + } + #ifdef RTV_MTU /* if route characteristics exist ... */ /* * While we're here, check if there's an initial rtt @@ -2823,58 +2841,52 @@ tcp_mss(tp, offer) ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, tp->t_rttmin, TCPTV_REXMTMAX); } + /* * if there's an mtu associated with the route and we support * path MTU discovery for the underlying protocol family, use it. */ - /* - * XXX It's wrong to use PMTU values to determine the MSS we - * are going to advertise; we should only use the input interface's - * MTU instead (see draft-ietf-tcpimpl-pmtud-03.txt). tcp_mss() - * should be changed to be aware whether it's called for input or - * output MSS calculation, and act accordingly. - */ if (rt->rt_rmx.rmx_mtu) { /* * One may wish to lower MSS to take into account options, * especially security-related options. */ - mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcphdr); - switch (tp->pf) { -#ifdef INET6 - case AF_INET6: - mss -= sizeof(struct ip6_hdr); - break; -#endif -#ifdef notdef /* no IPv4 path MTU discovery yet */ - case AF_INET: - mss -= sizeof(struct ip); - break; -#endif - default: - /* the family does not support path MTU discovery */ - mss = 0; - break; - } + mss = rt->rt_rmx.rmx_mtu - iphlen - sizeof(struct tcphdr); } else - mss = 0; -#else - mss = 0; #endif /* RTV_MTU */ - if (mss == 0) { + if (!ifp) /* * ifp may be null and rmx_mtu may be zero in certain * v6 cases (e.g., if ND wasn't able to resolve the * destination host. */ - mss = ifp ? ifp->if_mtu - sizeof(struct tcpiphdr) : 0; - switch (tp->pf) { - case AF_INET: - if (!in_localaddr(inp->inp_faddr)) - mss = min(mss, tcp_mssdflt); - break; + goto out; + else if (ip_mtudisc || ifp->if_flags & IFF_LOOPBACK) + mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); +#ifdef INET6 + else if (is_ipv6) { + if (IN6_IS_ADDR_V4MAPPED(&inp->inp_faddr6)) { + /* mapped addr case */ + struct in_addr d; + bcopy(&inp->inp_faddr6.s6_addr32[3], &d, sizeof(d)); + if (in_localaddr(d)) + mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); + } else { + if (in6_localaddr(&inp->inp_faddr6)) + mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); } } +#endif /* INET6 */ + else if (inp && in_localaddr(inp->inp_faddr)) + mss = ifp->if_mtu - iphlen - sizeof(struct tcphdr); + + /* Calculate the value that we offer in TCPOPT_MAXSEG */ + if (offer != -1) { + mssopt = ifp->if_mtu - iphlen - sizeof(struct tcphdr); + mssopt = max(tcp_mssdflt, mssopt); + } + + out: /* * The current mss, t_maxseg, is initialized to the default value. * If we compute a smaller value, reduce the current mss. @@ -2883,7 +2895,7 @@ tcp_mss(tp, offer) * unless we received an offer at least that large from peer. * However, do not accept offers under 32 bytes. */ - if (offer) + if (offer && offer != -1) mss = min(mss, offer); mss = max(mss, 64); /* sanity - at least max opt. space */ /* @@ -2953,7 +2965,8 @@ tcp_mss(tp, offer) tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh); } #endif /* RTV_MTU */ - return (mss); + + return (offer != -1 ? mssopt : mss); } #endif /* TUBA_INCLUDE */ |