currently the frontend uses seconds everywhere and
multiplies/divides by 1000.

Pass milliseconds around instead and extend the scanner to accept 'ms'
in timestrings.

Signed-off-by: Florian Westphal <f...@strlen.de>
---
 include/datatype.h                                |  2 +-
 src/datatype.c                                    | 48 ++++++++++++++++-------
 src/expression.c                                  |  4 +-
 src/parser_bison.y                                |  8 ++--
 src/rule.c                                        |  4 +-
 src/scanner.l                                     |  2 +-
 tests/shell/testcases/sets/0031set_timeout_size_0 |  7 +++-
 7 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/include/datatype.h b/include/datatype.h
index 3f612e52aec2..aca08decf142 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -264,7 +264,7 @@ extern const struct datatype *
 set_datatype_alloc(const struct datatype *orig_dtype, unsigned int byteorder);
 extern void set_datatype_destroy(const struct datatype *dtype);
 
-extern void time_print(uint64_t seconds, struct output_ctx *octx);
+extern void time_print(uint64_t msec, struct output_ctx *octx);
 extern struct error_record *time_parse(const struct location *loc,
                                       const char *c, uint64_t *res);
 
diff --git a/src/datatype.c b/src/datatype.c
index 446bde9f438d..4248f7e40c96 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -824,18 +824,21 @@ const struct datatype icmpx_code_type = {
        .sym_tbl        = &icmpx_code_tbl,
 };
 
