From: Pablo Neira Ayuso Date: Mon, 16 Jun 2025 20:48:04 +0000 (+0200) Subject: src: use EXPR_RANGE_VALUE in interval maps X-Git-Tag: v1.1.4~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=833b06467e14da2a470a36ccf9b2d5ea92008655;p=thirdparty%2Fnftables.git src: use EXPR_RANGE_VALUE in interval maps 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 --- diff --git a/src/evaluate.c b/src/evaluate.c index b00344a0..783a373b 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -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, diff --git a/src/netlink.c b/src/netlink.c index 31fe8b72..f3157d9d 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -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: diff --git a/src/optimize.c b/src/optimize.c index 5b7b0ab6..89ba0d9d 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: