8 #include <linux/netfilter/xt_rateest.h>
10 /* Ugly hack to pass info to final_check function. We should fix the API */
11 static struct xt_rateest_match_info *rateest_info;
13 static void rateest_help(void)
16 "rateest match options:\n"
17 " --rateest1 name Rate estimator name\n"
18 " --rateest2 name Rate estimator name\n"
19 " --rateest-delta Compare difference(s) to given rate(s)\n"
20 " --rateest-bps1 [bps] Compare bps\n"
21 " --rateest-pps1 [pps] Compare pps\n"
22 " --rateest-bps2 [bps] Compare bps\n"
23 " --rateest-pps2 [pps] Compare pps\n"
24 " [!] --rateest-lt Match if rate is less than given rate/estimator\n"
25 " [!] --rateest-gt Match if rate is greater than given rate/estimator\n"
26 " [!] --rateest-eq Match if rate is equal to given rate/estimator\n");
29 enum rateest_options {
42 static const struct option rateest_opts[] = {
43 { "rateest1", 1, NULL, OPT_RATEEST1 },
44 { "rateest", 1, NULL, OPT_RATEEST1 }, /* alias for absolute mode */
45 { "rateest2", 1, NULL, OPT_RATEEST2 },
46 { "rateest-bps1", 0, NULL, OPT_RATEEST_BPS1 },
47 { "rateest-pps1", 0, NULL, OPT_RATEEST_PPS1 },
48 { "rateest-bps2", 0, NULL, OPT_RATEEST_BPS2 },
49 { "rateest-pps2", 0, NULL, OPT_RATEEST_PPS2 },
50 { "rateest-bps", 0, NULL, OPT_RATEEST_BPS2 }, /* alias for absolute mode */
51 { "rateest-pps", 0, NULL, OPT_RATEEST_PPS2 }, /* alias for absolute mode */
52 { "rateest-delta", 0, NULL, OPT_RATEEST_DELTA },
53 { "rateest-lt", 0, NULL, OPT_RATEEST_LT },
54 { "rateest-gt", 0, NULL, OPT_RATEEST_GT },
55 { "rateest-eq", 0, NULL, OPT_RATEEST_EQ },
59 /* Copied from iproute. See http://physics.nist.gov/cuu/Units/binary.html */
60 static const struct rate_suffix {
67 { "mibit", 1024.*1024. },
69 { "gibit", 1024.*1024.*1024. },
70 { "gbit", 1000000000. },
71 { "tibit", 1024.*1024.*1024.*1024. },
72 { "tbit", 1000000000000. },
74 { "KiBps", 8.*1024. },
76 { "MiBps", 8.*1024*1024. },
78 { "GiBps", 8.*1024.*1024.*1024. },
79 { "GBps", 8000000000. },
80 { "TiBps", 8.*1024.*1024.*1024.*1024. },
81 { "TBps", 8000000000000. },
86 rateest_get_rate(u_int32_t *rate, const char *str)
89 double bps = strtod(str, &p);
90 const struct rate_suffix *s;
96 *rate = bps / 8.; /* assume bytes/sec */
100 for (s = suffixes; s->name; ++s) {
101 if (strcasecmp(s->name, p) == 0) {
102 *rate = (bps * s->scale) / 8.;
111 rateest_parse(int c, char **argv, int invert, unsigned int *flags,
112 const void *entry, struct xt_entry_match **match)
114 struct xt_rateest_match_info *info = (void *)(*match)->data;
120 check_inverse(optarg, &invert, &optind, 0);
122 exit_error(PARAMETER_PROBLEM,
123 "rateest: rateest can't be inverted");
125 if (*flags & (1 << c))
126 exit_error(PARAMETER_PROBLEM,
127 "rateest: can't specify --rateest1 twice");
130 strncpy(info->name1, optarg, sizeof(info->name1) - 1);
134 check_inverse(optarg, &invert, &optind, 0);
136 exit_error(PARAMETER_PROBLEM,
137 "rateest: rateest can't be inverted");
139 if (*flags & (1 << c))
140 exit_error(PARAMETER_PROBLEM,
141 "rateest: can't specify --rateest2 twice");
144 strncpy(info->name2, optarg, sizeof(info->name2) - 1);
145 info->flags |= XT_RATEEST_MATCH_REL;
148 case OPT_RATEEST_BPS1:
149 check_inverse(optarg, &invert, &optind, 0);
151 exit_error(PARAMETER_PROBLEM,
152 "rateest: rateest-bps can't be inverted");
154 if (*flags & (1 << c))
155 exit_error(PARAMETER_PROBLEM,
156 "rateest: can't specify --rateest-bps1 twice");
159 info->flags |= XT_RATEEST_MATCH_BPS;
161 /* The rate is optional and only required in absolute mode */
162 if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
165 if (rateest_get_rate(&info->bps1, argv[optind]) < 0)
166 exit_error(PARAMETER_PROBLEM,
167 "rateest: could not parse rate `%s'",
172 case OPT_RATEEST_PPS1:
173 check_inverse(optarg, &invert, &optind, 0);
175 exit_error(PARAMETER_PROBLEM,
176 "rateest: rateest-pps can't be inverted");
178 if (*flags & (1 << c))
179 exit_error(PARAMETER_PROBLEM,
180 "rateest: can't specify --rateest-pps1 twice");
183 info->flags |= XT_RATEEST_MATCH_PPS;
185 /* The rate is optional and only required in absolute mode */
186 if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
189 if (string_to_number(argv[optind], 0, 0, &info->pps1) < 0)
190 exit_error(PARAMETER_PROBLEM,
191 "rateest: could not parse pps `%s'",
196 case OPT_RATEEST_BPS2:
197 check_inverse(optarg, &invert, &optind, 0);
199 exit_error(PARAMETER_PROBLEM,
200 "rateest: rateest-bps can't be inverted");
202 if (*flags & (1 << c))
203 exit_error(PARAMETER_PROBLEM,
204 "rateest: can't specify --rateest-bps2 twice");
207 info->flags |= XT_RATEEST_MATCH_BPS;
209 /* The rate is optional and only required in absolute mode */
210 if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
213 if (rateest_get_rate(&info->bps2, argv[optind]) < 0)
214 exit_error(PARAMETER_PROBLEM,
215 "rateest: could not parse rate `%s'",
220 case OPT_RATEEST_PPS2:
221 check_inverse(optarg, &invert, &optind, 0);
223 exit_error(PARAMETER_PROBLEM,
224 "rateest: rateest-pps can't be inverted");
226 if (*flags & (1 << c))
227 exit_error(PARAMETER_PROBLEM,
228 "rateest: can't specify --rateest-pps2 twice");
231 info->flags |= XT_RATEEST_MATCH_PPS;
233 /* The rate is optional and only required in absolute mode */
234 if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
237 if (string_to_number(argv[optind], 0, 0, &info->pps2) < 0)
238 exit_error(PARAMETER_PROBLEM,
239 "rateest: could not parse pps `%s'",
244 case OPT_RATEEST_DELTA:
245 check_inverse(optarg, &invert, &optind, 0);
247 exit_error(PARAMETER_PROBLEM,
248 "rateest: rateest-delta can't be inverted");
250 if (*flags & (1 << c))
251 exit_error(PARAMETER_PROBLEM,
252 "rateest: can't specify --rateest-delta twice");
255 info->flags |= XT_RATEEST_MATCH_DELTA;
259 check_inverse(argv[optind-1], &invert, &optind, 0);
261 if (*flags & (1 << c))
262 exit_error(PARAMETER_PROBLEM,
263 "rateest: can't specify lt/gt/eq twice");
266 info->mode = XT_RATEEST_MATCH_EQ;
268 info->flags |= XT_RATEEST_MATCH_INVERT;
272 check_inverse(argv[optind-1], &invert, &optind, 0);
274 if (*flags & (1 << c))
275 exit_error(PARAMETER_PROBLEM,
276 "rateest: can't specify lt/gt/eq twice");
279 info->mode = XT_RATEEST_MATCH_LT;
281 info->flags |= XT_RATEEST_MATCH_INVERT;
285 check_inverse(argv[optind-1], &invert, &optind, 0);
287 if (*flags & (1 << c))
288 exit_error(PARAMETER_PROBLEM,
289 "rateest: can't specify lt/gt/eq twice");
292 info->mode = XT_RATEEST_MATCH_GT;
294 info->flags |= XT_RATEEST_MATCH_INVERT;
305 rateest_final_check(unsigned int flags)
307 struct xt_rateest_match_info *info = rateest_info;
309 if (!(info->flags & XT_RATEEST_MATCH_REL))
310 info->flags |= XT_RATEEST_MATCH_ABS;
314 rateest_print_rate(u_int32_t rate, int numeric)
316 double tmp = (double)rate*8;
320 else if (tmp >= 1000.0*1000000.0)
321 printf("%.0fMbit ", tmp/1000000.0);
322 else if (tmp >= 1000.0 * 1000.0)
323 printf("%.0fKbit ", tmp/1000.0);
325 printf("%.0fbit ", tmp);
329 rateest_print_mode(struct xt_rateest_match_info *info, const char *prefix)
331 if (info->flags & XT_RATEEST_MATCH_INVERT)
334 switch (info->mode) {
335 case XT_RATEEST_MATCH_EQ:
336 printf("%seq ", prefix);
338 case XT_RATEEST_MATCH_LT:
339 printf("%slt ", prefix);
341 case XT_RATEEST_MATCH_GT:
342 printf("%sgt ", prefix);
350 rateest_print(const void *ip, const struct xt_entry_match *match, int numeric)
352 struct xt_rateest_match_info *info = (void *)match->data;
354 printf("rateest match ");
356 printf("%s ", info->name1);
357 if (info->flags & XT_RATEEST_MATCH_DELTA)
360 if (info->flags & XT_RATEEST_MATCH_BPS) {
362 if (info->flags & XT_RATEEST_MATCH_DELTA)
363 rateest_print_rate(info->bps1, numeric);
364 if (info->flags & XT_RATEEST_MATCH_ABS) {
365 rateest_print_mode(info, "");
366 rateest_print_rate(info->bps2, numeric);
369 if (info->flags & XT_RATEEST_MATCH_PPS) {
371 if (info->flags & XT_RATEEST_MATCH_DELTA)
372 printf("%u ", info->pps1);
373 if (info->flags & XT_RATEEST_MATCH_ABS) {
374 rateest_print_mode(info, "");
375 printf("%u ", info->pps2);
379 if (info->flags & XT_RATEEST_MATCH_REL) {
380 rateest_print_mode(info, "");
382 printf("%s ", info->name2);
383 if (info->flags & XT_RATEEST_MATCH_DELTA)
386 if (info->flags & XT_RATEEST_MATCH_BPS) {
388 if (info->flags & XT_RATEEST_MATCH_DELTA)
389 rateest_print_rate(info->bps2, numeric);
391 if (info->flags & XT_RATEEST_MATCH_PPS) {
393 if (info->flags & XT_RATEEST_MATCH_DELTA)
394 printf("%u ", info->pps2);
400 rateest_save(const void *ip, const struct xt_entry_match *match)
402 struct xt_rateest_match_info *info = (void *)match->data;
404 if (info->flags & XT_RATEEST_MATCH_REL) {
405 printf("--rateest1 %s ", info->name1);
406 if (info->flags & XT_RATEEST_MATCH_BPS)
407 printf("--rateest-bps ");
408 if (info->flags & XT_RATEEST_MATCH_PPS)
409 printf("--rateest-pps ");
410 rateest_print_mode(info, "--rateest-");
411 printf("--rateest2 %s ", info->name2);
413 printf("--rateest %s ", info->name1);
414 if (info->flags & XT_RATEEST_MATCH_BPS) {
415 printf("--rateest-bps ");
416 rateest_print_mode(info, "--rateest-");
417 rateest_print_rate(info->bps2, 0);
419 if (info->flags & XT_RATEEST_MATCH_PPS) {
420 printf("--rateest-pps ");
421 rateest_print_mode(info, "--rateest-");
422 printf("%u ", info->pps2);
427 static struct xtables_match rateest_mt_reg = {
430 .version = XTABLES_VERSION,
431 .size = XT_ALIGN(sizeof(struct xt_rateest_match_info)),
432 .userspacesize = XT_ALIGN(offsetof(struct xt_rateest_match_info, est1)),
433 .help = rateest_help,
434 .parse = rateest_parse,
435 .final_check = rateest_final_check,
436 .print = rateest_print,
437 .save = rateest_save,
438 .extra_opts = rateest_opts,
443 xtables_register_match(&rateest_mt_reg);