netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeremy Sowden <jeremy@azazel.net>
To: Netfilter Devel <netfilter-devel@vger.kernel.org>
Subject: Re: [nft PATCH] parser: extend limit statement syntax.
Date: Sun, 3 Oct 2021 15:58:32 +0100	[thread overview]
Message-ID: <YVnFGPHsva1xm7F+@azazel.net> (raw)
In-Reply-To: <20211002152230.1568537-1-jeremy@azazel.net>

[-- Attachment #1: Type: text/plain, Size: 7567 bytes --]

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@azazel.net>
> ---
>
> 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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2021-10-03 14:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-02 15:22 [nft PATCH] parser: extend limit statement syntax Jeremy Sowden
2021-10-03 14:58 ` Jeremy Sowden [this message]
2021-10-27  9:21   ` Pablo Neira Ayuso
2021-10-27  9:31     ` Pablo Neira Ayuso
2021-10-28  8:06       ` Jeremy Sowden
2021-10-27 20:02     ` Jeremy Sowden

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YVnFGPHsva1xm7F+@azazel.net \
    --to=jeremy@azazel.net \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).