diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/proc.c | 1 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 11 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 26 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_timer.c | 1 |
7 files changed, 42 insertions, 9 deletions
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 4370f4246e86..073273b751f8 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -287,6 +287,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
287 | SNMP_MIB_ITEM("TCPAckCompressed", LINUX_MIB_TCPACKCOMPRESSED), | 287 | SNMP_MIB_ITEM("TCPAckCompressed", LINUX_MIB_TCPACKCOMPRESSED), |
288 | SNMP_MIB_ITEM("TCPZeroWindowDrop", LINUX_MIB_TCPZEROWINDOWDROP), | 288 | SNMP_MIB_ITEM("TCPZeroWindowDrop", LINUX_MIB_TCPZEROWINDOWDROP), |
289 | SNMP_MIB_ITEM("TCPRcvQDrop", LINUX_MIB_TCPRCVQDROP), | 289 | SNMP_MIB_ITEM("TCPRcvQDrop", LINUX_MIB_TCPRCVQDROP), |
290 | SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG), | ||
290 | SNMP_MIB_SENTINEL | 291 | SNMP_MIB_SENTINEL |
291 | }; | 292 | }; |
292 | 293 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index fa213bd8e233..b6f14af926fa 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -39,6 +39,8 @@ static int ip_local_port_range_min[] = { 1, 1 }; | |||
39 | static int ip_local_port_range_max[] = { 65535, 65535 }; | 39 | static int ip_local_port_range_max[] = { 65535, 65535 }; |
40 | static int tcp_adv_win_scale_min = -31; | 40 | static int tcp_adv_win_scale_min = -31; |
41 | static int tcp_adv_win_scale_max = 31; | 41 | static int tcp_adv_win_scale_max = 31; |
42 | static int tcp_min_snd_mss_min = TCP_MIN_SND_MSS; | ||
43 | static int tcp_min_snd_mss_max = 65535; | ||
42 | static int ip_privileged_port_min; | 44 | static int ip_privileged_port_min; |
43 | static int ip_privileged_port_max = 65535; | 45 | static int ip_privileged_port_max = 65535; |
44 | static int ip_ttl_min = 1; | 46 | static int ip_ttl_min = 1; |
@@ -770,6 +772,15 @@ static struct ctl_table ipv4_net_table[] = { | |||
770 | .proc_handler = proc_dointvec, | 772 | .proc_handler = proc_dointvec, |
771 | }, | 773 | }, |
772 | { | 774 | { |
775 | .procname = "tcp_min_snd_mss", | ||
776 | .data = &init_net.ipv4.sysctl_tcp_min_snd_mss, | ||
777 | .maxlen = sizeof(int), | ||
778 | .mode = 0644, | ||
779 | .proc_handler = proc_dointvec_minmax, | ||
780 | .extra1 = &tcp_min_snd_mss_min, | ||
781 | .extra2 = &tcp_min_snd_mss_max, | ||
782 | }, | ||
783 | { | ||
773 | .procname = "tcp_probe_threshold", | 784 | .procname = "tcp_probe_threshold", |
774 | .data = &init_net.ipv4.sysctl_tcp_probe_threshold, | 785 | .data = &init_net.ipv4.sysctl_tcp_probe_threshold, |
775 | .maxlen = sizeof(int), | 786 | .maxlen = sizeof(int), |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f448a288d158..7dc9ab84bb69 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -3873,6 +3873,7 @@ void __init tcp_init(void) | |||
3873 | unsigned long limit; | 3873 | unsigned long limit; |
3874 | unsigned int i; | 3874 | unsigned int i; |
3875 | 3875 | ||
3876 | BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE); | ||
3876 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > | 3877 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > |
3877 | FIELD_SIZEOF(struct sk_buff, cb)); | 3878 | FIELD_SIZEOF(struct sk_buff, cb)); |
3878 | 3879 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 38dfc308c0fb..d95ee40df6c2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1302,7 +1302,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *prev, | |||
1302 | TCP_SKB_CB(skb)->seq += shifted; | 1302 | TCP_SKB_CB(skb)->seq += shifted; |
1303 | 1303 | ||
1304 | tcp_skb_pcount_add(prev, pcount); | 1304 | tcp_skb_pcount_add(prev, pcount); |
1305 | BUG_ON(tcp_skb_pcount(skb) < pcount); | 1305 | WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount); |
1306 | tcp_skb_pcount_add(skb, -pcount); | 1306 | tcp_skb_pcount_add(skb, -pcount); |
1307 | 1307 | ||
1308 | /* When we're adding to gso_segs == 1, gso_size will be zero, | 1308 | /* When we're adding to gso_segs == 1, gso_size will be zero, |
@@ -1368,6 +1368,21 @@ static int skb_can_shift(const struct sk_buff *skb) | |||
1368 | return !skb_headlen(skb) && skb_is_nonlinear(skb); | 1368 | return !skb_headlen(skb) && skb_is_nonlinear(skb); |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, | ||
1372 | int pcount, int shiftlen) | ||
1373 | { | ||
1374 | /* TCP min gso_size is 8 bytes (TCP_MIN_GSO_SIZE) | ||
1375 | * Since TCP_SKB_CB(skb)->tcp_gso_segs is 16 bits, we need | ||
1376 | * to make sure not storing more than 65535 * 8 bytes per skb, | ||
1377 | * even if current MSS is bigger. | ||
1378 | */ | ||
1379 | if (unlikely(to->len + shiftlen >= 65535 * TCP_MIN_GSO_SIZE)) | ||
1380 | return 0; | ||
1381 | if (unlikely(tcp_skb_pcount(to) + pcount > 65535)) | ||
1382 | return 0; | ||
1383 | return skb_shift(to, from, shiftlen); | ||
1384 | } | ||
1385 | |||
1371 | /* Try collapsing SACK blocks spanning across multiple skbs to a single | 1386 | /* Try collapsing SACK blocks spanning across multiple skbs to a single |
1372 | * skb. | 1387 | * skb. |
1373 | */ | 1388 | */ |
@@ -1473,7 +1488,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, | |||
1473 | if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una)) | 1488 | if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una)) |
1474 | goto fallback; | 1489 | goto fallback; |
1475 | 1490 | ||
1476 | if (!skb_shift(prev, skb, len)) | 1491 | if (!tcp_skb_shift(prev, skb, pcount, len)) |
1477 | goto fallback; | 1492 | goto fallback; |
1478 | if (!tcp_shifted_skb(sk, prev, skb, state, pcount, len, mss, dup_sack)) | 1493 | if (!tcp_shifted_skb(sk, prev, skb, state, pcount, len, mss, dup_sack)) |
1479 | goto out; | 1494 | goto out; |
@@ -1491,11 +1506,10 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, | |||
1491 | goto out; | 1506 | goto out; |
1492 | 1507 | ||
1493 | len = skb->len; | 1508 | len = skb->len; |
1494 | if (skb_shift(prev, skb, len)) { | 1509 | pcount = tcp_skb_pcount(skb); |
1495 | pcount += tcp_skb_pcount(skb); | 1510 | if (tcp_skb_shift(prev, skb, pcount, len)) |
1496 | tcp_shifted_skb(sk, prev, skb, state, tcp_skb_pcount(skb), | 1511 | tcp_shifted_skb(sk, prev, skb, state, pcount, |
1497 | len, mss, 0); | 1512 | len, mss, 0); |
1498 | } | ||
1499 | 1513 | ||
1500 | out: | 1514 | out: |
1501 | return prev; | 1515 | return prev; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bc86f9735f45..cfa81190a1b1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -2628,6 +2628,7 @@ static int __net_init tcp_sk_init(struct net *net) | |||
2628 | net->ipv4.sysctl_tcp_ecn_fallback = 1; | 2628 | net->ipv4.sysctl_tcp_ecn_fallback = 1; |
2629 | 2629 | ||
2630 | net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS; | 2630 | net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS; |
2631 | net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS; | ||
2631 | net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; | 2632 | net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; |
2632 | net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; | 2633 | net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; |
2633 | 2634 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f429e856e263..00c01a01b547 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1296,6 +1296,11 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, | |||
1296 | if (nsize < 0) | 1296 | if (nsize < 0) |
1297 | nsize = 0; | 1297 | nsize = 0; |
1298 | 1298 | ||
1299 | if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf)) { | ||
1300 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG); | ||
1301 | return -ENOMEM; | ||
1302 | } | ||
1303 | |||
1299 | if (skb_unclone(skb, gfp)) | 1304 | if (skb_unclone(skb, gfp)) |
1300 | return -ENOMEM; | 1305 | return -ENOMEM; |
1301 | 1306 | ||
@@ -1454,8 +1459,7 @@ static inline int __tcp_mtu_to_mss(struct sock *sk, int pmtu) | |||
1454 | mss_now -= icsk->icsk_ext_hdr_len; | 1459 | mss_now -= icsk->icsk_ext_hdr_len; |
1455 | 1460 | ||
1456 | /* Then reserve room for full set of TCP options and 8 bytes of data */ | 1461 | /* Then reserve room for full set of TCP options and 8 bytes of data */ |
1457 | if (mss_now < 48) | 1462 | mss_now = max(mss_now, sock_net(sk)->ipv4.sysctl_tcp_min_snd_mss); |
1458 | mss_now = 48; | ||
1459 | return mss_now; | 1463 | return mss_now; |
1460 | } | 1464 | } |
1461 | 1465 | ||
@@ -2747,7 +2751,7 @@ static bool tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) | |||
2747 | if (next_skb_size <= skb_availroom(skb)) | 2751 | if (next_skb_size <= skb_availroom(skb)) |
2748 | skb_copy_bits(next_skb, 0, skb_put(skb, next_skb_size), | 2752 | skb_copy_bits(next_skb, 0, skb_put(skb, next_skb_size), |
2749 | next_skb_size); | 2753 | next_skb_size); |
2750 | else if (!skb_shift(skb, next_skb, next_skb_size)) | 2754 | else if (!tcp_skb_shift(skb, next_skb, 1, next_skb_size)) |
2751 | return false; | 2755 | return false; |
2752 | } | 2756 | } |
2753 | tcp_highest_sack_replace(sk, next_skb, skb); | 2757 | tcp_highest_sack_replace(sk, next_skb, skb); |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 5bad937ce779..c801cd37cc2a 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -155,6 +155,7 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) | |||
155 | mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; | 155 | mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; |
156 | mss = min(net->ipv4.sysctl_tcp_base_mss, mss); | 156 | mss = min(net->ipv4.sysctl_tcp_base_mss, mss); |
157 | mss = max(mss, 68 - tcp_sk(sk)->tcp_header_len); | 157 | mss = max(mss, 68 - tcp_sk(sk)->tcp_header_len); |
158 | mss = max(mss, net->ipv4.sysctl_tcp_min_snd_mss); | ||
158 | icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); | 159 | icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); |
159 | } | 160 | } |
160 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 161 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); |