summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/netlink_delinearize.c1
-rw-r--r--src/netlink_linearize.c1
-rw-r--r--src/parser_bison.y27
-rw-r--r--src/scanner.l2
-rw-r--r--src/statement.c11
5 files changed, 29 insertions, 13 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 841be609..3f017816 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -621,6 +621,7 @@ static void netlink_parse_limit(struct netlink_parse_ctx *ctx,
stmt->limit.unit = nftnl_expr_get_u64(nle, NFTNL_EXPR_LIMIT_UNIT);
stmt->limit.type = nftnl_expr_get_u32(nle, NFTNL_EXPR_LIMIT_TYPE);
stmt->limit.burst = nftnl_expr_get_u32(nle, NFTNL_EXPR_LIMIT_BURST);
+ stmt->limit.flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_LIMIT_FLAGS);
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index c77c462b..0dc7f97e 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -793,6 +793,7 @@ static void netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx,
if (stmt->limit.burst > 0)
nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_BURST,
stmt->limit.burst);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_FLAGS, stmt->limit.flags);
nftnl_rule_add_expr(ctx->nlr, nle);
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 833e7f5d..514dd7eb 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -367,6 +367,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token LIMIT "limit"
%token RATE "rate"
%token BURST "burst"
+%token OVER "over"
+%token UNTIL "until"
%token NANOSECOND "nanosecond"
%token MICROSECOND "microsecond"
@@ -458,7 +460,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <val> level_type
%type <stmt> limit_stmt
%destructor { stmt_free($$); } limit_stmt
-%type <val> limit_burst time_unit
+%type <val> limit_burst limit_mode time_unit
%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
@@ -1467,33 +1469,40 @@ level_type : LEVEL_EMERG { $$ = LOG_EMERG; }
| LEVEL_DEBUG { $$ = LOG_DEBUG; }
;
-limit_stmt : LIMIT RATE NUM SLASH time_unit limit_burst
+limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst
{
$$ = limit_stmt_alloc(&@$);
- $$->limit.rate = $3;
- $$->limit.unit = $5;
- $$->limit.burst = $6;
+ $$->limit.rate = $4;
+ $$->limit.unit = $6;
+ $$->limit.burst = $7;
$$->limit.type = NFT_LIMIT_PKTS;
+ $$->limit.flags = $3;
}
- | LIMIT RATE NUM STRING limit_burst
+ | LIMIT RATE limit_mode NUM STRING limit_burst
{
struct error_record *erec;
uint64_t rate, unit;
- erec = rate_parse(&@$, $4, &rate, &unit);
+ erec = rate_parse(&@$, $5, &rate, &unit);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
}
$$ = limit_stmt_alloc(&@$);
- $$->limit.rate = rate * $3;
+ $$->limit.rate = rate * $4;
$$->limit.unit = unit;
- $$->limit.burst = $5;
+ $$->limit.burst = $6;
$$->limit.type = NFT_LIMIT_PKT_BYTES;
+ $$->limit.flags = $3;
}
;
+limit_mode : OVER { $$ = NFT_LIMIT_F_INV; }
+ | UNTIL { $$ = 0; }
+ | /* empty */ { $$ = 0; }
+ ;
+
limit_burst : /* empty */ { $$ = 0; }
| BURST NUM PACKETS { $$ = $2; }
| BURST NUM BYTES { $$ = $2; }
diff --git a/src/scanner.l b/src/scanner.l
index a98e7b6a..e5ac8aa7 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -312,6 +312,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"limit" { return LIMIT; }
"rate" { return RATE; }
"burst" { return BURST; }
+"until" { return UNTIL; }
+"over" { return OVER; }
"nanosecond" { return NANOSECOND; }
"microsecond" { return MICROSECOND; }
diff --git a/src/statement.c b/src/statement.c
index 2d1a3e6b..153e93be 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -213,21 +213,24 @@ static const char *get_rate(uint64_t byte_rate, uint64_t *rate)
static void limit_stmt_print(const struct stmt *stmt)
{
+ bool inv = stmt->limit.flags & NFT_LIMIT_F_INV;
const char *data_unit;
uint64_t rate;
switch (stmt->limit.type) {
case NFT_LIMIT_PKTS:
- printf("limit rate %" PRIu64 "/%s",
- stmt->limit.rate, get_unit(stmt->limit.unit));
+ printf("limit rate %s%" PRIu64 "/%s",
+ inv ? "over " : "", stmt->limit.rate,
+ get_unit(stmt->limit.unit));
if (stmt->limit.burst > 0)
printf(" burst %u packets", stmt->limit.burst);
break;
case NFT_LIMIT_PKT_BYTES:
data_unit = get_rate(stmt->limit.rate, &rate);
- printf("limit rate %" PRIu64 " %s/%s",
- rate, data_unit, get_unit(stmt->limit.unit));
+ printf("limit rate %s%" PRIu64 " %s/%s",
+ inv ? "over " : "", rate, data_unit,
+ get_unit(stmt->limit.unit));
if (stmt->limit.burst > 0) {
uint64_t burst;