svn commit: r201653 - stable/7/sys/netinet

Bjoern A. Zeeb bz at FreeBSD.org
Wed Jan 6 16:43:10 UTC 2010


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 *


More information about the svn-src-all mailing list