diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 990a5849323..fe3b4bdfd25 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -362,6 +362,17 @@ struct tcp_out_options { | |||
362 | __u32 tsval, tsecr; /* need to include OPTION_TS */ | 362 | __u32 tsval, tsecr; /* need to include OPTION_TS */ |
363 | }; | 363 | }; |
364 | 364 | ||
365 | /* Beware: Something in the Internet is very sensitive to the ordering of | ||
366 | * TCP options, we learned this through the hard way, so be careful here. | ||
367 | * Luckily we can at least blame others for their non-compliance but from | ||
368 | * inter-operatibility perspective it seems that we're somewhat stuck with | ||
369 | * the ordering which we have been using if we want to keep working with | ||
370 | * those broken things (not that it currently hurts anybody as there isn't | ||
371 | * particular reason why the ordering would need to be changed). | ||
372 | * | ||
373 | * At least SACK_PERM as the first option is known to lead to a disaster | ||
374 | * (but it may well be that other scenarios fail similarly). | ||
375 | */ | ||
365 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | 376 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, |
366 | const struct tcp_out_options *opts, | 377 | const struct tcp_out_options *opts, |
367 | __u8 **md5_hash) { | 378 | __u8 **md5_hash) { |
@@ -376,6 +387,12 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
376 | *md5_hash = NULL; | 387 | *md5_hash = NULL; |
377 | } | 388 | } |
378 | 389 | ||
390 | if (unlikely(opts->mss)) { | ||
391 | *ptr++ = htonl((TCPOPT_MSS << 24) | | ||
392 | (TCPOLEN_MSS << 16) | | ||
393 | opts->mss); | ||
394 | } | ||
395 | |||
379 | if (likely(OPTION_TS & opts->options)) { | 396 | if (likely(OPTION_TS & opts->options)) { |
380 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { | 397 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { |
381 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | | 398 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | |
@@ -392,12 +409,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
392 | *ptr++ = htonl(opts->tsecr); | 409 | *ptr++ = htonl(opts->tsecr); |
393 | } | 410 | } |
394 | 411 | ||
395 | if (unlikely(opts->mss)) { | ||
396 | *ptr++ = htonl((TCPOPT_MSS << 24) | | ||
397 | (TCPOLEN_MSS << 16) | | ||
398 | opts->mss); | ||
399 | } | ||
400 | |||
401 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options && | 412 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options && |
402 | !(OPTION_TS & opts->options))) { | 413 | !(OPTION_TS & opts->options))) { |
403 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 414 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
@@ -432,7 +443,7 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
432 | 443 | ||
433 | if (tp->rx_opt.dsack) { | 444 | if (tp->rx_opt.dsack) { |
434 | tp->rx_opt.dsack = 0; | 445 | tp->rx_opt.dsack = 0; |
435 | tp->rx_opt.eff_sacks--; | 446 | tp->rx_opt.eff_sacks = tp->rx_opt.num_sacks; |
436 | } | 447 | } |
437 | } | 448 | } |
438 | } | 449 | } |
@@ -1017,10 +1028,6 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu) | |||
1017 | 1028 | ||
1018 | /* Compute the current effective MSS, taking SACKs and IP options, | 1029 | /* Compute the current effective MSS, taking SACKs and IP options, |
1019 | * and even PMTU discovery events into account. | 1030 | * and even PMTU discovery events into account. |
1020 | * | ||
1021 | * LARGESEND note: !tcp_urg_mode is overkill, only frames up to snd_up | ||
1022 | * cannot be large. However, taking into account rare use of URG, this | ||
1023 | * is not a big flaw. | ||
1024 | */ | 1031 | */ |
1025 | unsigned int tcp_current_mss(struct sock *sk, int large_allowed) | 1032 | unsigned int tcp_current_mss(struct sock *sk, int large_allowed) |
1026 | { | 1033 | { |
@@ -1035,7 +1042,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) | |||
1035 | 1042 | ||
1036 | mss_now = tp->mss_cache; | 1043 | mss_now = tp->mss_cache; |
1037 | 1044 | ||
1038 | if (large_allowed && sk_can_gso(sk) && !tcp_urg_mode(tp)) | 1045 | if (large_allowed && sk_can_gso(sk)) |
1039 | doing_tso = 1; | 1046 | doing_tso = 1; |
1040 | 1047 | ||
1041 | if (dst) { | 1048 | if (dst) { |
@@ -1505,6 +1512,10 @@ static int tcp_mtu_probe(struct sock *sk) | |||
1505 | * send_head. This happens as incoming acks open up the remote | 1512 | * send_head. This happens as incoming acks open up the remote |
1506 | * window for us. | 1513 | * window for us. |
1507 | * | 1514 | * |
1515 | * LARGESEND note: !tcp_urg_mode is overkill, only frames between | ||
1516 | * snd_up-64k-mss .. snd_up cannot be large. However, taking into | ||
1517 | * account rare use of URG, this is not a big flaw. | ||
1518 | * | ||
1508 | * Returns 1, if no segments are in flight and we have queued segments, but | 1519 | * Returns 1, if no segments are in flight and we have queued segments, but |
1509 | * cannot send anything now because of SWS or another problem. | 1520 | * cannot send anything now because of SWS or another problem. |
1510 | */ | 1521 | */ |
@@ -1556,7 +1567,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
1556 | } | 1567 | } |
1557 | 1568 | ||
1558 | limit = mss_now; | 1569 | limit = mss_now; |
1559 | if (tso_segs > 1) | 1570 | if (tso_segs > 1 && !tcp_urg_mode(tp)) |
1560 | limit = tcp_mss_split_point(sk, skb, mss_now, | 1571 | limit = tcp_mss_split_point(sk, skb, mss_now, |
1561 | cwnd_quota); | 1572 | cwnd_quota); |
1562 | 1573 | ||
@@ -1605,6 +1616,7 @@ void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, | |||
1605 | */ | 1616 | */ |
1606 | void tcp_push_one(struct sock *sk, unsigned int mss_now) | 1617 | void tcp_push_one(struct sock *sk, unsigned int mss_now) |
1607 | { | 1618 | { |
1619 | struct tcp_sock *tp = tcp_sk(sk); | ||
1608 | struct sk_buff *skb = tcp_send_head(sk); | 1620 | struct sk_buff *skb = tcp_send_head(sk); |
1609 | unsigned int tso_segs, cwnd_quota; | 1621 | unsigned int tso_segs, cwnd_quota; |
1610 | 1622 | ||
@@ -1619,7 +1631,7 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) | |||
1619 | BUG_ON(!tso_segs); | 1631 | BUG_ON(!tso_segs); |
1620 | 1632 | ||
1621 | limit = mss_now; | 1633 | limit = mss_now; |
1622 | if (tso_segs > 1) | 1634 | if (tso_segs > 1 && !tcp_urg_mode(tp)) |
1623 | limit = tcp_mss_split_point(sk, skb, mss_now, | 1635 | limit = tcp_mss_split_point(sk, skb, mss_now, |
1624 | cwnd_quota); | 1636 | cwnd_quota); |
1625 | 1637 | ||
@@ -2268,6 +2280,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2268 | } | 2280 | } |
2269 | 2281 | ||
2270 | memset(&opts, 0, sizeof(opts)); | 2282 | memset(&opts, 0, sizeof(opts)); |
2283 | #ifdef CONFIG_SYN_COOKIES | ||
2284 | if (unlikely(req->cookie_ts)) | ||
2285 | TCP_SKB_CB(skb)->when = cookie_init_timestamp(req); | ||
2286 | else | ||
2287 | #endif | ||
2271 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2288 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
2272 | tcp_header_size = tcp_synack_options(sk, req, mss, | 2289 | tcp_header_size = tcp_synack_options(sk, req, mss, |
2273 | skb, &opts, &md5) + | 2290 | skb, &opts, &md5) + |
@@ -2293,11 +2310,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2293 | 2310 | ||
2294 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ | 2311 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ |
2295 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2312 | th->window = htons(min(req->rcv_wnd, 65535U)); |
2296 | #ifdef CONFIG_SYN_COOKIES | ||
2297 | if (unlikely(req->cookie_ts)) | ||
2298 | TCP_SKB_CB(skb)->when = cookie_init_timestamp(req); | ||
2299 | else | ||
2300 | #endif | ||
2301 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 2313 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); |
2302 | th->doff = (tcp_header_size >> 2); | 2314 | th->doff = (tcp_header_size >> 2); |
2303 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 2315 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); |