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

[NETFILTER]: x_tables: add RATEEST target

Add new rate estimator target (using gen_estimator). In combination with
the rateest match (next patch) this can be used for load-based multipath
routing.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Patrick McHardy and committed by
David S. Miller
5859034d cb76c6a5

+244
+1
include/linux/netfilter/Kbuild
··· 10 10 header-y += xt_MARK.h 11 11 header-y += xt_NFLOG.h 12 12 header-y += xt_NFQUEUE.h 13 + header-y += xt_RATEEST.h 13 14 header-y += xt_SECMARK.h 14 15 header-y += xt_TCPMSS.h 15 16 header-y += xt_comment.h
+11
include/linux/netfilter/xt_RATEEST.h
··· 1 + #ifndef _XT_RATEEST_TARGET_H 2 + #define _XT_RATEEST_TARGET_H 3 + 4 + struct xt_rateest_target_info { 5 + char name[IFNAMSIZ]; 6 + int8_t interval; 7 + u_int8_t ewma_log; 8 + struct xt_rateest *est __attribute__((aligned(8))); 9 + }; 10 + 11 + #endif /* _XT_RATEEST_TARGET_H */
+17
include/net/netfilter/xt_rateest.h
··· 1 + #ifndef _XT_RATEEST_H 2 + #define _XT_RATEEST_H 3 + 4 + struct xt_rateest { 5 + struct hlist_node list; 6 + char name[IFNAMSIZ]; 7 + unsigned int refcnt; 8 + spinlock_t lock; 9 + struct gnet_estimator params; 10 + struct gnet_stats_rate_est rstats; 11 + struct gnet_stats_basic bstats; 12 + }; 13 + 14 + extern struct xt_rateest *xt_rateest_lookup(const char *name); 15 + extern void xt_rateest_put(struct xt_rateest *est); 16 + 17 + #endif /* _XT_RATEEST_H */
+10
net/netfilter/Kconfig
··· 357 357 If you want to compile it as a module, say M here and read 358 358 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. 359 359 360 + config NETFILTER_XT_TARGET_RATEEST 361 + tristate '"RATEEST" target support' 362 + depends on NETFILTER_XTABLES 363 + help 364 + This option adds a `RATEEST' target, which allows to measure 365 + rates similar to TC estimators. The `rateest' match can be 366 + used to match on the measured rates. 367 + 368 + To compile it as a module, choose M here. If unsure, say N. 369 + 360 370 config NETFILTER_XT_TARGET_TRACE 361 371 tristate '"TRACE" target support' 362 372 depends on NETFILTER_XTABLES
+1
net/netfilter/Makefile
··· 46 46 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 47 47 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o 48 48 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o 49 + obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o 49 50 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o 50 51 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o 51 52 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
+204
net/netfilter/xt_RATEEST.c
··· 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 + 16 + #include <linux/netfilter/x_tables.h> 17 + #include <linux/netfilter/xt_RATEEST.h> 18 + #include <net/netfilter/xt_rateest.h> 19 + 20 + static DEFINE_MUTEX(xt_rateest_mutex); 21 + 22 + #define RATEEST_HSIZE 16 23 + static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; 24 + static unsigned int jhash_rnd __read_mostly; 25 + 26 + static unsigned int xt_rateest_hash(const char *name) 27 + { 28 + return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & 29 + (RATEEST_HSIZE - 1); 30 + } 31 + 32 + static void xt_rateest_hash_insert(struct xt_rateest *est) 33 + { 34 + unsigned int h; 35 + 36 + h = xt_rateest_hash(est->name); 37 + hlist_add_head(&est->list, &rateest_hash[h]); 38 + } 39 + 40 + struct xt_rateest *xt_rateest_lookup(const char *name) 41 + { 42 + struct xt_rateest *est; 43 + struct hlist_node *n; 44 + unsigned int h; 45 + 46 + h = xt_rateest_hash(name); 47 + mutex_lock(&xt_rateest_mutex); 48 + hlist_for_each_entry(est, n, &rateest_hash[h], list) { 49 + if (strcmp(est->name, name) == 0) { 50 + est->refcnt++; 51 + mutex_unlock(&xt_rateest_mutex); 52 + return est; 53 + } 54 + } 55 + mutex_unlock(&xt_rateest_mutex); 56 + return NULL; 57 + } 58 + EXPORT_SYMBOL_GPL(xt_rateest_lookup); 59 + 60 + void xt_rateest_put(struct xt_rateest *est) 61 + { 62 + mutex_lock(&xt_rateest_mutex); 63 + if (--est->refcnt == 0) { 64 + hlist_del(&est->list); 65 + gen_kill_estimator(&est->bstats, &est->rstats); 66 + kfree(est); 67 + } 68 + mutex_unlock(&xt_rateest_mutex); 69 + } 70 + EXPORT_SYMBOL_GPL(xt_rateest_put); 71 + 72 + static unsigned int 73 + xt_rateest_tg(struct sk_buff *skb, 74 + const struct net_device *in, 75 + const struct net_device *out, 76 + unsigned int hooknum, 77 + const struct xt_target *target, 78 + const void *targinfo) 79 + { 80 + const struct xt_rateest_target_info *info = targinfo; 81 + struct gnet_stats_basic *stats = &info->est->bstats; 82 + 83 + spin_lock_bh(&info->est->lock); 84 + stats->bytes += skb->len; 85 + stats->packets++; 86 + spin_unlock_bh(&info->est->lock); 87 + 88 + return XT_CONTINUE; 89 + } 90 + 91 + static bool 92 + xt_rateest_tg_checkentry(const char *tablename, 93 + const void *entry, 94 + const struct xt_target *target, 95 + void *targinfo, 96 + unsigned int hook_mask) 97 + { 98 + struct xt_rateest_target_info *info = (void *)targinfo; 99 + struct xt_rateest *est; 100 + struct { 101 + struct rtattr opt; 102 + struct gnet_estimator est; 103 + } cfg; 104 + 105 + est = xt_rateest_lookup(info->name); 106 + if (est) { 107 + /* 108 + * If estimator parameters are specified, they must match the 109 + * existing estimator. 110 + */ 111 + if ((!info->interval && !info->ewma_log) || 112 + (info->interval != est->params.interval || 113 + info->ewma_log != est->params.ewma_log)) { 114 + xt_rateest_put(est); 115 + return false; 116 + } 117 + info->est = est; 118 + return true; 119 + } 120 + 121 + est = kzalloc(sizeof(*est), GFP_KERNEL); 122 + if (!est) 123 + goto err1; 124 + 125 + strlcpy(est->name, info->name, sizeof(est->name)); 126 + spin_lock_init(&est->lock); 127 + est->refcnt = 1; 128 + est->params.interval = info->interval; 129 + est->params.ewma_log = info->ewma_log; 130 + 131 + cfg.opt.rta_len = RTA_LENGTH(sizeof(cfg.est)); 132 + cfg.opt.rta_type = TCA_STATS_RATE_EST; 133 + cfg.est.interval = info->interval; 134 + cfg.est.ewma_log = info->ewma_log; 135 + 136 + if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, 137 + &cfg.opt) < 0) 138 + goto err2; 139 + 140 + info->est = est; 141 + xt_rateest_hash_insert(est); 142 + 143 + return true; 144 + 145 + err2: 146 + kfree(est); 147 + err1: 148 + return false; 149 + } 150 + 151 + static void xt_rateest_tg_destroy(const struct xt_target *target, 152 + void *targinfo) 153 + { 154 + struct xt_rateest_target_info *info = targinfo; 155 + 156 + xt_rateest_put(info->est); 157 + } 158 + 159 + static struct xt_target xt_rateest_target[] __read_mostly = { 160 + { 161 + .family = AF_INET, 162 + .name = "RATEEST", 163 + .target = xt_rateest_tg, 164 + .checkentry = xt_rateest_tg_checkentry, 165 + .destroy = xt_rateest_tg_destroy, 166 + .targetsize = sizeof(struct xt_rateest_target_info), 167 + .me = THIS_MODULE, 168 + }, 169 + { 170 + .family = AF_INET6, 171 + .name = "RATEEST", 172 + .target = xt_rateest_tg, 173 + .checkentry = xt_rateest_tg_checkentry, 174 + .destroy = xt_rateest_tg_destroy, 175 + .targetsize = sizeof(struct xt_rateest_target_info), 176 + .me = THIS_MODULE, 177 + }, 178 + }; 179 + 180 + static int __init xt_rateest_tg_init(void) 181 + { 182 + unsigned int i; 183 + 184 + for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) 185 + INIT_HLIST_HEAD(&rateest_hash[i]); 186 + 187 + get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); 188 + return xt_register_targets(xt_rateest_target, 189 + ARRAY_SIZE(xt_rateest_target)); 190 + } 191 + 192 + static void __exit xt_rateest_tg_fini(void) 193 + { 194 + xt_unregister_targets(xt_rateest_target, ARRAY_SIZE(xt_rateest_target)); 195 + } 196 + 197 + 198 + MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 199 + MODULE_LICENSE("GPL"); 200 + MODULE_DESCRIPTION("xtables rate estimator"); 201 + MODULE_ALIAS("ipt_RATEEST"); 202 + MODULE_ALIAS("ip6t_RATEEST"); 203 + module_init(xt_rateest_tg_init); 204 + module_exit(xt_rateest_tg_fini);