Instead of using the map expression, store dynamic key and data separately since they need special handling than constant maps. Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- include/statement.h | 3 ++- src/evaluate.c | 25 ++++++++++++++++++++++++- src/netlink_delinearize.c | 7 ++++++- src/netlink_linearize.c | 21 +++++++++++---------- src/parser_bison.y | 3 ++- src/statement.c | 7 ++++--- 6 files changed, 49 insertions(+), 17 deletions(-) diff --git a/include/statement.h b/include/statement.h index 7840e9d261da..6c583a918eb9 100644 --- a/include/statement.h +++ b/include/statement.h @@ -193,7 +193,8 @@ extern struct stmt *set_stmt_alloc(const struct location *loc); struct map_stmt { struct expr *set; - struct expr *map; + struct expr *key; + struct expr *data; enum nft_dynset_ops op; }; diff --git a/src/evaluate.c b/src/evaluate.c index 3f15b322d503..9bc67d8f71f1 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2714,8 +2714,31 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt) static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt) { - if (expr_evaluate(ctx, &stmt->map.map->map) < 0) + expr_set_context(&ctx->ectx, NULL, 0); + if (expr_evaluate(ctx, &stmt->map.set) < 0) return -1; + if (stmt->map.set->ops->type != EXPR_SET_REF) + return expr_error(ctx->msgs, stmt->map.set, + "Expression does not refer to a set"); + + if (stmt_evaluate_arg(ctx, stmt, + stmt->map.set->set->key->dtype, + stmt->map.set->set->key->len, + stmt->map.set->set->key->byteorder, + &stmt->map.key) < 0) + return -1; + if (expr_is_constant(stmt->map.key)) + return expr_error(ctx->msgs, stmt->map.key, + "Key expression can not be constant"); + if (stmt->map.key->comment != NULL) + return expr_error(ctx->msgs, stmt->map.key, + "Key expression comments are not supported"); + if (expr_is_constant(stmt->map.data)) + return expr_error(ctx->msgs, stmt->map.data, + "Data expression can not be constant"); + if (stmt->map.data->comment != NULL) + return expr_error(ctx->msgs, stmt->map.data, + "Data expression comments are not supported"); return 0; } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index dbf1f6186a3d..898c737f9b28 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -1321,7 +1321,8 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx, } else if (expr_data != NULL) { stmt = map_stmt_alloc(loc); stmt->map.set = set_ref_expr_alloc(loc, set); - stmt->map.map = map_expr_alloc(loc, expr, expr_data); + stmt->map.key = expr; + stmt->map.data = expr_data; stmt->map.op = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP); } else { stmt = set_stmt_alloc(loc); @@ -2508,6 +2509,10 @@ static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *r case STMT_SET: expr_postprocess(&rctx, &stmt->set.key); break; + case STMT_MAP: + expr_postprocess(&rctx, &stmt->map.key); + expr_postprocess(&rctx, &stmt->map.data); + break; case STMT_DUP: if (stmt->dup.to != NULL) expr_postprocess(&rctx, &stmt->dup.to); diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 442c5a940bc3..821fcd0a6377 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -1274,26 +1274,27 @@ static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx, static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx, const struct stmt *stmt) { - struct nftnl_expr *nle; - enum nft_registers sreg_key; + struct set *set = stmt->map.set->set; enum nft_registers sreg_data; + enum nft_registers sreg_key; + struct nftnl_expr *nle; - sreg_key = get_register(ctx, stmt->map.map->map->key); - netlink_gen_expr(ctx, stmt->map.map->map->key, sreg_key); + sreg_key = get_register(ctx, stmt->map.key); + netlink_gen_expr(ctx, stmt->map.key, sreg_key); - sreg_data = get_register(ctx, stmt->map.map->mappings); - netlink_gen_expr(ctx, stmt->map.map->mappings, sreg_data); + sreg_data = get_register(ctx, stmt->map.data); + netlink_gen_expr(ctx, stmt->map.data, sreg_data); - release_register(ctx, stmt->map.map->map->key); - release_register(ctx, stmt->map.map->mappings); + release_register(ctx, stmt->map.key); + release_register(ctx, stmt->map.data); nle = alloc_nft_expr("dynset"); netlink_put_register(nle, NFTNL_EXPR_DYNSET_SREG_KEY, sreg_key); netlink_put_register(nle, NFTNL_EXPR_DYNSET_SREG_DATA, sreg_data); nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_OP, stmt->map.op); - nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, stmt->map.set->identifier); - nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, stmt->map.set->set->handle.set_id); + nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, set->handle.set.name); + nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id); nftnl_rule_add_expr(ctx->nlr, nle); } diff --git a/src/parser_bison.y b/src/parser_bison.y index bc6f72779dd7..199ef13d8c1d 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -2872,7 +2872,8 @@ map_stmt : set_stmt_op symbol_expr '{' set_elem_expr_stmt COLON set_elem_expr_s { $$ = map_stmt_alloc(&@$); $$->map.op = $1; - $$->map.map = map_expr_alloc(&@$, $4, $6); + $$->map.key = $4; + $$->map.data = $6; $$->map.set = $2; } ; diff --git a/src/statement.c b/src/statement.c index cec83c19e529..039ca943e92c 100644 --- a/src/statement.c +++ b/src/statement.c @@ -657,15 +657,16 @@ static void map_stmt_print(const struct stmt *stmt, struct output_ctx *octx) nft_print(octx, "%s ", set_stmt_op_names[stmt->map.op]); expr_print(stmt->map.set, octx); nft_print(octx, " { "); - expr_print(stmt->map.map->map->key, octx); + expr_print(stmt->map.key, octx); nft_print(octx, " : "); - expr_print(stmt->map.map->mappings, octx); + expr_print(stmt->map.data, octx); nft_print(octx, " }"); } static void map_stmt_destroy(struct stmt *stmt) { - expr_free(stmt->map.map); + expr_free(stmt->map.key); + expr_free(stmt->map.data); expr_free(stmt->map.set); } -- 2.11.0