@@ -307,6 +307,7 @@ struct expr {
struct expr *expr;
uint32_t mod;
uint32_t seed;
+ uint32_t offset;
} hash;
struct {
/* EXPR_FIB */
@@ -14,6 +14,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 */
@@ -773,6 +773,7 @@ enum nft_rt_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,
@@ -781,6 +782,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)
@@ -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;
}
@@ -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);
@@ -136,6 +136,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);
}
@@ -2580,14 +2580,14 @@ numgen_expr : NUMGEN numgen_type MOD NUM offset_opt
}
;
-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, selrandom());
+ $$ = hash_expr_alloc(&@$, $4, selrandom(), $5);
$$->hash.expr = $2;
}
;
@@ -2,4 +2,5 @@
*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
dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 };ok
@@ -5,6 +5,13 @@ ip test-ip4 pre
[ hash reg 1 = jhash(reg 2, 8, 0xdeadbeef) % mod 2 ]
[ ct set mark with reg 1 ]
+# ct mark set jhash ip saddr . ip daddr mod 2 seed 0xdeadbeef offset 100
+ip test-ip4 pre
+ [ payload load 4b @ network header + 12 => reg 2 ]
+ [ payload load 4b @ network header + 16 => reg 13 ]
+ [ hash reg 1 = jhash(reg 2, 8, 0xdeadbeef) % mod 2 offset 100 ]
+ [ ct set mark with reg 1 ]
+
# dnat to jhash ip saddr mod 2 seed 0xdeadbeef map { 0 : 192.168.20.100, 1 : 192.168.30.100 }
__map%d test-ip4 b
__map%d test-ip4 0
Add support to add an offset to the hash generator, eg. ct mark set hash ip saddr mod 10 offset 100 This will generate marks with series between 100-109. Signed-off-by: Laura Garcia Liebana <nevola@gmail.com> --- Changes in v2: - Adapt the code to the repository changes. - Include test payload. - This patch depends on 1/4 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 | 8 ++++---- tests/py/ip/hash.t | 1 + tests/py/ip/hash.t.payload | 7 +++++++ 9 files changed, 28 insertions(+), 9 deletions(-)