From b259d1aca0db1bed5af3e4fe378f8aeb4d3ce645 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Sat, 5 Oct 2013 09:44:56 -0700 Subject: src: operational limit match The nft limit match currently does not work at all. Below patches to nftables, libnftables, and kernel address the issue. A few notes on the implementation: - Removed support for nano/micro/milli second limits. These seem pointless, given we are using jiffies in the limit match, not a hpet. And who really needs to limit items down to sub-second level?? - 'depth' member is removed as unnecessary. All we need in the kernel is the rate and the unit. - 'stamp' member becomes the time we need to next refresh the token bucket, instead of being updated on every packet which goes through the match. This closes netfilter bugzilla #827, reported by Eric Leblond. Signed-off-by: Phil Oester Signed-off-by: Pablo Neira Ayuso --- include/statement.h | 1 - src/netlink_delinearize.c | 4 ++-- src/netlink_linearize.c | 4 ++-- src/parser.y | 13 +++++-------- src/statement.c | 12 ++++++++++-- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/statement.h b/include/statement.h index 53702317..6ecbb18d 100644 --- a/include/statement.h +++ b/include/statement.h @@ -41,7 +41,6 @@ extern struct stmt *log_stmt_alloc(const struct location *loc); struct limit_stmt { uint64_t rate; uint64_t unit; - uint64_t depth; }; extern struct stmt *limit_stmt_alloc(const struct location *loc); diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index d80fc78d..3bb143b8 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -385,8 +385,8 @@ static void netlink_parse_limit(struct netlink_parse_ctx *ctx, struct stmt *stmt; stmt = limit_stmt_alloc(loc); - stmt->limit.rate = nft_rule_expr_get_u32(nle, NFT_EXPR_LIMIT_RATE); - stmt->limit.depth = nft_rule_expr_get_u32(nle, NFT_EXPR_LIMIT_DEPTH); + stmt->limit.rate = nft_rule_expr_get_u64(nle, NFT_EXPR_LIMIT_RATE); + stmt->limit.unit = nft_rule_expr_get_u64(nle, NFT_EXPR_LIMIT_UNIT); list_add_tail(&stmt->list, &ctx->rule->stmts); } diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 72c59e56..fd91155b 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -551,8 +551,8 @@ static void netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx, struct nft_rule_expr *nle; nle = alloc_nft_expr("limit"); - nft_rule_expr_set_u32(nle, NFT_EXPR_LIMIT_RATE, stmt->limit.rate); - nft_rule_expr_set_u32(nle, NFT_EXPR_LIMIT_DEPTH, stmt->limit.depth); + nft_rule_expr_set_u64(nle, NFT_EXPR_LIMIT_RATE, stmt->limit.rate); + nft_rule_expr_set_u64(nle, NFT_EXPR_LIMIT_UNIT, stmt->limit.unit); nft_rule_add_expr(ctx->nlr, nle); } diff --git a/src/parser.y b/src/parser.y index 074f0758..cfe1e863 100644 --- a/src/parser.y +++ b/src/parser.y @@ -1003,14 +1003,11 @@ limit_stmt : LIMIT RATE NUM SLASH time_unit } ; -time_unit : NANOSECOND { $$ = 1ULL; } - | MICROSECOND { $$ = 1ULL * 1000; } - | MILLISECOND { $$ = 1ULL * 1000 * 1000; } - | SECOND { $$ = 1ULL * 1000 * 1000 * 1000; } - | MINUTE { $$ = 1ULL * 1000 * 1000 * 1000 * 60; } - | HOUR { $$ = 1ULL * 1000 * 1000 * 1000 * 60 * 60; } - | DAY { $$ = 1ULL * 1000 * 1000 * 1000 * 60 * 60 * 24; } - | WEEK { $$ = 1ULL * 1000 * 1000 * 1000 * 60 * 60 * 24 * 7; } +time_unit : SECOND { $$ = 1ULL; } + | MINUTE { $$ = 1ULL * 60; } + | HOUR { $$ = 1ULL * 60 * 60; } + | DAY { $$ = 1ULL * 60 * 60 * 24; } + | WEEK { $$ = 1ULL * 60 * 60 * 24 * 7; } ; reject_stmt : _REJECT diff --git a/src/statement.c b/src/statement.c index 69db48f6..658dc5ff 100644 --- a/src/statement.c +++ b/src/statement.c @@ -144,8 +144,16 @@ struct stmt *log_stmt_alloc(const struct location *loc) static void limit_stmt_print(const struct stmt *stmt) { - printf("limit rate %" PRIu64 " depth %" PRIu64, - stmt->limit.rate, stmt->limit.depth); + static const char *units[] = { + [1] = "second", + [1 * 60] = "minute", + [1 * 60 * 60] = "hour", + [1 * 60 * 60 * 24] = "day", + [1 * 60 * 60 * 24 * 7] = "week", + }; + + printf("limit rate %" PRIu64 "/%s", + stmt->limit.rate, units[stmt->limit.unit]); } static const struct stmt_ops limit_stmt_ops = { -- cgit v1.2.3