-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 78294 b: refs/heads/master c: 5859034 h: refs/heads/master v: v3
- Loading branch information
Patrick McHardy
authored and
David S. Miller
committed
Jan 28, 2008
1 parent
f4bffe0
commit 27f8945
Showing
7 changed files
with
245 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: cb76c6a597350534d211ba79d92da1f9771f8226 | ||
refs/heads/master: 5859034d7eb8793d3d78d3af515c4175e7b9d03a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef _XT_RATEEST_TARGET_H | ||
#define _XT_RATEEST_TARGET_H | ||
|
||
struct xt_rateest_target_info { | ||
char name[IFNAMSIZ]; | ||
int8_t interval; | ||
u_int8_t ewma_log; | ||
struct xt_rateest *est __attribute__((aligned(8))); | ||
}; | ||
|
||
#endif /* _XT_RATEEST_TARGET_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef _XT_RATEEST_H | ||
#define _XT_RATEEST_H | ||
|
||
struct xt_rateest { | ||
struct hlist_node list; | ||
char name[IFNAMSIZ]; | ||
unsigned int refcnt; | ||
spinlock_t lock; | ||
struct gnet_estimator params; | ||
struct gnet_stats_rate_est rstats; | ||
struct gnet_stats_basic bstats; | ||
}; | ||
|
||
extern struct xt_rateest *xt_rateest_lookup(const char *name); | ||
extern void xt_rateest_put(struct xt_rateest *est); | ||
|
||
#endif /* _XT_RATEEST_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
/* | ||
* (C) 2007 Patrick McHardy <kaber@trash.net> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
#include <linux/module.h> | ||
#include <linux/skbuff.h> | ||
#include <linux/gen_stats.h> | ||
#include <linux/jhash.h> | ||
#include <linux/rtnetlink.h> | ||
#include <linux/random.h> | ||
#include <net/gen_stats.h> | ||
|
||
#include <linux/netfilter/x_tables.h> | ||
#include <linux/netfilter/xt_RATEEST.h> | ||
#include <net/netfilter/xt_rateest.h> | ||
|
||
static DEFINE_MUTEX(xt_rateest_mutex); | ||
|
||
#define RATEEST_HSIZE 16 | ||
static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; | ||
static unsigned int jhash_rnd __read_mostly; | ||
|
||
static unsigned int xt_rateest_hash(const char *name) | ||
{ | ||
return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & | ||
(RATEEST_HSIZE - 1); | ||
} | ||
|
||
static void xt_rateest_hash_insert(struct xt_rateest *est) | ||
{ | ||
unsigned int h; | ||
|
||
h = xt_rateest_hash(est->name); | ||
hlist_add_head(&est->list, &rateest_hash[h]); | ||
} | ||
|
||
struct xt_rateest *xt_rateest_lookup(const char *name) | ||
{ | ||
struct xt_rateest *est; | ||
struct hlist_node *n; | ||
unsigned int h; | ||
|
||
h = xt_rateest_hash(name); | ||
mutex_lock(&xt_rateest_mutex); | ||
hlist_for_each_entry(est, n, &rateest_hash[h], list) { | ||
if (strcmp(est->name, name) == 0) { | ||
est->refcnt++; | ||
mutex_unlock(&xt_rateest_mutex); | ||
return est; | ||
} | ||
} | ||
mutex_unlock(&xt_rateest_mutex); | ||
return NULL; | ||
} | ||
EXPORT_SYMBOL_GPL(xt_rateest_lookup); | ||
|
||
void xt_rateest_put(struct xt_rateest *est) | ||
{ | ||
mutex_lock(&xt_rateest_mutex); | ||
if (--est->refcnt == 0) { | ||
hlist_del(&est->list); | ||
gen_kill_estimator(&est->bstats, &est->rstats); | ||
kfree(est); | ||
} | ||
mutex_unlock(&xt_rateest_mutex); | ||
} | ||
EXPORT_SYMBOL_GPL(xt_rateest_put); | ||
|
||
static unsigned int | ||
xt_rateest_tg(struct sk_buff *skb, | ||
const struct net_device *in, | ||
const struct net_device *out, | ||
unsigned int hooknum, | ||
const struct xt_target *target, | ||
const void *targinfo) | ||
{ | ||
const struct xt_rateest_target_info *info = targinfo; | ||
struct gnet_stats_basic *stats = &info->est->bstats; | ||
|
||
spin_lock_bh(&info->est->lock); | ||
stats->bytes += skb->len; | ||
stats->packets++; | ||
spin_unlock_bh(&info->est->lock); | ||
|
||
return XT_CONTINUE; | ||
} | ||
|
||
static bool | ||
xt_rateest_tg_checkentry(const char *tablename, | ||
const void *entry, | ||
const struct xt_target *target, | ||
void *targinfo, | ||
unsigned int hook_mask) | ||
{ | ||
struct xt_rateest_target_info *info = (void *)targinfo; | ||
struct xt_rateest *est; | ||
struct { | ||
struct rtattr opt; | ||
struct gnet_estimator est; | ||
} cfg; | ||
|
||
est = xt_rateest_lookup(info->name); | ||
if (est) { | ||
/* | ||
* If estimator parameters are specified, they must match the | ||
* existing estimator. | ||
*/ | ||
if ((!info->interval && !info->ewma_log) || | ||
(info->interval != est->params.interval || | ||
info->ewma_log != est->params.ewma_log)) { | ||
xt_rateest_put(est); | ||
return false; | ||
} | ||
info->est = est; | ||
return true; | ||
} | ||
|
||
est = kzalloc(sizeof(*est), GFP_KERNEL); | ||
if (!est) | ||
goto err1; | ||
|
||
strlcpy(est->name, info->name, sizeof(est->name)); | ||
spin_lock_init(&est->lock); | ||
est->refcnt = 1; | ||
est->params.interval = info->interval; | ||
est->params.ewma_log = info->ewma_log; | ||
|
||
cfg.opt.rta_len = RTA_LENGTH(sizeof(cfg.est)); | ||
cfg.opt.rta_type = TCA_STATS_RATE_EST; | ||
cfg.est.interval = info->interval; | ||
cfg.est.ewma_log = info->ewma_log; | ||
|
||
if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, | ||
&cfg.opt) < 0) | ||
goto err2; | ||
|
||
info->est = est; | ||
xt_rateest_hash_insert(est); | ||
|
||
return true; | ||
|
||
err2: | ||
kfree(est); | ||
err1: | ||
return false; | ||
} | ||
|
||
static void xt_rateest_tg_destroy(const struct xt_target *target, | ||
void *targinfo) | ||
{ | ||
struct xt_rateest_target_info *info = targinfo; | ||
|
||
xt_rateest_put(info->est); | ||
} | ||
|
||
static struct xt_target xt_rateest_target[] __read_mostly = { | ||
{ | ||
.family = AF_INET, | ||
.name = "RATEEST", | ||
.target = xt_rateest_tg, | ||
.checkentry = xt_rateest_tg_checkentry, | ||
.destroy = xt_rateest_tg_destroy, | ||
.targetsize = sizeof(struct xt_rateest_target_info), | ||
.me = THIS_MODULE, | ||
}, | ||
{ | ||
.family = AF_INET6, | ||
.name = "RATEEST", | ||
.target = xt_rateest_tg, | ||
.checkentry = xt_rateest_tg_checkentry, | ||
.destroy = xt_rateest_tg_destroy, | ||
.targetsize = sizeof(struct xt_rateest_target_info), | ||
.me = THIS_MODULE, | ||
}, | ||
}; | ||
|
||
static int __init xt_rateest_tg_init(void) | ||
{ | ||
unsigned int i; | ||
|
||
for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) | ||
INIT_HLIST_HEAD(&rateest_hash[i]); | ||
|
||
get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); | ||
return xt_register_targets(xt_rateest_target, | ||
ARRAY_SIZE(xt_rateest_target)); | ||
} | ||
|
||
static void __exit xt_rateest_tg_fini(void) | ||
{ | ||
xt_unregister_targets(xt_rateest_target, ARRAY_SIZE(xt_rateest_target)); | ||
} | ||
|
||
|
||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_DESCRIPTION("xtables rate estimator"); | ||
MODULE_ALIAS("ipt_RATEEST"); | ||
MODULE_ALIAS("ip6t_RATEEST"); | ||
module_init(xt_rateest_tg_init); | ||
module_exit(xt_rateest_tg_fini); |