aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inetpeer.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-02-04 18:55:25 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-04 18:59:53 -0500
commit92d8682926342d2b6aa5b2ecc02221e00e1573a0 (patch)
tree7f70b9cc2975716ab60ddd632b9fecf0a51b828d /net/ipv4/inetpeer.c
parent0131ba451e20239c5dc701027c1a2edef95e1a6e (diff)
inetpeer: Move ICMP rate limiting state into inet_peer entries.
Like metrics, the ICMP rate limiting bits are cached state about a destination. So move it into the inet_peer entries. If an inet_peer cannot be bound (the reason is memory allocation failure or similar), the policy is to allow. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/inetpeer.c')
-rw-r--r--net/ipv4/inetpeer.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index b6513b13d729..709fbb4132d7 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -513,6 +513,8 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
513 atomic_set(&p->ip_id_count, secure_ip_id(daddr->a4)); 513 atomic_set(&p->ip_id_count, secure_ip_id(daddr->a4));
514 p->tcp_ts_stamp = 0; 514 p->tcp_ts_stamp = 0;
515 p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW; 515 p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
516 p->rate_tokens = 0;
517 p->rate_last = 0;
516 INIT_LIST_HEAD(&p->unused); 518 INIT_LIST_HEAD(&p->unused);
517 519
518 520
@@ -580,3 +582,44 @@ void inet_putpeer(struct inet_peer *p)
580 local_bh_enable(); 582 local_bh_enable();
581} 583}
582EXPORT_SYMBOL_GPL(inet_putpeer); 584EXPORT_SYMBOL_GPL(inet_putpeer);
585
586/*
587 * Check transmit rate limitation for given message.
588 * The rate information is held in the inet_peer entries now.
589 * This function is generic and could be used for other purposes
590 * too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.
591 *
592 * Note that the same inet_peer fields are modified by functions in
593 * route.c too, but these work for packet destinations while xrlim_allow
594 * works for icmp destinations. This means the rate limiting information
595 * for one "ip object" is shared - and these ICMPs are twice limited:
596 * by source and by destination.
597 *
598 * RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate
599 * SHOULD allow setting of rate limits
600 *
601 * Shared between ICMPv4 and ICMPv6.
602 */
603#define XRLIM_BURST_FACTOR 6
604bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout)
605{
606 unsigned long now, token;
607 bool rc = false;
608
609 if (!peer)
610 return true;
611
612 token = peer->rate_tokens;
613 now = jiffies;
614 token += now - peer->rate_last;
615 peer->rate_last = now;
616 if (token > XRLIM_BURST_FACTOR * timeout)
617 token = XRLIM_BURST_FACTOR * timeout;
618 if (token >= timeout) {
619 token -= timeout;
620 rc = true;
621 }
622 peer->rate_tokens = token;
623 return rc;
624}
625EXPORT_SYMBOL(inet_peer_xrlim_allow);