* [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline
@ 2012-05-07 20:51 Florian Westphal
2012-05-07 20:51 ` [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper Florian Westphal
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Florian Westphal @ 2012-05-07 20:51 UTC (permalink / raw)
To: netfilter-devel
credit_cap can be set to credit, which avoids inlining user2credits
twice. Also, remove inline keyword and let compiler decide.
old:
684 192 0 876 36c net/netfilter/xt_limit.o
4927 344 32 5303 14b7 net/netfilter/xt_hashlimit.o
now:
668 192 0 860 35c net/netfilter/xt_limit.o
4793 344 32 5169 1431 net/netfilter/xt_hashlimit.o
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/xt_hashlimit.c | 8 +++-----
net/netfilter/xt_limit.c | 5 ++---
2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d95f9c9..2195eb0 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -389,8 +389,7 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
/* Precision saver. */
-static inline u_int32_t
-user2credits(u_int32_t user)
+static u32 user2credits(u32 user)
{
/* If multiplying would overflow... */
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
@@ -400,7 +399,7 @@ user2credits(u_int32_t user)
return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE;
}
-static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
+static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
{
dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY;
if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
@@ -535,8 +534,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
dh->rateinfo.prev = jiffies;
dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
hinfo->cfg.burst);
- dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
- hinfo->cfg.burst);
+ dh->rateinfo.credit_cap = dh->rateinfo.credit;
dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
} else {
/* update expiration timeout */
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 32b7a57..5c22ce8 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -88,8 +88,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
}
/* Precision saver. */
-static u_int32_t
-user2credits(u_int32_t user)
+static u32 user2credits(u32 user)
{
/* If multiplying would overflow... */
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
@@ -123,7 +122,7 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
128. */
priv->prev = jiffies;
priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
- r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
+ r->credit_cap = priv->credit; /* Credits full. */
r->cost = user2credits(r->avg);
}
return 0;
--
1.7.3.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper
2012-05-07 20:51 [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Florian Westphal
@ 2012-05-07 20:51 ` Florian Westphal
2012-05-09 11:25 ` Pablo Neira Ayuso
2012-05-07 20:51 ` [PATCH next 3/3] netfilter: hashlimit: byte-based limit mode Florian Westphal
2012-05-09 11:25 ` [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Pablo Neira Ayuso
2 siblings, 1 reply; 6+ messages in thread
From: Florian Westphal @ 2012-05-07 20:51 UTC (permalink / raw)
To: netfilter-devel
followup patch would bloat main match function too much.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/xt_hashlimit.c | 15 ++++++++++-----
1 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 2195eb0..b6bbd06 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -407,6 +407,15 @@ static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
dh->rateinfo.prev = now;
}
+static void rateinfo_init(struct dsthash_ent *dh,
+ struct xt_hashlimit_htable *hinfo)
+{
+ dh->rateinfo.prev = jiffies;
+ dh->rateinfo.credit = user2credits(hinfo->cfg.avg * hinfo->cfg.burst);
+ dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
+ dh->rateinfo.credit_cap = dh->rateinfo.credit;
+}
+
static inline __be32 maskl(__be32 a, unsigned int l)
{
return l ? htonl(ntohl(a) & ~0 << (32 - l)) : 0;
@@ -531,11 +540,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
goto hotdrop;
}
dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
- dh->rateinfo.prev = jiffies;
- dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
- hinfo->cfg.burst);
- dh->rateinfo.credit_cap = dh->rateinfo.credit;
- dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
+ rateinfo_init(dh, hinfo);
} else {
/* update expiration timeout */
dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH next 3/3] netfilter: hashlimit: byte-based limit mode
2012-05-07 20:51 [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Florian Westphal
2012-05-07 20:51 ` [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper Florian Westphal
@ 2012-05-07 20:51 ` Florian Westphal
2012-05-09 11:25 ` Pablo Neira Ayuso
2012-05-09 11:25 ` [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Pablo Neira Ayuso
2 siblings, 1 reply; 6+ messages in thread
From: Florian Westphal @ 2012-05-07 20:51 UTC (permalink / raw)
To: netfilter-devel
can be used e.g. for ingress traffic policing or
to detect when a host/port consumes more bandwidth than expected.
This is done by optionally making cost to mean
"cost per 16-byte-chunk-of-data" instead of "cost per packet".
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/netfilter/xt_hashlimit.h | 9 ++-
net/netfilter/xt_hashlimit.c | 116 ++++++++++++++++++++++++++-----
2 files changed, 105 insertions(+), 20 deletions(-)
diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h
index b1925b5..a5e9ea2 100644
--- a/include/linux/netfilter/xt_hashlimit.h
+++ b/include/linux/netfilter/xt_hashlimit.h
@@ -6,7 +6,10 @@
/* timings are in milliseconds. */
#define XT_HASHLIMIT_SCALE 10000
/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
- seconds, or one every 59 hours. */
+ seconds, or one packet every 59 hours. */
+
+/* packet length accounting is done in 16-byte steps */
+#define XT_HASHLIMIT_BYTE_SHIFT 4
/* details of this structure hidden by the implementation */
struct xt_hashlimit_htable;
@@ -17,6 +20,10 @@ enum {
XT_HASHLIMIT_HASH_SIP = 1 << 2,
XT_HASHLIMIT_HASH_SPT = 1 << 3,
XT_HASHLIMIT_INVERT = 1 << 4,
+ XT_HASHLIMIT_BYTES = 1 << 5,
+#ifdef __KERNEL__
+ XT_HASHLIMIT_MAX = 1 << 6,
+#endif
};
struct hashlimit_cfg {
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index b6bbd06..d0424f9 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -388,6 +388,18 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
+/* in byte mode, the lowest possible rate is one packet/second.
+ * credit_cap is used as a counter that tells us how many times we can
+ * refill the "credits available" counter when it becomes empty.
+ */
+#define MAX_CPJ_BYTES (0xFFFFFFFF / HZ)
+#define CREDITS_PER_JIFFY_BYTES POW2_BELOW32(MAX_CPJ_BYTES)
+
+static u32 xt_hashlimit_len_to_chunks(u32 len)
+{
+ return (len >> XT_HASHLIMIT_BYTE_SHIFT) + 1;
+}
+
/* Precision saver. */
static u32 user2credits(u32 user)
{
@@ -399,21 +411,53 @@ static u32 user2credits(u32 user)
return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE;
}
-static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
+static u32 user2credits_byte(u32 user)
{
- dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY;
- if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
- dh->rateinfo.credit = dh->rateinfo.credit_cap;
+ u64 us = user;
+ us *= HZ * CREDITS_PER_JIFFY_BYTES;
+ return (u32) (us >> 32);
+}
+
+static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now, u32 mode)
+{
+ unsigned long delta = now - dh->rateinfo.prev;
+ u32 cap;
+
+ if (delta == 0)
+ return;
+
dh->rateinfo.prev = now;
+
+ if (mode & XT_HASHLIMIT_BYTES) {
+ u32 tmp = dh->rateinfo.credit;
+ dh->rateinfo.credit += CREDITS_PER_JIFFY_BYTES * delta;
+ cap = CREDITS_PER_JIFFY_BYTES * HZ;
+ if (tmp >= dh->rateinfo.credit) {/* overflow */
+ dh->rateinfo.credit = cap;
+ return;
+ }
+ } else {
+ dh->rateinfo.credit += delta * CREDITS_PER_JIFFY;
+ cap = dh->rateinfo.credit_cap;
+ }
+ if (dh->rateinfo.credit > cap)
+ dh->rateinfo.credit = cap;
}
static void rateinfo_init(struct dsthash_ent *dh,
struct xt_hashlimit_htable *hinfo)
{
dh->rateinfo.prev = jiffies;
- dh->rateinfo.credit = user2credits(hinfo->cfg.avg * hinfo->cfg.burst);
- dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
- dh->rateinfo.credit_cap = dh->rateinfo.credit;
+ if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) {
+ dh->rateinfo.credit = CREDITS_PER_JIFFY_BYTES * HZ;
+ dh->rateinfo.cost = user2credits_byte(hinfo->cfg.avg);
+ dh->rateinfo.credit_cap = hinfo->cfg.burst;
+ } else {
+ dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
+ hinfo->cfg.burst);
+ dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
+ dh->rateinfo.credit_cap = dh->rateinfo.credit;
+ }
}
static inline __be32 maskl(__be32 a, unsigned int l)
@@ -519,6 +563,21 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
return 0;
}
+static u32 hashlimit_byte_cost(unsigned int len, struct dsthash_ent *dh)
+{
+ u64 tmp = xt_hashlimit_len_to_chunks(len);
+ tmp = tmp * dh->rateinfo.cost;
+
+ if (unlikely(tmp > CREDITS_PER_JIFFY_BYTES * HZ))
+ tmp = CREDITS_PER_JIFFY_BYTES * HZ;
+
+ if (dh->rateinfo.credit < tmp && dh->rateinfo.credit_cap) {
+ dh->rateinfo.credit_cap--;
+ dh->rateinfo.credit = CREDITS_PER_JIFFY_BYTES * HZ;
+ }
+ return (u32) tmp;
+}
+
static bool
hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
@@ -527,6 +586,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
unsigned long now = jiffies;
struct dsthash_ent *dh;
struct dsthash_dst dst;
+ u32 cost;
if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
goto hotdrop;
@@ -544,12 +604,17 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
} else {
/* update expiration timeout */
dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
- rateinfo_recalc(dh, now);
+ rateinfo_recalc(dh, now, hinfo->cfg.mode);
}
- if (dh->rateinfo.credit >= dh->rateinfo.cost) {
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES)
+ cost = hashlimit_byte_cost(skb->len, dh);
+ else
+ cost = dh->rateinfo.cost;
+
+ if (dh->rateinfo.credit >= cost) {
/* below the limit */
- dh->rateinfo.credit -= dh->rateinfo.cost;
+ dh->rateinfo.credit -= cost;
spin_unlock(&dh->lock);
rcu_read_unlock_bh();
return !(info->cfg.mode & XT_HASHLIMIT_INVERT);
@@ -571,14 +636,6 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
int ret;
- /* Check for overflow. */
- if (info->cfg.burst == 0 ||
- user2credits(info->cfg.avg * info->cfg.burst) <
- user2credits(info->cfg.avg)) {
- pr_info("overflow, try lower: %u/%u\n",
- info->cfg.avg, info->cfg.burst);
- return -ERANGE;
- }
if (info->cfg.gc_interval == 0 || info->cfg.expire == 0)
return -EINVAL;
if (info->name[sizeof(info->name)-1] != '\0')
@@ -591,6 +648,26 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
return -EINVAL;
}
+ if (info->cfg.mode >= XT_HASHLIMIT_MAX) {
+ pr_info("Unknown mode mask %X, kernel too old?\n",
+ info->cfg.mode);
+ return -EINVAL;
+ }
+
+ /* Check for overflow. */
+ if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
+ if (user2credits_byte(info->cfg.avg) == 0) {
+ pr_info("overflow, rate too high: %u\n", info->cfg.avg);
+ return -EINVAL;
+ }
+ } else if (info->cfg.burst == 0 ||
+ user2credits(info->cfg.avg * info->cfg.burst) <
+ user2credits(info->cfg.avg)) {
+ pr_info("overflow, try lower: %u/%u\n",
+ info->cfg.avg, info->cfg.burst);
+ return -ERANGE;
+ }
+
mutex_lock(&hashlimit_mutex);
info->hinfo = htable_find_get(net, info->name, par->family);
if (info->hinfo == NULL) {
@@ -683,10 +760,11 @@ static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family,
struct seq_file *s)
{
int res;
+ const struct xt_hashlimit_htable *ht = s->private;
spin_lock(&ent->lock);
/* recalculate to show accurate numbers */
- rateinfo_recalc(ent, jiffies);
+ rateinfo_recalc(ent, jiffies, ht->cfg.mode);
switch (family) {
case NFPROTO_IPV4:
--
1.7.3.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline
2012-05-07 20:51 [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Florian Westphal
2012-05-07 20:51 ` [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper Florian Westphal
2012-05-07 20:51 ` [PATCH next 3/3] netfilter: hashlimit: byte-based limit mode Florian Westphal
@ 2012-05-09 11:25 ` Pablo Neira Ayuso
2 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2012-05-09 11:25 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Mon, May 07, 2012 at 10:51:43PM +0200, Florian Westphal wrote:
> credit_cap can be set to credit, which avoids inlining user2credits
> twice. Also, remove inline keyword and let compiler decide.
>
> old:
> 684 192 0 876 36c net/netfilter/xt_limit.o
> 4927 344 32 5303 14b7 net/netfilter/xt_hashlimit.o
> now:
> 668 192 0 860 35c net/netfilter/xt_limit.o
> 4793 344 32 5169 1431 net/netfilter/xt_hashlimit.o
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied, thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper
2012-05-07 20:51 ` [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper Florian Westphal
@ 2012-05-09 11:25 ` Pablo Neira Ayuso
0 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2012-05-09 11:25 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Mon, May 07, 2012 at 10:51:44PM +0200, Florian Westphal wrote:
> followup patch would bloat main match function too much.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied, thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH next 3/3] netfilter: hashlimit: byte-based limit mode
2012-05-07 20:51 ` [PATCH next 3/3] netfilter: hashlimit: byte-based limit mode Florian Westphal
@ 2012-05-09 11:25 ` Pablo Neira Ayuso
0 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2012-05-09 11:25 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Mon, May 07, 2012 at 10:51:45PM +0200, Florian Westphal wrote:
> can be used e.g. for ingress traffic policing or
> to detect when a host/port consumes more bandwidth than expected.
>
> This is done by optionally making cost to mean
> "cost per 16-byte-chunk-of-data" instead of "cost per packet".
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
Applied, thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-05-09 11:25 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-07 20:51 [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Florian Westphal
2012-05-07 20:51 ` [PATCH next 2/3] netfilter: hashlimit: move rateinfo initialization to helper Florian Westphal
2012-05-09 11:25 ` Pablo Neira Ayuso
2012-05-07 20:51 ` [PATCH next 3/3] netfilter: hashlimit: byte-based limit mode Florian Westphal
2012-05-09 11:25 ` Pablo Neira Ayuso
2012-05-09 11:25 ` [PATCH next 1/3] netfilter: limit, hashlimit: avoid duplicated inline Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).