From owner-svn-src-all@FreeBSD.ORG Wed Jan 6 16:43:10 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 641E3106568B; Wed, 6 Jan 2010 16:43:10 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 51EE48FC15; Wed, 6 Jan 2010 16:43:10 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o06GhANf080277; Wed, 6 Jan 2010 16:43:10 GMT (envelope-from bz@svn.freebsd.org) Received: (from bz@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o06GhANT080243; Wed, 6 Jan 2010 16:43:10 GMT (envelope-from bz@svn.freebsd.org) Message-Id: <201001061643.o06GhANT080243@svn.freebsd.org> From: "Bjoern A. Zeeb" Date: Wed, 6 Jan 2010 16:43:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r201653 - stable/7/sys/netinet X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Jan 2010 16:43:10 -0000 Author: bz Date: Wed Jan 6 16:43:09 2010 New Revision: 201653 URL: http://svn.freebsd.org/changeset/base/201653 Log: MFC r182851: 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. Modified: stable/7/sys/netinet/tcp_input.c stable/7/sys/netinet/tcp_subr.c stable/7/sys/netinet/tcp_var.h Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/netinet/tcp_input.c ============================================================================== --- stable/7/sys/netinet/tcp_input.c Wed Jan 6 16:39:16 2010 (r201652) +++ stable/7/sys/netinet/tcp_input.c Wed Jan 6 16:43:09 2010 (r201653) @@ -2727,13 +2727,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; @@ -2766,6 +2764,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: @@ -2789,19 +2791,14 @@ tcp_mss(struct tcpcb *tp, int offer) * to at least minmss. */ offer = max(offer, 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 @@ -2824,10 +2821,36 @@ tcp_mss(struct tcpcb *tp, int offer) !in_localaddr(inp->inp_faddr)) mss = min(mss, 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 * segment. We need to store this value (maxopd) apart @@ -2853,6 +2876,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, @@ -2959,10 +3004,6 @@ tcp_mss(struct tcpcb *tp, int offer) tp->snd_cwnd = mss * ss_fltsz_local; else tp->snd_cwnd = mss * ss_fltsz; - - /* Check the interface for TSO capabilities. */ - if (mtuflags & CSUM_TSO) - tp->t_flags |= TF_TSO; } /* Modified: stable/7/sys/netinet/tcp_subr.c ============================================================================== --- stable/7/sys/netinet/tcp_subr.c Wed Jan 6 16:39:16 2010 (r201652) +++ stable/7/sys/netinet/tcp_subr.c Wed Jan 6 16:43:09 2010 (r201653) @@ -1509,13 +1509,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_flags & INP_TIMEWAIT) || @@ -1525,72 +1519,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 ? tcp_v6mssdflt : -#endif /* INET6 */ - 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); tcpstat.tcps_mturesent++; tp->t_rtttime = 0; Modified: stable/7/sys/netinet/tcp_var.h ============================================================================== --- stable/7/sys/netinet/tcp_var.h Wed Jan 6 16:39:16 2010 (r201652) +++ stable/7/sys/netinet/tcp_var.h Wed Jan 6 16:43:09 2010 (r201653) @@ -544,6 +544,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 *