Skip to contentSkip to conversation

src: changes related to numgen and hash expressions

PATCH Applied Laura Garcia Liebana 2 participants 10 messages Oct 22, 2016 – Oct 27, 2016 netfilter

v1 of 3 Applied Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover src: changes related to numgen and hash expressions

This patchset provides several improvements for numgen and hash expressions:

- support of OFFSET attribute for numgen and hash expressions
- makes SEED attribute optional and randomly generated
- fix the TYPE attribute to be treated as a register

Laura Garcia Liebana (4):
src: make hash seed attribute optional
src: add offset attribute for hash expression
src: add offset attribute for numgen expression
netlink: fix linearize numgen type

 configure.ac                        | 14 +++++++++++++-
 include/expression.h                |  2 ++
 include/hash.h                      | 13 ++++++++++++-
 include/linux/netfilter/nf_tables.h |  4 ++++
 include/numgen.h                    |  3 ++-
 src/hash.c                          |  9 +++++++--
 src/netlink_delinearize.c           | 10 ++++++----
 src/netlink_linearize.c             |  4 +++-
 src/numgen.c                        | 10 ++++++++--
 src/parser_bison.y                  | 20 +++++++++++++++-----
 src/scanner.l                       |  1 +
 tests/py/ip/hash.t                  |  4 ++++
 tests/py/ip/numgen.t                |  1 +
 13 files changed, 78 insertions(+), 17 deletions(-)
Signature · 1 line
2.9.3
#1 lore raw

PATCH 1/4 src: make hash seed attribute optional

The hash expression requires a seed attribute to call the jhash operation, eg.

 # nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2 \
	seed 0xdeadbeef

With this patch the seed attribute is optional and it's generated by a random function from userspace, eg.

 # nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2

To generate a secure random number it has been included the libbsd library dependency by default, that implements the arc4random() function generator. But it's possible to get rid of this dependency applying the option --without-arc4random during the configure of the package.

---
 configure.ac       | 14 +++++++++++++-
 include/hash.h     | 10 ++++++++++
 src/parser_bison.y |  5 +++++
 tests/py/ip/hash.t |  2 ++
 4 files changed, 30 insertions(+), 1 deletion(-)
configure.ac +13 -1
index 7e0b75c..8c93981 100644
@@ -108,6 +108,17 @@ AC_DEFINE([HAVE_LIBXTABLES], [1], [0])
 AC_SUBST(with_libxtables)
 AM_CONDITIONAL([BUILD_XTABLES], [test "x$with_libxtables" == xyes])
 
+AC_ARG_WITH([arc4random], [AS_HELP_STRING([--without-arc4random],
+            [disable arc4random (libbsd dev support)])],
+            [], [with_arc4random=yes])
+AS_IF([test "x$with_arc4random" != xno], [
+AC_CHECK_LIB([bsd], [arc4random], ,
+	     AC_MSG_ERROR([No suitable version of libbsd dev found]))
+AC_DEFINE([HAVE_LIBBSD], [1], [])
+])
+AC_SUBST(with_arc4random)
+AM_CONDITIONAL([BUILD_ARC4RANDOM], [test "x$with_arc4random" != xno])
+
 # Checks for header files.
 AC_HEADER_STDC
 AC_HEADER_ASSERT
@@ -158,4 +169,5 @@ nft configuration:
   enable debugging:		${with_debug}
   use mini-gmp:			${with_mini_gmp}
   enable pdf documentation:	${enable_pdf_doc}
-  libxtables support:		${with_libxtables}"
+  libxtables support:		${with_libxtables}
+  arc4random support:		${with_arc4random}"
include/hash.h +10 -0
index bc8c86a..5350cb2 100644
@@ -1,6 +1,16 @@
 #ifndef NFTABLES_HASH_H
 #define NFTABLES_HASH_H
 
