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)
This commit is contained in:
parent
4b3f4d3818
commit
91d6cfa6b1
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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 *
|
||||
|
Loading…
x
Reference in New Issue
Block a user