]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: use constant range expression for interval+concatenation sets
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 16 Jun 2025 20:47:57 +0000 (22:47 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 23 Jun 2025 16:55:22 +0000 (18:55 +0200)
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>
src/evaluate.c
src/netlink.c

index cc35f88417bc53abcb6d7bd86ac9b7e0f3ee8650..b00344a04c553f8e3f8fd0e2bc606e51b10dd634 100644 (file)
@@ -1740,6 +1740,7 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
                        break;
                case EXPR_RANGE:
                case EXPR_PREFIX:
+               case EXPR_RANGE_VALUE:
                        /* allowed on RHS (e.g. th dport . mark { 1-65535 . 42 }
                         *                                       ~~~~~~~~ allowed
                         * but not on LHS (e.g  1-4 . mark { ...}
@@ -1763,7 +1764,6 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
                case EXPR_SET_REF:
                case EXPR_MAPPING:
                case EXPR_SET_ELEM_CATCHALL:
-               case EXPR_RANGE_VALUE:
                case EXPR_RANGE_SYMBOL:
                        return expr_error(ctx->msgs, i,
                                          "cannot use %s in concatenation",
@@ -1939,6 +1939,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:
@@ -1946,6 +1947,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;
@@ -2426,9 +2428,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,
index b5c092b499036cb89cea5a50d3893549a8ffa37f..31fe8b72f4e63206b5d0b0d997f4aa782e673ec4 100644 (file)
@@ -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) {