* [PATCH nft 1/3,v2] src: use constant range expression for interval+concatenation sets
2025-06-16 21:57 [PATCH nft 0/3] memory reduction in concatenation and maps Pablo Neira Ayuso
@ 2025-06-16 21:57 ` Pablo Neira Ayuso
2025-06-16 21:57 ` [PATCH nft 2/3] expression: constant range is not a singleton Pablo Neira Ayuso
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2025-06-16 21:57 UTC (permalink / raw)
To: netfilter-devel
Expand 347039f64509 ("src: add symbol range expression to further
compact intervals") to use constant range expression for elements with
concatenation of intervals.
Ruleset with 100k elements of this type:
table inet x {
set y {
typeof ip saddr . tcp dport
flags interval
elements = {
0.1.2.0-0.1.2.240 . 0-1,
...
}
}
}
Memory consumption for this set:
Before: 123.80 Mbytes
After: 80.19 Mbytes (-35.23%)
This patch keeps the workaround 2fbade3cd990 ("netlink: bogus
concatenated set ranges with netlink message overrun") in place.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: fix error hint when flags interval is missing in set declaration
src/evaluate.c | 5 +++--
src/netlink.c | 11 +++++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index 9c7f23cb080e..b157a9c9d935 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1879,6 +1879,7 @@ static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
switch (elem->key->etype) {
case EXPR_PREFIX:
case EXPR_RANGE:
+ case EXPR_RANGE_VALUE:
key = elem->key;
goto err_missing_flag;
case EXPR_CONCAT:
@@ -1886,6 +1887,7 @@ static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
switch (key->etype) {
case EXPR_PREFIX:
case EXPR_RANGE:
+ case EXPR_RANGE_VALUE:
goto err_missing_flag;
default:
break;
@@ -2366,9 +2368,8 @@ static int expr_evaluate_symbol_range(struct eval_ctx *ctx, struct expr **exprp)
left = range->left;
right = range->right;
- /* concatenation and maps need more work to use constant_range_expr. */
+ /* maps need more work to use constant_range_expr. */
if (ctx->set && !set_is_map(ctx->set->flags) &&
- set_is_non_concat_range(ctx->set) &&
left->etype == EXPR_VALUE &&
right->etype == EXPR_VALUE) {
constant_range = constant_range_expr_alloc(&expr->location,
diff --git a/src/netlink.c b/src/netlink.c
index 73fe579a477c..94cf177213fd 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -285,6 +285,17 @@ static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
byteorder_switch_expr_value(value, expr);
i = expr;
+ break;
+ case EXPR_RANGE_VALUE:
+ if (flags & EXPR_F_INTERVAL_END)
+ mpz_init_set(value, i->range.high);
+ else
+ mpz_init_set(value, i->range.low);
+
+ if (expr_basetype(i)->type == TYPE_INTEGER &&
+ i->byteorder == BYTEORDER_HOST_ENDIAN)
+ byteorder_switch_expr_value(value, i);
+
break;
case EXPR_PREFIX:
if (flags & EXPR_F_INTERVAL_END) {
--
2.30.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH nft 3/3] src: use EXPR_RANGE_VALUE in interval maps
2025-06-16 21:57 [PATCH nft 0/3] memory reduction in concatenation and maps Pablo Neira Ayuso
2025-06-16 21:57 ` [PATCH nft 1/3,v2] src: use constant range expression for interval+concatenation sets Pablo Neira Ayuso
2025-06-16 21:57 ` [PATCH nft 2/3] expression: constant range is not a singleton Pablo Neira Ayuso
@ 2025-06-16 21:57 ` Pablo Neira Ayuso
2025-06-23 17:08 ` [PATCH nft 0/3] memory reduction in concatenation and maps Pablo Neira Ayuso
3 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2025-06-16 21:57 UTC (permalink / raw)
To: netfilter-devel
Remove the restriction on maps to use EXPR_RANGE_VALUE to reduce
memory consumption.
With 100k map with concatenation:
table inet x {
map y {
typeof ip saddr . tcp dport : ip saddr
flags interval
elements = {
1.0.2.0-1.0.2.240 . 0-2 : 1.0.2.10,
...
}
}
Before: 153.6 Mbytes
After: 108.9 Mbytes (-29.11%)
With 100k map without concatenation:
table inet x {
map y {
typeof ip saddr : ip saddr
flags interval
elements = {
1.0.2.0-1.0.2.240 : 1.0.2.10,
...
}
}
Before: 74.36 Mbytes
After: 62.39 Mbytes (-16.10%)
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 5 +++--
src/netlink.c | 50 +++++++++++++++++++++++++++++++++++++++++++-------
src/optimize.c | 3 +++
3 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index b157a9c9d935..fac6c657dcbb 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2268,6 +2268,7 @@ static bool data_mapping_has_interval(struct expr *data)
struct expr *i;
if (data->etype == EXPR_RANGE ||
+ data->etype == EXPR_RANGE_VALUE ||
data->etype == EXPR_PREFIX)
return true;
@@ -2276,6 +2277,7 @@ static bool data_mapping_has_interval(struct expr *data)
list_for_each_entry(i, &data->expressions, list) {
if (i->etype == EXPR_RANGE ||
+ i->etype == EXPR_RANGE_VALUE ||
i->etype == EXPR_PREFIX)
return true;
}
@@ -2368,8 +2370,7 @@ static int expr_evaluate_symbol_range(struct eval_ctx *ctx, struct expr **exprp)
left = range->left;
right = range->right;
- /* maps need more work to use constant_range_expr. */
- if (ctx->set && !set_is_map(ctx->set->flags) &&
+ if (ctx->set &&
left->etype == EXPR_VALUE &&
right->etype == EXPR_VALUE) {
constant_range = constant_range_expr_alloc(&expr->location,
diff --git a/src/netlink.c b/src/netlink.c
index 94cf177213fd..c07cbe6a0476 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -217,6 +217,7 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
case EXPR_VALUE:
case EXPR_RANGE:
case EXPR_PREFIX:
+ case EXPR_RANGE_VALUE:
nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_DATA,
nld.value, nld.len);
break;
@@ -369,29 +370,46 @@ static void netlink_gen_concat_key(const struct expr *expr,
static int __netlink_gen_concat_data(int end, const struct expr *i,
unsigned char *data)
{
+ mpz_t value;
+ int ret;
+
switch (i->etype) {
case EXPR_RANGE:
- i = end ? i->right : i->left;
+ if (end)
+ i = i->right;
+ else
+ i = i->left;
+
+ mpz_init_set(value, i->value);
+ break;
+ case EXPR_RANGE_VALUE:
+ if (end)
+ mpz_init_set(value, i->range.high);
+ else
+ mpz_init_set(value, i->range.low);
break;
case EXPR_PREFIX:
if (end) {
int count;
- mpz_t v;
- mpz_init_bitmask(v, i->len - i->prefix_len);
- mpz_add(v, i->prefix->value, v);
- count = netlink_export_pad(data, v, i);
- mpz_clear(v);
+ mpz_init_bitmask(value, i->len - i->prefix_len);
+ mpz_add(value, i->prefix->value, value);
+ count = netlink_export_pad(data, value, i);
+ mpz_clear(value);
return count;
}
return netlink_export_pad(data, i->prefix->value, i);
case EXPR_VALUE:
+ mpz_init_set(value, i->value);
break;
default:
BUG("invalid expression type '%s' in set", expr_ops(i)->name);
}
- return netlink_export_pad(data, i->value, i);
+ ret = netlink_export_pad(data, value, i);
+ mpz_clear(value);
+
+ return ret;
}
static void __netlink_gen_concat_expand(const struct expr *expr,
@@ -507,6 +525,22 @@ static void netlink_gen_range(const struct expr *expr,
nft_data_memcpy(nld, data, len);
}
+static void netlink_gen_range_value(const struct expr *expr,
+ struct nft_data_linearize *nld)
+{
+ unsigned int len = (netlink_padded_len(expr->len) / BITS_PER_BYTE) * 2;
+ unsigned char data[NFT_MAX_EXPR_LEN_BYTES];
+ unsigned int offset;
+
+ if (len > sizeof(data))
+ BUG("Value export of %u bytes would overflow", len);
+
+ memset(data, 0, sizeof(data));
+ offset = netlink_export_pad(data, expr->range.low, expr);
+ netlink_export_pad(data + offset, expr->range.high, expr);
+ nft_data_memcpy(nld, data, len);
+}
+
static void netlink_gen_prefix(const struct expr *expr,
struct nft_data_linearize *nld)
{
@@ -558,6 +592,8 @@ static void __netlink_gen_data(const struct expr *expr,
return netlink_gen_range(expr, data);
case EXPR_PREFIX:
return netlink_gen_prefix(expr, data);
+ case EXPR_RANGE_VALUE:
+ return netlink_gen_range_value(expr, data);
default:
BUG("invalid data expression type %s\n", expr_name(expr));
}
diff --git a/src/optimize.c b/src/optimize.c
index 5b7b0ab62fbc..89ba0d9dee6a 100644
--- a/src/optimize.c
+++ b/src/optimize.c
@@ -172,6 +172,7 @@ static bool stmt_expr_supported(const struct expr *expr)
case EXPR_SYMBOL:
case EXPR_RANGE_SYMBOL:
case EXPR_RANGE:
+ case EXPR_RANGE_VALUE:
case EXPR_PREFIX:
case EXPR_SET:
case EXPR_LIST:
@@ -667,6 +668,7 @@ static void __merge_concat(const struct optimize_ctx *ctx, uint32_t i,
case EXPR_PREFIX:
case EXPR_RANGE_SYMBOL:
case EXPR_RANGE:
+ case EXPR_RANGE_VALUE:
clone = expr_clone(stmt_a->expr->right);
compound_expr_add(concat, clone);
break;
@@ -778,6 +780,7 @@ static void build_verdict_map(struct expr *expr, struct stmt *verdict,
case EXPR_PREFIX:
case EXPR_RANGE_SYMBOL:
case EXPR_RANGE:
+ case EXPR_RANGE_VALUE:
case EXPR_VALUE:
case EXPR_SYMBOL:
case EXPR_CONCAT:
--
2.30.2
^ permalink raw reply related [flat|nested] 5+ messages in thread