[PATCH nft] src: support timeouts in milliseconds

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux