diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 23:15:09 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:49:50 -0400 |
commit | a019d6fe2b9da68ea4ba6cf3c4e86fc1dbf554c3 (patch) | |
tree | f82f0523c313228d64998fac30790edcfd0785c3 /net/ipv4/tcp_timer.c | |
parent | 7c657876b63cb1d8a2ec06f8fc6c37bb8412e66c (diff) |
[ICSK]: Move generalised functions from tcp to inet_connection_sock
This also improves reqsk_queue_prune and renames it to
inet_csk_reqsk_queue_prune, as it deals with both inet_connection_sock
and inet_request_sock objects, not just with request_sock ones thus
belonging to inet_request_sock.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_timer.c')
-rw-r--r-- | net/ipv4/tcp_timer.c | 93 |
1 files changed, 2 insertions, 91 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index b614ad4d30c9..72cec6981830 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -424,103 +424,14 @@ out_unlock: | |||
424 | sock_put(sk); | 424 | sock_put(sk); |
425 | } | 425 | } |
426 | 426 | ||
427 | void reqsk_queue_prune(struct request_sock_queue *queue, struct sock *parent, | ||
428 | const unsigned long interval, const unsigned long timeout, | ||
429 | const unsigned long max_rto, int max_retries) | ||
430 | { | ||
431 | struct inet_connection_sock *icsk = inet_csk(parent); | ||
432 | struct listen_sock *lopt = queue->listen_opt; | ||
433 | int thresh = max_retries; | ||
434 | unsigned long now = jiffies; | ||
435 | struct request_sock **reqp, *req; | ||
436 | int i, budget; | ||
437 | |||
438 | if (lopt == NULL || lopt->qlen == 0) | ||
439 | return; | ||
440 | |||
441 | /* Normally all the openreqs are young and become mature | ||
442 | * (i.e. converted to established socket) for first timeout. | ||
443 | * If synack was not acknowledged for 3 seconds, it means | ||
444 | * one of the following things: synack was lost, ack was lost, | ||
445 | * rtt is high or nobody planned to ack (i.e. synflood). | ||
446 | * When server is a bit loaded, queue is populated with old | ||
447 | * open requests, reducing effective size of queue. | ||
448 | * When server is well loaded, queue size reduces to zero | ||
449 | * after several minutes of work. It is not synflood, | ||
450 | * it is normal operation. The solution is pruning | ||
451 | * too old entries overriding normal timeout, when | ||
452 | * situation becomes dangerous. | ||
453 | * | ||
454 | * Essentially, we reserve half of room for young | ||
455 | * embrions; and abort old ones without pity, if old | ||
456 | * ones are about to clog our table. | ||
457 | */ | ||
458 | if (lopt->qlen>>(lopt->max_qlen_log-1)) { | ||
459 | int young = (lopt->qlen_young<<1); | ||
460 | |||
461 | while (thresh > 2) { | ||
462 | if (lopt->qlen < young) | ||
463 | break; | ||
464 | thresh--; | ||
465 | young <<= 1; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | if (queue->rskq_defer_accept) | ||
470 | max_retries = queue->rskq_defer_accept; | ||
471 | |||
472 | budget = 2 * (lopt->nr_table_entries / (timeout / interval)); | ||
473 | i = lopt->clock_hand; | ||
474 | |||
475 | do { | ||
476 | reqp=&lopt->syn_table[i]; | ||
477 | while ((req = *reqp) != NULL) { | ||
478 | if (time_after_eq(now, req->expires)) { | ||
479 | if ((req->retrans < thresh || | ||
480 | (inet_rsk(req)->acked && req->retrans < max_retries)) | ||
481 | && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) { | ||
482 | unsigned long timeo; | ||
483 | |||
484 | if (req->retrans++ == 0) | ||
485 | lopt->qlen_young--; | ||
486 | timeo = min((timeout << req->retrans), max_rto); | ||
487 | req->expires = now + timeo; | ||
488 | reqp = &req->dl_next; | ||
489 | continue; | ||
490 | } | ||
491 | |||
492 | /* Drop this request */ | ||
493 | inet_csk_reqsk_queue_unlink(parent, req, reqp); | ||
494 | reqsk_queue_removed(&icsk->icsk_accept_queue, req); | ||
495 | reqsk_free(req); | ||
496 | continue; | ||
497 | } | ||
498 | reqp = &req->dl_next; | ||
499 | } | ||
500 | |||
501 | i = (i + 1) & (lopt->nr_table_entries - 1); | ||
502 | |||
503 | } while (--budget > 0); | ||
504 | |||
505 | lopt->clock_hand = i; | ||
506 | |||
507 | if (lopt->qlen) | ||
508 | inet_csk_reset_keepalive_timer(parent, interval); | ||
509 | } | ||
510 | |||
511 | EXPORT_SYMBOL_GPL(reqsk_queue_prune); | ||
512 | |||
513 | /* | 427 | /* |
514 | * Timer for listening sockets | 428 | * Timer for listening sockets |
515 | */ | 429 | */ |
516 | 430 | ||
517 | static void tcp_synack_timer(struct sock *sk) | 431 | static void tcp_synack_timer(struct sock *sk) |
518 | { | 432 | { |
519 | struct inet_connection_sock *icsk = inet_csk(sk); | 433 | inet_csk_reqsk_queue_prune(sk, TCP_SYNQ_INTERVAL, |
520 | const int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; | 434 | TCP_TIMEOUT_INIT, TCP_RTO_MAX); |
521 | |||
522 | reqsk_queue_prune(&icsk->icsk_accept_queue, sk, TCP_SYNQ_INTERVAL, | ||
523 | TCP_TIMEOUT_INIT, TCP_RTO_MAX, max_retries); | ||
524 | } | 435 | } |
525 | 436 | ||
526 | void tcp_set_keepalive(struct sock *sk, int val) | 437 | void tcp_set_keepalive(struct sock *sk, int val) |