diff --git a/include/datatype.h b/include/datatype.h index 63dba330..4c5d6ff8 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -309,10 +309,6 @@ extern void time_print(uint64_t msec, struct output_ctx *octx); 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; }; diff --git a/include/parser.h b/include/parser.h index 8cfd22e9..889302ba 100644 --- a/include/parser.h +++ b/include/parser.h @@ -47,6 +47,7 @@ enum startcond_type { PARSER_SC_META, PARSER_SC_POLICY, PARSER_SC_QUOTA, + PARSER_SC_RATE, PARSER_SC_SCTP, PARSER_SC_SECMARK, PARSER_SC_TCP, diff --git a/src/datatype.c b/src/datatype.c index 1950a2f3..18973851 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -1488,67 +1488,6 @@ const struct datatype *set_datatype_alloc(const struct datatype *orig_dtype, 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 = { diff --git a/src/parser_bison.y b/src/parser_bison.y index 9639352a..18174859 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1113,6 +1113,7 @@ close_scope_osf : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_OSF); } 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); }; @@ -3557,7 +3558,7 @@ limit_stmt_alloc : LIMIT RATE } ; -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 @@ -3652,21 +3653,7 @@ limit_burst_bytes : /* empty */ { $$ = 0; } | 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; @@ -4897,7 +4884,7 @@ ct_obj_alloc : /* empty */ } ; -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; @@ -4908,7 +4895,7 @@ limit_config : RATE limit_mode limit_rate_pkts limit_burst_pkts 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; diff --git a/src/scanner.l b/src/scanner.l index 4cbc8a44..9d8fade8 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -219,6 +219,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) %s SCANSTATE_META %s SCANSTATE_POLICY %s SCANSTATE_QUOTA +%x SCANSTATE_RATE %s SCANSTATE_SCTP %s SCANSTATE_SECMARK %s SCANSTATE_TCP @@ -275,12 +276,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "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 '('; } @@ -297,7 +298,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "or" { return '|'; } "!" { return NOT; } "not" { return NOT; } -"/" { return SLASH; } +<*>"/" { return SLASH; } "-" { return DASH; } "*" { return ASTERISK; } "@" { scanner_push_start_cond(yyscanner, SCANSTATE_AT); return AT; } @@ -410,12 +411,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "hooks" { return HOOKS; } } -"counter" { scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; } +<*>"counter" { scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; } "name" { return NAME; } -"packets" { return PACKETS; } -"bytes" { return BYTES; } -"kbytes" { return KBYTES; } -"mbytes" { return MBYTES; } +"packets" { return PACKETS; } +"bytes" { return BYTES; } +"kbytes" { return KBYTES; } +"mbytes" { return MBYTES; } "last" { scanner_push_start_cond(yyscanner, SCANSTATE_LAST); return LAST; } { @@ -428,7 +429,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "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; } "prefix" { return PREFIX; } { "snaplen" { return SNAPLEN; } @@ -453,8 +454,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "fanout" { return FANOUT;} } "limit" { scanner_push_start_cond(yyscanner, SCANSTATE_LIMIT); return LIMIT; } -{ - "rate" { return RATE; } +{ + "rate" { scanner_push_start_cond(yyscanner, SCANSTATE_RATE); return RATE; } "burst" { return BURST; } /* time_unit */ @@ -462,17 +463,17 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "minute" { return MINUTE; } "week" { return WEEK; } } -"over" { return OVER; } +"over" { return OVER; } "quota" { scanner_push_start_cond(yyscanner, SCANSTATE_QUOTA); return QUOTA; } -{ +{ "until" { return UNTIL; } } "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; } { @@ -901,7 +902,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) return STRING; } -{hexstring} { +<*>{hexstring} { errno = 0; yylval->val = strtoull(yytext, NULL, 16); if (errno != 0) { @@ -911,7 +912,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) return NUM; } -{decstring} { +<*>{decstring} { int base = yytext[0] == '0' ? 8 : 10; char *end; @@ -945,32 +946,32 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) 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} -<> { +<*><> { update_pos(yyget_extra(yyscanner), yylloc, 1); scanner_pop_buffer(yyscanner); if (YY_CURRENT_BUFFER == NULL) return TOKEN_EOF; } -. { return JUNK; } +<*>. { return JUNK; } %% diff --git a/tests/py/any/limit.t b/tests/py/any/limit.t index 2a84e3f5..5c95ffa5 100644 --- a/tests/py/any/limit.t +++ b/tests/py/any/limit.t @@ -49,3 +49,9 @@ limit rate over 10230 mbytes/second;ok 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 diff --git a/tests/py/any/limit.t.json b/tests/py/any/limit.t.json index 73160b27..49a48960 100644 --- a/tests/py/any/limit.t.json +++ b/tests/py/any/limit.t.json @@ -360,3 +360,73 @@ } } ] + +# 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" + } + } +] diff --git a/tests/py/any/limit.t.payload b/tests/py/any/limit.t.payload index dc6701b3..901275da 100644 --- a/tests/py/any/limit.t.payload +++ b/tests/py/any/limit.t.payload @@ -122,3 +122,23 @@ ip test-ip4 output # 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 ]