aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2008-11-06 13:25:59 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2008-11-06 13:25:59 +0000
commit91d6cfa6b14fa2941ba44e4cd52e7916ac0d636d (patch)
tree487bf156bdb934ed2a4387c9c02646258633623d /sys/netinet/tcp_input.c
parent4b3f4d381827fc63e00d6d43399943c062db2211 (diff)
downloadsrc-91d6cfa6b14fa2941ba44e4cd52e7916ac0d636d.tar.gz
src-91d6cfa6b14fa2941ba44e4cd52e7916ac0d636d.zip
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)
Notes
Notes: svn path=/head/; revision=184722
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 9dd7b8c625ec..a1e72e83bc07 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -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 offer, struct hc_metrics_lite *metricptr)
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 offer, struct hc_metrics_lite *metricptr)
/* 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 offer, struct hc_metrics_lite *metricptr)
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;
}
/*