extern struct error_record *time_parse(const struct location *loc,
const char *c, uint64_t *res);
-extern struct error_record *rate_parse(const struct location *loc,
- const char *str, uint64_t *rate,
- uint64_t *unit);
-
struct limit_rate {
uint64_t rate, unit;
};
PARSER_SC_META,
PARSER_SC_POLICY,
PARSER_SC_QUOTA,
+ PARSER_SC_RATE,
PARSER_SC_SCTP,
PARSER_SC_SECMARK,
PARSER_SC_TCP,
return dtype;
}
-static struct error_record *time_unit_parse(const struct location *loc,
- const char *str, uint64_t *unit)
-{
- if (strcmp(str, "second") == 0)
- *unit = 1ULL;
- else if (strcmp(str, "minute") == 0)
- *unit = 1ULL * 60;
- else if (strcmp(str, "hour") == 0)
- *unit = 1ULL * 60 * 60;
- else if (strcmp(str, "day") == 0)
- *unit = 1ULL * 60 * 60 * 24;
- else if (strcmp(str, "week") == 0)
- *unit = 1ULL * 60 * 60 * 24 * 7;
- else
- return error(loc, "Wrong time format, expecting second, minute, hour, day or week");
-
- return NULL;
-}
-
-static struct error_record *data_unit_parse(const struct location *loc,
- const char *str, uint64_t *rate)
-{
- if (strcmp(str, "bytes") == 0)
- *rate = 1ULL;
- else if (strcmp(str, "kbytes") == 0)
- *rate = 1024;
- else if (strcmp(str, "mbytes") == 0)
- *rate = 1024 * 1024;
- else
- return error(loc, "Wrong unit format, expecting bytes, kbytes or mbytes");
-
- return NULL;
-}
-
-struct error_record *rate_parse(const struct location *loc, const char *str,
- uint64_t *rate, uint64_t *unit)
-{
- const char *slash, *rate_str;
- struct error_record *erec;
-
- slash = strchr(str, '/');
- if (!slash)
- return error(loc, "wrong rate format, expecting {bytes,kbytes,mbytes}/{second,minute,hour,day,week}");
-
- rate_str = strndup(str, slash - str);
- if (!rate_str)
- memory_allocation_error();
-
- erec = data_unit_parse(loc, rate_str, rate);
- free_const(rate_str);
-
- if (erec != NULL)
- return erec;
-
- erec = time_unit_parse(loc, slash + 1, unit);
- if (erec != NULL)
- return erec;
-
- return NULL;
-}
-
static const struct symbol_table boolean_tbl = {
.base = BASE_DECIMAL,
.symbols = {
close_scope_policy : { scanner_pop_start_cond(nft->scanner, PARSER_SC_POLICY); };
close_scope_quota : { scanner_pop_start_cond(nft->scanner, PARSER_SC_QUOTA); };
close_scope_queue : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_QUEUE); };
+close_scope_rate : { scanner_pop_start_cond(nft->scanner, PARSER_SC_RATE); };
close_scope_reject : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_REJECT); };
close_scope_reset : { scanner_pop_start_cond(nft->scanner, PARSER_SC_CMD_RESET); };
close_scope_rt : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_RT); };
}
;
-limit_stmt : limit_stmt_alloc limit_args
+limit_stmt : limit_stmt_alloc limit_args close_scope_rate
;
limit_args : limit_mode limit_rate_pkts limit_burst_pkts
| BURST NUM bytes_unit { $$ = $2 * $3; }
;
-limit_rate_bytes : NUM STRING
- {
- struct error_record *erec;
- uint64_t rate, unit;
-
- erec = rate_parse(&@$, $2, &rate, &unit);
- free_const($2);
- if (erec != NULL) {
- erec_queue(erec, state->msgs);
- YYERROR;
- }
- $$.rate = rate * $1;
- $$.unit = unit;
- }
- | NUM bytes_unit SLASH time_unit
+limit_rate_bytes : NUM bytes_unit SLASH time_unit
{
$$.rate = $1 * $2;
$$.unit = $4;
}
;
-limit_config : RATE limit_mode limit_rate_pkts limit_burst_pkts
+limit_config : RATE limit_mode limit_rate_pkts limit_burst_pkts close_scope_rate
{
struct limit *limit;
limit->type = NFT_LIMIT_PKTS;
limit->flags = $2;
}
- | RATE limit_mode limit_rate_bytes limit_burst_bytes
+ | RATE limit_mode limit_rate_bytes limit_burst_bytes close_scope_rate
{
struct limit *limit;
%s SCANSTATE_META
%s SCANSTATE_POLICY
%s SCANSTATE_QUOTA
+%x SCANSTATE_RATE
%s SCANSTATE_SCTP
%s SCANSTATE_SECMARK
%s SCANSTATE_TCP
"ge" { return GTE; }
">" { return GT; }
"gt" { return GT; }
-"," { return COMMA; }
+<*>"," { return COMMA; }
"." { return DOT; }
":" { return COLON; }
-";" { return SEMICOLON; }
+<*>";" { return SEMICOLON; }
"{" { return '{'; }
-"}" { return '}'; }
+<*>"}" { return '}'; }
"[" { return '['; }
"]" { return ']'; }
"(" { return '('; }
"or" { return '|'; }
"!" { return NOT; }
"not" { return NOT; }
-"/" { return SLASH; }
+<*>"/" { return SLASH; }
"-" { return DASH; }
"*" { return ASTERISK; }
"@" { scanner_push_start_cond(yyscanner, SCANSTATE_AT); return AT; }
"hooks" { return HOOKS; }
}
-"counter" { scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; }
+<*>"counter" { scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; }
<SCANSTATE_COUNTER,SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_STMT_SYNPROXY,SCANSTATE_EXPR_OSF,SCANSTATE_TUNNEL>"name" { return NAME; }
-<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT>"packets" { return PACKETS; }
-<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA>"bytes" { return BYTES; }
-<SCANSTATE_LIMIT,SCANSTATE_QUOTA>"kbytes" { return KBYTES; }
-<SCANSTATE_LIMIT,SCANSTATE_QUOTA>"mbytes" { return MBYTES; }
+<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_RATE>"packets" { return PACKETS; }
+<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_RATE>"bytes" { return BYTES; }
+<SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_RATE>"kbytes" { return KBYTES; }
+<SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_RATE>"mbytes" { return MBYTES; }
"last" { scanner_push_start_cond(yyscanner, SCANSTATE_LAST); return LAST; }
<SCANSTATE_LAST>{
"rules" { return RULES; }
}
-"log" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_LOG); return LOG; }
+<*>"log" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_LOG); return LOG; }
<SCANSTATE_STMT_LOG,SCANSTATE_STMT_NAT,SCANSTATE_IP,SCANSTATE_IP6>"prefix" { return PREFIX; }
<SCANSTATE_STMT_LOG>{
"snaplen" { return SNAPLEN; }
"fanout" { return FANOUT;}
}
"limit" { scanner_push_start_cond(yyscanner, SCANSTATE_LIMIT); return LIMIT; }
-<SCANSTATE_LIMIT>{
- "rate" { return RATE; }
+<SCANSTATE_LIMIT,SCANSTATE_RATE>{
+ "rate" { scanner_push_start_cond(yyscanner, SCANSTATE_RATE); return RATE; }
"burst" { return BURST; }
/* time_unit */
"minute" { return MINUTE; }
"week" { return WEEK; }
}
-<SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA>"over" { return OVER; }
+<SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_RATE>"over" { return OVER; }
"quota" { scanner_push_start_cond(yyscanner, SCANSTATE_QUOTA); return QUOTA; }
-<SCANSTATE_QUOTA>{
+<SCANSTATE_QUOTA,SCANSTATE_RATE>{
"until" { return UNTIL; }
}
<SCANSTATE_QUOTA,SCANSTATE_LAST>"used" { return USED; }
-"hour" { return HOUR; }
-"day" { return DAY; }
+<*>"hour" { return HOUR; }
+<*>"day" { return DAY; }
"reject" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_REJECT); return _REJECT; }
<SCANSTATE_STMT_REJECT>{
return STRING;
}
-{hexstring} {
+<*>{hexstring} {
errno = 0;
yylval->val = strtoull(yytext, NULL, 16);
if (errno != 0) {
return NUM;
}
-{decstring} {
+<*>{decstring} {
int base = yytext[0] == '0' ? 8 : 10;
char *end;
return STRING;
}
-{newline_crlf} { return CRLF; }
+<*>{newline_crlf} { return CRLF; }
-\\{newline} {
+<*>\\{newline} {
reset_pos(yyget_extra(yyscanner), yylloc);
}
-{newline} {
+<*>{newline} {
reset_pos(yyget_extra(yyscanner), yylloc);
return NEWLINE;
}
-{tab}+
-{space}+
-{comment_line} {
+<*>{tab}+
+<*>{space}+
+<*>{comment_line} {
reset_pos(yyget_extra(yyscanner), yylloc);
}
-{comment}
+<*>{comment}
-<<EOF>> {
+<*><<EOF>> {
update_pos(yyget_extra(yyscanner), yylloc, 1);
scanner_pop_buffer(yyscanner);
if (YY_CURRENT_BUFFER == NULL)
return TOKEN_EOF;
}
-. { return JUNK; }
+<*>. { return JUNK; }
%%
limit rate over 1025 bytes/second burst 512 bytes;ok
limit rate over 1025 kbytes/second burst 1023 kbytes;ok
limit rate over 1025 mbytes/second burst 1025 kbytes;ok
+
+limit rate over 1025bytes/second burst 512bytes;ok;limit rate over 1025 bytes/second burst 512 bytes
+limit rate over 1025bytes /second burst 512bytes;ok;limit rate over 1025 bytes/second burst 512 bytes
+limit rate over 1025bytes/ second burst 512bytes;ok;limit rate over 1025 bytes/second burst 512 bytes
+limit rate over 1025bytes / second burst 512bytes;ok;limit rate over 1025 bytes/second burst 512 bytes
+limit rate over 1025 bytes / second burst 512bytes;ok;limit rate over 1025 bytes/second burst 512 bytes
}
}
]
+
+# limit rate over 1025bytes/second burst 512bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate over 1025bytes /second burst 512bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate over 1025bytes/ second burst 512bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate over 1025bytes / second burst 512bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
+
+# limit rate over 1025 bytes / second burst 512bytes
+[
+ {
+ "limit": {
+ "burst": 512,
+ "burst_unit": "bytes",
+ "inv": true,
+ "per": "second",
+ "rate": 1025,
+ "rate_unit": "bytes"
+ }
+ }
+]
# limit rate over 1025 mbytes/second burst 1025 kbytes
ip test-ip4 output
[ limit rate 1074790400/second burst 1049600 type bytes flags 0x1 ]
+
+# limit rate over 1025bytes/second burst 512bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x1 ]
+
+# limit rate over 1025bytes /second burst 512bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x1 ]
+
+# limit rate over 1025bytes/ second burst 512bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x1 ]
+
+# limit rate over 1025bytes / second burst 512bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x1 ]
+
+# limit rate over 1025 bytes / second burst 512bytes
+ip test-ip4 output
+ [ limit rate 1025/second burst 512 type bytes flags 0x1 ]