* [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
* 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
* [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 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
* 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
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 an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.