|
@@ -2232,6 +2232,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
|
|
struct sk_buff *skb;
|
|
|
struct tcp_md5sig_key *md5;
|
|
|
__u8 *md5_hash_location;
|
|
|
+ int mss;
|
|
|
|
|
|
skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
|
|
|
if (skb == NULL)
|
|
@@ -2242,13 +2243,17 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
|
|
|
|
|
skb->dst = dst_clone(dst);
|
|
|
|
|
|
+ mss = dst_metric(dst, RTAX_ADVMSS);
|
|
|
+ if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
|
|
|
+ mss = tp->rx_opt.user_mss;
|
|
|
+
|
|
|
if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
|
|
|
__u8 rcv_wscale;
|
|
|
/* Set this up on the first call only */
|
|
|
req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW);
|
|
|
/* tcp_full_space because it is guaranteed to be the first packet */
|
|
|
tcp_select_initial_window(tcp_full_space(sk),
|
|
|
- dst_metric(dst, RTAX_ADVMSS) - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
|
|
|
+ mss - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
|
|
|
&req->rcv_wnd,
|
|
|
&req->window_clamp,
|
|
|
ireq->wscale_ok,
|
|
@@ -2258,8 +2263,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
|
|
|
|
|
memset(&opts, 0, sizeof(opts));
|
|
|
TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
|
|
- tcp_header_size = tcp_synack_options(sk, req,
|
|
|
- dst_metric(dst, RTAX_ADVMSS),
|
|
|
+ tcp_header_size = tcp_synack_options(sk, req, mss,
|
|
|
skb, &opts, &md5) +
|
|
|
sizeof(struct tcphdr);
|
|
|
|
|
@@ -2333,6 +2337,9 @@ static void tcp_connect_init(struct sock *sk)
|
|
|
if (!tp->window_clamp)
|
|
|
tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
|
|
|
tp->advmss = dst_metric(dst, RTAX_ADVMSS);
|
|
|
+ if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < tp->advmss)
|
|
|
+ tp->advmss = tp->rx_opt.user_mss;
|
|
|
+
|
|
|
tcp_initialize_rcv_mss(sk);
|
|
|
|
|
|
tcp_select_initial_window(tcp_full_space(sk),
|