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>
This commit is contained in:
@@ -513,6 +513,8 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
|
||||
atomic_set(&p->ip_id_count, secure_ip_id(daddr->a4));
|
||||
p->tcp_ts_stamp = 0;
|
||||
p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
|
||||
p->rate_tokens = 0;
|
||||
p->rate_last = 0;
|
||||
INIT_LIST_HEAD(&p->unused);
|
||||
|
||||
|
||||
@@ -580,3 +582,44 @@ void inet_putpeer(struct inet_peer *p)
|
||||
local_bh_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(inet_putpeer);
|
||||
|
||||
/*
|
||||
* Check transmit rate limitation for given message.
|
||||
* The rate information is held in the inet_peer entries now.
|
||||
* This function is generic and could be used for other purposes
|
||||
* too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.
|
||||
*
|
||||
* Note that the same inet_peer fields are modified by functions in
|
||||
* route.c too, but these work for packet destinations while xrlim_allow
|
||||
* works for icmp destinations. This means the rate limiting information
|
||||
* for one "ip object" is shared - and these ICMPs are twice limited:
|
||||
* by source and by destination.
|
||||
*
|
||||
* RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate
|
||||
* SHOULD allow setting of rate limits
|
||||
*
|
||||
* Shared between ICMPv4 and ICMPv6.
|
||||
*/
|
||||
#define XRLIM_BURST_FACTOR 6
|
||||
bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout)
|
||||
{
|
||||
unsigned long now, token;
|
||||
bool rc = false;
|
||||
|
||||
if (!peer)
|
||||
return true;
|
||||
|
||||
token = peer->rate_tokens;
|
||||
now = jiffies;
|
||||
token += now - peer->rate_last;
|
||||
peer->rate_last = now;
|
||||
if (token > XRLIM_BURST_FACTOR * timeout)
|
||||
token = XRLIM_BURST_FACTOR * timeout;
|
||||
if (token >= timeout) {
|
||||
token -= timeout;
|
||||
rc = true;
|
||||
}
|
||||
peer->rate_tokens = token;
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(inet_peer_xrlim_allow);
|
||||
|
Reference in New Issue
Block a user