+#ifdef HAVE_LIBBSD
+#include <bsd/stdlib.h>
+#define getrandom()	(arc4random() % ((uint32_t)RAND_MAX + 1))
+
+#else
+#include <time.h>
+#include <stdlib.h>
+#define getrandom()	({ srand(time(NULL)); (uint32_t)rand(); })
+#endif
+
 extern struct expr *hash_expr_alloc(const struct location *loc,
 				    uint32_t modulus, uint32_t seed);
 
src/parser_bison.y +5 -0
index 36dbc8d..0fa469d 100644
@@ -2485,6 +2485,11 @@ hash_expr		:	JHASH	expr	MOD	NUM	SEED	NUM
 				$$ = hash_expr_alloc(&@$, $4, $6);
 				$$->hash.expr = $2;
 			}
+			|	JHASH	expr	MOD	NUM
+			{
+				$$ = hash_expr_alloc(&@$, $4, getrandom());
+				$$->hash.expr = $2;
+			}
 			;
 
 ct_expr			: 	CT	ct_key
tests/py/ip/hash.t +2 -0
index 6dfa965..85f9b18 100644
@@ -2,4 +2,6 @@
 *ip;test-ip4;pre
 
 ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef;ok
+ct mark set jhash ip saddr . ip daddr mod 2;ok
 dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
+dnat to jhash ip saddr mod 2 map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
Signature · 1 line
2.9.3
#2 lore raw

Re: [PATCH nft 1/4] src: make hash seed attribute optional

Quoted 34 lines · Laura Garcia Liebana

The hash expression requires a seed attribute to call the jhash operation, eg.

 # nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2 \
	seed 0xdeadbeef

With this patch the seed attribute is optional and it's generated by a random function from userspace, eg.

 # nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2

To generate a secure random number it has been included the libbsd library dependency by default, that implements the arc4random() function generator. But it's possible to get rid of this dependency applying the option --without-arc4random during the configure of the package.

---
 configure.ac       | 14 +++++++++++++-
 include/hash.h     | 10 ++++++++++
 src/parser_bison.y |  5 +++++
 tests/py/ip/hash.t |  2 ++
 4 files changed, 30 insertions(+), 1 deletion(-)
configure.ac +0 -0
index 7e0b75c..8c93981 100644
@@ -108,6 +108,17 @@ AC_DEFINE([HAVE_LIBXTABLES], [1], [0])
 AC_SUBST(with_libxtables)
 AM_CONDITIONAL([BUILD_XTABLES], [test "x$with_libxtables" == xyes])
 

configure.ac AC_DEFINE([HAVE_LIBXTABLES], [1], [0]) · line 120

Quoted 10 lines
configure.ac +10 -0
+AC_ARG_WITH([arc4random], [AS_HELP_STRING([--without-arc4random],
+            [disable arc4random (libbsd dev support)])],
+            [], [with_arc4random=yes])
+AS_IF([test "x$with_arc4random" != xno], [
+AC_CHECK_LIB([bsd], [arc4random], ,
+	     AC_MSG_ERROR([No suitable version of libbsd dev found]))
+AC_DEFINE([HAVE_LIBBSD], [1], [])
+])
+AC_SUBST(with_arc4random)
+AM_CONDITIONAL([BUILD_ARC4RANDOM], [test "x$with_arc4random" != xno])

We have getrandom() already around for a while:

https://lwn.net/Articles/605828/

Main problem is that your libc version may not yet support this. But in case HAVE_GETRANDOM is not set, otherwise fallback on the poorman version by now.

configure.ac nft configuration: · line 173

Quoted 10 lines
configure.ac +2 -1
 # Checks for header files.
 AC_HEADER_STDC
 AC_HEADER_ASSERT
@@ -158,4 +169,5 @@ nft configuration:
   enable debugging:		${with_debug}
   use mini-gmp:			${with_mini_gmp}
   enable pdf documentation:	${enable_pdf_doc}
-  libxtables support:		${with_libxtables}"
+  libxtables support:		${with_libxtables}
+  arc4random support:		${with_arc4random}"

It would be good to indicate here what random approach we follow, just for the record.

Thanks.

#3 lore raw

Re: [PATCH nft 1/4] src: make hash seed attribute optional

