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 <fw@xxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html