-void time_print(uint64_t seconds, struct output_ctx *octx)
+void time_print(uint64_t ms, struct output_ctx *octx)
 {
-       uint64_t days, hours, minutes;
+       uint64_t days, hours, minutes, seconds;
 
-       days = seconds / 86400;
-       seconds %= 86400;
+       days = ms / 86400000;
+       ms %= 86400000;
 
-       hours = seconds / 3600;
-       seconds %= 3600;
+       hours = ms / 3600000;
+       ms %= 3600000;
 
-       minutes = seconds / 60;
-       seconds %= 60;
+       minutes = ms / 60000;
+       ms %= 60000;
+
+       seconds = ms / 1000;
+       ms %= 1000;
 
        if (days > 0)
                nft_print(octx, "%" PRIu64 "d", days);
@@ -845,6 +848,8 @@ void time_print(uint64_t seconds, struct output_ctx *octx)
                nft_print(octx, "%" PRIu64 "m", minutes);
        if (seconds > 0)
                nft_print(octx, "%" PRIu64 "s", seconds);
+       if (ms > 0)
+               nft_print(octx, "%" PRIu64 "ms", ms);
 }
 
 enum {
@@ -852,6 +857,7 @@ enum {
        HOUR    = (1 << 1),
        MIN     = (1 << 2),
        SECS    = (1 << 3),
+       MSECS   = (1 << 4),
 };
 
 static uint32_t str2int(const char *str)
@@ -869,7 +875,7 @@ struct error_record *time_parse(const struct location *loc, 
const char *str,
        int i, len;
        unsigned int k = 0;
        const char *c;
-       uint64_t d = 0, h = 0, m = 0, s = 0;
+       uint64_t d = 0, h = 0, m = 0, s = 0, ms = 0;
        uint32_t mask = 0;
 
        c = str;
@@ -895,6 +901,18 @@ struct error_record *time_parse(const struct location 
*loc, const char *str,
                        mask |= HOUR;
                        break;
                case 'm':
+                       if (strcmp(c, "ms") == 0) {
+                               if (mask & MSECS)
+                                       return error(loc,
+                                                    "Millisecond has been 
specified twice");
+                               ms = str2int(c - k);
+                               c++;
+                               i++;
+                               k = 0;
+                               mask |= MSECS;
+                               break;
+                       }
+
                        if (mask & MIN)
                                return error(loc,
                                             "Minute has been specified twice");
@@ -924,18 +942,21 @@ struct error_record *time_parse(const struct location 
*loc, const char *str,
 
        /* default to seconds if no unit was specified */
        if (!mask)
-               s = atoi(str);
+               ms = atoi(str) * MSEC_PER_SEC;
        else
-               s = 24*60*60*d+60*60*h+60*m+s;
+               ms = 24*60*60*MSEC_PER_SEC * d +
+                       60*60*MSEC_PER_SEC * h +
+                          60*MSEC_PER_SEC * m +
+                             MSEC_PER_SEC * s + ms;
 
-       *res = s;
+       *res = ms;
        return NULL;
 }
 
 
 static void time_type_print(const struct expr *expr, struct output_ctx *octx)
 {
-       time_print(mpz_get_uint64(expr->value) / MSEC_PER_SEC, octx);
+       time_print(mpz_get_uint64(expr->value), octx);
 }
 
 static struct error_record *time_type_parse(const struct expr *sym,
@@ -948,7 +969,6 @@ static struct error_record *time_type_parse(const struct 
expr *sym,
        if (erec != NULL)
                return erec;
 
-       s *= MSEC_PER_SEC;
        if (s > UINT32_MAX)
                return error(&sym->location, "value too large");
 
diff --git a/src/expression.c b/src/expression.c
index 239cf8825c4f..c3b6fb22ceef 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -1020,11 +1020,11 @@ static void set_elem_expr_print(const struct expr *expr,
        expr_print(expr->key, octx);
        if (expr->timeout) {
                nft_print(octx, " timeout ");
-               time_print(expr->timeout / 1000, octx);
+               time_print(expr->timeout, octx);
        }
        if (!octx->stateless && expr->expiration) {
                nft_print(octx, " expires ");
-               time_print(expr->expiration / 1000, octx);
+               time_print(expr->expiration, octx);
        }
        if (expr->comment)
                nft_print(octx, " comment \"%s\"", expr->comment);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 7238a94ec758..24210b2bd58e 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1496,12 +1496,12 @@ set_block               :       /* empty */     { $$ = 
$<set>-1; }
                        }
                        |       set_block       TIMEOUT         time_spec       
stmt_separator
                        {
-                               $1->timeout = $3 * 1000;
+                               $1->timeout = $3;
                                $$ = $1;
                        }
                        |       set_block       GC_INTERVAL     time_spec       
stmt_separator
                        {
-                               $1->gc_int = $3 * 1000;
+                               $1->gc_int = $3;
                                $$ = $1;
                        }
                        |       set_block       ELEMENTS        '='             
set_block_expr
@@ -1544,7 +1544,7 @@ map_block         :       /* empty */     { $$ = 
$<set>-1; }
                        |       map_block       stmt_separator
                        |       map_block       TIMEOUT         time_spec       
stmt_separator
                        {
-                               $1->timeout = $3 * 1000;
+                               $1->timeout = $3;
                                $$ = $1;
                        }
                        |       map_block       TYPE
@@ -3052,7 +3052,7 @@ set_elem_options  :       set_elem_option
 
 set_elem_option                :       TIMEOUT                 time_spec
                        {
-                               $<expr>0->timeout = $2 * 1000;
+                               $<expr>0->timeout = $2;
                        }
                        |       comment_spec
                        {
diff --git a/src/rule.c b/src/rule.c
index 2f0123b7a4a5..bdfc10f3b59f 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -379,12 +379,12 @@ static void set_print_declaration(const struct set *set,
 
        if (set->timeout) {
                nft_print(octx, "%s%stimeout ", opts->tab, opts->tab);
-               time_print(set->timeout / 1000, octx);
+               time_print(set->timeout, octx);
                nft_print(octx, "%s", opts->stmt_separator);
        }
        if (set->gc_int) {
                nft_print(octx, "%s%sgc-interval ", opts->tab, opts->tab);
-               time_print(set->gc_int / 1000, octx);
+               time_print(set->gc_int, octx);
                nft_print(octx, "%s", opts->stmt_separator);
        }
 }
diff --git a/src/scanner.l b/src/scanner.l
index 70366d193035..bd641345f605 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -118,7 +118,7 @@ asteriskstring      ({string}\*|{string}\\\*)
 comment                #.*$
 slash          \/
 
-timestring     ([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?
+timestring     ([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?
 
 hex4           ([[:xdigit:]]{1,4})
 v680           (({hex4}:){7}{hex4})
diff --git a/tests/shell/testcases/sets/0031set_timeout_size_0 
b/tests/shell/testcases/sets/0031set_timeout_size_0
index 3d3f919ab97a..a401ffa69dcb 100755
--- a/tests/shell/testcases/sets/0031set_timeout_size_0
+++ b/tests/shell/testcases/sets/0031set_timeout_size_0
@@ -1,7 +1,12 @@
 #!/bin/bash
 
 RULESET="add table x
-add set x y { type ipv4_addr; size 128; timeout 30s; }"
+add set x y { type ipv4_addr; size 128; timeout 30s; }
+add chain x test
+add rule x test set update ip saddr timeout 1d2h3m4s5ms @y
+add rule x test set update ip daddr timeout 321ms @y"
 
 set -e
 $NFT -f - <<< $RULESET
+$NFT list chain x test | grep -q 'update @y { ip saddr timeout 1d2h3m4s5ms }'
+$NFT list chain x test | grep -q 'update @y { ip daddr timeout 321ms }'
-- 
2.16.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to