Quoted 48 lines · Pablo Neira Ayuso
Quoted 34 lines · Laura Garcia Liebana

The hash expression requires a seed attribute to call the jhash operation, eg.

 # nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2 \
	seed 0xdeadbeef

With this patch the seed attribute is optional and it's generated by a random function from userspace, eg.

 # nft add rule x y meta mark set jhash ip saddr . ip daddr mod 2

To generate a secure random number it has been included the libbsd library dependency by default, that implements the arc4random() function generator. But it's possible to get rid of this dependency applying the option --without-arc4random during the configure of the package.

---
 configure.ac       | 14 +++++++++++++-
 include/hash.h     | 10 ++++++++++
 src/parser_bison.y |  5 +++++
 tests/py/ip/hash.t |  2 ++
 4 files changed, 30 insertions(+), 1 deletion(-)
configure.ac +0 -0
index 7e0b75c..8c93981 100644
@@ -108,6 +108,17 @@ AC_DEFINE([HAVE_LIBXTABLES], [1], [0])
 AC_SUBST(with_libxtables)
 AM_CONDITIONAL([BUILD_XTABLES], [test "x$with_libxtables" == xyes])
 

configure.ac AC_DEFINE([HAVE_LIBXTABLES], [1], [0]) · line 120

Quoted 10 lines
configure.ac +10 -0
+AC_ARG_WITH([arc4random], [AS_HELP_STRING([--without-arc4random],
+            [disable arc4random (libbsd dev support)])],
+            [], [with_arc4random=yes])
+AS_IF([test "x$with_arc4random" != xno], [
+AC_CHECK_LIB([bsd], [arc4random], ,
+	     AC_MSG_ERROR([No suitable version of libbsd dev found]))
+AC_DEFINE([HAVE_LIBBSD], [1], [])
+])
+AC_SUBST(with_arc4random)
+AM_CONDITIONAL([BUILD_ARC4RANDOM], [test "x$with_arc4random" != xno])

We have getrandom() already around for a while:

Quoted 5 lines

https://lwn.net/Articles/605828/

Main problem is that your libc version may not yet support this. But in case HAVE_GETRANDOM is not set, otherwise fallback on the poorman version by now.

I mean, we can add this to configure.ac:

AC_CHECK_FUNCS(getrandom)

So config.h will define HAVE_GETRANDOM if available. This constant will tell us what implementation we can use for this.

#4 lore raw

PATCH 2/4 src: add offset attribute for hash expression

In reply to Laura Garcia Liebana

Add support to add an offset to the hash generator.

Example:

ct mark set hash ip saddr mod 10 offset 100

This will generate marks with series between 100-110.

---
 include/expression.h                |  1 +
 include/hash.h                      |  3 ++-
 include/linux/netfilter/nf_tables.h |  2 ++
 src/hash.c                          |  9 +++++++--
 src/netlink_delinearize.c           |  5 +++--
 src/netlink_linearize.c             |  1 +
 src/parser_bison.y                  | 15 ++++++++++-----
 src/scanner.l                       |  1 +
 tests/py/ip/hash.t                  |  2 ++
 9 files changed, 29 insertions(+), 10 deletions(-)
include/expression.h +1 -0
index 13ca315..38073ee 100644
@@ -297,6 +297,7 @@ struct expr {
 			struct expr		*expr;
 			uint32_t		mod;
 			uint32_t		seed;
+			uint32_t		offset;
 		} hash;
 	};
 };
include/hash.h +2 -1
index 5350cb2..7883277 100644
@@ -12,6 +12,7 @@
 #endif
 
 extern struct expr *hash_expr_alloc(const struct location *loc,
-				    uint32_t modulus, uint32_t seed);
+				    uint32_t modulus, uint32_t seed,
+				    uint32_t offset);
 
 #endif /* NFTABLES_HASH_H */
