Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cb4bbd7 authored by Liping Zhang's avatar Liping Zhang Committed by Pablo Neira Ayuso
Browse files

netfilter: limit: use per-rule spinlock to improve the scalability



The limit token is independent between each rules, so there's no
need to use a global spinlock.

Signed-off-by: default avatarLiping Zhang <zlpnobody@gmail.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent fc09e4a7
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -17,9 +17,8 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h>

static DEFINE_SPINLOCK(limit_lock);

struct nft_limit {
	spinlock_t	lock;
	u64		last;
	u64		tokens;
	u64		tokens_max;
@@ -34,7 +33,7 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
	u64 now, tokens;
	s64 delta;

	spin_lock_bh(&limit_lock);
	spin_lock_bh(&limit->lock);
	now = ktime_get_ns();
	tokens = limit->tokens + now - limit->last;
	if (tokens > limit->tokens_max)
@@ -44,11 +43,11 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
	delta = tokens - cost;
	if (delta >= 0) {
		limit->tokens = delta;
		spin_unlock_bh(&limit_lock);
		spin_unlock_bh(&limit->lock);
		return limit->invert;
	}
	limit->tokens = tokens;
	spin_unlock_bh(&limit_lock);
	spin_unlock_bh(&limit->lock);
	return !limit->invert;
}

@@ -86,6 +85,7 @@ static int nft_limit_init(struct nft_limit *limit,
			limit->invert = true;
	}
	limit->last = ktime_get_ns();
	spin_lock_init(&limit->lock);

	return 0;
}
+6 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/netfilter/xt_limit.h>

struct xt_limit_priv {
	spinlock_t lock;
	unsigned long prev;
	uint32_t credit;
};
@@ -32,8 +33,6 @@ MODULE_ALIAS("ip6t_limit");
 * see net/sched/sch_tbf.c in the linux source tree
 */

static DEFINE_SPINLOCK(limit_lock);

/* Rusty: This is my (non-mathematically-inclined) understanding of
   this algorithm.  The `average rate' in jiffies becomes your initial
   amount of credit `credit' and the most credit you can ever have
@@ -72,7 +71,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
	struct xt_limit_priv *priv = r->master;
	unsigned long now = jiffies;

	spin_lock_bh(&limit_lock);
	spin_lock_bh(&priv->lock);
	priv->credit += (now - xchg(&priv->prev, now)) * CREDITS_PER_JIFFY;
	if (priv->credit > r->credit_cap)
		priv->credit = r->credit_cap;
@@ -80,11 +79,11 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
	if (priv->credit >= r->cost) {
		/* We're not limited. */
		priv->credit -= r->cost;
		spin_unlock_bh(&limit_lock);
		spin_unlock_bh(&priv->lock);
		return true;
	}

	spin_unlock_bh(&limit_lock);
	spin_unlock_bh(&priv->lock);
	return false;
}

@@ -126,6 +125,8 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
		r->credit_cap = priv->credit; /* Credits full. */
		r->cost = user2credits(r->avg);
	}
	spin_lock_init(&priv->lock);

	return 0;
}