libxt_RATEEST.c revision 68818f746bf9c68de04a75fbe756bf2c73e0fb32
1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <math.h> 5 6#include <xtables.h> 7#include <linux/netfilter/x_tables.h> 8#include <linux/netfilter/xt_RATEEST.h> 9 10/* hack to pass raw values to final_check */ 11static unsigned int interval; 12static unsigned int ewma_log; 13 14static void 15RATEEST_help(void) 16{ 17 printf( 18"RATEEST target options:\n" 19" --rateest-name name Rate estimator name\n" 20" --rateest-interval sec Rate measurement interval in seconds\n" 21" --rateest-ewmalog value Rate measurement averaging time constant\n"); 22} 23 24enum { 25 O_NAME = 0, 26 O_INTERVAL, 27 O_EWMALOG, 28}; 29 30#define s struct xt_rateest_target_info 31static const struct xt_option_entry RATEEST_opts[] = { 32 {.name = "rateest-name", .id = O_NAME, .type = XTTYPE_STRING, 33 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name)}, 34 {.name = "rateest-interval", .id = O_INTERVAL, .type = XTTYPE_STRING, 35 .flags = XTOPT_MAND}, 36 {.name = "rateest-ewmalog", .id = O_EWMALOG, .type = XTTYPE_STRING, 37 .flags = XTOPT_MAND}, 38 XTOPT_TABLEEND, 39}; 40#undef s 41 42/* Copied from iproute */ 43#define TIME_UNITS_PER_SEC 1000000 44 45static int 46RATEEST_get_time(unsigned int *time, const char *str) 47{ 48 double t; 49 char *p; 50 51 t = strtod(str, &p); 52 if (p == str) 53 return -1; 54 55 if (*p) { 56 if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 || 57 strcasecmp(p, "secs")==0) 58 t *= TIME_UNITS_PER_SEC; 59 else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 || 60 strcasecmp(p, "msecs") == 0) 61 t *= TIME_UNITS_PER_SEC/1000; 62 else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 || 63 strcasecmp(p, "usecs") == 0) 64 t *= TIME_UNITS_PER_SEC/1000000; 65 else 66 return -1; 67 } 68 69 *time = t; 70 return 0; 71} 72 73static void 74RATEEST_print_time(unsigned int time) 75{ 76 double tmp = time; 77 78 if (tmp >= TIME_UNITS_PER_SEC) 79 printf(" %.1fs", tmp / TIME_UNITS_PER_SEC); 80 else if (tmp >= TIME_UNITS_PER_SEC/1000) 81 printf(" %.1fms", tmp / (TIME_UNITS_PER_SEC / 1000)); 82 else 83 printf(" %uus", time); 84} 85 86static void RATEEST_parse(struct xt_option_call *cb) 87{ 88 xtables_option_parse(cb); 89 switch (cb->entry->id) { 90 case O_INTERVAL: 91 if (RATEEST_get_time(&interval, cb->arg) < 0) 92 xtables_error(PARAMETER_PROBLEM, 93 "RATEEST: bad interval value \"%s\"", 94 cb->arg); 95 break; 96 case O_EWMALOG: 97 if (RATEEST_get_time(&ewma_log, cb->arg) < 0) 98 xtables_error(PARAMETER_PROBLEM, 99 "RATEEST: bad ewmalog value \"%s\"", 100 cb->arg); 101 break; 102 } 103} 104 105static void RATEEST_final_check(struct xt_fcheck_call *cb) 106{ 107 struct xt_rateest_target_info *info = cb->data; 108 109 for (info->interval = 0; info->interval <= 5; info->interval++) { 110 if (interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4)) 111 break; 112 } 113 114 if (info->interval > 5) 115 xtables_error(PARAMETER_PROBLEM, 116 "RATEEST: interval value is too large"); 117 info->interval -= 2; 118 119 for (info->ewma_log = 1; info->ewma_log < 32; info->ewma_log++) { 120 double w = 1.0 - 1.0 / (1 << info->ewma_log); 121 if (interval / (-log(w)) > ewma_log) 122 break; 123 } 124 info->ewma_log--; 125 126 if (info->ewma_log == 0 || info->ewma_log >= 31) 127 xtables_error(PARAMETER_PROBLEM, 128 "RATEEST: ewmalog value is out of range"); 129} 130 131static void 132__RATEEST_print(const struct xt_entry_target *target, const char *prefix) 133{ 134 const struct xt_rateest_target_info *info = (const void *)target->data; 135 unsigned int local_interval; 136 unsigned int local_ewma_log; 137 138 local_interval = (TIME_UNITS_PER_SEC << (info->interval + 2)) / 4; 139 local_ewma_log = local_interval * (1 << (info->ewma_log)); 140 141 printf(" %sname %s", prefix, info->name); 142 printf(" %sinterval", prefix); 143 RATEEST_print_time(local_interval); 144 printf(" %sewmalog", prefix); 145 RATEEST_print_time(local_ewma_log); 146} 147 148static void 149RATEEST_print(const void *ip, const struct xt_entry_target *target, 150 int numeric) 151{ 152 __RATEEST_print(target, ""); 153} 154 155static void 156RATEEST_save(const void *ip, const struct xt_entry_target *target) 157{ 158 __RATEEST_print(target, "--rateest-"); 159} 160 161static struct xtables_target rateest_tg_reg = { 162 .family = NFPROTO_UNSPEC, 163 .name = "RATEEST", 164 .version = XTABLES_VERSION, 165 .size = XT_ALIGN(sizeof(struct xt_rateest_target_info)), 166 .userspacesize = XT_ALIGN(sizeof(struct xt_rateest_target_info)), 167 .help = RATEEST_help, 168 .x6_parse = RATEEST_parse, 169 .x6_fcheck = RATEEST_final_check, 170 .print = RATEEST_print, 171 .save = RATEEST_save, 172 .x6_options = RATEEST_opts, 173}; 174 175void _init(void) 176{ 177 xtables_register_target(&rateest_tg_reg); 178} 179