include/linux/netfilter/nf_tables.h +2 -0
index b21a844..335102d 100644
@@ -760,6 +760,7 @@ enum nft_meta_keys {
  * @NFTA_HASH_LEN: source data length (NLA_U32)
  * @NFTA_HASH_MODULUS: modulus value (NLA_U32)
  * @NFTA_HASH_SEED: seed value (NLA_U32)
+ * @NFTA_HASH_OFFSET: offset value (NLA_U32)
  */
 enum nft_hash_attributes {
 	NFTA_HASH_UNSPEC,
@@ -768,6 +769,7 @@ enum nft_hash_attributes {
 	NFTA_HASH_LEN,
 	NFTA_HASH_MODULUS,
 	NFTA_HASH_SEED,
+	NFTA_HASH_OFFSET,
 	__NFTA_HASH_MAX,
 };
 #define NFTA_HASH_MAX	(__NFTA_HASH_MAX - 1)
src/hash.c +7 -2
index 125b320..d26b2ed 100644
@@ -22,13 +22,16 @@ static void hash_expr_print(const struct expr *expr)
 	printf(" mod %u", expr->hash.mod);
 	if (expr->hash.seed)
 		printf(" seed 0x%x", expr->hash.seed);
+	if (expr->hash.offset)
+		printf(" offset %u", expr->hash.offset);
 }
 
 static bool hash_expr_cmp(const struct expr *e1, const struct expr *e2)
 {
 	return expr_cmp(e1->hash.expr, e2->hash.expr) &&
 	       e1->hash.mod == e2->hash.mod &&
-	       e1->hash.seed == e2->hash.seed;
+	       e1->hash.seed == e2->hash.seed &&
+	       e1->hash.offset == e2->hash.offset;
 }
 
 static void hash_expr_clone(struct expr *new, const struct expr *expr)
@@ -36,6 +39,7 @@ static void hash_expr_clone(struct expr *new, const struct expr *expr)
 	new->hash.expr = expr_clone(expr->hash.expr);
 	new->hash.mod = expr->hash.mod;
 	new->hash.seed = expr->hash.seed;
+	new->hash.offset = expr->hash.offset;
 }
 
 static const struct expr_ops hash_expr_ops = {
@@ -47,7 +51,7 @@ static const struct expr_ops hash_expr_ops = {
 };
 
 struct expr *hash_expr_alloc(const struct location *loc, uint32_t mod,
-			     uint32_t seed)
+			     uint32_t seed, uint32_t offset)
 {
 	struct expr *expr;
 
@@ -55,6 +59,7 @@ struct expr *hash_expr_alloc(const struct location *loc, uint32_t mod,
 			  BYTEORDER_HOST_ENDIAN, 4 * BITS_PER_BYTE);
 	expr->hash.mod  = mod;
 	expr->hash.seed = seed;
+	expr->hash.offset = offset;
 
 	return expr;
 }
src/netlink_delinearize.c +3 -2
index d8d1d7d..7db109d 100644
@@ -513,7 +513,7 @@ static void netlink_parse_hash(struct netlink_parse_ctx *ctx,
 {
 	enum nft_registers sreg, dreg;
 	struct expr *expr, *hexpr;
-	uint32_t mod, seed, len;
+	uint32_t mod, seed, len, offset;
 
 	sreg = netlink_parse_register(nle, NFTNL_EXPR_HASH_SREG);
 	hexpr = netlink_get_register(ctx, loc, sreg);
@@ -521,6 +521,7 @@ static void netlink_parse_hash(struct netlink_parse_ctx *ctx,
 		return netlink_error(ctx, loc,
 				     "hash statement has no expression");
 
+	offset = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_OFFSET);
 	seed = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_SEED);
 	mod  = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_MODULUS);
 	len = nftnl_expr_get_u32(nle, NFTNL_EXPR_HASH_LEN) * BITS_PER_BYTE;
@@ -531,7 +532,7 @@ static void netlink_parse_hash(struct netlink_parse_ctx *ctx,
 			return;
 	}
 
-	expr = hash_expr_alloc(loc, mod, seed);
+	expr = hash_expr_alloc(loc, mod, seed, offset);
 	expr->hash.expr = hexpr;
 
 	dreg = netlink_parse_register(nle, NFTNL_EXPR_HASH_DREG);
