libxt_RATEEST.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdbool.h> 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <getopt.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <xtables.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <linux/netfilter/x_tables.h> 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <linux/netfilter/xt_RATEEST.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* hack to pass raw values to final_check */ 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct xt_rateest_target_info *RATEEST_info; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int interval; 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic unsigned int ewma_log; 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void 19effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochRATEEST_help(void) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf( 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch"RATEEST target options:\n" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)" --rateest-name name Rate estimator name\n" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)" --rateest-interval sec Rate measurement interval in seconds\n" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)" --rateest-ewmalog value Rate measurement averaging time constant\n"); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum RATEEST_options { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RATEEST_OPT_NAME, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RATEEST_OPT_INTERVAL, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RATEEST_OPT_EWMALOG, 32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct option RATEEST_opts[] = { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {.name = "rateest-name", .has_arg = true, .val = RATEEST_OPT_NAME}, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {.name = "rateest-interval", .has_arg = true, .val = RATEEST_OPT_INTERVAL}, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {.name = "rateest-ewmalog", .has_arg = true, .val = RATEEST_OPT_EWMALOG}, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XT_GETOPT_TABLEEND, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copied from iproute */ 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TIME_UNITS_PER_SEC 1000000 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RATEEST_get_time(unsigned int *time, const char *str) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double t; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t = strtod(str, &p); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p == str) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*p) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 || 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcasecmp(p, "secs")==0) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t *= TIME_UNITS_PER_SEC; 58 else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 || 59 strcasecmp(p, "msecs") == 0) 60 t *= TIME_UNITS_PER_SEC/1000; 61 else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 || 62 strcasecmp(p, "usecs") == 0) 63 t *= TIME_UNITS_PER_SEC/1000000; 64 else 65 return -1; 66 } 67 68 *time = t; 69 return 0; 70} 71 72static void 73RATEEST_print_time(unsigned int time) 74{ 75 double tmp = time; 76 77 if (tmp >= TIME_UNITS_PER_SEC) 78 printf(" %.1fs", tmp / TIME_UNITS_PER_SEC); 79 else if (tmp >= TIME_UNITS_PER_SEC/1000) 80 printf(" %.1fms", tmp / (TIME_UNITS_PER_SEC / 1000)); 81 else 82 printf(" %uus", time); 83} 84 85static void 86RATEEST_init(struct xt_entry_target *target) 87{ 88 interval = 0; 89 ewma_log = 0; 90} 91 92static int 93RATEEST_parse(int c, char **argv, int invert, unsigned int *flags, 94 const void *entry, struct xt_entry_target **target) 95{ 96 struct xt_rateest_target_info *info = (void *)(*target)->data; 97 98 RATEEST_info = info; 99 100 switch (c) { 101 case RATEEST_OPT_NAME: 102 if (*flags & (1 << c)) 103 xtables_error(PARAMETER_PROBLEM, 104 "RATEEST: can't specify --rateest-name twice"); 105 *flags |= 1 << c; 106 107 strncpy(info->name, optarg, sizeof(info->name) - 1); 108 break; 109 110 case RATEEST_OPT_INTERVAL: 111 if (*flags & (1 << c)) 112 xtables_error(PARAMETER_PROBLEM, 113 "RATEEST: can't specify --rateest-interval twice"); 114 *flags |= 1 << c; 115 116 if (RATEEST_get_time(&interval, optarg) < 0) 117 xtables_error(PARAMETER_PROBLEM, 118 "RATEEST: bad interval value `%s'", optarg); 119 120 break; 121 122 case RATEEST_OPT_EWMALOG: 123 if (*flags & (1 << c)) 124 xtables_error(PARAMETER_PROBLEM, 125 "RATEEST: can't specify --rateest-ewmalog twice"); 126 *flags |= 1 << c; 127 128 if (RATEEST_get_time(&ewma_log, optarg) < 0) 129 xtables_error(PARAMETER_PROBLEM, 130 "RATEEST: bad ewmalog value `%s'", optarg); 131 132 break; 133 } 134 135 return 1; 136} 137 138static void 139RATEEST_final_check(unsigned int flags) 140{ 141 struct xt_rateest_target_info *info = RATEEST_info; 142 143 if (!(flags & (1 << RATEEST_OPT_NAME))) 144 xtables_error(PARAMETER_PROBLEM, "RATEEST: no name specified"); 145 if (!(flags & (1 << RATEEST_OPT_INTERVAL))) 146 xtables_error(PARAMETER_PROBLEM, "RATEEST: no interval specified"); 147 if (!(flags & (1 << RATEEST_OPT_EWMALOG))) 148 xtables_error(PARAMETER_PROBLEM, "RATEEST: no ewmalog specified"); 149 150 for (info->interval = 0; info->interval <= 5; info->interval++) { 151 if (interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4)) 152 break; 153 } 154 155 if (info->interval > 5) 156 xtables_error(PARAMETER_PROBLEM, 157 "RATEEST: interval value is too large"); 158 info->interval -= 2; 159 160 for (info->ewma_log = 1; info->ewma_log < 32; info->ewma_log++) { 161 double w = 1.0 - 1.0 / (1 << info->ewma_log); 162 if (interval / (-log(w)) > ewma_log) 163 break; 164 } 165 info->ewma_log--; 166 167 if (info->ewma_log == 0 || info->ewma_log >= 31) 168 xtables_error(PARAMETER_PROBLEM, 169 "RATEEST: ewmalog value is out of range"); 170} 171 172static void 173__RATEEST_print(const struct xt_entry_target *target, const char *prefix) 174{ 175 const struct xt_rateest_target_info *info = (const void *)target->data; 176 unsigned int local_interval; 177 unsigned int local_ewma_log; 178 179 local_interval = (TIME_UNITS_PER_SEC << (info->interval + 2)) / 4; 180 local_ewma_log = local_interval * (1 << (info->ewma_log)); 181 182 printf(" %sname %s", prefix, info->name); 183 printf(" %sinterval", prefix); 184 RATEEST_print_time(local_interval); 185 printf(" %sewmalog", prefix); 186 RATEEST_print_time(local_ewma_log); 187} 188 189static void 190RATEEST_print(const void *ip, const struct xt_entry_target *target, 191 int numeric) 192{ 193 __RATEEST_print(target, ""); 194} 195 196static void 197RATEEST_save(const void *ip, const struct xt_entry_target *target) 198{ 199 __RATEEST_print(target, "--rateest-"); 200} 201 202static struct xtables_target rateest_tg_reg = { 203 .family = NFPROTO_UNSPEC, 204 .name = "RATEEST", 205 .version = XTABLES_VERSION, 206 .size = XT_ALIGN(sizeof(struct xt_rateest_target_info)), 207 .userspacesize = XT_ALIGN(sizeof(struct xt_rateest_target_info)), 208 .help = RATEEST_help, 209 .init = RATEEST_init, 210 .parse = RATEEST_parse, 211 .final_check = RATEEST_final_check, 212 .print = RATEEST_print, 213 .save = RATEEST_save, 214 .extra_opts = RATEEST_opts, 215}; 216 217void _init(void) 218{ 219 xtables_register_target(&rateest_tg_reg); 220} 221