On 2021-10-02, at 16:22:30 +0100, Jeremy Sowden wrote: > The documentation describes the syntax of limit statements thus: > > limit rate [over] packet_number / TIME_UNIT [burst packet_number packets] > limit rate [over] byte_number BYTE_UNIT / TIME_UNIT [burst byte_number BYTE_UNIT] > > TIME_UNIT := second | minute | hour | day > BYTE_UNIT := bytes | kbytes | mbytes > > This implies that one may specify a limit as either of the following: > > limit rate 1048576 / second > limit rate 1048576 mbytes / second > > However, the latter currently does not parse: > > $ sudo /usr/sbin/nft add filter input limit rate 1048576 mbytes / second > Error: wrong rate format > add filter input limit rate 1048576 mbytes / second > ^^^^^^^^^^^^^^^^^^^^^^^^^ > > Extend the parser to support it. > > Signed-off-by: Jeremy Sowden <jeremy@xxxxxxxxxx> > --- > > I can't help thinking that it ought to be possible to fold the two > > limit rate [over] byte_number BYTE_UNIT / TIME_UNIT [burst byte_number BYTE_UNIT] > > rules into one. However, my attempts to get the scanner to tokenize > "bytes/second" as "bytes" "/" "second" (for example) failed. Having reread the Flex manual, I've changed my mind. While it would be possible, it would be rather fiddly and require more effort than it would be worth. > src/parser_bison.y | 58 +++++++++++++++++++++++++++++++----- > tests/py/any/limit.t | 5 ++++ > tests/py/any/limit.t.json | 39 ++++++++++++++++++++++++ > tests/py/any/limit.t.payload | 13 ++++++++ > 4 files changed, 108 insertions(+), 7 deletions(-) > > diff --git a/src/parser_bison.y b/src/parser_bison.y > index c25af6ba114a..4a41e9e3a293 100644 > --- a/src/parser_bison.y > +++ b/src/parser_bison.y > @@ -689,7 +689,7 @@ int nft_lex(void *, void *, void *); > %type <val> level_type log_flags log_flags_tcp log_flag_tcp > %type <stmt> limit_stmt quota_stmt connlimit_stmt > %destructor { stmt_free($$); } limit_stmt quota_stmt connlimit_stmt > -%type <val> limit_burst_pkts limit_burst_bytes limit_mode time_unit quota_mode > +%type <val> limit_burst_pkts limit_burst_bytes limit_mode limit_bytes time_unit quota_mode > %type <stmt> reject_stmt reject_stmt_alloc > %destructor { stmt_free($$); } reject_stmt reject_stmt_alloc > %type <stmt> nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc > @@ -3184,6 +3184,21 @@ limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst_pkts close_s > $$->limit.type = NFT_LIMIT_PKT_BYTES; > $$->limit.flags = $3; > } > + | LIMIT RATE limit_mode limit_bytes SLASH time_unit limit_burst_bytes close_scope_limit > + { > + if ($7 == 0) { > + erec_queue(error(&@7, "limit burst must be > 0"), > + state->msgs); > + YYERROR; > + } > + > + $$ = limit_stmt_alloc(&@$); > + $$->limit.rate = $4; > + $$->limit.unit = $6; > + $$->limit.burst = $7; > + $$->limit.type = NFT_LIMIT_PKT_BYTES; > + $$->limit.flags = $3; > + } > | LIMIT NAME stmt_expr close_scope_limit > { > $$ = objref_stmt_alloc(&@$); > @@ -3251,19 +3266,22 @@ limit_burst_pkts : /* empty */ { $$ = 5; } > ; > > limit_burst_bytes : /* empty */ { $$ = 5; } > - | BURST NUM BYTES { $$ = $2; } > - | BURST NUM STRING > + | BURST limit_bytes { $$ = $2; } > + ; > + > +limit_bytes : NUM BYTES { $$ = $1; } > + | NUM STRING > { > struct error_record *erec; > uint64_t rate; > > - erec = data_unit_parse(&@$, $3, &rate); > - xfree($3); > + erec = data_unit_parse(&@$, $2, &rate); > + xfree($2); > if (erec != NULL) { > erec_queue(erec, state->msgs); > YYERROR; > } > - $$ = $2 * rate; > + $$ = $1 * rate; > } > ; > > @@ -4317,7 +4335,22 @@ set_elem_stmt : COUNTER close_scope_counter > $$->limit.burst = $6; > $$->limit.type = NFT_LIMIT_PKT_BYTES; > $$->limit.flags = $3; > - } > + } > + | LIMIT RATE limit_mode limit_bytes SLASH time_unit limit_burst_bytes close_scope_limit > + { > + if ($7 == 0) { > + erec_queue(error(&@7, "limit burst must be > 0"), > + state->msgs); > + YYERROR; > + } > + > + $$ = limit_stmt_alloc(&@$); > + $$->limit.rate = $4; > + $$->limit.unit = $6; > + $$->limit.burst = $7; > + $$->limit.type = NFT_LIMIT_PKT_BYTES; > + $$->limit.flags = $3; > + } > | CT COUNT NUM close_scope_ct > { > $$ = connlimit_stmt_alloc(&@$); > @@ -4581,6 +4614,17 @@ limit_config : RATE limit_mode NUM SLASH time_unit limit_burst_pkts > limit->type = NFT_LIMIT_PKT_BYTES; > limit->flags = $2; > } > + | RATE limit_mode limit_bytes SLASH time_unit limit_burst_bytes > + { > + struct limit *limit; > + > + limit = &$<obj>0->limit; > + limit->rate = $3; > + limit->unit = $5; > + limit->burst = $6; > + limit->type = NFT_LIMIT_PKT_BYTES; > + limit->flags = $2; > + } > ; > > limit_obj : /* empty */ > diff --git a/tests/py/any/limit.t b/tests/py/any/limit.t > index ef7f93133297..b4b4e5296088 100644 > --- a/tests/py/any/limit.t > +++ b/tests/py/any/limit.t > @@ -24,6 +24,11 @@ limit rate 10230 mbytes/second;ok > limit rate 1023000 mbytes/second;ok > limit rate 512 kbytes/second burst 5 packets;fail > > +limit rate 1 bytes / second;ok;limit rate 1 bytes/second > +limit rate 1 kbytes / second;ok;limit rate 1 kbytes/second > +limit rate 1 mbytes / second;ok;limit rate 1 mbytes/second > +limit rate 1 gbytes / second;fail > + > limit rate 1025 bytes/second burst 512 bytes;ok > limit rate 1025 kbytes/second burst 1023 kbytes;ok > limit rate 1025 mbytes/second burst 1025 kbytes;ok > diff --git a/tests/py/any/limit.t.json b/tests/py/any/limit.t.json > index 8bab7e3d79b4..b41ae60a3bd6 100644 > --- a/tests/py/any/limit.t.json > +++ b/tests/py/any/limit.t.json > @@ -125,6 +125,45 @@ > } > ] > > +# limit rate 1 bytes / second > +[ > + { > + "limit": { > + "burst": 5, > + "burst_unit": "bytes", > + "per": "second", > + "rate": 1, > + "rate_unit": "bytes" > + } > + } > +] > + > +# limit rate 1 kbytes / second > +[ > + { > + "limit": { > + "burst": 5, > + "burst_unit": "bytes", > + "per": "second", > + "rate": 1, > + "rate_unit": "kbytes" > + } > + } > +] > + > +# limit rate 1 mbytes / second > +[ > + { > + "limit": { > + "burst": 5, > + "burst_unit": "bytes", > + "per": "second", > + "rate": 1, > + "rate_unit": "mbytes" > + } > + } > +] > + > # limit rate 1025 bytes/second burst 512 bytes > [ > { > diff --git a/tests/py/any/limit.t.payload b/tests/py/any/limit.t.payload > index dc6cea9b2846..3bd85f4ebf45 100644 > --- a/tests/py/any/limit.t.payload > +++ b/tests/py/any/limit.t.payload > @@ -46,6 +46,19 @@ ip test-ip4 output > ip test-ip4 output > [ limit rate 1072693248000/second burst 5 type bytes flags 0x0 ] > > +# limit rate 1 bytes / second > +ip > + [ limit rate 1/second burst 5 type bytes flags 0x0 ] > + > +# limit rate 1 kbytes / second > +ip > + [ limit rate 1024/second burst 5 type bytes flags 0x0 ] > + > +# limit rate 1 mbytes / second > +ip > + [ limit rate 1048576/second burst 5 type bytes flags 0x0 ] > + > + > # limit rate 1025 bytes/second burst 512 bytes > ip test-ip4 output > [ limit rate 1025/second burst 512 type bytes flags 0x0 ] > -- > 2.33.0 > >
Attachment:
signature.asc
Description: PGP signature