src/netlink_linearize.c +1 -0
index 0072dca..117ea8c 100644
@@ -122,6 +122,7 @@ static void netlink_gen_hash(struct netlink_linearize_ctx *ctx,
 			   div_round_up(expr->hash.expr->len, BITS_PER_BYTE));
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_MODULUS, expr->hash.mod);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_SEED, expr->hash.seed);
+	nftnl_expr_set_u32(nle, NFTNL_EXPR_HASH_OFFSET, expr->hash.offset);
 	nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
src/parser_bison.y +10 -5
index 0fa469d..bb9320d 100644
@@ -413,6 +413,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 
 %token JHASH			"jhash"
 %token SEED			"seed"
+%token OFFSET			"offset"
 
 %token POSITION			"position"
 %token COMMENT			"comment"
@@ -561,7 +562,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <val>			arp_hdr_field
 %type <expr>			ip_hdr_expr	icmp_hdr_expr		numgen_expr	hash_expr
 %destructor { expr_free($$); }	ip_hdr_expr	icmp_hdr_expr		numgen_expr	hash_expr
-%type <val>			ip_hdr_field	icmp_hdr_field
+%type <val>			ip_hdr_field	icmp_hdr_field		offset_opt
 %type <expr>			ip6_hdr_expr    icmp6_hdr_expr
 %destructor { expr_free($$); }	ip6_hdr_expr	icmp6_hdr_expr
 %type <val>			ip6_hdr_field   icmp6_hdr_field
@@ -2480,18 +2481,22 @@ numgen_expr		:	NUMGEN	numgen_type	MOD	NUM
 			}
 			;
 
-hash_expr		:	JHASH	expr	MOD	NUM	SEED	NUM
+hash_expr		:	JHASH	expr	MOD	NUM	SEED	NUM	offset_opt
 			{
-				$$ = hash_expr_alloc(&@$, $4, $6);
+				$$ = hash_expr_alloc(&@$, $4, $6, $7);
 				$$->hash.expr = $2;
 			}
-			|	JHASH	expr	MOD	NUM
+			|	JHASH	expr	MOD	NUM	offset_opt
 			{
-				$$ = hash_expr_alloc(&@$, $4, getrandom());
+				$$ = hash_expr_alloc(&@$, $4, getrandom(), $5);
 				$$->hash.expr = $2;
 			}
 			;
 
