blob: 62bcb5e81292e440d8387ecaa4f4829168852b20 [file] [log] [blame]
Patrick McHardy25282582008-01-15 17:25:39 +00001#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
Patrick McHardy25282582008-01-15 17:25:39 +00004#include <math.h>
5
6#include <xtables.h>
7#include <linux/netfilter/x_tables.h>
8#include <linux/netfilter/xt_RATEEST.h>
9
Jan Engelhardt12bc22a2011-06-21 14:22:20 +020010struct rateest_tg_udata {
11 unsigned int interval;
12 unsigned int ewma_log;
13};
Patrick McHardy25282582008-01-15 17:25:39 +000014
15static void
16RATEEST_help(void)
17{
18 printf(
Jan Engelhardtbce1c212008-03-27 05:48:14 +010019"RATEEST target options:\n"
Patrick McHardy25282582008-01-15 17:25:39 +000020" --rateest-name name Rate estimator name\n"
21" --rateest-interval sec Rate measurement interval in seconds\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020022" --rateest-ewmalog value Rate measurement averaging time constant\n");
Patrick McHardy25282582008-01-15 17:25:39 +000023}
24
Jan Engelhardt68818f72011-06-21 14:20:15 +020025enum {
26 O_NAME = 0,
27 O_INTERVAL,
28 O_EWMALOG,
Patrick McHardy25282582008-01-15 17:25:39 +000029};
30
Jan Engelhardt68818f72011-06-21 14:20:15 +020031#define s struct xt_rateest_target_info
32static const struct xt_option_entry RATEEST_opts[] = {
33 {.name = "rateest-name", .id = O_NAME, .type = XTTYPE_STRING,
34 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name)},
35 {.name = "rateest-interval", .id = O_INTERVAL, .type = XTTYPE_STRING,
36 .flags = XTOPT_MAND},
37 {.name = "rateest-ewmalog", .id = O_EWMALOG, .type = XTTYPE_STRING,
38 .flags = XTOPT_MAND},
39 XTOPT_TABLEEND,
Patrick McHardy25282582008-01-15 17:25:39 +000040};
Jan Engelhardt68818f72011-06-21 14:20:15 +020041#undef s
Patrick McHardy25282582008-01-15 17:25:39 +000042
43/* Copied from iproute */
44#define TIME_UNITS_PER_SEC 1000000
45
46static int
47RATEEST_get_time(unsigned int *time, const char *str)
48{
49 double t;
50 char *p;
51
52 t = strtod(str, &p);
53 if (p == str)
54 return -1;
55
56 if (*p) {
57 if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
58 strcasecmp(p, "secs")==0)
59 t *= TIME_UNITS_PER_SEC;
60 else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
61 strcasecmp(p, "msecs") == 0)
62 t *= TIME_UNITS_PER_SEC/1000;
63 else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 ||
64 strcasecmp(p, "usecs") == 0)
65 t *= TIME_UNITS_PER_SEC/1000000;
66 else
67 return -1;
68 }
69
70 *time = t;
71 return 0;
72}
73
74static void
75RATEEST_print_time(unsigned int time)
76{
77 double tmp = time;
78
79 if (tmp >= TIME_UNITS_PER_SEC)
Jan Engelhardt73866352010-12-18 02:04:59 +010080 printf(" %.1fs", tmp / TIME_UNITS_PER_SEC);
Patrick McHardy25282582008-01-15 17:25:39 +000081 else if (tmp >= TIME_UNITS_PER_SEC/1000)
Jan Engelhardt73866352010-12-18 02:04:59 +010082 printf(" %.1fms", tmp / (TIME_UNITS_PER_SEC / 1000));
Patrick McHardy25282582008-01-15 17:25:39 +000083 else
Jan Engelhardt73866352010-12-18 02:04:59 +010084 printf(" %uus", time);
Patrick McHardy25282582008-01-15 17:25:39 +000085}
86
Jan Engelhardt68818f72011-06-21 14:20:15 +020087static void RATEEST_parse(struct xt_option_call *cb)
Patrick McHardy25282582008-01-15 17:25:39 +000088{
Jan Engelhardt12bc22a2011-06-21 14:22:20 +020089 struct rateest_tg_udata *udata = cb->udata;
90
Jan Engelhardt68818f72011-06-21 14:20:15 +020091 xtables_option_parse(cb);
92 switch (cb->entry->id) {
93 case O_INTERVAL:
Jan Engelhardt12bc22a2011-06-21 14:22:20 +020094 if (RATEEST_get_time(&udata->interval, cb->arg) < 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010095 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt68818f72011-06-21 14:20:15 +020096 "RATEEST: bad interval value \"%s\"",
97 cb->arg);
Patrick McHardy25282582008-01-15 17:25:39 +000098 break;
Jan Engelhardt68818f72011-06-21 14:20:15 +020099 case O_EWMALOG:
Jan Engelhardt12bc22a2011-06-21 14:22:20 +0200100 if (RATEEST_get_time(&udata->ewma_log, cb->arg) < 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100101 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt68818f72011-06-21 14:20:15 +0200102 "RATEEST: bad ewmalog value \"%s\"",
103 cb->arg);
Patrick McHardy25282582008-01-15 17:25:39 +0000104 break;
Patrick McHardy25282582008-01-15 17:25:39 +0000105 }
Patrick McHardy25282582008-01-15 17:25:39 +0000106}
107
Jan Engelhardt68818f72011-06-21 14:20:15 +0200108static void RATEEST_final_check(struct xt_fcheck_call *cb)
Patrick McHardy25282582008-01-15 17:25:39 +0000109{
Jan Engelhardt68818f72011-06-21 14:20:15 +0200110 struct xt_rateest_target_info *info = cb->data;
Jan Engelhardt12bc22a2011-06-21 14:22:20 +0200111 struct rateest_tg_udata *udata = cb->udata;
Patrick McHardy25282582008-01-15 17:25:39 +0000112
113 for (info->interval = 0; info->interval <= 5; info->interval++) {
Jan Engelhardt12bc22a2011-06-21 14:22:20 +0200114 if (udata->interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4))
Patrick McHardy25282582008-01-15 17:25:39 +0000115 break;
116 }
117
118 if (info->interval > 5)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100119 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy25282582008-01-15 17:25:39 +0000120 "RATEEST: interval value is too large");
121 info->interval -= 2;
122
123 for (info->ewma_log = 1; info->ewma_log < 32; info->ewma_log++) {
124 double w = 1.0 - 1.0 / (1 << info->ewma_log);
Jan Engelhardt12bc22a2011-06-21 14:22:20 +0200125 if (udata->interval / (-log(w)) > udata->ewma_log)
Patrick McHardy25282582008-01-15 17:25:39 +0000126 break;
127 }
128 info->ewma_log--;
129
130 if (info->ewma_log == 0 || info->ewma_log >= 31)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100131 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy25282582008-01-15 17:25:39 +0000132 "RATEEST: ewmalog value is out of range");
133}
134
135static void
136__RATEEST_print(const struct xt_entry_target *target, const char *prefix)
137{
Jan Engelhardt69f564e2009-05-26 13:14:06 +0200138 const struct xt_rateest_target_info *info = (const void *)target->data;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100139 unsigned int local_interval;
140 unsigned int local_ewma_log;
Patrick McHardy25282582008-01-15 17:25:39 +0000141
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100142 local_interval = (TIME_UNITS_PER_SEC << (info->interval + 2)) / 4;
143 local_ewma_log = local_interval * (1 << (info->ewma_log));
Patrick McHardy25282582008-01-15 17:25:39 +0000144
Jan Engelhardt73866352010-12-18 02:04:59 +0100145 printf(" %sname %s", prefix, info->name);
146 printf(" %sinterval", prefix);
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100147 RATEEST_print_time(local_interval);
Jan Engelhardt73866352010-12-18 02:04:59 +0100148 printf(" %sewmalog", prefix);
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100149 RATEEST_print_time(local_ewma_log);
Patrick McHardy25282582008-01-15 17:25:39 +0000150}
151
152static void
153RATEEST_print(const void *ip, const struct xt_entry_target *target,
154 int numeric)
155{
156 __RATEEST_print(target, "");
157}
158
159static void
160RATEEST_save(const void *ip, const struct xt_entry_target *target)
161{
162 __RATEEST_print(target, "--rateest-");
163}
164
Jan Engelhardt23545c22008-02-14 04:23:04 +0100165static struct xtables_target rateest_tg_reg = {
Jan Engelhardt42979362009-06-01 11:56:23 +0200166 .family = NFPROTO_UNSPEC,
Patrick McHardy25282582008-01-15 17:25:39 +0000167 .name = "RATEEST",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200168 .version = XTABLES_VERSION,
Patrick McHardy25282582008-01-15 17:25:39 +0000169 .size = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
170 .userspacesize = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
171 .help = RATEEST_help,
Jan Engelhardt68818f72011-06-21 14:20:15 +0200172 .x6_parse = RATEEST_parse,
173 .x6_fcheck = RATEEST_final_check,
Patrick McHardy25282582008-01-15 17:25:39 +0000174 .print = RATEEST_print,
175 .save = RATEEST_save,
Jan Engelhardt68818f72011-06-21 14:20:15 +0200176 .x6_options = RATEEST_opts,
Jan Engelhardt12bc22a2011-06-21 14:22:20 +0200177 .udata_size = sizeof(struct rateest_tg_udata),
Patrick McHardy25282582008-01-15 17:25:39 +0000178};
179
180void _init(void)
181{
Jan Engelhardt23545c22008-02-14 04:23:04 +0100182 xtables_register_target(&rateest_tg_reg);
Patrick McHardy25282582008-01-15 17:25:39 +0000183}