Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.34-rc2 188 lines 4.5 kB view raw
1/* 2 * (C) 2007 Patrick McHardy <kaber@trash.net> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8#include <linux/module.h> 9#include <linux/skbuff.h> 10#include <linux/gen_stats.h> 11#include <linux/jhash.h> 12#include <linux/rtnetlink.h> 13#include <linux/random.h> 14#include <net/gen_stats.h> 15#include <net/netlink.h> 16 17#include <linux/netfilter/x_tables.h> 18#include <linux/netfilter/xt_RATEEST.h> 19#include <net/netfilter/xt_rateest.h> 20 21static DEFINE_MUTEX(xt_rateest_mutex); 22 23#define RATEEST_HSIZE 16 24static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; 25static unsigned int jhash_rnd __read_mostly; 26static bool rnd_inited __read_mostly; 27 28static unsigned int xt_rateest_hash(const char *name) 29{ 30 return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & 31 (RATEEST_HSIZE - 1); 32} 33 34static void xt_rateest_hash_insert(struct xt_rateest *est) 35{ 36 unsigned int h; 37 38 h = xt_rateest_hash(est->name); 39 hlist_add_head(&est->list, &rateest_hash[h]); 40} 41 42struct xt_rateest *xt_rateest_lookup(const char *name) 43{ 44 struct xt_rateest *est; 45 struct hlist_node *n; 46 unsigned int h; 47 48 h = xt_rateest_hash(name); 49 mutex_lock(&xt_rateest_mutex); 50 hlist_for_each_entry(est, n, &rateest_hash[h], list) { 51 if (strcmp(est->name, name) == 0) { 52 est->refcnt++; 53 mutex_unlock(&xt_rateest_mutex); 54 return est; 55 } 56 } 57 mutex_unlock(&xt_rateest_mutex); 58 return NULL; 59} 60EXPORT_SYMBOL_GPL(xt_rateest_lookup); 61 62void xt_rateest_put(struct xt_rateest *est) 63{ 64 mutex_lock(&xt_rateest_mutex); 65 if (--est->refcnt == 0) { 66 hlist_del(&est->list); 67 gen_kill_estimator(&est->bstats, &est->rstats); 68 kfree(est); 69 } 70 mutex_unlock(&xt_rateest_mutex); 71} 72EXPORT_SYMBOL_GPL(xt_rateest_put); 73 74static unsigned int 75xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) 76{ 77 const struct xt_rateest_target_info *info = par->targinfo; 78 struct gnet_stats_basic_packed *stats = &info->est->bstats; 79 80 spin_lock_bh(&info->est->lock); 81 stats->bytes += skb->len; 82 stats->packets++; 83 spin_unlock_bh(&info->est->lock); 84 85 return XT_CONTINUE; 86} 87 88static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) 89{ 90 struct xt_rateest_target_info *info = par->targinfo; 91 struct xt_rateest *est; 92 struct { 93 struct nlattr opt; 94 struct gnet_estimator est; 95 } cfg; 96 97 if (unlikely(!rnd_inited)) { 98 get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); 99 rnd_inited = true; 100 } 101 102 est = xt_rateest_lookup(info->name); 103 if (est) { 104 /* 105 * If estimator parameters are specified, they must match the 106 * existing estimator. 107 */ 108 if ((!info->interval && !info->ewma_log) || 109 (info->interval != est->params.interval || 110 info->ewma_log != est->params.ewma_log)) { 111 xt_rateest_put(est); 112 return false; 113 } 114 info->est = est; 115 return true; 116 } 117 118 est = kzalloc(sizeof(*est), GFP_KERNEL); 119 if (!est) 120 goto err1; 121 122 strlcpy(est->name, info->name, sizeof(est->name)); 123 spin_lock_init(&est->lock); 124 est->refcnt = 1; 125 est->params.interval = info->interval; 126 est->params.ewma_log = info->ewma_log; 127 128 cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); 129 cfg.opt.nla_type = TCA_STATS_RATE_EST; 130 cfg.est.interval = info->interval; 131 cfg.est.ewma_log = info->ewma_log; 132 133 if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, 134 &cfg.opt) < 0) 135 goto err2; 136 137 info->est = est; 138 xt_rateest_hash_insert(est); 139 140 return true; 141 142err2: 143 kfree(est); 144err1: 145 return false; 146} 147 148static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) 149{ 150 struct xt_rateest_target_info *info = par->targinfo; 151 152 xt_rateest_put(info->est); 153} 154 155static struct xt_target xt_rateest_tg_reg __read_mostly = { 156 .name = "RATEEST", 157 .revision = 0, 158 .family = NFPROTO_UNSPEC, 159 .target = xt_rateest_tg, 160 .checkentry = xt_rateest_tg_checkentry, 161 .destroy = xt_rateest_tg_destroy, 162 .targetsize = sizeof(struct xt_rateest_target_info), 163 .me = THIS_MODULE, 164}; 165 166static int __init xt_rateest_tg_init(void) 167{ 168 unsigned int i; 169 170 for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) 171 INIT_HLIST_HEAD(&rateest_hash[i]); 172 173 return xt_register_target(&xt_rateest_tg_reg); 174} 175 176static void __exit xt_rateest_tg_fini(void) 177{ 178 xt_unregister_target(&xt_rateest_tg_reg); 179} 180 181 182MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 183MODULE_LICENSE("GPL"); 184MODULE_DESCRIPTION("Xtables: packet rate estimator"); 185MODULE_ALIAS("ipt_RATEEST"); 186MODULE_ALIAS("ip6t_RATEEST"); 187module_init(xt_rateest_tg_init); 188module_exit(xt_rateest_tg_fini);