+offset_opt		:	/* empty */	{ $$ = 0; }
+			|	OFFSET	NUM	{ $$ = $2; }
+			;
+
 ct_expr			: 	CT	ct_key
 			{
 				$$ = ct_expr_alloc(&@$, $2, -1);
src/scanner.l +1 -0
index 8b5a383..868b77b 100644
@@ -473,6 +473,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 
 "jhash"			{ return JHASH; }
 "seed"			{ return SEED; }
+"offset"		{ return OFFSET; }
 
 "dup"			{ return DUP; }
 "fwd"			{ return FWD; }
tests/py/ip/hash.t +2 -0
index 85f9b18..27a9dbe 100644
@@ -2,6 +2,8 @@
 *ip;test-ip4;pre
 
 ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef;ok
+ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100;ok
 ct mark set jhash ip saddr . ip daddr mod 2;ok
+ct mark set jhash ip saddr . ip daddr mod 2 offset 100;ok
 dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
 dnat to jhash ip saddr mod 2 map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
Signature · 1 line
2.9.3
#5 lore raw

Re: [PATCH nft 2/4] src: add offset attribute for hash expression

Quoted 5 lines · Laura Garcia Liebana

Add support to add an offset to the hash generator.

Example:

ct mark set hash ip saddr mod 10 offset 100

This patch depends on the random seed that you posted in 1/4. Please, address 1/4 comments and resubmit.

Thanks a lot!

#6 lore raw

PATCH 3/4 src: add offset attribute for numgen expression

In reply to Laura Garcia Liebana

Add support to add an offset to the numgen generated value.

Example:

ct mark set numgen inc mod 2 offset 100

This will generate marks with serie like 100, 101, 100, ...

---
 include/expression.h                |  1 +
 include/linux/netfilter/nf_tables.h |  2 ++
 include/numgen.h                    |  3 ++-
 src/netlink_delinearize.c           |  5 +++--
 src/netlink_linearize.c             |  1 +
 src/numgen.c                        | 10 ++++++++--
 src/parser_bison.y                  |  4 ++--
 tests/py/ip/numgen.t                |  1 +
 8 files changed, 20 insertions(+), 7 deletions(-)
include/expression.h +1 -0
index 38073ee..960c21e 100644
@@ -291,6 +291,7 @@ struct expr {
 			/* EXPR_NUMGEN */
 			enum nft_ng_types	type;
 			uint32_t		mod;
+			uint32_t		offset;
 		} numgen;
 		struct {
 			/* EXPR_HASH */
include/linux/netfilter/nf_tables.h +2 -0
index 335102d..73cf897 100644
@@ -1159,12 +1159,14 @@ enum nft_trace_types {
  * @NFTA_NG_DREG: destination register (NLA_U32)
  * @NFTA_NG_MODULUS: maximum counter value (NLA_U32)
  * @NFTA_NG_TYPE: operation type (NLA_U32)
+ * @NFTA_NG_OFFSET: offset value (NLA_U32)
  */
 enum nft_ng_attributes {
 	NFTA_NG_UNSPEC,
 	NFTA_NG_DREG,
 	NFTA_NG_MODULUS,
 	NFTA_NG_TYPE,
+	NFTA_NG_OFFSET,
 	__NFTA_NG_MAX
 };
 #define NFTA_NG_MAX	(__NFTA_NG_MAX - 1)
include/numgen.h +2 -1
index bec18e5..b230620 100644
@@ -2,6 +2,7 @@
 #define NFTABLES_NUMGEN_H
 
 extern struct expr *numgen_expr_alloc(const struct location *loc,
-				      enum nft_ng_types type, uint32_t until);
+				      enum nft_ng_types type, uint32_t until,
+				      uint32_t offset);
 
 #endif /* NFTABLES_NUMGEN_H */
src/netlink_delinearize.c +3 -2
index 7db109d..1f14456 100644
@@ -591,13 +591,14 @@ static void netlink_parse_numgen(struct netlink_parse_ctx *ctx,
 				 const struct nftnl_expr *nle)
 {
 	enum nft_registers dreg;
-	uint32_t type, until;
+	uint32_t type, until, offset;
 	struct expr *expr;
 
 	type  = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_TYPE);
 	until = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_MODULUS);
+	offset = nftnl_expr_get_u32(nle, NFTNL_EXPR_NG_OFFSET);
 
-	expr = numgen_expr_alloc(loc, type, until);
+	expr = numgen_expr_alloc(loc, type, until, offset);
 	dreg = netlink_parse_register(nle, NFTNL_EXPR_NG_DREG);
 	netlink_set_register(ctx, dreg, expr);
 }
src/netlink_linearize.c +1 -0
index 117ea8c..15a8953 100644
@@ -183,6 +183,7 @@ static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx,
 	netlink_put_register(nle, NFTNL_EXPR_NG_DREG, dreg);
 	netlink_put_register(nle, NFTNL_EXPR_NG_TYPE, expr->numgen.type);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_MODULUS, expr->numgen.mod);
+	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_OFFSET, expr->numgen.offset);
 	nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
