]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: use EXPR_RANGE_VALUE in interval maps
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 16 Jun 2025 20:48:04 +0000 (22:48 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 23 Jun 2025 16:55:27 +0000 (18:55 +0200)
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
src/netlink.c
src/optimize.c

index b00344a04c553f8e3f8fd0e2bc606e51b10dd634..783a373b6268a871210dc22275606839a706894d 100644 (file)
@@ -2328,6 +2328,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;
 
@@ -2336,6 +2337,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;
        }
@@ -2428,8 +2430,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,
index 31fe8b72f4e63206b5d0b0d997f4aa782e673ec4..f3157d9d7f1c962496f9f5929c60c152c6bf1218 100644 (file)
@@ -216,6 +216,7 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
                        /* fallthrough */
                case EXPR_VALUE:
                case EXPR_RANGE:
+               case EXPR_RANGE_VALUE:
                case EXPR_PREFIX:
                        nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_DATA,
                                           nld.value, nld.len);
@@ -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)
 {
@@ -556,6 +590,8 @@ static void __netlink_gen_data(const struct expr *expr,
                return netlink_gen_verdict(expr, data);
        case EXPR_RANGE:
                return netlink_gen_range(expr, data);
+       case EXPR_RANGE_VALUE:
+               return netlink_gen_range_value(expr, data);
        case EXPR_PREFIX:
                return netlink_gen_prefix(expr, data);
        default:
index 5b7b0ab62fbc3871a0822adee52794ca754bc46d..89ba0d9dee6a85ec0da99875f386d98c1b8884f4 100644 (file)
@@ -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: