Split tcp_mss() in tcp_mss() and tcp_mss_update() where the former

calls the latter.

Merge tcp_mss_update() with code from tcp_mtudisc() basically
doing the same thing.

This gives us one central place where we calcuate and check mss values
to update t_maxopd (maximum mss + options length) instead of two slightly
different but almost equal implementations to maintain.

PR:		kern/118455
Reviewed by:	silby (back in March)
MFC after:	2 months
This commit is contained in:
Bjoern A. Zeeb 2008-09-07 18:50:25 +00:00
parent 941f9f10b2
commit 3cee92e074
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=182851
3 changed files with 66 additions and 88 deletions

View file

@ -2790,13 +2790,11 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt)
* segment. Outgoing SYN/ACK MSS settings are handled in tcp_mssopt().
*/
void
tcp_mss(struct tcpcb *tp, int offer)
tcp_mss_update(struct tcpcb *tp, int offer, struct hc_metrics_lite *metricptr)
{
int rtt, mss;
u_long bufsize;
int mss;
u_long maxmtu;
struct inpcb *inp = tp->t_inpcb;
struct socket *so;
struct hc_metrics_lite metrics;
int origoffer = offer;
int mtuflags = 0;
@ -2829,6 +2827,10 @@ tcp_mss(struct tcpcb *tp, int offer)
if (maxmtu == 0)
return;
/* Check the interface for TSO capabilities. */
if (mtuflags & CSUM_TSO)
tp->t_flags |= TF_TSO;
/* What have we got? */
switch (offer) {
case 0:
@ -2852,19 +2854,14 @@ tcp_mss(struct tcpcb *tp, int offer)
* to at least minmss.
*/
offer = max(offer, V_tcp_minmss);
/*
* Sanity check: make sure that maxopd will be large
* enough to allow some data on segments even if the
* all the option space is used (40bytes). Otherwise
* funny things may happen in tcp_output.
*/
offer = max(offer, 64);
}
/*
* rmx information is now retrieved from tcp_hostcache.
*/
tcp_hc_get(&inp->inp_inc, &metrics);
if (metricptr != NULL)
bcopy(&metrics, metricptr, sizeof(struct hc_metrics_lite));
/*
* If there's a discovered mtu int tcp hostcache, use it
@ -2887,9 +2884,35 @@ tcp_mss(struct tcpcb *tp, int offer)
!in_localaddr(inp->inp_faddr))
mss = min(mss, V_tcp_mssdflt);
}
/*
* XXX - The above conditional (mss = maxmtu - min_protoh)
* probably violates the TCP spec.
* The problem is that, since we don't know the
* other end's MSS, we are supposed to use a conservative
* default. But, if we do that, then MTU discovery will
* never actually take place, because the conservative
* default is much less than the MTUs typically seen
* on the Internet today. For the moment, we'll sweep
* this under the carpet.
*
* The conservative default might not actually be a problem
* if the only case this occurs is when sending an initial
* SYN with options and data to a host we've never talked
* to before. Then, they will reply with an MSS value which
* will get recorded and the new parameters should get
* recomputed. For Further Study.
*/
}
mss = min(mss, offer);
/*
* Sanity check: make sure that maxopd will be large
* enough to allow some data on segments even if the
* all the option space is used (40bytes). Otherwise
* funny things may happen in tcp_output.
*/
mss = max(mss, 64);
/*
* maxopd stores the maximum length of data AND options
* in a segment; maxseg is the amount of data in a normal
@ -2916,6 +2939,28 @@ tcp_mss(struct tcpcb *tp, int offer)
mss = mss / MCLBYTES * MCLBYTES;
#endif
tp->t_maxseg = mss;
}
void
tcp_mss(struct tcpcb *tp, int offer)
{
int rtt, mss;
u_long bufsize;
struct inpcb *inp;
struct socket *so;
struct hc_metrics_lite metrics;
#ifdef INET6
int isipv6;
#endif
KASSERT(tp != NULL, ("%s: tp == NULL", __func__));
tcp_mss_update(tp, offer, &metrics);
mss = tp->t_maxseg;
inp = tp->t_inpcb;
#ifdef INET6
isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0;
#endif
/*
* If there's a pipesize, change the socket buffer to that size,
@ -3022,10 +3067,6 @@ tcp_mss(struct tcpcb *tp, int offer)
tp->snd_cwnd = mss * V_ss_fltsz_local;
else
tp->snd_cwnd = mss * V_ss_fltsz;
/* Check the interface for TSO capabilities. */
if (mtuflags & CSUM_TSO)
tp->t_flags |= TF_TSO;
}
/*

View file

@ -1514,13 +1514,7 @@ struct inpcb *
tcp_mtudisc(struct inpcb *inp, int errno)
{
struct tcpcb *tp;
struct socket *so = inp->inp_socket;
u_int maxmtu;
u_int romtu;
int mss;
#ifdef INET6
int isipv6;
#endif /* INET6 */
struct socket *so;
INP_WLOCK_ASSERT(inp);
if ((inp->inp_vflag & INP_TIMEWAIT) ||
@ -1530,72 +1524,14 @@ tcp_mtudisc(struct inpcb *inp, int errno)
tp = intotcpcb(inp);
KASSERT(tp != NULL, ("tcp_mtudisc: tp == NULL"));
#ifdef INET6
isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
#endif
maxmtu = tcp_hc_getmtu(&inp->inp_inc); /* IPv4 and IPv6 */
romtu =
#ifdef INET6
isipv6 ? tcp_maxmtu6(&inp->inp_inc, NULL) :
#endif /* INET6 */
tcp_maxmtu(&inp->inp_inc, NULL);
if (!maxmtu)
maxmtu = romtu;
else
maxmtu = min(maxmtu, romtu);
if (!maxmtu) {
tp->t_maxopd = tp->t_maxseg =
#ifdef INET6
isipv6 ? V_tcp_v6mssdflt :
#endif /* INET6 */
V_tcp_mssdflt;
return (inp);
}
mss = maxmtu -
#ifdef INET6
(isipv6 ? sizeof(struct ip6_hdr) + sizeof(struct tcphdr) :
#endif /* INET6 */
sizeof(struct tcpiphdr)
#ifdef INET6
)
#endif /* INET6 */
;
/*
* XXX - The above conditional probably violates the TCP
* spec. The problem is that, since we don't know the
* other end's MSS, we are supposed to use a conservative
* default. But, if we do that, then MTU discovery will
* never actually take place, because the conservative
* default is much less than the MTUs typically seen
* on the Internet today. For the moment, we'll sweep
* this under the carpet.
*
* The conservative default might not actually be a problem
* if the only case this occurs is when sending an initial
* SYN with options and data to a host we've never talked
* to before. Then, they will reply with an MSS value which
* will get recorded and the new parameters should get
* recomputed. For Further Study.
*/
if (tp->t_maxopd <= mss)
return (inp);
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 (so->so_snd.sb_hiwat < mss)
mss = so->so_snd.sb_hiwat;
tp->t_maxseg = mss;
tcp_mss_update(tp, -1, NULL);
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_snd);
/* If the mss is larger than the socket buffer, decrease the mss. */
if (so->so_snd.sb_hiwat < tp->t_maxseg)
tp->t_maxseg = so->so_snd.sb_hiwat;
SOCKBUF_UNLOCK(&so->so_snd);
V_tcpstat.tcps_mturesent++;
tp->t_rtttime = 0;

View file

@ -546,6 +546,7 @@ void tcp_reass_init(void);
void tcp_input(struct mbuf *, int);
u_long tcp_maxmtu(struct in_conninfo *, int *);
u_long tcp_maxmtu6(struct in_conninfo *, int *);
void tcp_mss_update(struct tcpcb *, int, struct hc_metrics_lite *);
void tcp_mss(struct tcpcb *, int);
int tcp_mssopt(struct in_conninfo *);
struct inpcb *