* [PATCH nft 0/4] detach concat, list and set expression layouts
@ 2025-07-08 23:23 Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 1/4] evaluate: mappings require set expression Pablo Neira Ayuso
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2025-07-08 23:23 UTC (permalink / raw)
To: netfilter-devel
Hi,
These three expressions use the same layout but they have a different
purpose, it is better to split them in independent layouts.
The compound expression still remains in place, there, the initial
layout to store the list of expressions and size is still in the same
in these expressions.
The initial three patch address type confusions uncovered by patch
4/4 in this series.
This is implicitly reducing the size of one of the largest structs
in the union area of struct expr, still EXPR_SET_ELEM remains the
largest so no gain is achieved in this iteration.
Pablo Neira Ayuso (4):
evaluate: mappings require set expression
evaluate: validate set expression type before accessing flags
src: convert set to list expression
src: detach set, list and concatenation expression layout
include/expression.h | 22 ++++-
src/cmd.c | 5 +-
src/evaluate.c | 185 ++++++++++++++++++++++++--------------
src/expression.c | 41 ++++-----
src/intervals.c | 80 ++++++++---------
src/json.c | 10 +--
src/mergesort.c | 2 +-
src/mnl.c | 13 ++-
src/monitor.c | 2 +-
src/netlink.c | 26 +++---
src/netlink_delinearize.c | 14 +--
src/netlink_linearize.c | 2 +-
src/optimize.c | 22 ++---
src/parser_bison.y | 2 +-
src/parser_json.c | 5 +-
src/rule.c | 4 +-
src/segtree.c | 22 ++---
17 files changed, 261 insertions(+), 196 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH nft 1/4] evaluate: mappings require set expression
2025-07-08 23:23 [PATCH nft 0/4] detach concat, list and set expression layouts Pablo Neira Ayuso
@ 2025-07-08 23:23 ` Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 2/4] evaluate: validate set expression type before accessing flags Pablo Neira Ayuso
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2025-07-08 23:23 UTC (permalink / raw)
To: netfilter-devel
While EXPR_CONCAT and EXPR_LIST share the same layout in struct expr,
these expressions are not possible at this stage.
Fall back to error out with "invalid mapping expression".
Fixes: 02d44b4f9917 ("evaluate: fix expression data corruption")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index a2d5d7c29514..83381b4ef3d0 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2211,8 +2211,6 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
mappings = map->mappings;
switch (map->mappings->etype) {
- case EXPR_CONCAT:
- case EXPR_LIST:
case EXPR_SET:
set_flags |= mappings->set_flags;
/* fallthrough */
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH nft 2/4] evaluate: validate set expression type before accessing flags
2025-07-08 23:23 [PATCH nft 0/4] detach concat, list and set expression layouts Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 1/4] evaluate: mappings require set expression Pablo Neira Ayuso
@ 2025-07-08 23:23 ` Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 3/4] src: convert set to list expression Pablo Neira Ayuso
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2025-07-08 23:23 UTC (permalink / raw)
To: netfilter-devel
Validate set->init is of EXPR_SET before accessing set_flags.
Fixes: 81e36530fcac ("src: replace interval segment tree overlap and automerge")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 83381b4ef3d0..f4f72ee4a4f7 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5290,7 +5290,8 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
set->flags |= NFT_SET_EXPR;
if (set_is_anonymous(set->flags)) {
- if (set_is_interval(set->init->set_flags) &&
+ if (set->init->etype == EXPR_SET &&
+ set_is_interval(set->init->set_flags) &&
!(set->init->set_flags & NFT_SET_CONCAT) &&
interval_set_eval(ctx, set, set->init) < 0)
return -1;
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH nft 3/4] src: convert set to list expression
2025-07-08 23:23 [PATCH nft 0/4] detach concat, list and set expression layouts Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 1/4] evaluate: mappings require set expression Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 2/4] evaluate: validate set expression type before accessing flags Pablo Neira Ayuso
@ 2025-07-08 23:23 ` Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 4/4] src: detach set, list and concatenation expression layout Pablo Neira Ayuso
2025-07-09 13:58 ` [PATCH nft 0/4] detach concat, list and set expression layouts Florian Westphal
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2025-07-08 23:23 UTC (permalink / raw)
To: netfilter-devel
The following definition:
define xyz = { "dummy0", "dummy1" }
is represented as a set expression to ease integration with sets.
However, this definition can be used in chains and flowtables to specify
the devices, for instance:
table netdev x {
chain y {
type filter hook ingress devices = $xyz priority 0; policy drop;
}
}
in this context, $xyz defines a _list_ of devices, not a set.
Transform the set to list expression from the evaluation step for chains
and flowtables.
This patch also handles:
define xyz = { "dummy0", $abc }
where $abc is also transformed to a list expression in the context of
chains and flowtables.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 66 +++++++++++++++++++++++++++++++++++++++++++-------
src/mnl.c | 1 -
2 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index f4f72ee4a4f7..fb6c4e06ae32 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5393,9 +5393,54 @@ static bool evaluate_expr_variable(struct eval_ctx *ctx, struct expr **exprp)
return true;
}
-static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
+static struct expr *expr_set_to_list(struct eval_ctx *ctx, struct expr *dev_expr)
{
struct expr *expr, *next, *key;
+ struct location loc;
+ LIST_HEAD(tmp);
+
+ list_for_each_entry_safe(expr, next, &dev_expr->expressions, list) {
+ list_del(&expr->list);
+
+ switch (expr->etype) {
+ case EXPR_VARIABLE:
+ expr_set_context(&ctx->ectx, &ifname_type,
+ IFNAMSIZ * BITS_PER_BYTE);
+ if (!evaluate_expr_variable(ctx, &expr))
+ return false;
+
+ if (expr->etype == EXPR_SET) {
+ expr = expr_set_to_list(ctx, expr);
+ list_splice_init(&expr->expressions, &tmp);
+ expr_free(expr);
+ continue;
+ }
+ break;
+ case EXPR_SET_ELEM:
+ key = expr_clone(expr->key);
+ expr_free(expr);
+ expr = key;
+ break;
+ case EXPR_VALUE:
+ break;
+ default:
+ break;
+ }
+
+ list_add(&expr->list, &tmp);
+ }
+
+ loc = dev_expr->location;
+ expr_free(dev_expr);
+ dev_expr = compound_expr_alloc(&loc, EXPR_LIST);
+ list_splice_init(&tmp, &dev_expr->expressions);
+
+ return dev_expr;
+}
+
+static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
+{
+ struct expr *expr, *next;
LIST_HEAD(tmp);
if ((*dev_expr)->etype == EXPR_VARIABLE) {
@@ -5405,9 +5450,10 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
return false;
}
- if ((*dev_expr)->etype != EXPR_SET &&
- (*dev_expr)->etype != EXPR_LIST)
- return true;
+ if ((*dev_expr)->etype == EXPR_SET)
+ *dev_expr = expr_set_to_list(ctx, *dev_expr);
+
+ assert((*dev_expr)->etype == EXPR_LIST);
list_for_each_entry_safe(expr, next, &(*dev_expr)->expressions, list) {
list_del(&expr->list);
@@ -5418,11 +5464,13 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
IFNAMSIZ * BITS_PER_BYTE);
if (!evaluate_expr_variable(ctx, &expr))
return false;
- break;
- case EXPR_SET_ELEM:
- key = expr_clone(expr->key);
- expr_free(expr);
- expr = key;
+
+ if (expr->etype == EXPR_SET) {
+ expr = expr_set_to_list(ctx, expr);
+ list_splice_init(&expr->expressions, &tmp);
+ expr_free(expr);
+ continue;
+ }
break;
case EXPR_VALUE:
break;
diff --git a/src/mnl.c b/src/mnl.c
index 8a8dc4d6ef1c..cc20908fd636 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -757,7 +757,6 @@ static struct nft_dev *nft_dev_array(const struct expr *dev_expr, int *num_devs)
struct expr *expr;
switch (dev_expr->etype) {
- case EXPR_SET:
case EXPR_LIST:
list_for_each_entry(expr, &dev_expr->expressions, list)
len++;
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH nft 4/4] src: detach set, list and concatenation expression layout
2025-07-08 23:23 [PATCH nft 0/4] detach concat, list and set expression layouts Pablo Neira Ayuso
` (2 preceding siblings ...)
2025-07-08 23:23 ` [PATCH nft 3/4] src: convert set to list expression Pablo Neira Ayuso
@ 2025-07-08 23:23 ` Pablo Neira Ayuso
2025-07-09 13:58 ` [PATCH nft 0/4] detach concat, list and set expression layouts Florian Westphal
4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2025-07-08 23:23 UTC (permalink / raw)
To: netfilter-devel
These three expressions use the same layout, but they have a different
purpose. Several fields are specific of a given expression:
- set_flags is only required by set expressions.
- field_len and field_count are only used by concatenation expressions.
Add accessors to validate the expression type before accessing the union
fields:
#define expr_set(__expr) (assert((__expr)->etype == EXPR_SET), &(__expr)->expr_set)
#define expr_concat(__expr) (assert((__expr)->etype == EXPR_CONCAT), &(__expr)->expr_concat)
#define expr_list(__expr) (assert((__expr)->etype == EXPR_LIST), &(__expr)->expr_list)
This should help catch subtle bugs due to type confusion.
assert() could be later enabled only in debugging builds to run tests,
keep it by now.
compound_expr_*() still works and it needs the same initial layout for
all of these expressions:
struct list_head expressions;
unsigned int size;
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/expression.h | 22 +++++--
src/cmd.c | 5 +-
src/evaluate.c | 124 +++++++++++++++++++-------------------
src/expression.c | 41 +++++++------
src/intervals.c | 80 ++++++++++++------------
src/json.c | 10 +--
src/mergesort.c | 2 +-
src/mnl.c | 12 ++--
src/monitor.c | 2 +-
src/netlink.c | 26 ++++----
src/netlink_delinearize.c | 14 ++---
src/netlink_linearize.c | 2 +-
src/optimize.c | 22 +++----
src/parser_bison.y | 2 +-
src/parser_json.c | 5 +-
src/rule.c | 4 +-
src/segtree.c | 22 +++----
17 files changed, 207 insertions(+), 188 deletions(-)
diff --git a/include/expression.h b/include/expression.h
index f42a0c2b3419..5b60c1b0825e 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -293,14 +293,24 @@ struct expr {
struct expr *prefix;
unsigned int prefix_len;
};
- struct {
- /* EXPR_CONCAT, EXPR_LIST, EXPR_SET */
+ struct expr_concat {
+ /* EXPR_CONCAT */
struct list_head expressions;
unsigned int size;
- uint32_t set_flags;
uint8_t field_len[NFT_REG32_COUNT];
uint8_t field_count;
- };
+ } expr_concat;
+ struct expr_set {
+ /* EXPR_SET */
+ struct list_head expressions;
+ unsigned int size;
+ uint32_t set_flags;
+ } expr_set;
+ struct expr_list {
+ /* EXPR_LIST */
+ struct list_head expressions;
+ unsigned int size;
+ } expr_list;
struct {
/* EXPR_SET_REF */
struct set *set;
@@ -403,6 +413,10 @@ struct expr {
};
};
+#define expr_set(__expr) (assert((__expr)->etype == EXPR_SET), &(__expr)->expr_set)
+#define expr_concat(__expr) (assert((__expr)->etype == EXPR_CONCAT), &(__expr)->expr_concat)
+#define expr_list(__expr) (assert((__expr)->etype == EXPR_LIST), &(__expr)->expr_list)
+
extern struct expr *expr_alloc(const struct location *loc,
enum expr_types etype,
const struct datatype *dtype,
diff --git a/src/cmd.c b/src/cmd.c
index eb44b986a49a..ff634af2ac24 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -398,8 +398,9 @@ bool nft_cmd_collapse_elems(enum cmd_ops op, struct list_head *cmds,
strcmp(last_cmd->handle.set.name, handle->set.name))
return false;
- list_splice_tail_init(&init->expressions, &last_cmd->expr->expressions);
- last_cmd->expr->size += init->size;
+ list_splice_tail_init(&expr_set(init)->expressions,
+ &expr_set(last_cmd->expr)->expressions);
+ expr_set(last_cmd->expr)->size += expr_set(init)->size;
return true;
}
diff --git a/src/evaluate.c b/src/evaluate.c
index fb6c4e06ae32..1fa4cb784a88 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -191,7 +191,7 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr,
if ((*expr)->etype == EXPR_CONCAT) {
struct expr *i, *next, *unary;
- list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_concat(*expr)->expressions, list) {
if (i->byteorder == BYTEORDER_BIG_ENDIAN)
continue;
@@ -1669,12 +1669,12 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
if (ctx->ectx.key && ctx->ectx.key->etype == EXPR_CONCAT) {
key_ctx = ctx->ectx.key;
- assert(!list_empty(&ctx->ectx.key->expressions));
- key = list_first_entry(&ctx->ectx.key->expressions, struct expr, list);
- expressions = &ctx->ectx.key->expressions;
+ assert(!list_empty(&expr_concat(ctx->ectx.key)->expressions));
+ key = list_first_entry(&expr_concat(ctx->ectx.key)->expressions, struct expr, list);
+ expressions = &expr_concat(ctx->ectx.key)->expressions;
}
- list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_concat(*expr)->expressions, list) {
enum byteorder bo = BYTEORDER_INVALID;
unsigned dsize_bytes, dsize = 0;
@@ -1798,7 +1798,7 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
ntype = concat_subtype_add(ntype, i->dtype->type);
dsize_bytes = div_round_up(dsize, BITS_PER_BYTE);
- (*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
+ expr_concat(*expr)->field_len[expr_concat(*expr)->field_count++] = dsize_bytes;
size += netlink_padded_len(dsize);
if (key && expressions) {
if (list_is_last(&key->list, expressions))
@@ -1839,7 +1839,7 @@ static int expr_evaluate_list(struct eval_ctx *ctx, struct expr **expr)
mpz_t val;
mpz_init_set_ui(val, 0);
- list_for_each_entry_safe(i, next, &list->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_list(list)->expressions, list) {
if (list_member_evaluate(ctx, &i) < 0) {
mpz_clear(val);
return -1;
@@ -1943,7 +1943,7 @@ static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
key = elem->key;
goto err_missing_flag;
case EXPR_CONCAT:
- list_for_each_entry(key, &elem->key->expressions, list) {
+ list_for_each_entry(key, &expr_concat(elem->key)->expressions, list) {
switch (key->etype) {
case EXPR_PREFIX:
case EXPR_RANGE:
@@ -2039,7 +2039,7 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
struct expr *set = *expr, *i, *next;
const struct expr *elem;
- list_for_each_entry_safe(i, next, &set->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(set)->expressions, list) {
if (list_member_evaluate(ctx, &i) < 0)
return -1;
@@ -2048,12 +2048,12 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
i->left->key->etype == EXPR_SET) {
struct expr *new, *j;
- list_for_each_entry(j, &i->left->key->expressions, list) {
+ list_for_each_entry(j, &expr_set(i->left->key)->expressions, list) {
new = mapping_expr_alloc(&i->location,
expr_get(j),
expr_get(i->right));
- list_add_tail(&new->list, &set->expressions);
- set->size++;
+ list_add_tail(&new->list, &expr_set(set)->expressions);
+ expr_set(set)->size++;
}
list_del(&i->list);
expr_free(i);
@@ -2071,7 +2071,7 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
elem->key->etype == EXPR_SET) {
struct expr *new = expr_get(elem->key);
- set->set_flags |= elem->key->set_flags;
+ expr_set(set)->set_flags |= expr_set(elem->key)->set_flags;
list_replace(&i->list, &new->list);
expr_free(i);
i = new;
@@ -2084,24 +2084,24 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
if (i->etype == EXPR_SET) {
/* Merge recursive set definitions */
- list_splice_tail_init(&i->expressions, &i->list);
+ list_splice_tail_init(&expr_set(i)->expressions, &i->list);
list_del(&i->list);
- set->size += i->size - 1;
- set->set_flags |= i->set_flags;
+ expr_set(set)->size += expr_set(i)->size - 1;
+ expr_set(set)->set_flags |= expr_set(i)->set_flags;
expr_free(i);
} else if (!expr_is_singleton(i)) {
- set->set_flags |= NFT_SET_INTERVAL;
+ expr_set(set)->set_flags |= NFT_SET_INTERVAL;
if (elem->key->etype == EXPR_CONCAT)
- set->set_flags |= NFT_SET_CONCAT;
+ expr_set(set)->set_flags |= NFT_SET_CONCAT;
}
}
if (ctx->set) {
if (ctx->set->flags & NFT_SET_CONCAT)
- set->set_flags |= NFT_SET_CONCAT;
+ expr_set(set)->set_flags |= NFT_SET_CONCAT;
}
- set->set_flags |= NFT_SET_CONSTANT;
+ expr_set(set)->set_flags |= NFT_SET_CONSTANT;
datatype_set(set, ctx->ectx.dtype);
set->len = ctx->ectx.len;
@@ -2114,13 +2114,15 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr);
static void map_set_concat_info(struct expr *map)
{
- map->mappings->set->flags |= map->mappings->set->init->set_flags;
+ map->mappings->set->flags |= expr_set(map->mappings->set->init)->set_flags;
if (map->mappings->set->flags & NFT_SET_INTERVAL &&
map->map->etype == EXPR_CONCAT) {
- memcpy(&map->mappings->set->desc.field_len, &map->map->field_len,
+ memcpy(&map->mappings->set->desc.field_len,
+ &expr_concat(map->map)->field_len,
sizeof(map->mappings->set->desc.field_len));
- map->mappings->set->desc.field_count = map->map->field_count;
+ map->mappings->set->desc.field_count =
+ expr_concat(map->map)->field_count;
map->mappings->flags |= NFT_SET_CONCAT;
}
}
@@ -2137,7 +2139,7 @@ static void __mapping_expr_expand(struct expr *i)
i->right = range;
break;
case EXPR_CONCAT:
- list_for_each_entry_safe(j, next, &i->right->expressions, list) {
+ list_for_each_entry_safe(j, next, &expr_concat(i->right)->expressions, list) {
if (j->etype != EXPR_VALUE)
continue;
@@ -2159,7 +2161,7 @@ static int mapping_expr_expand(struct eval_ctx *ctx)
if (!set_is_anonymous(ctx->set->flags))
return 0;
- list_for_each_entry(i, &ctx->set->init->expressions, list) {
+ list_for_each_entry(i, &expr_set(ctx->set->init)->expressions, list) {
if (i->etype != EXPR_MAPPING)
return expr_error(ctx->msgs, i,
"expected mapping, not %s", expr_name(i));
@@ -2191,7 +2193,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
else if (map->map->etype == EXPR_CONCAT) {
struct expr *i;
- list_for_each_entry(i, &map->map->expressions, list) {
+ list_for_each_entry(i, &expr_concat(map->map)->expressions, list) {
if (i->etype == EXPR_CT &&
(i->ct.key == NFT_CT_SRC ||
i->ct.key == NFT_CT_DST))
@@ -2212,7 +2214,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
switch (map->mappings->etype) {
case EXPR_SET:
- set_flags |= mappings->set_flags;
+ set_flags |= expr_set(mappings)->set_flags;
/* fallthrough */
case EXPR_VARIABLE:
if (ctx->ectx.key && ctx->ectx.key->etype == EXPR_CONCAT) {
@@ -2262,8 +2264,8 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
"Expression is not a map");
}
- if (set_is_interval(map->mappings->set->init->set_flags) &&
- !(map->mappings->set->init->set_flags & NFT_SET_CONCAT) &&
+ if (set_is_interval(expr_set(map->mappings->set->init)->set_flags) &&
+ !(expr_set(map->mappings->set->init)->set_flags & NFT_SET_CONCAT) &&
interval_set_eval(ctx, ctx->set, map->mappings->set->init) < 0)
return -1;
@@ -2333,7 +2335,7 @@ static bool data_mapping_has_interval(struct expr *data)
if (data->etype != EXPR_CONCAT)
return false;
- list_for_each_entry(i, &data->expressions, list) {
+ list_for_each_entry(i, &expr_concat(data)->expressions, list) {
if (i->etype == EXPR_RANGE ||
i->etype == EXPR_RANGE_VALUE ||
i->etype == EXPR_PREFIX)
@@ -2639,12 +2641,12 @@ static int __binop_transfer(struct eval_ctx *ctx,
return -1;
break;
case EXPR_SET:
- list_for_each_entry(i, &(*right)->expressions, list) {
+ list_for_each_entry(i, &expr_set(*right)->expressions, list) {
err = binop_can_transfer(ctx, left, i);
if (err <= 0)
return err;
}
- list_for_each_entry_safe(i, next, &(*right)->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(*right)->expressions, list) {
list_del(&i->list);
err = binop_transfer_one(ctx, left, &i);
list_add_tail(&i->list, &next->list);
@@ -2710,7 +2712,7 @@ static void optimize_singleton_set(struct expr *rel, struct expr **expr)
{
struct expr *set = rel->right, *i;
- i = list_first_entry(&set->expressions, struct expr, list);
+ i = list_first_entry(&expr_set(set)->expressions, struct expr, list);
if (i->etype == EXPR_SET_ELEM &&
list_empty(&i->stmt_list)) {
@@ -2819,7 +2821,7 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
case OP_EQ:
case OP_IMPLICIT:
case OP_NEQ:
- if (right->etype == EXPR_SET && right->size == 1)
+ if (right->etype == EXPR_SET && expr_set(right)->size == 1)
optimize_singleton_set(rel, &right);
break;
default:
@@ -2868,14 +2870,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
return -1;
break;
case EXPR_SET:
- if (right->size == 0)
+ if (expr_set(right)->size == 0)
return expr_error(ctx->msgs, right, "Set is empty");
right = rel->right =
implicit_set_declaration(ctx, "__set%d",
expr_get(left), NULL,
right,
- right->set_flags | NFT_SET_ANONYMOUS);
+ expr_set(right)->set_flags | NFT_SET_ANONYMOUS);
if (!right)
return -1;
@@ -3633,12 +3635,12 @@ static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
set = set_expr_alloc(&key->location, existing_set);
if (key->timeout)
- set->set_flags |= NFT_SET_TIMEOUT;
+ expr_set(set)->set_flags |= NFT_SET_TIMEOUT;
- set->set_flags |= NFT_SET_EVAL;
+ expr_set(set)->set_flags |= NFT_SET_EVAL;
setref = implicit_set_declaration(ctx, stmt->meter.name,
expr_get(key), NULL, set,
- NFT_SET_EVAL | set->set_flags);
+ NFT_SET_EVAL | expr_set(set)->set_flags);
if (setref)
setref->set->desc.size = stmt->meter.size;
}
@@ -4168,7 +4170,7 @@ static bool nat_evaluate_addr_has_th_expr(const struct expr *map)
if (concat ->etype != EXPR_CONCAT)
return false;
- list_for_each_entry(i, &concat->expressions, list) {
+ list_for_each_entry(i, &expr_concat(concat)->expressions, list) {
enum proto_bases base;
if (i->etype == EXPR_PAYLOAD &&
@@ -4245,7 +4247,7 @@ static void expr_family_infer(struct proto_ctx *pctx, const struct expr *expr,
if (expr->etype == EXPR_MAP) {
switch (expr->map->etype) {
case EXPR_CONCAT:
- list_for_each_entry(i, &expr->map->expressions, list) {
+ list_for_each_entry(i, &expr_concat(expr->map)->expressions, list) {
if (i->etype == EXPR_PAYLOAD) {
if (i->payload.desc == &proto_ip)
*family = NFPROTO_IPV4;
@@ -4356,10 +4358,10 @@ static int stmt_evaluate_nat_map(struct eval_ctx *ctx, struct stmt *stmt)
goto out;
}
- one = list_first_entry(&data->expressions, struct expr, list);
+ one = list_first_entry(&expr_concat(data)->expressions, struct expr, list);
two = list_entry(one->list.next, struct expr, list);
- if (one == two || !list_is_last(&two->list, &data->expressions)) {
+ if (one == two || !list_is_last(&two->list, &expr_concat(data)->expressions)) {
err = __stmt_evaluate_arg(ctx, stmt, dtype, dtype->size,
BYTEORDER_BIG_ENDIAN,
&stmt->nat.addr);
@@ -4397,7 +4399,7 @@ static bool nat_concat_map(struct eval_ctx *ctx, struct stmt *stmt)
switch (stmt->nat.addr->mappings->etype) {
case EXPR_SET:
- list_for_each_entry(i, &stmt->nat.addr->mappings->expressions, list) {
+ list_for_each_entry(i, &expr_set(stmt->nat.addr->mappings)->expressions, list) {
if (i->etype == EXPR_MAPPING &&
i->right->etype == EXPR_CONCAT) {
stmt->nat.type_flags |= STMT_NAT_F_CONCAT;
@@ -4867,7 +4869,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
switch (map->mappings->etype) {
case EXPR_SET:
- set_flags |= mappings->set_flags;
+ set_flags |= expr_set(mappings)->set_flags;
/* fallthrough */
case EXPR_VARIABLE:
key = constant_expr_alloc(&stmt->location,
@@ -4893,8 +4895,8 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
"Expression is not a map");
}
- if (set_is_interval(map->mappings->set->init->set_flags) &&
- !(map->mappings->set->init->set_flags & NFT_SET_CONCAT) &&
+ if (set_is_interval(expr_set(map->mappings->set->init)->set_flags) &&
+ !(expr_set(map->mappings->set->init)->set_flags & NFT_SET_CONCAT) &&
interval_set_eval(ctx, ctx->set, map->mappings->set->init) < 0)
return -1;
@@ -5054,7 +5056,7 @@ static int setelem_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
return -1;
assert(cmd->expr->etype == EXPR_SET);
- cmd->expr->set_flags |= NFT_SET_INTERVAL;
+ expr_set(cmd->expr)->set_flags |= NFT_SET_INTERVAL;
}
ctx->set = NULL;
@@ -5082,7 +5084,7 @@ static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
uint32_t ntype = 0, size = 0;
struct expr *i, *next;
- list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_concat(*expr)->expressions, list) {
unsigned dsize_bytes;
if (i->etype == EXPR_CT &&
@@ -5117,7 +5119,7 @@ static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
if (i->dtype->size)
assert(dsize_bytes == div_round_up(i->dtype->size, BITS_PER_BYTE));
- (*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
+ expr_concat(*expr)->field_len[expr_concat(*expr)->field_count++] = dsize_bytes;
size += netlink_padded_len(i->len);
if (size > NFT_MAX_EXPR_LEN_BITS)
@@ -5228,9 +5230,9 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
}
if (set->flags & NFT_SET_INTERVAL && set->key->etype == EXPR_CONCAT) {
- memcpy(&set->desc.field_len, &set->key->field_len,
+ memcpy(&set->desc.field_len, &expr_concat(set->key)->field_len,
sizeof(set->desc.field_len));
- set->desc.field_count = set->key->field_count;
+ set->desc.field_count = expr_concat(set->key)->field_count;
set->flags |= NFT_SET_CONCAT;
if (set->automerge)
@@ -5240,7 +5242,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
if (set_is_anonymous(set->flags) && set->key->etype == EXPR_CONCAT) {
struct expr *i;
- list_for_each_entry(i, &set->init->expressions, list) {
+ list_for_each_entry(i, &expr_set(set->init)->expressions, list) {
if ((i->etype == EXPR_SET_ELEM &&
i->key->etype != EXPR_CONCAT &&
i->key->etype != EXPR_SET_ELEM_CATCHALL) ||
@@ -5291,8 +5293,8 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
if (set_is_anonymous(set->flags)) {
if (set->init->etype == EXPR_SET &&
- set_is_interval(set->init->set_flags) &&
- !(set->init->set_flags & NFT_SET_CONCAT) &&
+ set_is_interval(expr_set(set->init)->set_flags) &&
+ !(expr_set(set->init)->set_flags & NFT_SET_CONCAT) &&
interval_set_eval(ctx, set, set->init) < 0)
return -1;
@@ -5399,7 +5401,7 @@ static struct expr *expr_set_to_list(struct eval_ctx *ctx, struct expr *dev_expr
struct location loc;
LIST_HEAD(tmp);
- list_for_each_entry_safe(expr, next, &dev_expr->expressions, list) {
+ list_for_each_entry_safe(expr, next, &expr_set(dev_expr)->expressions, list) {
list_del(&expr->list);
switch (expr->etype) {
@@ -5411,7 +5413,7 @@ static struct expr *expr_set_to_list(struct eval_ctx *ctx, struct expr *dev_expr
if (expr->etype == EXPR_SET) {
expr = expr_set_to_list(ctx, expr);
- list_splice_init(&expr->expressions, &tmp);
+ list_splice_init(&expr_list(expr)->expressions, &tmp);
expr_free(expr);
continue;
}
@@ -5433,7 +5435,7 @@ static struct expr *expr_set_to_list(struct eval_ctx *ctx, struct expr *dev_expr
loc = dev_expr->location;
expr_free(dev_expr);
dev_expr = compound_expr_alloc(&loc, EXPR_LIST);
- list_splice_init(&tmp, &dev_expr->expressions);
+ list_splice_init(&tmp, &expr_list(dev_expr)->expressions);
return dev_expr;
}
@@ -5455,7 +5457,7 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
assert((*dev_expr)->etype == EXPR_LIST);
- list_for_each_entry_safe(expr, next, &(*dev_expr)->expressions, list) {
+ list_for_each_entry_safe(expr, next, &expr_list(*dev_expr)->expressions, list) {
list_del(&expr->list);
switch (expr->etype) {
@@ -5467,7 +5469,7 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
if (expr->etype == EXPR_SET) {
expr = expr_set_to_list(ctx, expr);
- list_splice_init(&expr->expressions, &tmp);
+ list_splice_init(&expr_list(expr)->expressions, &tmp);
expr_free(expr);
continue;
}
@@ -5481,7 +5483,7 @@ static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr)
list_add(&expr->list, &tmp);
}
- list_splice_init(&tmp, &(*dev_expr)->expressions);
+ list_splice_init(&tmp, &expr_list(*dev_expr)->expressions);
return true;
}
diff --git a/src/expression.c b/src/expression.c
index aa97413d0794..8cb639797284 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -940,7 +940,7 @@ void relational_expr_pctx_update(struct proto_ctx *ctx,
if (expr_is_singleton(right))
ops->pctx_update(ctx, &expr->location, left, right);
else if (right->etype == EXPR_SET) {
- list_for_each_entry(i, &right->expressions, list) {
+ list_for_each_entry(i, &expr_set(right)->expressions, list) {
if (i->etype == EXPR_SET_ELEM &&
i->key->etype == EXPR_VALUE)
ops->pctx_update(ctx, &expr->location, left, i->key);
@@ -1022,7 +1022,8 @@ struct expr *compound_expr_alloc(const struct location *loc,
struct expr *expr;
expr = expr_alloc(loc, etype, &invalid_type, BYTEORDER_INVALID, 0);
- init_list_head(&expr->expressions);
+ /* same layout for EXPR_CONCAT, EXPR_SET and EXPR_LIST. */
+ init_list_head(&expr->expr_set.expressions);
return expr;
}
@@ -1030,8 +1031,8 @@ static void compound_expr_clone(struct expr *new, const struct expr *expr)
{
struct expr *i;
- init_list_head(&new->expressions);
- list_for_each_entry(i, &expr->expressions, list)
+ init_list_head(&new->expr_set.expressions);
+ list_for_each_entry(i, &expr->expr_set.expressions, list)
compound_expr_add(new, expr_clone(i));
}
@@ -1039,7 +1040,7 @@ static void compound_expr_destroy(struct expr *expr)
{
struct expr *i, *next;
- list_for_each_entry_safe(i, next, &expr->expressions, list)
+ list_for_each_entry_safe(i, next, &expr->expr_set.expressions, list)
expr_free(i);
}
@@ -1049,7 +1050,7 @@ static void compound_expr_print(const struct expr *expr, const char *delim,
const struct expr *i;
const char *d = "";
- list_for_each_entry(i, &expr->expressions, list) {
+ list_for_each_entry(i, &expr->expr_set.expressions, list) {
nft_print(octx, "%s", d);
expr_print(i, octx);
d = delim;
@@ -1058,13 +1059,13 @@ static void compound_expr_print(const struct expr *expr, const char *delim,
void compound_expr_add(struct expr *compound, struct expr *expr)
{
- list_add_tail(&expr->list, &compound->expressions);
- compound->size++;
+ list_add_tail(&expr->list, &compound->expr_set.expressions);
+ compound->expr_set.size++;
}
void compound_expr_remove(struct expr *compound, struct expr *expr)
{
- compound->size--;
+ compound->expr_set.size--;
list_del(&expr->list);
}
@@ -1104,7 +1105,7 @@ static int concat_expr_build_udata(struct nftnl_udata_buf *udbuf,
struct expr *expr, *tmp;
unsigned int i = 0;
- list_for_each_entry_safe(expr, tmp, &concat_expr->expressions, list) {
+ list_for_each_entry_safe(expr, tmp, &expr_concat(concat_expr)->expressions, list) {
struct nftnl_udata *nest_expr;
int err;
@@ -1268,12 +1269,12 @@ struct expr *list_expr_to_binop(struct expr *expr)
{
struct expr *first, *last = NULL, *i;
- assert(!list_empty(&expr->expressions));
+ assert(!list_empty(&expr_list(expr)->expressions));
- first = list_first_entry(&expr->expressions, struct expr, list);
+ first = list_first_entry(&expr_list(expr)->expressions, struct expr, list);
i = first;
- list_for_each_entry_continue(i, &expr->expressions, list) {
+ list_for_each_entry_continue(i, &expr_list(expr)->expressions, list) {
if (first) {
last = binop_expr_alloc(&expr->location, OP_OR, first, i);
first = NULL;
@@ -1285,7 +1286,7 @@ struct expr *list_expr_to_binop(struct expr *expr)
assert(!first);
/* zap list expressions, they have been moved to binop expression. */
- init_list_head(&expr->expressions);
+ init_list_head(&expr_list(expr)->expressions);
expr_free(expr);
return last;
@@ -1300,7 +1301,7 @@ static const char *calculate_delim(const struct expr *expr, int *count,
if (octx->force_newline)
return newline;
- if (set_is_anonymous(expr->set_flags))
+ if (set_is_anonymous(expr_set(expr)->set_flags))
return singleline;
if (!expr->dtype)
@@ -1348,7 +1349,7 @@ static void set_expr_print(const struct expr *expr, struct output_ctx *octx)
nft_print(octx, "{ ");
- list_for_each_entry(i, &expr->expressions, list) {
+ list_for_each_entry(i, &expr_set(expr)->expressions, list) {
nft_print(octx, "%s", d);
expr_print(i, octx);
count++;
@@ -1364,7 +1365,7 @@ static void set_expr_set_type(const struct expr *expr,
{
struct expr *i;
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_set(expr)->expressions, list)
expr_set_type(i, dtype, byteorder);
}
@@ -1385,7 +1386,7 @@ struct expr *set_expr_alloc(const struct location *loc, const struct set *set)
if (!set)
return set_expr;
- set_expr->set_flags = set->flags;
+ expr_set(set_expr)->set_flags = set->flags;
datatype_set(set_expr, set->key->dtype);
return set_expr;
@@ -1443,10 +1444,10 @@ static bool __set_expr_is_vmap(const struct expr *mappings)
{
const struct expr *mapping;
- if (list_empty(&mappings->expressions))
+ if (list_empty(&expr_set(mappings)->expressions))
return false;
- mapping = list_first_entry(&mappings->expressions, struct expr, list);
+ mapping = list_first_entry(&expr_set(mappings)->expressions, struct expr, list);
if (mapping->etype == EXPR_MAPPING &&
mapping->right->etype == EXPR_VERDICT)
return true;
diff --git a/src/intervals.c b/src/intervals.c
index e5bbb0384964..8c8ce8c8a305 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -88,7 +88,7 @@ static void purge_elem(struct set_automerge_ctx *ctx, struct expr *i)
i->key->range.low,
i->key->range.high);
}
- list_move_tail(&i->list, &ctx->purge->expressions);
+ list_move_tail(&i->list, &expr_set(ctx->purge)->expressions);
}
static void remove_overlapping_range(struct set_automerge_ctx *ctx,
@@ -101,7 +101,7 @@ static void remove_overlapping_range(struct set_automerge_ctx *ctx,
}
list_del(&i->list);
expr_free(i);
- ctx->init->size--;
+ expr_set(ctx->init)->size--;
}
struct range {
@@ -129,7 +129,7 @@ static bool merge_ranges(struct set_automerge_ctx *ctx,
mpz_set(prev_range->high, range->high);
list_del(&i->list);
expr_free(i);
- ctx->init->size--;
+ expr_set(ctx->init)->size--;
}
return false;
}
@@ -139,16 +139,16 @@ static void set_sort_splice(struct expr *init, struct set *set)
struct set *existing_set = set->existing_set;
set_to_range(init);
- list_expr_sort(&init->expressions);
+ list_expr_sort(&expr_set(init)->expressions);
if (!existing_set || existing_set->errors)
return;
if (existing_set->init) {
set_to_range(existing_set->init);
- list_splice_sorted(&existing_set->init->expressions,
- &init->expressions);
- init_list_head(&existing_set->init->expressions);
+ list_splice_sorted(&expr_set(existing_set->init)->expressions,
+ &expr_set(init)->expressions);
+ init_list_head(&expr_set(existing_set->init)->expressions);
} else {
existing_set->init = set_expr_alloc(&internal_location, set);
}
@@ -174,7 +174,7 @@ static void setelem_automerge(struct set_automerge_ctx *ctx)
mpz_init(range.high);
mpz_init(rop);
- list_for_each_entry_safe(i, next, &ctx->init->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(ctx->init)->expressions, list) {
if (i->key->etype == EXPR_SET_ELEM_CATCHALL)
continue;
@@ -237,7 +237,7 @@ static void set_to_range(struct expr *init)
{
struct expr *i, *elem;
- list_for_each_entry(i, &init->expressions, list) {
+ list_for_each_entry(i, &expr_set(init)->expressions, list) {
elem = interval_expr_key(i);
setelem_expr_to_range(elem);
}
@@ -258,7 +258,7 @@ int set_automerge(struct list_head *msgs, struct cmd *cmd, struct set *set,
if (set->flags & NFT_SET_MAP) {
set_to_range(init);
- list_expr_sort(&init->expressions);
+ list_expr_sort(&expr_set(init)->expressions);
return 0;
}
@@ -268,9 +268,9 @@ int set_automerge(struct list_head *msgs, struct cmd *cmd, struct set *set,
setelem_automerge(&ctx);
- list_for_each_entry_safe(i, next, &init->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(init)->expressions, list) {
if (i->flags & EXPR_F_KERNEL) {
- list_move_tail(&i->list, &existing_set->init->expressions);
+ list_move_tail(&i->list, &expr_set(existing_set->init)->expressions);
} else if (existing_set) {
if (debug_mask & NFT_DEBUG_SEGTREE) {
pr_gmp_debug("add: [%Zx-%Zx]\n",
@@ -278,11 +278,11 @@ int set_automerge(struct list_head *msgs, struct cmd *cmd, struct set *set,
}
clone = expr_clone(i);
clone->flags |= EXPR_F_KERNEL;
- list_add_tail(&clone->list, &existing_set->init->expressions);
+ list_add_tail(&clone->list, &expr_set(existing_set->init)->expressions);
}
}
- if (list_empty(&ctx.purge->expressions)) {
+ if (list_empty(&expr_set(ctx.purge)->expressions)) {
expr_free(ctx.purge);
return 0;
}
@@ -301,7 +301,7 @@ static void remove_elem(struct expr *prev, struct set *set, struct expr *purge)
if (prev->flags & EXPR_F_KERNEL) {
clone = expr_clone(prev);
- list_move_tail(&clone->list, &purge->expressions);
+ list_move_tail(&clone->list, &expr_set(purge)->expressions);
}
}
@@ -310,7 +310,7 @@ static void __adjust_elem_left(struct set *set, struct expr *prev, struct expr *
prev->flags &= ~EXPR_F_KERNEL;
mpz_set(prev->key->range.low, i->key->range.high);
mpz_add_ui(prev->key->range.low, prev->key->range.low, 1);
- list_move(&prev->list, &set->existing_set->init->expressions);
+ list_move(&prev->list, &expr_set(set->existing_set->init)->expressions);
}
static void adjust_elem_left(struct set *set, struct expr *prev, struct expr *i,
@@ -329,7 +329,7 @@ static void __adjust_elem_right(struct set *set, struct expr *prev, struct expr
prev->flags &= ~EXPR_F_KERNEL;
mpz_set(prev->key->range.high, i->key->range.low);
mpz_sub_ui(prev->key->range.high, prev->key->range.high, 1);
- list_move(&prev->list, &set->existing_set->init->expressions);
+ list_move(&prev->list, &expr_set(set->existing_set->init)->expressions);
}
static void adjust_elem_right(struct set *set, struct expr *prev, struct expr *i,
@@ -352,18 +352,18 @@ static void split_range(struct set *set, struct expr *prev, struct expr *i,
if (prev->flags & EXPR_F_KERNEL) {
clone = expr_clone(prev);
- list_move_tail(&clone->list, &purge->expressions);
+ list_move_tail(&clone->list, &expr_set(purge)->expressions);
}
prev->flags &= ~EXPR_F_KERNEL;
clone = expr_clone(prev);
mpz_set(clone->key->range.low, i->key->range.high);
mpz_add_ui(clone->key->range.low, i->key->range.high, 1);
- list_add_tail(&clone->list, &set->existing_set->init->expressions);
+ list_add_tail(&clone->list, &expr_set(set->existing_set->init)->expressions);
mpz_set(prev->key->range.high, i->key->range.low);
mpz_sub_ui(prev->key->range.high, i->key->range.low, 1);
- list_move(&prev->list, &set->existing_set->init->expressions);
+ list_move(&prev->list, &expr_set(set->existing_set->init)->expressions);
list_del(&i->list);
expr_free(i);
@@ -407,7 +407,7 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
mpz_init(range.high);
mpz_init(rop);
- list_for_each_entry_safe(elem, next, &elems->expressions, list) {
+ list_for_each_entry_safe(elem, next, &expr_set(elems)->expressions, list) {
i = interval_expr_key(elem);
if (i->key->etype == EXPR_SET_ELEM_CATCHALL) {
@@ -437,7 +437,7 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
if (elem->flags & EXPR_F_REMOVE) {
if (prev->flags & EXPR_F_KERNEL) {
prev->location = elem->location;
- list_move_tail(&prev->list, &purge->expressions);
+ list_move_tail(&prev->list, &expr_set(purge)->expressions);
}
list_del(&elem->list);
@@ -476,7 +476,7 @@ static void automerge_delete(struct list_head *msgs, struct set *set,
};
ctx.purge = set_expr_alloc(&internal_location, set);
- list_expr_sort(&init->expressions);
+ list_expr_sort(&expr_set(init)->expressions);
setelem_automerge(&ctx);
expr_free(ctx.purge);
}
@@ -486,8 +486,8 @@ static int __set_delete(struct list_head *msgs, struct expr *i, struct set *set,
unsigned int debug_mask)
{
i->flags |= EXPR_F_REMOVE;
- list_move_tail(&i->list, &existing_set->init->expressions);
- list_expr_sort(&existing_set->init->expressions);
+ list_move_tail(&i->list, &expr_set(existing_set->init)->expressions);
+ list_expr_sort(&expr_set(existing_set->init)->expressions);
return setelem_delete(msgs, set, init, existing_set->init, debug_mask);
}
@@ -513,38 +513,38 @@ int set_delete(struct list_head *msgs, struct cmd *cmd, struct set *set,
existing_set->init = set_expr_alloc(&internal_location, set);
}
- list_splice_init(&init->expressions, &del_list);
+ list_splice_init(&expr_set(init)->expressions, &del_list);
list_for_each_entry_safe(i, next, &del_list, list) {
err = __set_delete(msgs, i, set, init, existing_set, debug_mask);
if (err < 0) {
- list_splice(&del_list, &init->expressions);
+ list_splice(&del_list, &expr_set(init)->expressions);
return err;
}
}
add = set_expr_alloc(&internal_location, set);
- list_for_each_entry(i, &existing_set->init->expressions, list) {
+ list_for_each_entry(i, &expr_set(existing_set->init)->expressions, list) {
if (!(i->flags & EXPR_F_KERNEL)) {
clone = expr_clone(i);
- list_add_tail(&clone->list, &add->expressions);
+ list_add_tail(&clone->list, &expr_set(add)->expressions);
i->flags |= EXPR_F_KERNEL;
}
}
if (debug_mask & NFT_DEBUG_SEGTREE) {
- list_for_each_entry(i, &init->expressions, list)
+ list_for_each_entry(i, &expr_set(init)->expressions, list)
pr_gmp_debug("remove: [%Zx-%Zx]\n",
i->key->range.low, i->key->range.high);
- list_for_each_entry(i, &add->expressions, list)
+ list_for_each_entry(i, &expr_set(add)->expressions, list)
pr_gmp_debug("add: [%Zx-%Zx]\n",
i->key->range.low, i->key->range.high);
- list_for_each_entry(i, &existing_set->init->expressions, list)
+ list_for_each_entry(i, &expr_set(existing_set->init)->expressions, list)
pr_gmp_debug("existing: [%Zx-%Zx]\n",
i->key->range.low, i->key->range.high);
}
- if (list_empty(&add->expressions)) {
+ if (list_empty(&expr_set(add)->expressions)) {
expr_free(add);
return 0;
}
@@ -571,7 +571,7 @@ static int setelem_overlap(struct list_head *msgs, struct set *set,
mpz_init(range.high);
mpz_init(rop);
- list_for_each_entry_safe(elem, next, &init->expressions, list) {
+ list_for_each_entry_safe(elem, next, &expr_set(init)->expressions, list) {
i = interval_expr_key(elem);
if (i->key->etype == EXPR_SET_ELEM_CATCHALL)
@@ -640,13 +640,13 @@ int set_overlap(struct list_head *msgs, struct set *set, struct expr *init)
err = setelem_overlap(msgs, set, init);
- list_for_each_entry_safe(i, n, &init->expressions, list) {
+ list_for_each_entry_safe(i, n, &expr_set(init)->expressions, list) {
if (i->flags & EXPR_F_KERNEL)
- list_move_tail(&i->list, &existing_set->init->expressions);
+ list_move_tail(&i->list, &expr_set(existing_set->init)->expressions);
else if (existing_set) {
clone = expr_clone(i);
clone->flags |= EXPR_F_KERNEL;
- list_add_tail(&clone->list, &existing_set->init->expressions);
+ list_add_tail(&clone->list, &expr_set(existing_set->init)->expressions);
}
}
@@ -665,7 +665,7 @@ static bool segtree_needs_first_segment(const struct set *set,
* 4) This set is created with a number of initial elements.
*/
if ((set_is_anonymous(set->flags)) ||
- (set->init && set->init->size == 0) ||
+ (set->init && expr_set(set->init)->size == 0) ||
(set->init == NULL && init) ||
(set->init == init)) {
return true;
@@ -683,7 +683,7 @@ int set_to_intervals(const struct set *set, struct expr *init, bool add)
LIST_HEAD(intervals);
mpz_t p;
- list_for_each_entry_safe(i, n, &init->expressions, list) {
+ list_for_each_entry_safe(i, n, &expr_set(init)->expressions, list) {
elem = interval_expr_key(i);
if (elem->key->etype == EXPR_SET_ELEM_CATCHALL)
@@ -715,7 +715,7 @@ int set_to_intervals(const struct set *set, struct expr *init, bool add)
prev = i;
}
- list_splice_init(&intervals, &init->expressions);
+ list_splice_init(&intervals, &expr_set(init)->expressions);
return 0;
}
diff --git a/src/json.c b/src/json.c
index f0430776851c..5d34b27eb915 100644
--- a/src/json.c
+++ b/src/json.c
@@ -232,11 +232,11 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
if (set->automerge)
json_object_set_new(root, "auto-merge", json_true());
- if (!nft_output_terse(octx) && set->init && set->init->size > 0) {
+ if (!nft_output_terse(octx) && set->init && expr_set(set->init)->size > 0) {
json_t *array = json_array();
const struct expr *i;
- list_for_each_entry(i, &set->init->expressions, list)
+ list_for_each_entry(i, &expr_set(set->init)->expressions, list)
json_array_append_new(array, expr_print_json(i, octx));
json_object_set_new(root, "elem", array);
@@ -658,7 +658,7 @@ json_t *concat_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *array = json_array();
const struct expr *i;
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list)
json_array_append_new(array, expr_print_json(i, octx));
return nft_json_pack("{s:o}", "concat", array);
@@ -669,7 +669,7 @@ json_t *set_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *array = json_array();
const struct expr *i;
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_set(expr)->expressions, list)
json_array_append_new(array, expr_print_json(i, octx));
return nft_json_pack("{s:o}", "set", array);
@@ -738,7 +738,7 @@ json_t *list_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *array = json_array();
const struct expr *i;
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_list(expr)->expressions, list)
json_array_append_new(array, expr_print_json(i, octx));
//return nft_json_pack("{s:s, s:o}", "type", "list", "val", array);
diff --git a/src/mergesort.c b/src/mergesort.c
index 0452d60ad42b..bd1c21877b21 100644
--- a/src/mergesort.c
+++ b/src/mergesort.c
@@ -18,7 +18,7 @@ static void concat_expr_msort_value(const struct expr *expr, mpz_t value)
const struct expr *i;
char data[512];
- list_for_each_entry(i, &expr->expressions, list) {
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list) {
ilen = div_round_up(i->len, BITS_PER_BYTE);
mpz_export_data(data + len, i->value, i->byteorder, ilen);
len += ilen;
diff --git a/src/mnl.c b/src/mnl.c
index cc20908fd636..e6da401374ad 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -758,12 +758,12 @@ static struct nft_dev *nft_dev_array(const struct expr *dev_expr, int *num_devs)
switch (dev_expr->etype) {
case EXPR_LIST:
- list_for_each_entry(expr, &dev_expr->expressions, list)
+ list_for_each_entry(expr, &expr_list(dev_expr)->expressions, list)
len++;
dev_array = xmalloc(sizeof(struct nft_dev) * len);
- list_for_each_entry(expr, &dev_expr->expressions, list) {
+ list_for_each_entry(expr, &expr_list(dev_expr)->expressions, list) {
nft_dev_add(dev_array, expr, i);
i++;
}
@@ -1793,7 +1793,7 @@ static int mnl_nft_setelem_batch(const struct nftnl_set *nls, struct cmd *cmd,
flags |= NLM_F_CREATE;
if (init)
- expr = list_first_entry(&init->expressions, struct expr, list);
+ expr = list_first_entry(&expr_set(init)->expressions, struct expr, list);
next:
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch), msg_type,
@@ -1813,16 +1813,16 @@ next:
htonl(nftnl_set_get_u32(nls, NFTNL_SET_ID)));
}
- if (!init || list_empty(&init->expressions))
+ if (!init || list_empty(&expr_set(init)->expressions))
return 0;
assert(expr);
nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
- list_for_each_entry_from(expr, &init->expressions, list) {
+ list_for_each_entry_from(expr, &expr_set(init)->expressions, list) {
if (set_is_non_concat_range(set)) {
if (set_is_anonymous(set->flags) &&
- !list_is_last(&expr->list, &init->expressions))
+ !list_is_last(&expr->list, &expr_set(init)->expressions))
next = list_next_entry(expr, list);
else
next = NULL;
diff --git a/src/monitor.c b/src/monitor.c
index e3e38c2a12b7..ecd32d935472 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -402,7 +402,7 @@ static bool netlink_event_range_cache(struct set *cached_set,
}
/* don't cache half-open range elements */
- elem = list_entry(dummyset->init->expressions.prev, struct expr, list);
+ elem = list_entry(expr_set(dummyset->init)->expressions.prev, struct expr, list);
if (!set_elem_is_open_interval(elem) &&
dummyset->desc.field_count <= 1) {
cached_set->rg_cache = expr_clone(elem);
diff --git a/src/netlink.c b/src/netlink.c
index f3157d9d7f1c..d18aeb10b294 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -134,8 +134,8 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
case EXPR_SET_ELEM_CATCHALL:
break;
default:
- if (set->set_flags & NFT_SET_INTERVAL &&
- key->etype == EXPR_CONCAT && key->field_count > 1) {
+ if (expr_set(set)->set_flags & NFT_SET_INTERVAL &&
+ key->etype == EXPR_CONCAT && expr_concat(key)->field_count > 1) {
key->flags |= EXPR_F_INTERVAL;
netlink_gen_key(key, &nld);
key->flags &= ~EXPR_F_INTERVAL;
@@ -201,7 +201,7 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
nftnl_udata_buf_len(udbuf));
nftnl_udata_buf_free(udbuf);
}
- if (set_is_datamap(set->set_flags) && data != NULL) {
+ if (set_is_datamap(expr_set(set)->set_flags) && data != NULL) {
__netlink_gen_data(data, &nld, !(data->flags & EXPR_F_SINGLETON));
switch (data->etype) {
case EXPR_VERDICT:
@@ -226,7 +226,7 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
break;
}
}
- if (set_is_objmap(set->set_flags) && data != NULL) {
+ if (set_is_objmap(expr_set(set)->set_flags) && data != NULL) {
netlink_gen_data(data, &nld);
nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_OBJREF,
nld.value, nld.len);
@@ -361,7 +361,7 @@ static void netlink_gen_concat_key(const struct expr *expr,
memset(data, 0, sizeof(data));
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list)
offset += __netlink_gen_concat_key(expr->flags, i, data + offset);
nft_data_memcpy(nld, data, len);
@@ -425,10 +425,10 @@ static void __netlink_gen_concat_expand(const struct expr *expr,
memset(data, 0, sizeof(data));
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list)
offset += __netlink_gen_concat_data(false, i, data + offset);
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list)
offset += __netlink_gen_concat_data(true, i, data + offset);
nft_data_memcpy(nld, data, len);
@@ -447,7 +447,7 @@ static void __netlink_gen_concat(const struct expr *expr,
memset(data, 0, sizeof(data));
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list)
offset += __netlink_gen_concat_data(expr->flags, i, data + offset);
nft_data_memcpy(nld, data, len);
@@ -1215,7 +1215,7 @@ void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls)
struct nftnl_set_elem *nlse;
const struct expr *expr;
- list_for_each_entry(expr, &set->expressions, list) {
+ list_for_each_entry(expr, &expr_set(set)->expressions, list) {
nlse = alloc_nftnl_setelem(set, expr);
nftnl_set_elem_add(nls, nlse);
}
@@ -1362,7 +1362,7 @@ static struct expr *netlink_parse_concat_elem_key(const struct set *set,
int off = dtype->subtypes;
if (set->key->etype == EXPR_CONCAT)
- n = list_first_entry(&set->key->expressions, struct expr, list);
+ n = list_first_entry(&expr_concat(set->key)->expressions, struct expr, list);
concat = concat_expr_alloc(&data->location);
while (off > 0) {
@@ -1410,7 +1410,7 @@ static struct expr *netlink_parse_concat_elem(const struct set *set,
}
assert(list_empty(&expressions));
} else {
- list_splice_tail(&expressions, &concat->expressions);
+ list_splice_tail(&expressions, &expr_concat(concat)->expressions);
}
expr_free(data);
@@ -1681,7 +1681,7 @@ int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
else if (set->flags & NFT_SET_INTERVAL)
interval_map_decompose(set->init);
else
- list_expr_sort(&ctx->set->init->expressions);
+ list_expr_sort(&expr_set(ctx->set->init)->expressions);
nftnl_set_free(nls);
ctx->set = NULL;
@@ -1725,7 +1725,7 @@ int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
else if (set->flags & NFT_SET_INTERVAL)
err = get_set_decompose(cache_set, set);
else
- list_expr_sort(&ctx->set->init->expressions);
+ list_expr_sort(&expr_set(ctx->set->init)->expressions);
nftnl_set_free(nls);
nftnl_set_free(nls_out);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 48a3e33adc8f..b4d4a3da3b37 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2186,10 +2186,10 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx,
if (set_is_anonymous(set->flags) &&
set->init &&
- !list_empty(&set->init->expressions)) {
+ !list_empty(&expr_set(set->init)->expressions)) {
struct expr *elem;
- elem = list_first_entry(&set->init->expressions, struct expr, list);
+ elem = list_first_entry(&expr_set(set->init)->expressions, struct expr, list);
if (elem->etype == EXPR_SET_ELEM &&
elem->key->etype == EXPR_VALUE)
@@ -2476,7 +2476,7 @@ static void binop_adjust(const struct expr *binop, struct expr *right,
if (!set_is_anonymous(right->set->flags))
break;
- list_for_each_entry(i, &right->set->init->expressions, list) {
+ list_for_each_entry(i, &expr_set(right->set->init)->expressions, list) {
switch (i->key->etype) {
case EXPR_VALUE:
binop_adjust_one(binop, i->key, shift);
@@ -2822,7 +2822,7 @@ static void expr_postprocess_concat(struct rule_pp_ctx *ctx, struct expr **exprp
assert(expr->etype == EXPR_CONCAT);
ctx->flags |= RULE_PP_IN_CONCATENATION;
- list_for_each_entry_safe(i, n, &expr->expressions, list) {
+ list_for_each_entry_safe(i, n, &expr_concat(expr)->expressions, list) {
if (type) {
dtype = concat_subtype_lookup(type, --off);
expr_set_type(i, dtype, dtype->byteorder);
@@ -2834,7 +2834,7 @@ static void expr_postprocess_concat(struct rule_pp_ctx *ctx, struct expr **exprp
ntype = concat_subtype_add(ntype, i->dtype->type);
}
ctx->flags &= ~RULE_PP_IN_CONCATENATION;
- list_splice(&tmp, &expr->expressions);
+ list_splice(&tmp, &expr_concat(expr)->expressions);
__datatype_set(expr, concat_type_alloc(ntype));
}
@@ -2861,7 +2861,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
expr_postprocess(ctx, &expr->right);
break;
case EXPR_SET:
- list_for_each_entry(i, &expr->expressions, list)
+ list_for_each_entry(i, &expr_set(expr)->expressions, list)
expr_postprocess(ctx, &i);
break;
case EXPR_CONCAT:
@@ -3432,7 +3432,7 @@ static bool has_inner_desc(const struct expr *expr)
case EXPR_BINOP:
return has_inner_desc(expr->left);
case EXPR_CONCAT:
- list_for_each_entry(i, &expr->expressions, list) {
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list) {
if (has_inner_desc(i))
return true;
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 5f73183bf19a..8ac33d344de4 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -123,7 +123,7 @@ static void netlink_gen_concat(struct netlink_linearize_ctx *ctx,
{
const struct expr *i;
- list_for_each_entry(i, &expr->expressions, list) {
+ list_for_each_entry(i, &expr_concat(expr)->expressions, list) {
netlink_gen_expr(ctx, i, dreg);
dreg += netlink_register_space(i->len);
}
diff --git a/src/optimize.c b/src/optimize.c
index 89ba0d9dee6a..40756cecbbc3 100644
--- a/src/optimize.c
+++ b/src/optimize.c
@@ -565,7 +565,7 @@ static void merge_expr_stmts(const struct optimize_ctx *ctx,
uint32_t i;
set = set_expr_alloc(&internal_location, NULL);
- set->set_flags |= NFT_SET_ANONYMOUS;
+ expr_set(set)->set_flags |= NFT_SET_ANONYMOUS;
expr_a = stmt_a->expr->right;
elem = set_elem_expr_alloc(&internal_location, expr_get(expr_a));
@@ -588,7 +588,7 @@ static void merge_vmap(const struct optimize_ctx *ctx,
struct expr *mappings, *mapping, *expr;
mappings = stmt_b->expr->mappings;
- list_for_each_entry(expr, &mappings->expressions, list) {
+ list_for_each_entry(expr, &expr_set(mappings)->expressions, list) {
mapping = expr_clone(expr);
compound_expr_add(stmt_a->expr->mappings, mapping);
}
@@ -654,7 +654,7 @@ static void __merge_concat(const struct optimize_ctx *ctx, uint32_t i,
stmt_a = ctx->stmt_matrix[i][merge->stmt[k]];
switch (stmt_a->expr->right->etype) {
case EXPR_SET:
- list_for_each_entry(expr, &stmt_a->expr->right->expressions, list) {
+ list_for_each_entry(expr, &expr_set(stmt_a->expr->right)->expressions, list) {
concat_clone = expr_clone(concat);
clone = expr_clone(expr->key);
compound_expr_add(concat_clone, clone);
@@ -673,7 +673,7 @@ static void __merge_concat(const struct optimize_ctx *ctx, uint32_t i,
compound_expr_add(concat, clone);
break;
case EXPR_LIST:
- list_for_each_entry(expr, &stmt_a->expr->right->expressions, list) {
+ list_for_each_entry(expr, &expr_list(stmt_a->expr->right)->expressions, list) {
concat_clone = expr_clone(concat);
clone = expr_clone(expr);
compound_expr_add(concat_clone, clone);
@@ -727,7 +727,7 @@ static void merge_concat_stmts(const struct optimize_ctx *ctx,
/* build set data contenation, eg. { eth0 . 1.1.1.1 . 22 } */
set = set_expr_alloc(&internal_location, NULL);
- set->set_flags |= NFT_SET_ANONYMOUS;
+ expr_set(set)->set_flags |= NFT_SET_ANONYMOUS;
for (i = from; i <= to; i++)
__merge_concat_stmts(ctx, i, merge, set);
@@ -750,7 +750,7 @@ static void build_verdict_map(struct expr *expr, struct stmt *verdict,
switch (expr->etype) {
case EXPR_LIST:
- list_for_each_entry(item, &expr->expressions, list) {
+ list_for_each_entry(item, &expr_list(expr)->expressions, list) {
elem = set_elem_expr_alloc(&internal_location, expr_get(item));
if (counter) {
counter_elem = counter_stmt_alloc(&counter->location);
@@ -764,7 +764,7 @@ static void build_verdict_map(struct expr *expr, struct stmt *verdict,
stmt_free(counter);
break;
case EXPR_SET:
- list_for_each_entry(item, &expr->expressions, list) {
+ list_for_each_entry(item, &expr_set(expr)->expressions, list) {
elem = set_elem_expr_alloc(&internal_location, expr_get(item->key));
if (counter) {
counter_elem = counter_stmt_alloc(&counter->location);
@@ -851,7 +851,7 @@ static void merge_stmts_vmap(const struct optimize_ctx *ctx,
assert(k >= 0);
set = set_expr_alloc(&internal_location, NULL);
- set->set_flags |= NFT_SET_ANONYMOUS;
+ expr_set(set)->set_flags |= NFT_SET_ANONYMOUS;
expr_a = stmt_a->expr->right;
verdict_a = ctx->stmt_matrix[from][k];
@@ -925,7 +925,7 @@ static void merge_concat_stmts_vmap(const struct optimize_ctx *ctx,
/* build set data contenation, eg. { eth0 . 1.1.1.1 . 22 : accept } */
set = set_expr_alloc(&internal_location, NULL);
- set->set_flags |= NFT_SET_ANONYMOUS;
+ expr_set(set)->set_flags |= NFT_SET_ANONYMOUS;
for (i = from; i <= to; i++) {
verdict = ctx->stmt_matrix[i][k];
@@ -1050,7 +1050,7 @@ static void merge_nat(const struct optimize_ctx *ctx,
assert(k >= 0);
set = set_expr_alloc(&internal_location, NULL);
- set->set_flags |= NFT_SET_ANONYMOUS;
+ expr_set(set)->set_flags |= NFT_SET_ANONYMOUS;
for (i = from; i <= to; i++) {
stmt = ctx->stmt_matrix[i][merge->stmt[0]];
@@ -1102,7 +1102,7 @@ static void merge_concat_nat(const struct optimize_ctx *ctx,
assert(k >= 0);
set = set_expr_alloc(&internal_location, NULL);
- set->set_flags |= NFT_SET_ANONYMOUS;
+ expr_set(set)->set_flags |= NFT_SET_ANONYMOUS;
for (i = from; i <= to; i++) {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index f9cc909836bc..5b84331f220d 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2073,7 +2073,7 @@ chain_block : /* empty */ { $$ = $<chain>-1; }
| chain_block DEVICES '=' flowtable_expr stmt_separator
{
if ($$->dev_expr) {
- list_splice_init(&$4->expressions, &$$->dev_expr->expressions);
+ list_splice_init(&expr_list($4)->expressions, &expr_list($$->dev_expr)->expressions);
expr_free($4);
break;
}
diff --git a/src/parser_json.c b/src/parser_json.c
index 08657f2849a5..bd865de59007 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1286,10 +1286,11 @@ static struct expr *json_parse_binop_expr(struct json_ctx *ctx,
static struct expr *json_check_concat_expr(struct json_ctx *ctx, struct expr *e)
{
- if (e->size >= 2)
+ if (expr_concat(e)->size >= 2)
return e;
- json_error(ctx, "Concatenation with %d elements is illegal", e->size);
+ json_error(ctx, "Concatenation with %d elements is illegal",
+ expr_concat(e)->size);
expr_free(e);
return NULL;
}
diff --git a/src/rule.c b/src/rule.c
index 3e3cc3b0fb7d..0ad948ea87f2 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -424,7 +424,7 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts,
return;
}
- if (set->init != NULL && set->init->size > 0) {
+ if (set->init != NULL && expr_set(set->init)->size > 0) {
nft_print(octx, "%s%selements = ", opts->tab, opts->tab);
if (set->timeout || set->elem_has_comment ||
@@ -1459,7 +1459,7 @@ void cmd_free(struct cmd *cmd)
static int __do_add_elements(struct netlink_ctx *ctx, struct cmd *cmd,
struct set *set, struct expr *expr, uint32_t flags)
{
- expr->set_flags |= set->flags;
+ expr_set(expr)->set_flags |= set->flags;
if (mnl_nft_setelem_add(ctx, cmd, set, expr, flags) < 0)
return -1;
diff --git a/src/segtree.c b/src/segtree.c
index 00db8810cdba..70b4416cf39b 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -77,9 +77,9 @@ struct expr *get_set_intervals(const struct set *set, const struct expr *init)
mpz_init2(low, set->key->len);
mpz_init2(high, set->key->len);
- new_init = list_expr_alloc(&internal_location);
+ new_init = set_expr_alloc(&internal_location, NULL);
- list_for_each_entry(i, &init->expressions, list) {
+ list_for_each_entry(i, &expr_set(init)->expressions, list) {
switch (i->key->etype) {
case EXPR_VALUE:
set_elem_add(set, new_init, i->key->value,
@@ -135,7 +135,7 @@ static struct expr *get_set_interval_find(const struct set *cache_set,
mpz_init2(val, set->key->len);
- list_for_each_entry(i, &set->init->expressions, list) {
+ list_for_each_entry(i, &expr_set(set->init)->expressions, list) {
key = expr_value(i);
switch (key->etype) {
case EXPR_VALUE:
@@ -236,7 +236,7 @@ int get_set_decompose(struct set *cache_set, struct set *set)
new_init = set_expr_alloc(&internal_location, set);
- list_for_each_entry_safe(i, next, &set->init->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(set->init)->expressions, list) {
if (i->flags & EXPR_F_INTERVAL_END && left) {
list_del(&left->list);
list_del(&i->list);
@@ -354,7 +354,7 @@ void concat_range_aggregate(struct expr *set)
int prefix_len, free_r1;
mpz_t range, p;
- list_for_each_entry_safe(i, next, &set->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(set)->expressions, list) {
if (!start) {
start = i;
continue;
@@ -366,10 +366,10 @@ void concat_range_aggregate(struct expr *set)
* store them by replacing r2 expressions, and free r1
* expressions.
*/
- r2 = list_first_entry(&expr_value(end)->expressions,
+ r2 = list_first_entry(&expr_concat(expr_value(end))->expressions,
struct expr, list);
list_for_each_entry_safe(r1, r1_next,
- &expr_value(start)->expressions,
+ &expr_concat(expr_value(start))->expressions,
list) {
bool string_type = false;
@@ -564,15 +564,15 @@ void interval_map_decompose(struct expr *set)
unsigned int n, m, size;
bool interval;
- if (set->size == 0)
+ if (expr_set(set)->size == 0)
return;
- elements = xmalloc_array(set->size, sizeof(struct expr *));
- ranges = xmalloc_array(set->size * 2, sizeof(struct expr *));
+ elements = xmalloc_array(expr_set(set)->size, sizeof(struct expr *));
+ ranges = xmalloc_array(expr_set(set)->size * 2, sizeof(struct expr *));
/* Sort elements */
n = 0;
- list_for_each_entry_safe(i, next, &set->expressions, list) {
+ list_for_each_entry_safe(i, next, &expr_set(set)->expressions, list) {
key = NULL;
if (i->etype == EXPR_SET_ELEM)
key = i->key;
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH nft 0/4] detach concat, list and set expression layouts
2025-07-08 23:23 [PATCH nft 0/4] detach concat, list and set expression layouts Pablo Neira Ayuso
` (3 preceding siblings ...)
2025-07-08 23:23 ` [PATCH nft 4/4] src: detach set, list and concatenation expression layout Pablo Neira Ayuso
@ 2025-07-09 13:58 ` Florian Westphal
4 siblings, 0 replies; 6+ messages in thread
From: Florian Westphal @ 2025-07-09 13:58 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> These three expressions use the same layout but they have a different
> purpose, it is better to split them in independent layouts.
Agreed.
> This is implicitly reducing the size of one of the largest structs
> in the union area of struct expr, still EXPR_SET_ELEM remains the
> largest so no gain is achieved in this iteration.
Still, I'm all for reducing the number of anon structs in the union
and remove the SET/LIST/CONCAT joint struct.
Please, feel free to push this out.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-07-09 13:58 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-08 23:23 [PATCH nft 0/4] detach concat, list and set expression layouts Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 1/4] evaluate: mappings require set expression Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 2/4] evaluate: validate set expression type before accessing flags Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 3/4] src: convert set to list expression Pablo Neira Ayuso
2025-07-08 23:23 ` [PATCH nft 4/4] src: detach set, list and concatenation expression layout Pablo Neira Ayuso
2025-07-09 13:58 ` [PATCH nft 0/4] detach concat, list and set expression layouts Florian Westphal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).