[PATCH nft 3/3] src: use EXPR_RANGE_VALUE in interval maps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxx>
---
 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





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux