There already is a start condition for "monitor" keyword and also a DESTROY token. So just add the missing one and get rid of the intermediate string buffer. Keep checking the struct monitor::event value in eval phase just to be on the safe side. --- Changes since RFC: - Introduce and use enum cmd_monitor_event type in struct monitor. Signed-off-by: Phil Sutter --- include/rule.h | 20 ++++++++++++++------ src/evaluate.c | 22 ++-------------------- src/parser_bison.y | 10 +++++----- src/rule.c | 4 ++-- src/scanner.l | 2 ++ 5 files changed, 25 insertions(+), 33 deletions(-) diff --git a/include/rule.h b/include/rule.h index e8b3c0376e367..e67a01522d318 100644 --- a/include/rule.h +++ b/include/rule.h @@ -739,15 +739,23 @@ enum { CMD_MONITOR_OBJ_MAX }; +enum cmd_monitor_event { + CMD_MONITOR_EVENT_ANY, + CMD_MONITOR_EVENT_NEW, + CMD_MONITOR_EVENT_DEL +}; +#define CMD_MONITOR_EVENT_MAX (CMD_MONITOR_EVENT_DEL + 1) + struct monitor { - struct location location; - uint32_t format; - uint32_t flags; - uint32_t type; - const char *event; + struct location location; + uint32_t format; + uint32_t flags; + uint32_t type; + enum cmd_monitor_event event; }; -struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event); +struct monitor *monitor_alloc(uint32_t format, uint32_t type, + enum cmd_monitor_event event); void monitor_free(struct monitor *m); #define NFT_NLATTR_LOC_MAX 32 diff --git a/src/evaluate.c b/src/evaluate.c index 4be5299274d26..b42b5a6fba631 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -6452,13 +6452,6 @@ static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd) return 0; } -enum { - CMD_MONITOR_EVENT_ANY, - CMD_MONITOR_EVENT_NEW, - CMD_MONITOR_EVENT_DEL, - CMD_MONITOR_EVENT_MAX -}; - static uint32_t monitor_flags[CMD_MONITOR_EVENT_MAX][CMD_MONITOR_OBJ_MAX] = { [CMD_MONITOR_EVENT_ANY] = { [CMD_MONITOR_OBJ_ANY] = 0xffffffff, @@ -6528,20 +6521,9 @@ static uint32_t monitor_flags[CMD_MONITOR_EVENT_MAX][CMD_MONITOR_OBJ_MAX] = { static int cmd_evaluate_monitor(struct eval_ctx *ctx, struct cmd *cmd) { - uint32_t event; - - if (cmd->monitor->event == NULL) - event = CMD_MONITOR_EVENT_ANY; - else if (strcmp(cmd->monitor->event, "new") == 0) - event = CMD_MONITOR_EVENT_NEW; - else if (strcmp(cmd->monitor->event, "destroy") == 0) - event = CMD_MONITOR_EVENT_DEL; - else { - return monitor_error(ctx, cmd->monitor, "invalid event %s", - cmd->monitor->event); - } + uint32_t *monitor_event_flags = monitor_flags[cmd->monitor->event]; - cmd->monitor->flags = monitor_flags[event][cmd->monitor->type]; + cmd->monitor->flags = monitor_event_flags[cmd->monitor->type]; return 0; } diff --git a/src/parser_bison.y b/src/parser_bison.y index 3ceef79469d7d..96d0e151b1586 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -353,6 +353,7 @@ int nft_lex(void *, void *, void *); %token DESCRIBE "describe" %token IMPORT "import" %token EXPORT "export" +%token NEW "new" %token DESTROY "destroy" %token MONITOR "monitor" @@ -985,9 +986,7 @@ int nft_lex(void *, void *, void *); %destructor { expr_free($$); } osf_expr %type markup_format -%type monitor_event -%destructor { free_const($$); } monitor_event -%type monitor_object monitor_format +%type monitor_event monitor_object monitor_format %type synproxy_ts synproxy_sack @@ -1892,8 +1891,9 @@ monitor_cmd : monitor_event monitor_object monitor_format } ; -monitor_event : /* empty */ { $$ = NULL; } - | STRING { $$ = $1; } +monitor_event : /* empty */ { $$ = CMD_MONITOR_EVENT_ANY; } + | NEW { $$ = CMD_MONITOR_EVENT_NEW; } + | DESTROY { $$ = CMD_MONITOR_EVENT_DEL; } ; monitor_object : /* empty */ { $$ = CMD_MONITOR_OBJ_ANY; } diff --git a/src/rule.c b/src/rule.c index 8f8b77f1e8836..dabc16204f108 100644 --- a/src/rule.c +++ b/src/rule.c @@ -1389,7 +1389,8 @@ void markup_free(struct markup *m) free(m); } -struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event) +struct monitor *monitor_alloc(uint32_t format, uint32_t type, + enum cmd_monitor_event event) { struct monitor *mon; @@ -1404,7 +1405,6 @@ struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event) void monitor_free(struct monitor *m) { - free_const(m->event); free(m); } diff --git a/src/scanner.l b/src/scanner.l index df8e536be2276..99ace05773816 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -322,6 +322,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) { "rules" { return RULES; } "trace" { return TRACE; } + "new" { return NEW; } + "destroy" { return DESTROY; } } "hook" { return HOOK; } "device" { return DEVICE; } -- 2.51.0 Use the already existing SCANSTATE_TYPE for keyword scoping. This is a bit of back-n-forth from string to token and back to string but it eliminates the helper function and also takes care of error handling. Note that JSON parser does not validate the type string at all but relies upon the kernel to reject wrong ones. --- Changes since RFC: - Fix for leaking chain_type token. Signed-off-by: Phil Sutter --- include/rule.h | 1 - src/parser_bison.y | 28 ++++++++++++++-------------- src/rule.c | 19 ------------------- src/scanner.l | 6 ++++++ 4 files changed, 20 insertions(+), 34 deletions(-) diff --git a/include/rule.h b/include/rule.h index e67a01522d318..7c704be846485 100644 --- a/include/rule.h +++ b/include/rule.h @@ -260,7 +260,6 @@ struct chain { #define STD_PRIO_BUFSIZE 100 extern int std_prio_lookup(const char *std_prio_name, int family, int hook); -extern const char *chain_type_name_lookup(const char *name); extern const char *chain_hookname_lookup(const char *name); extern struct chain *chain_alloc(void); extern struct chain *chain_get(struct chain *chain); diff --git a/src/parser_bison.y b/src/parser_bison.y index 96d0e151b1586..405fe8f2690ca 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -715,6 +715,10 @@ int nft_lex(void *, void *, void *); %token XT "xt" +%token FILTER "filter" +%token NAT "nat" +%token ROUTE "route" + %type limit_rate_pkts %type limit_rate_bytes @@ -1034,6 +1038,9 @@ int nft_lex(void *, void *, void *); %type set_elem_key_expr %destructor { expr_free($$); } set_elem_key_expr +%type chain_type +%destructor { free_const($$); } chain_type + %% input : /* empty */ @@ -2736,22 +2743,10 @@ type_identifier : STRING { $$ = $1; } | CLASSID { $$ = xstrdup("classid"); } ; -hook_spec : TYPE close_scope_type STRING HOOK STRING dev_spec prio_spec +hook_spec : TYPE chain_type close_scope_type HOOK STRING dev_spec prio_spec { - const char *chain_type = chain_type_name_lookup($3); - - if (chain_type == NULL) { - erec_queue(error(&@3, "unknown chain type"), - state->msgs); - free_const($3); - free_const($5); - expr_free($6); - expr_free($7.expr); - YYERROR; - } $0->type.loc = @3; - $0->type.str = xstrdup(chain_type); - free_const($3); + $0->type.str = $2; $0->loc = @$; $0->hook.loc = @5; @@ -2772,6 +2767,11 @@ hook_spec : TYPE close_scope_type STRING HOOK STRING dev_spec prio_spec } ; +chain_type : FILTER { $$ = xstrdup("filter"); } + | NAT { $$ = xstrdup("nat"); } + | ROUTE { $$ = xstrdup("route"); } + ; + prio_spec : PRIORITY extended_prio_spec { $$ = $2; diff --git a/src/rule.c b/src/rule.c index dabc16204f108..c32e08319d149 100644 --- a/src/rule.c +++ b/src/rule.c @@ -676,25 +676,6 @@ struct symbol *symbol_lookup_fuzzy(const struct scope *scope, return st.obj; } -static const char * const chain_type_str_array[] = { - "filter", - "nat", - "route", - NULL, -}; - -const char *chain_type_name_lookup(const char *name) -{ - int i; - - for (i = 0; chain_type_str_array[i]; i++) { - if (!strcmp(name, chain_type_str_array[i])) - return chain_type_str_array[i]; - } - - return NULL; -} - static const char * const chain_hookname_str_array[] = { "prerouting", "input", diff --git a/src/scanner.l b/src/scanner.l index 99ace05773816..b397a147ef9bd 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -858,6 +858,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "out" { return OUT; } } +{ + "filter" { return FILTER; } + "nat" { return NAT; } + "route" { return ROUTE; } +} + "secmark" { scanner_push_start_cond(yyscanner, SCANSTATE_SECMARK); return SECMARK; } "xt" { scanner_push_start_cond(yyscanner, SCANSTATE_XT); return XT; } -- 2.51.0 Eliminate the open-coded string parsing and error handling. Signed-off-by: Phil Sutter Reviewed-by: Florian Westphal --- src/parser_bison.y | 24 ++++++------------------ src/scanner.l | 6 ++++++ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/parser_bison.y b/src/parser_bison.y index 405fe8f2690ca..ba485a8c25b50 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -719,6 +719,9 @@ int nft_lex(void *, void *, void *); %token NAT "nat" %token ROUTE "route" +%token LOOSE "loose" +%token SKIP "skip" + %type limit_rate_pkts %type limit_rate_bytes @@ -4485,24 +4488,9 @@ osf_expr : OSF osf_ttl HDRVERSION close_scope_osf } ; -osf_ttl : /* empty */ - { - $$ = NF_OSF_TTL_TRUE; - } - | TTL STRING - { - if (!strcmp($2, "loose")) - $$ = NF_OSF_TTL_LESS; - else if (!strcmp($2, "skip")) - $$ = NF_OSF_TTL_NOCHECK; - else { - erec_queue(error(&@2, "invalid ttl option"), - state->msgs); - free_const($2); - YYERROR; - } - free_const($2); - } +osf_ttl : /* empty */ { $$ = NF_OSF_TTL_TRUE; } + | TTL LOOSE { $$ = NF_OSF_TTL_LESS; } + | TTL SKIP { $$ = NF_OSF_TTL_NOCHECK; } ; shift_expr : primary_expr diff --git a/src/scanner.l b/src/scanner.l index b397a147ef9bd..e0f0aabb683a3 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -533,6 +533,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) { "ttl" { return TTL; } } + +{ + "loose" { return LOOSE; } + "skip" { return SKIP; } +} + "protocol" { return PROTOCOL; } { "checksum" { return CHECKSUM; } -- 2.51.0 Since log statement is scoped already, it's just a matter of declaring the tokens in that scope and using them. This eliminates the redundant copy of log level string parsing in parser_bison.y - the remaining one, namely log_level_parse() in statement.c is used by JSON parser. Signed-off-by: Phil Sutter Reviewed-by: Florian Westphal --- src/parser_bison.y | 46 ++++++++++++++++++---------------------------- src/scanner.l | 9 +++++++++ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/parser_bison.y b/src/parser_bison.y index ba485a8c25b50..8e07671cb80e9 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -643,6 +643,15 @@ int nft_lex(void *, void *, void *); %token SNAPLEN "snaplen" %token QUEUE_THRESHOLD "queue-threshold" %token LEVEL "level" +%token EMERG "emerg" +%token ALERT "alert" +%token CRIT "crit" +%token ERR "err" +%token WARN "warn" +%token NOTICE "notice" +%token INFO "info" +%token DEBUG_TOKEN "debug" +%token AUDIT "audit" %token LIMIT "limit" %token RATE "rate" @@ -3490,34 +3499,15 @@ log_arg : PREFIX string } ; -level_type : string - { - if (!strcmp("emerg", $1)) - $$ = NFT_LOGLEVEL_EMERG; - else if (!strcmp("alert", $1)) - $$ = NFT_LOGLEVEL_ALERT; - else if (!strcmp("crit", $1)) - $$ = NFT_LOGLEVEL_CRIT; - else if (!strcmp("err", $1)) - $$ = NFT_LOGLEVEL_ERR; - else if (!strcmp("warn", $1)) - $$ = NFT_LOGLEVEL_WARNING; - else if (!strcmp("notice", $1)) - $$ = NFT_LOGLEVEL_NOTICE; - else if (!strcmp("info", $1)) - $$ = NFT_LOGLEVEL_INFO; - else if (!strcmp("debug", $1)) - $$ = NFT_LOGLEVEL_DEBUG; - else if (!strcmp("audit", $1)) - $$ = NFT_LOGLEVEL_AUDIT; - else { - erec_queue(error(&@1, "invalid log level"), - state->msgs); - free_const($1); - YYERROR; - } - free_const($1); - } +level_type : EMERG { $$ = NFT_LOGLEVEL_EMERG; } + | ALERT { $$ = NFT_LOGLEVEL_ALERT; } + | CRIT { $$ = NFT_LOGLEVEL_CRIT; } + | ERR { $$ = NFT_LOGLEVEL_ERR; } + | WARN { $$ = NFT_LOGLEVEL_WARNING; } + | NOTICE { $$ = NFT_LOGLEVEL_NOTICE; } + | INFO { $$ = NFT_LOGLEVEL_INFO; } + | DEBUG_TOKEN { $$ = NFT_LOGLEVEL_DEBUG; } + | AUDIT { $$ = NFT_LOGLEVEL_AUDIT; } ; log_flags : TCP log_flags_tcp close_scope_tcp diff --git a/src/scanner.l b/src/scanner.l index e0f0aabb683a3..ca570e2bfe066 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -433,6 +433,15 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "queue-threshold" { return QUEUE_THRESHOLD; } "level" { return LEVEL; } "group" { return GROUP; } + "emerg" { return EMERG; } + "alert" { return ALERT; } + "crit" { return CRIT; } + "err" { return ERR; } + "warn" { return WARN; } + "notice" { return NOTICE; } + "info" { return INFO; } + "debug" { return DEBUG_TOKEN; } + "audit" { return AUDIT; } } "queue" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_QUEUE); return QUEUE;} -- 2.51.0 Introduce scoped tokens for "kbytes" and "mbytes", completing already existing "bytes" one. Then generalize the unit for byte values and replace both quota_unit and limit_bytes by a combination of NUM and bytes_unit. With this in place, data_unit_parse() is not called outside of datatype.c, so make it static. Signed-off-by: Phil Sutter Reviewed-by: Florian Westphal --- include/datatype.h | 3 -- src/datatype.c | 4 +-- src/parser_bison.y | 75 +++++++++++----------------------------------- src/scanner.l | 2 ++ 4 files changed, 22 insertions(+), 62 deletions(-) diff --git a/include/datatype.h b/include/datatype.h index 4fb47f158fc2f..63dba330137a0 100644 --- a/include/datatype.h +++ b/include/datatype.h @@ -313,9 +313,6 @@ extern struct error_record *rate_parse(const struct location *loc, const char *str, uint64_t *rate, uint64_t *unit); -extern struct error_record *data_unit_parse(const struct location *loc, - const char *str, uint64_t *rate); - struct limit_rate { uint64_t rate, unit; }; diff --git a/src/datatype.c b/src/datatype.c index fac4eb9cdcecd..1950a2f3757b8 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -1507,8 +1507,8 @@ static struct error_record *time_unit_parse(const struct location *loc, return NULL; } -struct error_record *data_unit_parse(const struct location *loc, - const char *str, uint64_t *rate) +static struct error_record *data_unit_parse(const struct location *loc, + const char *str, uint64_t *rate) { if (strcmp(str, "bytes") == 0) *rate = 1ULL; diff --git a/src/parser_bison.y b/src/parser_bison.y index 8e07671cb80e9..9639352a4b47d 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -617,6 +617,8 @@ int nft_lex(void *, void *, void *); %token NAME "name" %token PACKETS "packets" %token BYTES "bytes" +%token KBYTES "kbytes" +%token MBYTES "mbytes" %token AVGPKT "avgpkt" %token LAST "last" @@ -774,8 +776,8 @@ int nft_lex(void *, void *, void *); %type extended_prio_spec prio_spec %destructor { expr_free($$.expr); } extended_prio_spec prio_spec -%type extended_prio_name quota_unit basehook_device_name -%destructor { free_const($$); } extended_prio_name quota_unit basehook_device_name +%type extended_prio_name basehook_device_name +%destructor { free_const($$); } extended_prio_name basehook_device_name %type dev_spec %destructor { free($$); } dev_spec @@ -828,7 +830,7 @@ int nft_lex(void *, void *, void *); %type level_type log_flags log_flags_tcp log_flag_tcp %type limit_stmt quota_stmt connlimit_stmt %destructor { stmt_free($$); } limit_stmt quota_stmt connlimit_stmt -%type limit_burst_pkts limit_burst_bytes limit_mode limit_bytes time_unit quota_mode +%type limit_burst_pkts limit_burst_bytes limit_mode bytes_unit time_unit quota_mode %type reject_stmt reject_stmt_alloc %destructor { stmt_free($$); } reject_stmt reject_stmt_alloc %type nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc @@ -3596,23 +3598,15 @@ quota_mode : OVER { $$ = NFT_QUOTA_F_INV; } | /* empty */ { $$ = 0; } ; -quota_unit : BYTES { $$ = xstrdup("bytes"); } - | STRING { $$ = $1; } +bytes_unit : BYTES { $$ = 1; } + | KBYTES { $$ = 1024; } + | MBYTES { $$ = 1024 * 1024; } ; quota_used : /* empty */ { $$ = 0; } - | USED NUM quota_unit + | USED NUM bytes_unit { - struct error_record *erec; - uint64_t rate; - - erec = data_unit_parse(&@$, $3, &rate); - free_const($3); - if (erec != NULL) { - erec_queue(erec, state->msgs); - YYERROR; - } - $$ = $2 * rate; + $$ = $2 * $3; } ; @@ -3625,22 +3619,14 @@ quota_stmt_alloc : QUOTA quota_stmt : quota_stmt_alloc quota_args ; -quota_args : quota_mode NUM quota_unit quota_used +quota_args : quota_mode NUM bytes_unit quota_used { - struct error_record *erec; struct quota_stmt *quota; - uint64_t rate; assert($0->type == STMT_QUOTA); - erec = data_unit_parse(&@$, $3, &rate); - free_const($3); - if (erec != NULL) { - erec_queue(erec, state->msgs); - YYERROR; - } quota = &$0->quota; - quota->bytes = $2 * rate; + quota->bytes = $2 * $3; quota->used = $4; quota->flags = $1; } @@ -3663,7 +3649,7 @@ limit_rate_pkts : NUM SLASH time_unit ; limit_burst_bytes : /* empty */ { $$ = 0; } - | BURST limit_bytes { $$ = $2; } + | BURST NUM bytes_unit { $$ = $2 * $3; } ; limit_rate_bytes : NUM STRING @@ -3680,26 +3666,10 @@ limit_rate_bytes : NUM STRING $$.rate = rate * $1; $$.unit = unit; } - | limit_bytes SLASH time_unit + | NUM bytes_unit SLASH time_unit { - $$.rate = $1; - $$.unit = $3; - } - ; - -limit_bytes : NUM BYTES { $$ = $1; } - | NUM STRING - { - struct error_record *erec; - uint64_t rate; - - erec = data_unit_parse(&@$, $2, &rate); - free_const($2); - if (erec != NULL) { - erec_queue(erec, state->msgs); - YYERROR; - } - $$ = $1 * rate; + $$.rate = $1 * $2; + $$.unit = $4; } ; @@ -4767,21 +4737,12 @@ counter_obj : /* empty */ } ; -quota_config : quota_mode NUM quota_unit quota_used +quota_config : quota_mode NUM bytes_unit quota_used { - struct error_record *erec; struct quota *quota; - uint64_t rate; - - erec = data_unit_parse(&@$, $3, &rate); - free_const($3); - if (erec != NULL) { - erec_queue(erec, state->msgs); - YYERROR; - } quota = &$0->quota; - quota->bytes = $2 * rate; + quota->bytes = $2 * $3; quota->used = $4; quota->flags = $1; } diff --git a/src/scanner.l b/src/scanner.l index ca570e2bfe066..4cbc8a44c89c8 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -414,6 +414,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "name" { return NAME; } "packets" { return PACKETS; } "bytes" { return BYTES; } +"kbytes" { return KBYTES; } +"mbytes" { return MBYTES; } "last" { scanner_push_start_cond(yyscanner, SCANSTATE_LAST); return LAST; } { -- 2.51.0 This is a first exclusive start condition, i.e. one which rejects unscoped tokens. When tokenizing, flex all too easily falls back into treating something as STRING when it could be split into tokens instead. Via an exclusive start condition, the string-fallback can be disabled as needed. With rates in typical formatting /, tokenizer result depended on whitespace placement. SCANSTATE_RATE forces flex to split the string into tokens and fall back to JUNK upon failure. For this to work, tokens which shall still be recognized must be enabled in SCANSTATE_RATE (or all scopes denoted by '*'). This includes any tokens possibly following SCANSTATE_RATE to please the parser's lookahead behaviour. Signed-off-by: Phil Sutter --- include/datatype.h | 4 --- include/parser.h | 1 + src/datatype.c | 61 ------------------------------- src/parser_bison.y | 23 +++--------- src/scanner.l | 55 ++++++++++++++-------------- tests/py/any/limit.t | 6 ++++ tests/py/any/limit.t.json | 70 ++++++++++++++++++++++++++++++++++++ tests/py/any/limit.t.payload | 20 +++++++++++ 8 files changed, 130 insertions(+), 110 deletions(-) diff --git a/include/datatype.h b/include/datatype.h index 63dba330137a0..4c5d6ff8d9002 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 8cfd22e9e6c42..889302baf5950 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 1950a2f3757b8..189738513bf8c 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 9639352a4b47d..18174859434c8 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 4cbc8a44c89c8..9d8fade8308d3 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 2a84e3f56e4ef..5c95ffa52ee8a 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 73160b27fad81..49a48960ecf86 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 dc6701b3521c9..901275dafcaa0 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 ] -- 2.51.0