diff options
author | Phil Sutter <phil@nwl.cc> | 2024-04-10 14:29:07 +0200 |
---|---|---|
committer | Phil Sutter <phil@nwl.cc> | 2024-07-05 17:31:15 +0200 |
commit | fc94d862bdb87d0dddf215d3b60032010f53d0f4 (patch) | |
tree | 843276b1cb972b57a32b11602ddc4d47443e23af | |
parent | d84846df1329c774a0a9e777d6c5adeb157b7499 (diff) |
expr: limit: Prepare for odd time units
When limit->unit is not a known timespan, use the largest possible unit
and print the value along with it. This enables libnftnl debug output to
correctly print arbitrary quotients, like '3/5 minutes' for instance.
Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1214
Suggested-by: Cyril <boite.pour.spam@gmail.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
-rw-r--r-- | src/expr/limit.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/src/expr/limit.c b/src/expr/limit.c index 9d02592..5b82108 100644 --- a/src/expr/limit.c +++ b/src/expr/limit.c @@ -158,16 +158,28 @@ nftnl_expr_limit_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static const char *get_unit(uint64_t u) +static const char *get_time(uint64_t seconds, uint64_t *val) { - switch (u) { - case 1: return "second"; - case 60: return "minute"; - case 60 * 60: return "hour"; - case 60 * 60 * 24: return "day"; - case 60 * 60 * 24 * 7: return "week"; + static const struct { + unsigned int size; + const char *name; + } units[] = { + { 0, "second" }, + { 60, "minute" }, + { 60, "hour" }, + { 24, "day" }, + { 7, "week" } + }; + int i; + + for (i = 1; i < array_size(units); i++) { + if (seconds % units[i].size) + break; + seconds /= units[i].size; } - return "error"; + if (val) + *val = seconds; + return units[i - 1].name; } static const char *limit_to_type(enum nft_limit_type type) @@ -186,10 +198,26 @@ nftnl_expr_limit_snprintf(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e) { struct nftnl_expr_limit *limit = nftnl_expr_data(e); + unsigned int offset = 0; + const char *time_unit; + uint64_t time_val; + int ret; + + ret = snprintf(buf, len, "rate %"PRIu64"/", limit->rate); + SNPRINTF_BUFFER_SIZE(ret, len, offset); + + time_unit = get_time(limit->unit, &time_val); + if (time_val > 1) { + ret = snprintf(buf + offset, len, "%"PRIu64" ", time_val); + SNPRINTF_BUFFER_SIZE(ret, len, offset); + } + + ret = snprintf(buf + offset, len, "%s burst %u type %s flags 0x%x ", + time_unit, limit->burst, limit_to_type(limit->type), + limit->flags); + SNPRINTF_BUFFER_SIZE(ret, len, offset); - return snprintf(buf, len, "rate %"PRIu64"/%s burst %u type %s flags 0x%x ", - limit->rate, get_unit(limit->unit), limit->burst, - limit_to_type(limit->type), limit->flags); + return offset; } static struct attr_policy limit_attr_policy[__NFTNL_EXPR_LIMIT_MAX] = { |