diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 74 |
1 files changed, 56 insertions, 18 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 64d0af675823..f1813bc71088 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -326,6 +326,43 @@ void tcp_enter_memory_pressure(struct sock *sk) | |||
326 | 326 | ||
327 | EXPORT_SYMBOL(tcp_enter_memory_pressure); | 327 | EXPORT_SYMBOL(tcp_enter_memory_pressure); |
328 | 328 | ||
329 | /* Convert seconds to retransmits based on initial and max timeout */ | ||
330 | static u8 secs_to_retrans(int seconds, int timeout, int rto_max) | ||
331 | { | ||
332 | u8 res = 0; | ||
333 | |||
334 | if (seconds > 0) { | ||
335 | int period = timeout; | ||
336 | |||
337 | res = 1; | ||
338 | while (seconds > period && res < 255) { | ||
339 | res++; | ||
340 | timeout <<= 1; | ||
341 | if (timeout > rto_max) | ||
342 | timeout = rto_max; | ||
343 | period += timeout; | ||
344 | } | ||
345 | } | ||
346 | return res; | ||
347 | } | ||
348 | |||
349 | /* Convert retransmits to seconds based on initial and max timeout */ | ||
350 | static int retrans_to_secs(u8 retrans, int timeout, int rto_max) | ||
351 | { | ||
352 | int period = 0; | ||
353 | |||
354 | if (retrans > 0) { | ||
355 | period = timeout; | ||
356 | while (--retrans) { | ||
357 | timeout <<= 1; | ||
358 | if (timeout > rto_max) | ||
359 | timeout = rto_max; | ||
360 | period += timeout; | ||
361 | } | ||
362 | } | ||
363 | return period; | ||
364 | } | ||
365 | |||
329 | /* | 366 | /* |
330 | * Wait for a TCP event. | 367 | * Wait for a TCP event. |
331 | * | 368 | * |
@@ -1146,7 +1183,9 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied) | |||
1146 | #if TCP_DEBUG | 1183 | #if TCP_DEBUG |
1147 | struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); | 1184 | struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); |
1148 | 1185 | ||
1149 | WARN_ON(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq)); | 1186 | WARN(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq), |
1187 | KERN_INFO "cleanup rbuf bug: copied %X seq %X rcvnxt %X\n", | ||
1188 | tp->copied_seq, TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt); | ||
1150 | #endif | 1189 | #endif |
1151 | 1190 | ||
1152 | if (inet_csk_ack_scheduled(sk)) { | 1191 | if (inet_csk_ack_scheduled(sk)) { |
@@ -1393,11 +1432,13 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1393 | /* Now that we have two receive queues this | 1432 | /* Now that we have two receive queues this |
1394 | * shouldn't happen. | 1433 | * shouldn't happen. |
1395 | */ | 1434 | */ |
1396 | if (before(*seq, TCP_SKB_CB(skb)->seq)) { | 1435 | if (WARN(before(*seq, TCP_SKB_CB(skb)->seq), |
1397 | printk(KERN_INFO "recvmsg bug: copied %X " | 1436 | KERN_INFO "recvmsg bug: copied %X " |
1398 | "seq %X\n", *seq, TCP_SKB_CB(skb)->seq); | 1437 | "seq %X rcvnxt %X fl %X\n", *seq, |
1438 | TCP_SKB_CB(skb)->seq, tp->rcv_nxt, | ||
1439 | flags)) | ||
1399 | break; | 1440 | break; |
1400 | } | 1441 | |
1401 | offset = *seq - TCP_SKB_CB(skb)->seq; | 1442 | offset = *seq - TCP_SKB_CB(skb)->seq; |
1402 | if (tcp_hdr(skb)->syn) | 1443 | if (tcp_hdr(skb)->syn) |
1403 | offset--; | 1444 | offset--; |
@@ -1405,7 +1446,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1405 | goto found_ok_skb; | 1446 | goto found_ok_skb; |
1406 | if (tcp_hdr(skb)->fin) | 1447 | if (tcp_hdr(skb)->fin) |
1407 | goto found_fin_ok; | 1448 | goto found_fin_ok; |
1408 | WARN_ON(!(flags & MSG_PEEK)); | 1449 | WARN(!(flags & MSG_PEEK), KERN_INFO "recvmsg bug 2: " |
1450 | "copied %X seq %X rcvnxt %X fl %X\n", | ||
1451 | *seq, TCP_SKB_CB(skb)->seq, | ||
1452 | tp->rcv_nxt, flags); | ||
1409 | } | 1453 | } |
1410 | 1454 | ||
1411 | /* Well, if we have backlog, try to process it now yet. */ | 1455 | /* Well, if we have backlog, try to process it now yet. */ |
@@ -2163,16 +2207,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2163 | break; | 2207 | break; |
2164 | 2208 | ||
2165 | case TCP_DEFER_ACCEPT: | 2209 | case TCP_DEFER_ACCEPT: |
2166 | icsk->icsk_accept_queue.rskq_defer_accept = 0; | 2210 | /* Translate value in seconds to number of retransmits */ |
2167 | if (val > 0) { | 2211 | icsk->icsk_accept_queue.rskq_defer_accept = |
2168 | /* Translate value in seconds to number of | 2212 | secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, |
2169 | * retransmits */ | 2213 | TCP_RTO_MAX / HZ); |
2170 | while (icsk->icsk_accept_queue.rskq_defer_accept < 32 && | ||
2171 | val > ((TCP_TIMEOUT_INIT / HZ) << | ||
2172 | icsk->icsk_accept_queue.rskq_defer_accept)) | ||
2173 | icsk->icsk_accept_queue.rskq_defer_accept++; | ||
2174 | icsk->icsk_accept_queue.rskq_defer_accept++; | ||
2175 | } | ||
2176 | break; | 2214 | break; |
2177 | 2215 | ||
2178 | case TCP_WINDOW_CLAMP: | 2216 | case TCP_WINDOW_CLAMP: |
@@ -2353,8 +2391,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
2353 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; | 2391 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; |
2354 | break; | 2392 | break; |
2355 | case TCP_DEFER_ACCEPT: | 2393 | case TCP_DEFER_ACCEPT: |
2356 | val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 : | 2394 | val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept, |
2357 | ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1)); | 2395 | TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ); |
2358 | break; | 2396 | break; |
2359 | case TCP_WINDOW_CLAMP: | 2397 | case TCP_WINDOW_CLAMP: |
2360 | val = tp->window_clamp; | 2398 | val = tp->window_clamp; |