diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 12 |
3 files changed, 26 insertions, 0 deletions
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index e6a2460587d4..c1bc074f61b7 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -582,6 +582,13 @@ static struct ctl_table ipv4_table[] = { | |||
582 | .mode = 0644, | 582 | .mode = 0644, |
583 | .proc_handler = proc_dointvec | 583 | .proc_handler = proc_dointvec |
584 | }, | 584 | }, |
585 | { | ||
586 | .procname = "tcp_thin_dupack", | ||
587 | .data = &sysctl_tcp_thin_dupack, | ||
588 | .maxlen = sizeof(int), | ||
589 | .mode = 0644, | ||
590 | .proc_handler = proc_dointvec | ||
591 | }, | ||
585 | { | 592 | { |
586 | .procname = "udp_mem", | 593 | .procname = "udp_mem", |
587 | .data = &sysctl_udp_mem, | 594 | .data = &sysctl_udp_mem, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 21bae9afefea..5901010fad55 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2236,6 +2236,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2236 | tp->thin_lto = val; | 2236 | tp->thin_lto = val; |
2237 | break; | 2237 | break; |
2238 | 2238 | ||
2239 | case TCP_THIN_DUPACK: | ||
2240 | if (val < 0 || val > 1) | ||
2241 | err = -EINVAL; | ||
2242 | else | ||
2243 | tp->thin_dupack = val; | ||
2244 | break; | ||
2245 | |||
2239 | case TCP_CORK: | 2246 | case TCP_CORK: |
2240 | /* When set indicates to always queue non-full frames. | 2247 | /* When set indicates to always queue non-full frames. |
2241 | * Later the user clears this option and we transmit | 2248 | * Later the user clears this option and we transmit |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3fddc69ccccc..788851ca8c5d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -89,6 +89,8 @@ int sysctl_tcp_frto __read_mostly = 2; | |||
89 | int sysctl_tcp_frto_response __read_mostly; | 89 | int sysctl_tcp_frto_response __read_mostly; |
90 | int sysctl_tcp_nometrics_save __read_mostly; | 90 | int sysctl_tcp_nometrics_save __read_mostly; |
91 | 91 | ||
92 | int sysctl_tcp_thin_dupack __read_mostly; | ||
93 | |||
92 | int sysctl_tcp_moderate_rcvbuf __read_mostly = 1; | 94 | int sysctl_tcp_moderate_rcvbuf __read_mostly = 1; |
93 | int sysctl_tcp_abc __read_mostly; | 95 | int sysctl_tcp_abc __read_mostly; |
94 | 96 | ||
@@ -2447,6 +2449,16 @@ static int tcp_time_to_recover(struct sock *sk) | |||
2447 | return 1; | 2449 | return 1; |
2448 | } | 2450 | } |
2449 | 2451 | ||
2452 | /* If a thin stream is detected, retransmit after first | ||
2453 | * received dupack. Employ only if SACK is supported in order | ||
2454 | * to avoid possible corner-case series of spurious retransmissions | ||
2455 | * Use only if there are no unsent data. | ||
2456 | */ | ||
2457 | if ((tp->thin_dupack || sysctl_tcp_thin_dupack) && | ||
2458 | tcp_stream_is_thin(tp) && tcp_dupack_heuristics(tp) > 1 && | ||
2459 | tcp_is_sack(tp) && !tcp_send_head(sk)) | ||
2460 | return 1; | ||
2461 | |||
2450 | return 0; | 2462 | return 0; |
2451 | } | 2463 | } |
2452 | 2464 | ||