diff options
author | David S. Miller <davem@davemloft.net> | 2009-10-27 04:03:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-27 04:03:26 -0400 |
commit | cfadf853f6cd9689f79a63ca960c6f9d6665314f (patch) | |
tree | 35418e342d9783f0974ea33ef03875aa21d2362a /net/ipv4 | |
parent | 05423b241311c9380b7280179295bac7794281b6 (diff) | |
parent | f568a926a353d6816b3704d7367f34371df44ce7 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/sh_eth.c
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 34 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 59 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 5 |
4 files changed, 82 insertions, 23 deletions
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index f6a0af759932..26fb50e91311 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -447,6 +447,28 @@ extern int sysctl_tcp_synack_retries; | |||
447 | 447 | ||
448 | EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add); | 448 | EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add); |
449 | 449 | ||
450 | /* Decide when to expire the request and when to resend SYN-ACK */ | ||
451 | static inline void syn_ack_recalc(struct request_sock *req, const int thresh, | ||
452 | const int max_retries, | ||
453 | const u8 rskq_defer_accept, | ||
454 | int *expire, int *resend) | ||
455 | { | ||
456 | if (!rskq_defer_accept) { | ||
457 | *expire = req->retrans >= thresh; | ||
458 | *resend = 1; | ||
459 | return; | ||
460 | } | ||
461 | *expire = req->retrans >= thresh && | ||
462 | (!inet_rsk(req)->acked || req->retrans >= max_retries); | ||
463 | /* | ||
464 | * Do not resend while waiting for data after ACK, | ||
465 | * start to resend on end of deferring period to give | ||
466 | * last chance for data or ACK to create established socket. | ||
467 | */ | ||
468 | *resend = !inet_rsk(req)->acked || | ||
469 | req->retrans >= rskq_defer_accept - 1; | ||
470 | } | ||
471 | |||
450 | void inet_csk_reqsk_queue_prune(struct sock *parent, | 472 | void inet_csk_reqsk_queue_prune(struct sock *parent, |
451 | const unsigned long interval, | 473 | const unsigned long interval, |
452 | const unsigned long timeout, | 474 | const unsigned long timeout, |
@@ -502,9 +524,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, | |||
502 | reqp=&lopt->syn_table[i]; | 524 | reqp=&lopt->syn_table[i]; |
503 | while ((req = *reqp) != NULL) { | 525 | while ((req = *reqp) != NULL) { |
504 | if (time_after_eq(now, req->expires)) { | 526 | if (time_after_eq(now, req->expires)) { |
505 | if ((req->retrans < thresh || | 527 | int expire = 0, resend = 0; |
506 | (inet_rsk(req)->acked && req->retrans < max_retries)) | 528 | |
507 | && !req->rsk_ops->rtx_syn_ack(parent, req)) { | 529 | syn_ack_recalc(req, thresh, max_retries, |
530 | queue->rskq_defer_accept, | ||
531 | &expire, &resend); | ||
532 | if (!expire && | ||
533 | (!resend || | ||
534 | !req->rsk_ops->rtx_syn_ack(parent, req) || | ||
535 | inet_rsk(req)->acked)) { | ||
508 | unsigned long timeo; | 536 | unsigned long timeo; |
509 | 537 | ||
510 | if (req->retrans++ == 0) | 538 | if (req->retrans++ == 0) |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2445fedec0b8..a72f43ce33be 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -634,17 +634,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
634 | break; | 634 | break; |
635 | } | 635 | } |
636 | dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr); | 636 | dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr); |
637 | if (dev) { | 637 | if (dev) |
638 | mreq.imr_ifindex = dev->ifindex; | 638 | mreq.imr_ifindex = dev->ifindex; |
639 | dev_put(dev); | ||
640 | } | ||
641 | } else | 639 | } else |
642 | dev = __dev_get_by_index(sock_net(sk), mreq.imr_ifindex); | 640 | dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex); |
643 | 641 | ||
644 | 642 | ||
645 | err = -EADDRNOTAVAIL; | 643 | err = -EADDRNOTAVAIL; |
646 | if (!dev) | 644 | if (!dev) |
647 | break; | 645 | break; |
646 | dev_put(dev); | ||
648 | 647 | ||
649 | err = -EINVAL; | 648 | err = -EINVAL; |
650 | if (sk->sk_bound_dev_if && | 649 | if (sk->sk_bound_dev_if && |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 206a291dff03..e0cfa633680a 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 | * |
@@ -1405,7 +1442,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1405 | goto found_ok_skb; | 1442 | goto found_ok_skb; |
1406 | if (tcp_hdr(skb)->fin) | 1443 | if (tcp_hdr(skb)->fin) |
1407 | goto found_fin_ok; | 1444 | goto found_fin_ok; |
1408 | WARN_ON(!(flags & MSG_PEEK)); | 1445 | WARN(!(flags & MSG_PEEK), KERN_INFO "recvmsg bug 2: " |
1446 | "copied %X seq %X\n", *seq, | ||
1447 | TCP_SKB_CB(skb)->seq); | ||
1409 | } | 1448 | } |
1410 | 1449 | ||
1411 | /* Well, if we have backlog, try to process it now yet. */ | 1450 | /* Well, if we have backlog, try to process it now yet. */ |
@@ -2163,16 +2202,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2163 | break; | 2202 | break; |
2164 | 2203 | ||
2165 | case TCP_DEFER_ACCEPT: | 2204 | case TCP_DEFER_ACCEPT: |
2166 | icsk->icsk_accept_queue.rskq_defer_accept = 0; | 2205 | /* Translate value in seconds to number of retransmits */ |
2167 | if (val > 0) { | 2206 | icsk->icsk_accept_queue.rskq_defer_accept = |
2168 | /* Translate value in seconds to number of | 2207 | secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, |
2169 | * retransmits */ | 2208 | 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; | 2209 | break; |
2177 | 2210 | ||
2178 | case TCP_WINDOW_CLAMP: | 2211 | case TCP_WINDOW_CLAMP: |
@@ -2353,8 +2386,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
2353 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; | 2386 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; |
2354 | break; | 2387 | break; |
2355 | case TCP_DEFER_ACCEPT: | 2388 | case TCP_DEFER_ACCEPT: |
2356 | val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 : | 2389 | val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept, |
2357 | ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1)); | 2390 | TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ); |
2358 | break; | 2391 | break; |
2359 | case TCP_WINDOW_CLAMP: | 2392 | case TCP_WINDOW_CLAMP: |
2360 | val = tp->window_clamp; | 2393 | val = tp->window_clamp; |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index e320afea07fc..4c03598ed924 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -641,10 +641,9 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
641 | if (!(flg & TCP_FLAG_ACK)) | 641 | if (!(flg & TCP_FLAG_ACK)) |
642 | return NULL; | 642 | return NULL; |
643 | 643 | ||
644 | /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ | 644 | /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */ |
645 | if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | 645 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && |
646 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | 646 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { |
647 | inet_csk(sk)->icsk_accept_queue.rskq_defer_accept--; | ||
648 | inet_rsk(req)->acked = 1; | 647 | inet_rsk(req)->acked = 1; |
649 | return NULL; | 648 | return NULL; |
650 | } | 649 | } |