Blame view
net/netfilter/xt_RATEEST.c
4.59 KB
5859034d7 [NETFILTER]: x_ta... |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * (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> |
5a0e3ad6a include cleanup: ... |
14 |
#include <linux/slab.h> |
5859034d7 [NETFILTER]: x_ta... |
15 |
#include <net/gen_stats.h> |
1e90474c3 [NET_SCHED]: Conv... |
16 |
#include <net/netlink.h> |
5859034d7 [NETFILTER]: x_ta... |
17 18 19 20 21 22 23 24 25 26 |
#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; |
5191d5019 netfilter: xtable... |
27 |
static bool rnd_inited __read_mostly; |
5859034d7 [NETFILTER]: x_ta... |
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
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; |
5859034d7 [NETFILTER]: x_ta... |
46 47 48 49 |
unsigned int h; h = xt_rateest_hash(name); mutex_lock(&xt_rateest_mutex); |
b67bfe0d4 hlist: drop the n... |
50 |
hlist_for_each_entry(est, &rateest_hash[h], list) { |
5859034d7 [NETFILTER]: x_ta... |
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
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); |
c7de2cf05 pkt_sched: gen_ki... |
68 69 70 71 |
/* * gen_estimator est_timer() might access est->lock or bstats, * wait a RCU grace period before freeing 'est' */ |
cefcb6020 net,rcu: Convert ... |
72 |
kfree_rcu(est, rcu); |
5859034d7 [NETFILTER]: x_ta... |
73 74 75 76 77 78 |
} mutex_unlock(&xt_rateest_mutex); } EXPORT_SYMBOL_GPL(xt_rateest_put); static unsigned int |
4b560b447 netfilter: xtable... |
79 |
xt_rateest_tg(struct sk_buff *skb, const struct xt_action_param *par) |
5859034d7 [NETFILTER]: x_ta... |
80 |
{ |
7eb355865 netfilter: xtable... |
81 |
const struct xt_rateest_target_info *info = par->targinfo; |
c1a8f1f1c net: restore gnet... |
82 |
struct gnet_stats_basic_packed *stats = &info->est->bstats; |
5859034d7 [NETFILTER]: x_ta... |
83 84 85 86 87 88 89 90 |
spin_lock_bh(&info->est->lock); stats->bytes += skb->len; stats->packets++; spin_unlock_bh(&info->est->lock); return XT_CONTINUE; } |
135367b8f netfilter: xtable... |
91 |
static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) |
5859034d7 [NETFILTER]: x_ta... |
92 |
{ |
af5d6dc20 netfilter: xtable... |
93 |
struct xt_rateest_target_info *info = par->targinfo; |
5859034d7 [NETFILTER]: x_ta... |
94 95 |
struct xt_rateest *est; struct { |
1e90474c3 [NET_SCHED]: Conv... |
96 |
struct nlattr opt; |
5859034d7 [NETFILTER]: x_ta... |
97 98 |
struct gnet_estimator est; } cfg; |
4a5a5c73b netfilter: xtable... |
99 |
int ret; |
5859034d7 [NETFILTER]: x_ta... |
100 |
|
5191d5019 netfilter: xtable... |
101 102 103 104 |
if (unlikely(!rnd_inited)) { get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); rnd_inited = true; } |
5859034d7 [NETFILTER]: x_ta... |
105 106 107 108 109 110 111 112 113 114 |
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); |
d6b00a534 netfilter: xtable... |
115 |
return -EINVAL; |
5859034d7 [NETFILTER]: x_ta... |
116 117 |
} info->est = est; |
d6b00a534 netfilter: xtable... |
118 |
return 0; |
5859034d7 [NETFILTER]: x_ta... |
119 |
} |
4a5a5c73b netfilter: xtable... |
120 |
ret = -ENOMEM; |
5859034d7 [NETFILTER]: x_ta... |
121 122 123 124 125 126 127 128 129 |
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; |
1e90474c3 [NET_SCHED]: Conv... |
130 131 |
cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); cfg.opt.nla_type = TCA_STATS_RATE_EST; |
5859034d7 [NETFILTER]: x_ta... |
132 133 |
cfg.est.interval = info->interval; cfg.est.ewma_log = info->ewma_log; |
22e0f8b93 net: sched: make ... |
134 |
ret = gen_new_estimator(&est->bstats, NULL, &est->rstats, |
4a5a5c73b netfilter: xtable... |
135 136 |
&est->lock, &cfg.opt); if (ret < 0) |
5859034d7 [NETFILTER]: x_ta... |
137 138 139 140 |
goto err2; info->est = est; xt_rateest_hash_insert(est); |
d6b00a534 netfilter: xtable... |
141 |
return 0; |
5859034d7 [NETFILTER]: x_ta... |
142 143 144 145 |
err2: kfree(est); err1: |
4a5a5c73b netfilter: xtable... |
146 |
return ret; |
5859034d7 [NETFILTER]: x_ta... |
147 |
} |
a2df1648b netfilter: xtable... |
148 |
static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) |
5859034d7 [NETFILTER]: x_ta... |
149 |
{ |
a2df1648b netfilter: xtable... |
150 |
struct xt_rateest_target_info *info = par->targinfo; |
5859034d7 [NETFILTER]: x_ta... |
151 152 153 |
xt_rateest_put(info->est); } |
55b69e910 netfilter: implem... |
154 155 156 157 158 159 160 161 162 |
static struct xt_target xt_rateest_tg_reg __read_mostly = { .name = "RATEEST", .revision = 0, .family = NFPROTO_UNSPEC, .target = xt_rateest_tg, .checkentry = xt_rateest_tg_checkentry, .destroy = xt_rateest_tg_destroy, .targetsize = sizeof(struct xt_rateest_target_info), .me = THIS_MODULE, |
5859034d7 [NETFILTER]: x_ta... |
163 164 165 166 167 168 169 170 |
}; 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]); |
55b69e910 netfilter: implem... |
171 |
return xt_register_target(&xt_rateest_tg_reg); |
5859034d7 [NETFILTER]: x_ta... |
172 173 174 175 |
} static void __exit xt_rateest_tg_fini(void) { |
55b69e910 netfilter: implem... |
176 |
xt_unregister_target(&xt_rateest_tg_reg); |
5859034d7 [NETFILTER]: x_ta... |
177 178 179 180 181 |
} MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); MODULE_LICENSE("GPL"); |
2ae15b64e [NETFILTER]: Upda... |
182 |
MODULE_DESCRIPTION("Xtables: packet rate estimator"); |
5859034d7 [NETFILTER]: x_ta... |
183 184 185 186 |
MODULE_ALIAS("ipt_RATEEST"); MODULE_ALIAS("ip6t_RATEEST"); module_init(xt_rateest_tg_init); module_exit(xt_rateest_tg_fini); |