From: Jeremy Sowden <jeremy@azazel.net>
To: Netfilter Devel <netfilter-devel@vger.kernel.org>
Subject: [nft PATCH] parser: extend limit statement syntax.
Date: Sat, 2 Oct 2021 16:22:30 +0100 [thread overview]
Message-ID: <20211002152230.1568537-1-jeremy@azazel.net> (raw)
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.
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
next reply other threads:[~2021-10-02 15:26 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-02 15:22 Jeremy Sowden [this message]
2021-10-03 14:58 ` [nft PATCH] parser: extend limit statement syntax Jeremy Sowden
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=20211002152230.1568537-1-jeremy@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).