From 9ef4f9e6fe0c766395d00701131289bc2007c23c Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 9 May 2018 00:52:30 +0200 Subject: src: support timeouts in milliseconds 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 --- src/datatype.c | 48 ++++++++++++++++++++++++++++++++++-------------- src/expression.c | 4 ++-- src/parser_bison.y | 8 ++++---- src/rule.c | 4 ++-- src/scanner.l | 2 +- 5 files changed, 43 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/datatype.c b/src/datatype.c index 446bde9f..4248f7e4 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 239cf882..c3b6fb22 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 7238a94e..24210b2b 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1496,12 +1496,12 @@ set_block : /* empty */ { $$ = $-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 */ { $$ = $-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 { - $0->timeout = $2 * 1000; + $0->timeout = $2; } | comment_spec { diff --git a/src/rule.c b/src/rule.c index 2f0123b7..bdfc10f3 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 70366d19..bd641345 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}) -- cgit v1.2.3