Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Nov 2008 13:25:59 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r184722 - head/sys/netinet
Message-ID:  <200811061325.mA6DPxDW056618@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Thu Nov  6 13:25:59 2008
New Revision: 184722
URL: http://svn.freebsd.org/changeset/base/184722

Log:
  Fix a bug introduced with r182851 splitting tcp_mss() into
  tcp_mss() and tcp_mss_update() so that tcp_mtudisc() could
  re-use the same code.
  
  Move the TSO logic back to tcp_mss() and out of tcp_mss_update().
  We tried to avoid that initially but if were are called from
  tcp_output() with EMSGSIZE, we cleared the TSO flag on the tcpcb
  there, called into tcp_mtudisc() and tcp_mss_update() which
  then would reenable TSO on the tcpcb based on TSO capabilities
  of the interface as learnt in tcp_maxmtu/6().
  So if TSO was enabled on the (possibly new) outgoing interface
  it was turned back on, which lead to an endless loop between
  tcp_output() and tcp_mtudisc() until we overflew the stack.
  
  Reported by:	kmacy
  MFC after:	2 months (along with r182851)

Modified:
  head/sys/netinet/tcp_input.c
  head/sys/netinet/tcp_subr.c
  head/sys/netinet/tcp_var.h

Modified: head/sys/netinet/tcp_input.c
==============================================================================
--- head/sys/netinet/tcp_input.c	Thu Nov  6 12:59:00 2008	(r184721)
+++ head/sys/netinet/tcp_input.c	Thu Nov  6 13:25:59 2008	(r184722)
@@ -2812,7 +2812,8 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt
  * segment. Outgoing SYN/ACK MSS settings are handled in tcp_mssopt().
  */
 void
-tcp_mss_update(struct tcpcb *tp, int offer, struct hc_metrics_lite *metricptr)
+tcp_mss_update(struct tcpcb *tp, int offer,
+    struct hc_metrics_lite *metricptr, int *mtuflags)
 {
 	INIT_VNET_INET(tp->t_inpcb->inp_vnet);
 	int mss;
@@ -2820,7 +2821,6 @@ tcp_mss_update(struct tcpcb *tp, int off
 	struct inpcb *inp = tp->t_inpcb;
 	struct hc_metrics_lite metrics;
 	int origoffer = offer;
-	int mtuflags = 0;
 #ifdef INET6
 	int isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0;
 	size_t min_protoh = isipv6 ?
@@ -2835,12 +2835,12 @@ tcp_mss_update(struct tcpcb *tp, int off
 	/* Initialize. */
 #ifdef INET6
 	if (isipv6) {
-		maxmtu = tcp_maxmtu6(&inp->inp_inc, &mtuflags);
+		maxmtu = tcp_maxmtu6(&inp->inp_inc, mtuflags);
 		tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
 	} else
 #endif
 	{
-		maxmtu = tcp_maxmtu(&inp->inp_inc, &mtuflags);
+		maxmtu = tcp_maxmtu(&inp->inp_inc, mtuflags);
 		tp->t_maxopd = tp->t_maxseg = V_tcp_mssdflt;
 	}
 
@@ -2858,10 +2858,6 @@ tcp_mss_update(struct tcpcb *tp, int off
 		return;
 	}
 
-	/* Check the interface for TSO capabilities. */
-	if (mtuflags & CSUM_TSO)
-		tp->t_flags |= TF_TSO;
-
 	/* What have we got? */
 	switch (offer) {
 		case 0:
@@ -2980,12 +2976,13 @@ tcp_mss(struct tcpcb *tp, int offer)
 	struct inpcb *inp;
 	struct socket *so;
 	struct hc_metrics_lite metrics;
+	int mtuflags = 0;
 #ifdef INET6
 	int isipv6;
 #endif
 	KASSERT(tp != NULL, ("%s: tp == NULL", __func__));
 	
-	tcp_mss_update(tp, offer, &metrics);
+	tcp_mss_update(tp, offer, &metrics, &mtuflags);
 
 	mss = tp->t_maxseg;
 	inp = tp->t_inpcb;
@@ -3098,6 +3095,10 @@ 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;
 }
 
 /*

Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c	Thu Nov  6 12:59:00 2008	(r184721)
+++ head/sys/netinet/tcp_subr.c	Thu Nov  6 13:25:59 2008	(r184722)
@@ -1562,7 +1562,7 @@ tcp_mtudisc(struct inpcb *inp, int errno
 	tp = intotcpcb(inp);
 	KASSERT(tp != NULL, ("tcp_mtudisc: tp == NULL"));
 
-	tcp_mss_update(tp, -1, NULL);
+	tcp_mss_update(tp, -1, NULL, NULL);
   
 	so = inp->inp_socket;
 	SOCKBUF_LOCK(&so->so_snd);

Modified: head/sys/netinet/tcp_var.h
==============================================================================
--- head/sys/netinet/tcp_var.h	Thu Nov  6 12:59:00 2008	(r184721)
+++ head/sys/netinet/tcp_var.h	Thu Nov  6 13:25:59 2008	(r184722)
@@ -546,7 +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_update(struct tcpcb *, int, struct hc_metrics_lite *, int *);
 void	 tcp_mss(struct tcpcb *, int);
 int	 tcp_mssopt(struct in_conninfo *);
 struct inpcb *



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811061325.mA6DPxDW056618>