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:
parent
941f9f10b2
commit
3cee92e074
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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 *
|
||||
|
Loading…
x
Reference in New Issue
Block a user