]> git.ipfire.org Git - thirdparty/libnftnl.git/commitdiff
expr: limit: Prepare for odd time units
authorPhil Sutter <phil@nwl.cc>
Wed, 10 Apr 2024 12:29:07 +0000 (14:29 +0200)
committerPhil Sutter <phil@nwl.cc>
Fri, 5 Jul 2024 15:31:15 +0000 (17:31 +0200)
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>
src/expr/limit.c

index 9d025920586b29680e3e9eb87fe4c4ed92c478c7..5b821081eb20d83c58a5047f7c2f4c37333c5f9b 100644 (file)
@@ -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] = {