This patch introduces a map as a numgen attribute, which permits to lookup a value based on the numgen result as the key. This approach only supports named maps. Signed-off-by: Laura Garcia Liebana <nevola@xxxxxxxxx> --- include/expression.h | 1 + include/linux/netfilter/nf_tables.h | 4 ++++ include/numgen.h | 2 +- src/expression.c | 3 ++- src/netlink_delinearize.c | 18 ++++++++++++++++-- src/netlink_linearize.c | 8 ++++++++ src/numgen.c | 13 +++++++++++-- src/parser_bison.y | 16 ++++++++++++---- 8 files changed, 55 insertions(+), 10 deletions(-) diff --git a/include/expression.h b/include/expression.h index f0ba6fc..8158579 100644 --- a/include/expression.h +++ b/include/expression.h @@ -309,6 +309,7 @@ struct expr { enum nft_ng_types type; uint32_t mod; uint32_t offset; + struct expr *ng_map; } numgen; struct { /* EXPR_HASH */ diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 517a39a..8612fe1 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -1382,6 +1382,8 @@ enum nft_trace_types { * @NFTA_NG_MODULUS: maximum counter value (NLA_U32) * @NFTA_NG_TYPE: operation type (NLA_U32) * @NFTA_NG_OFFSET: offset to be added to the counter (NLA_U32) + * @NFTA_NG_SET_NAME: name of the map to lookup (NLA_STRING) + * @NFTA_NG_SET_ID: if of the map (NLA_U32) */ enum nft_ng_attributes { NFTA_NG_UNSPEC, @@ -1389,6 +1391,8 @@ enum nft_ng_attributes { NFTA_NG_MODULUS, NFTA_NG_TYPE, NFTA_NG_OFFSET, + NFTA_NG_SET_NAME, + NFTA_NG_SET_ID, __NFTA_NG_MAX }; #define NFTA_NG_MAX (__NFTA_NG_MAX - 1) diff --git a/include/numgen.h b/include/numgen.h index b230620..60eaa37 100644 --- a/include/numgen.h +++ b/include/numgen.h @@ -3,6 +3,6 @@ extern struct expr *numgen_expr_alloc(const struct location *loc, enum nft_ng_types type, uint32_t until, - uint32_t offset); + uint32_t offset, struct expr *mappings); #endif /* NFTABLES_NUMGEN_H */ diff --git a/src/expression.c b/src/expression.c index e698b14..53393ec 100644 --- a/src/expression.c +++ b/src/expression.c @@ -945,7 +945,8 @@ static void map_expr_print(const struct expr *expr, struct output_ctx *octx) static void map_expr_clone(struct expr *new, const struct expr *expr) { - new->map = expr_clone(expr->map); + if (expr->map) + new->map = expr_clone(expr->map); new->mappings = expr_clone(expr->mappings); } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 2126cf2..a270a92 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -668,13 +668,27 @@ static void netlink_parse_numgen(struct netlink_parse_ctx *ctx, { enum nft_registers dreg; uint32_t type, until, offset; - struct expr *expr; + const char *name; + struct expr *expr, *right, *map_expr = NULL; + struct set *map; 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, offset); + name = nftnl_expr_get_str(nle, NFTNL_EXPR_NG_SET_NAME); + if (name != NULL) { + map = set_lookup(ctx->table, name); + if (map == NULL) { + return netlink_error(ctx, loc, + "Unknown map '%s' in numgen expression", + name); + } + right = set_ref_expr_alloc(loc, map); + map_expr = map_expr_alloc(loc, NULL, right); + } + + expr = numgen_expr_alloc(loc, type, until, offset, map_expr); dreg = netlink_parse_register(nle, NFTNL_EXPR_NG_DREG); netlink_set_register(ctx, dreg, expr); } diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 6c49969..6f8fdc7 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -218,6 +218,14 @@ static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx, 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); + + if (expr->numgen.ng_map) { + nftnl_expr_set_str(nle, NFTNL_EXPR_NG_SET_NAME, + expr->numgen.ng_map->mappings->identifier); + nftnl_expr_set_u32(nle, NFTNL_EXPR_NG_SET_ID, + expr->numgen.ng_map->mappings->set->handle.set_id); + } + nftnl_rule_add_expr(ctx->nlr, nle); } diff --git a/src/numgen.c b/src/numgen.c index aa6da49..cf35a407 100644 --- a/src/numgen.c +++ b/src/numgen.c @@ -35,13 +35,18 @@ static void numgen_expr_print(const struct expr *expr, struct output_ctx *octx) expr->numgen.mod); if (expr->numgen.offset) nft_print(octx, " offset %u", expr->numgen.offset); + if (expr->numgen.ng_map) { + nft_print(octx, " "); + expr_print(expr->numgen.ng_map->mappings, octx); + } } 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.offset == e2->numgen.offset; + e1->numgen.offset == e2->numgen.offset && + expr_cmp(e1->numgen.ng_map, e2->numgen.ng_map); } static void numgen_expr_clone(struct expr *new, const struct expr *expr) @@ -49,6 +54,8 @@ 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; + if (expr->numgen.ng_map) + new->numgen.ng_map = expr_clone(expr->numgen.ng_map); } static const struct expr_ops numgen_expr_ops = { @@ -61,7 +68,7 @@ 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, - uint32_t offset) + uint32_t offset, struct expr *mappings) { struct expr *expr; @@ -70,6 +77,8 @@ struct expr *numgen_expr_alloc(const struct location *loc, expr->numgen.type = type; expr->numgen.mod = mod; expr->numgen.offset = offset; + if (mappings) + expr->numgen.ng_map = mappings; return expr; } diff --git a/src/parser_bison.y b/src/parser_bison.y index f546b9e..4a010e6 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -660,8 +660,8 @@ int nft_lex(void *, void *, void *); %type <expr> arp_hdr_expr %destructor { expr_free($$); } arp_hdr_expr %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 <expr> ip_hdr_expr icmp_hdr_expr numgen_expr numgen_map_expr hash_expr +%destructor { expr_free($$); } ip_hdr_expr icmp_hdr_expr numgen_expr numgen_map_expr hash_expr %type <val> ip_hdr_field icmp_hdr_field %type <expr> ip6_hdr_expr icmp6_hdr_expr %destructor { expr_free($$); } ip6_hdr_expr icmp6_hdr_expr @@ -3509,12 +3509,20 @@ numgen_type : INC { $$ = NFT_NG_INCREMENTAL; } | RANDOM { $$ = NFT_NG_RANDOM; } ; -numgen_expr : NUMGEN numgen_type MOD NUM offset_opt +numgen_map_expr : /* empty */ { $$ = NULL; } + | symbol_expr { - $$ = numgen_expr_alloc(&@$, $2, $4, $5); + $$ = map_expr_alloc(&@$, NULL, $1); + $$->flags |= NFT_SET_OBJECT; } ; +numgen_expr : NUMGEN numgen_type MOD NUM offset_opt numgen_map_expr + { + $$ = numgen_expr_alloc(&@$, $2, $4, $5, $6); + } + ; + hash_expr : JHASH expr MOD NUM SEED NUM offset_opt { $$ = hash_expr_alloc(&@$, $4, true, $6, $7, NFT_HASH_JENKINS); -- 2.11.0 -- 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