src/numgen.c +8 -2
index d9a43aa..5c1d00a 100644
@@ -32,18 +32,22 @@ static void numgen_expr_print(const struct expr *expr)
 {
 	printf("numgen %s mod %u", numgen_type_str(expr->numgen.type),
 	       expr->numgen.mod);
+	if (expr->numgen.offset)
+		printf(" offset %u", expr->numgen.offset);
 }
 
 static bool numgen_expr_cmp(const struct expr *e1, const struct expr *e2)
 {
 	return e1->numgen.type == e2->numgen.type &&
-	       e1->numgen.mod == e2->numgen.mod;
+	       e1->numgen.mod == e2->numgen.mod &&
+	       e1->numgen.offset == e2->numgen.offset;
 }
 
 static void numgen_expr_clone(struct expr *new, const struct expr *expr)
 {
 	new->numgen.type = expr->numgen.type;
 	new->numgen.mod = expr->numgen.mod;
+	new->numgen.offset = expr->numgen.offset;
 }
 
 static const struct expr_ops numgen_expr_ops = {
@@ -55,7 +59,8 @@ static const struct expr_ops numgen_expr_ops = {
 };
 
 struct expr *numgen_expr_alloc(const struct location *loc,
-			       enum nft_ng_types type, uint32_t mod)
+			       enum nft_ng_types type, uint32_t mod,
+			       uint32_t offset)
 {
 	struct expr *expr;
 
@@ -63,6 +68,7 @@ struct expr *numgen_expr_alloc(const struct location *loc,
 			  BYTEORDER_HOST_ENDIAN, 4 * BITS_PER_BYTE);
 	expr->numgen.type  = type;
 	expr->numgen.mod   = mod;
+	expr->numgen.offset = offset;
 
 	return expr;
 }
src/parser_bison.y +2 -2
index bb9320d..0c03a55 100644
@@ -2475,9 +2475,9 @@ numgen_type		:	INC		{ $$ = NFT_NG_INCREMENTAL; }
 			|	RANDOM		{ $$ = NFT_NG_RANDOM; }
 			;
 
-numgen_expr		:	NUMGEN	numgen_type	MOD	NUM
+numgen_expr		:	NUMGEN	numgen_type	MOD	NUM	offset_opt
 			{
-				$$ = numgen_expr_alloc(&@$, $2, $4);
+				$$ = numgen_expr_alloc(&@$, $2, $4, $5);
 			}
 			;
 
tests/py/ip/numgen.t +1 -0
index 9ce0c71..29a6a10 100644
@@ -2,5 +2,6 @@
 *ip;test-ip4;pre
 
 ct mark set numgen inc mod 2;ok
+ct mark set numgen inc mod 2 offset 100;ok
 dnat to numgen inc mod 2 map { 0 : 192.168.10.100, 1 : 192.168.20.200 };ok
 dnat to numgen inc mod 10 map { 0-5 : 192.168.10.100, 6-9 : 192.168.20.200};ok
Signature · 1 line
2.9.3
maintainer Applied
#7 lore raw

Re: [PATCH nft 3/4] src: add offset attribute for numgen expression

Quoted 7 lines · Laura Garcia Liebana

Add support to add an offset to the numgen generated value.

Example:

ct mark set numgen inc mod 2 offset 100

This will generate marks with serie like 100, 101, 100, ...

Applied this patch, thanks Laura.

#8 lore raw

PATCH 4/4 netlink: fix linearize numgen type

In reply to Laura Garcia Liebana

Avoid to treat numgen type attribute as a register.

Fixes 345236211715 ("src: add hash expression")
---
 src/netlink_linearize.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
src/netlink_linearize.c +1 -1
index 15a8953..66552ac 100644
@@ -181,7 +181,7 @@ static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx,
 
 	nle = alloc_nft_expr("numgen");
 	netlink_put_register(nle, NFTNL_EXPR_NG_DREG, dreg);
-	netlink_put_register(nle, NFTNL_EXPR_NG_TYPE, expr->numgen.type);
+	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_TYPE, expr->numgen.type);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_MODULUS, expr->numgen.mod);
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_OFFSET, expr->numgen.offset);
 	nftnl_rule_add_expr(ctx->nlr, nle);
Signature · 1 line
2.9.3
#9 lore raw

Re: [PATCH nft 4/4] netlink: fix linearize numgen type

Quoted 1 line · Laura Garcia Liebana

Avoid to treat numgen type attribute as a register.

Also applied, thanks.