Blame SOURCES/0032-src-store-expr-not-dtype-to-track-data-in-sets.patch

fdae68
From 19da892698f1dce2125a796ad86239711896978f Mon Sep 17 00:00:00 2001
fdae68
From: Phil Sutter <psutter@redhat.com>
fdae68
Date: Mon, 7 Dec 2020 18:25:20 +0100
fdae68
Subject: [PATCH] src: store expr, not dtype to track data in sets
fdae68
fdae68
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1877022
fdae68
Upstream Status: nftables commit 343a51702656a
fdae68
fdae68
commit 343a51702656a6476e37cfb84609a82155c7fc5e
fdae68
Author: Florian Westphal <fw@strlen.de>
fdae68
Date:   Tue Jul 16 19:03:55 2019 +0200
fdae68
fdae68
    src: store expr, not dtype to track data in sets
fdae68
fdae68
    This will be needed once we add support for the 'typeof' keyword to
fdae68
    handle maps that could e.g. store 'ct helper' "type" values.
fdae68
fdae68
    Instead of:
fdae68
fdae68
    set foo {
fdae68
            type ipv4_addr . mark;
fdae68
fdae68
    this would allow
fdae68
fdae68
    set foo {
fdae68
            typeof(ip saddr) . typeof(ct mark);
fdae68
fdae68
    (exact syntax TBD).
fdae68
fdae68
    This would be needed to allow sets that store variable-sized data types
fdae68
    (string, integer and the like) that can't be used at at the moment.
fdae68
fdae68
    Adding special data types for everything is problematic due to the
fdae68
    large amount of different types needed.
fdae68
fdae68
    For anonymous sets, e.g. "string" can be used because the needed size can
fdae68
    be inferred from the statement, e.g.  'osf name { "Windows", "Linux }',
fdae68
    but in case of named sets that won't work because 'type string' lacks the
fdae68
    context needed to derive the size information.
fdae68
fdae68
    With 'typeof(osf name)' the context is there, but at the moment it won't
fdae68
    help because the expression is discarded instantly and only the data
fdae68
    type is retained.
fdae68
fdae68
    Signed-off-by: Florian Westphal <fw@strlen.de>
fdae68
---
fdae68
 include/datatype.h |  1 -
fdae68
 include/netlink.h  |  1 -
252916
 include/rule.h     |  6 ++---
252916
 src/datatype.c     |  5 ----
252916
 src/evaluate.c     | 58 ++++++++++++++++++++++++++++++++--------------
fdae68
 src/expression.c   |  2 +-
fdae68
 src/json.c         |  4 ++--
252916
 src/mnl.c          |  6 ++---
fdae68
 src/monitor.c      |  2 +-
252916
 src/netlink.c      | 32 ++++++++++++-------------
fdae68
 src/parser_bison.y |  3 +--
252916
 src/parser_json.c  |  8 +++++--
252916
 src/rule.c         |  8 +++----
252916
 src/segtree.c      |  8 +++++--
fdae68
 14 files changed, 81 insertions(+), 63 deletions(-)
fdae68
fdae68
diff --git a/include/datatype.h b/include/datatype.h
fdae68
index 49b8f60..04b4892 100644
fdae68
--- a/include/datatype.h
fdae68
+++ b/include/datatype.h
fdae68
@@ -293,7 +293,6 @@ concat_subtype_lookup(uint32_t type, unsigned int n)
fdae68
 
fdae68
 extern const struct datatype *
fdae68
 set_datatype_alloc(const struct datatype *orig_dtype, unsigned int byteorder);
fdae68
-extern void set_datatype_destroy(const struct datatype *dtype);
fdae68
 
fdae68
 extern void time_print(uint64_t msec, struct output_ctx *octx);
fdae68
 extern struct error_record *time_parse(const struct location *loc,
fdae68
diff --git a/include/netlink.h b/include/netlink.h
fdae68
index e694171..88d12ba 100644
fdae68
--- a/include/netlink.h
fdae68
+++ b/include/netlink.h
fdae68
@@ -189,6 +189,5 @@ int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
fdae68
 			    struct netlink_mon_handler *monh);
fdae68
 
fdae68
 enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype);
fdae68
-const struct datatype *dtype_map_from_kernel(enum nft_data_types type);
fdae68
 
fdae68
 #endif /* NFTABLES_NETLINK_H */
fdae68
diff --git a/include/rule.h b/include/rule.h
fdae68
index 626973e..3637462 100644
fdae68
--- a/include/rule.h
fdae68
+++ b/include/rule.h
fdae68
@@ -283,8 +283,7 @@ extern struct rule *rule_lookup_by_index(const struct chain *chain,
fdae68
  * @gc_int:	garbage collection interval
fdae68
  * @timeout:	default timeout value
fdae68
  * @key:	key expression (data type, length))
fdae68
- * @datatype:	mapping data type
fdae68
- * @datalen:	mapping data len
fdae68
+ * @data:	mapping data expression
fdae68
  * @objtype:	mapping object type
fdae68
  * @init:	initializer
fdae68
  * @rg_cache:	cached range element (left)
fdae68
@@ -303,8 +302,7 @@ struct set {
fdae68
 	uint32_t		gc_int;
fdae68
 	uint64_t		timeout;
fdae68
 	struct expr		*key;
fdae68
-	const struct datatype	*datatype;
fdae68
-	unsigned int		datalen;
fdae68
+	struct expr		*data;
fdae68
 	uint32_t		objtype;
fdae68
 	struct expr		*init;
fdae68
 	struct expr		*rg_cache;
fdae68
diff --git a/src/datatype.c b/src/datatype.c
fdae68
index b9e167e..189e1b4 100644
fdae68
--- a/src/datatype.c
fdae68
+++ b/src/datatype.c
fdae68
@@ -1190,11 +1190,6 @@ const struct datatype *set_datatype_alloc(const struct datatype *orig_dtype,
fdae68
 	return dtype;
fdae68
 }
fdae68
 
fdae68
-void set_datatype_destroy(const struct datatype *dtype)
fdae68
-{
fdae68
-	datatype_free(dtype);
fdae68
-}
fdae68
-
fdae68
 static struct error_record *time_unit_parse(const struct location *loc,
fdae68
 					    const char *str, uint64_t *unit)
fdae68
 {
fdae68
diff --git a/src/evaluate.c b/src/evaluate.c
fdae68
index f66251b..578dcae 100644
fdae68
--- a/src/evaluate.c
fdae68
+++ b/src/evaluate.c
fdae68
@@ -1383,6 +1383,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
fdae68
 {
fdae68
 	struct expr_ctx ectx = ctx->ectx;
fdae68
 	struct expr *map = *expr, *mappings;
fdae68
+	const struct datatype *dtype;
fdae68
 	struct expr *key;
fdae68
 
fdae68
 	expr_set_context(&ctx->ectx, NULL, 0);
fdae68
@@ -1405,10 +1406,14 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
fdae68
 		mappings = implicit_set_declaration(ctx, "__map%d",
fdae68
 						    key,
fdae68
 						    mappings);
fdae68
-		mappings->set->datatype =
fdae68
-			datatype_get(set_datatype_alloc(ectx.dtype,
fdae68
-							ectx.byteorder));
fdae68
-		mappings->set->datalen  = ectx.len;
fdae68
+
fdae68
+		dtype = set_datatype_alloc(ectx.dtype, ectx.byteorder);
fdae68
+
fdae68
+		mappings->set->data = constant_expr_alloc(&netlink_location,
fdae68
+							  dtype, dtype->byteorder,
fdae68
+							  ectx.len, NULL);
fdae68
+		if (ectx.len && mappings->set->data->len != ectx.len)
fdae68
+			BUG("%d vs %d\n", mappings->set->data->len, ectx.len);
fdae68
 
fdae68
 		map->mappings = mappings;
fdae68
 
fdae68
@@ -1444,7 +1449,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
fdae68
 					 map->mappings->set->key->dtype->desc,
fdae68
 					 map->map->dtype->desc);
fdae68
 
fdae68
-	datatype_set(map, map->mappings->set->datatype);
fdae68
+	datatype_set(map, map->mappings->set->data->dtype);
fdae68
 	map->flags |= EXPR_F_CONSTANT;
fdae68
 
fdae68
 	/* Data for range lookups needs to be in big endian order */
fdae68
@@ -1474,7 +1479,12 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
fdae68
 				  "Key must be a constant");
fdae68
 	mapping->flags |= mapping->left->flags & EXPR_F_SINGLETON;
fdae68
 
fdae68
-	expr_set_context(&ctx->ectx, set->datatype, set->datalen);
fdae68
+	if (set->data) {
fdae68
+		expr_set_context(&ctx->ectx, set->data->dtype, set->data->len);
fdae68
+	} else {
fdae68
+		assert((set->flags & NFT_SET_MAP) == 0);
fdae68
+	}
fdae68
+
fdae68
 	if (expr_evaluate(ctx, &mapping->right) < 0)
fdae68
 		return -1;
fdae68
 	if (!expr_is_constant(mapping->right))
fdae68
@@ -2119,7 +2129,7 @@ static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
fdae68
 					 (*expr)->len);
fdae68
 	else if ((*expr)->dtype->type != TYPE_INTEGER &&
fdae68
 		 !datatype_equal((*expr)->dtype, dtype))
fdae68
-		return stmt_binary_error(ctx, *expr, stmt,
fdae68
+		return stmt_binary_error(ctx, *expr, stmt,		/* verdict vs invalid? */
fdae68
 					 "datatype mismatch: expected %s, "
fdae68
 					 "expression has type %s",
fdae68
 					 dtype->desc, (*expr)->dtype->desc);
fdae68
@@ -3113,9 +3123,9 @@ static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
fdae68
 				  "Key expression comments are not supported");
fdae68
 
fdae68
 	if (stmt_evaluate_arg(ctx, stmt,
fdae68
-			      stmt->map.set->set->datatype,
fdae68
-			      stmt->map.set->set->datalen,
fdae68
-			      stmt->map.set->set->datatype->byteorder,
fdae68
+			      stmt->map.set->set->data->dtype,
fdae68
+			      stmt->map.set->set->data->len,
fdae68
+			      stmt->map.set->set->data->byteorder,
fdae68
 			      &stmt->map.data->key) < 0)
fdae68
 		return -1;
fdae68
 	if (expr_is_constant(stmt->map.data))
fdae68
@@ -3161,8 +3171,12 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
fdae68
 
fdae68
 		mappings = implicit_set_declaration(ctx, "__objmap%d",
fdae68
 						    key, mappings);
fdae68
-		mappings->set->datatype = &string_type;
fdae68
-		mappings->set->datalen  = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
fdae68
+
fdae68
+		mappings->set->data = constant_expr_alloc(&netlink_location,
fdae68
+							  &string_type,
fdae68
+							  BYTEORDER_HOST_ENDIAN,
fdae68
+							  NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
fdae68
+							  NULL);
fdae68
 		mappings->set->objtype  = stmt->objref.type;
fdae68
 
fdae68
 		map->mappings = mappings;
fdae68
@@ -3197,7 +3211,7 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt)
fdae68
 					 map->mappings->set->key->dtype->desc,
fdae68
 					 map->map->dtype->desc);
fdae68
 
fdae68
-	datatype_set(map, map->mappings->set->datatype);
fdae68
+	datatype_set(map, map->mappings->set->data->dtype);
fdae68
 	map->flags |= EXPR_F_CONSTANT;
fdae68
 
fdae68
 	/* Data for range lookups needs to be in big endian order */
fdae68
@@ -3346,17 +3360,25 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
fdae68
 	}
fdae68
 
fdae68
 	if (set_is_datamap(set->flags)) {
fdae68
-		if (set->datatype == NULL)
fdae68
+		if (set->data == NULL)
fdae68
 			return set_error(ctx, set, "map definition does not "
fdae68
 					 "specify mapping data type");
fdae68
 
fdae68
-		set->datalen = set->datatype->size;
fdae68
-		if (set->datalen == 0 && set->datatype->type != TYPE_VERDICT)
fdae68
+		if (set->data->len == 0 && set->data->dtype->type != TYPE_VERDICT)
fdae68
 			return set_error(ctx, set, "unqualified mapping data "
fdae68
 					 "type specified in map definition");
fdae68
 	} else if (set_is_objmap(set->flags)) {
fdae68
-		set->datatype = &string_type;
fdae68
-		set->datalen  = NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE;
fdae68
+		if (set->data) {
fdae68
+			assert(set->data->etype == EXPR_VALUE);
fdae68
+			assert(set->data->dtype == &string_type);
fdae68
+		}
fdae68
+
fdae68
+		assert(set->data == NULL);
fdae68
+		set->data = constant_expr_alloc(&netlink_location, &string_type,
fdae68
+						BYTEORDER_HOST_ENDIAN,
fdae68
+						NFT_OBJ_MAXNAMELEN * BITS_PER_BYTE,
fdae68
+						NULL);
fdae68
+
fdae68
 	}
fdae68
 
fdae68
 	ctx->set = set;
fdae68
diff --git a/src/expression.c b/src/expression.c
fdae68
index 5070b10..6fa2f1d 100644
fdae68
--- a/src/expression.c
fdae68
+++ b/src/expression.c
fdae68
@@ -1010,7 +1010,7 @@ static void map_expr_print(const struct expr *expr, struct output_ctx *octx)
fdae68
 {
fdae68
 	expr_print(expr->map, octx);
fdae68
 	if (expr->mappings->etype == EXPR_SET_REF &&
fdae68
-	    expr->mappings->set->datatype->type == TYPE_VERDICT)
fdae68
+	    expr->mappings->set->data->dtype->type == TYPE_VERDICT)
fdae68
 		nft_print(octx, " vmap ");
fdae68
 	else
fdae68
 		nft_print(octx, " map ");
fdae68
diff --git a/src/json.c b/src/json.c
fdae68
index 3498e24..1906e7d 100644
fdae68
--- a/src/json.c
fdae68
+++ b/src/json.c
fdae68
@@ -82,7 +82,7 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
fdae68
 
fdae68
 	if (set_is_datamap(set->flags)) {
fdae68
 		type = "map";
fdae68
-		datatype_ext = set->datatype->name;
fdae68
+		datatype_ext = set->data->dtype->name;
fdae68
 	} else if (set_is_objmap(set->flags)) {
fdae68
 		type = "map";
fdae68
 		datatype_ext = obj_type_name(set->objtype);
fdae68
@@ -645,7 +645,7 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
fdae68
 	const char *type = "map";
fdae68
 
fdae68
 	if (expr->mappings->etype == EXPR_SET_REF &&
fdae68
-	    expr->mappings->set->datatype->type == TYPE_VERDICT)
fdae68
+	    expr->mappings->set->data->dtype->type == TYPE_VERDICT)
fdae68
 		type = "vmap";
fdae68
 
fdae68
 	return json_pack("{s:{s:o, s:o}}", type,
fdae68
diff --git a/src/mnl.c b/src/mnl.c
fdae68
index 221ee05..23341e6 100644
fdae68
--- a/src/mnl.c
fdae68
+++ b/src/mnl.c
fdae68
@@ -839,9 +839,9 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
fdae68
 			  div_round_up(set->key->len, BITS_PER_BYTE));
fdae68
 	if (set_is_datamap(set->flags)) {
fdae68
 		nftnl_set_set_u32(nls, NFTNL_SET_DATA_TYPE,
fdae68
-				  dtype_map_to_kernel(set->datatype));
fdae68
+				  dtype_map_to_kernel(set->data->dtype));
fdae68
 		nftnl_set_set_u32(nls, NFTNL_SET_DATA_LEN,
fdae68
-				  set->datalen / BITS_PER_BYTE);
fdae68
+				  set->data->len / BITS_PER_BYTE);
fdae68
 	}
fdae68
 	if (set_is_objmap(set->flags))
fdae68
 		nftnl_set_set_u32(nls, NFTNL_SET_OBJ_TYPE, set->objtype);
fdae68
@@ -873,7 +873,7 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
fdae68
 
fdae68
 	if (set_is_datamap(set->flags) &&
fdae68
 	    !nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_DATABYTEORDER,
fdae68
-				 set->datatype->byteorder))
fdae68
+				 set->data->byteorder))
fdae68
 		memory_allocation_error();
fdae68
 
fdae68
 	if (set->automerge &&
fdae68
diff --git a/src/monitor.c b/src/monitor.c
fdae68
index fb803cf..7927b6f 100644
fdae68
--- a/src/monitor.c
fdae68
+++ b/src/monitor.c
fdae68
@@ -401,7 +401,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
fdae68
 	 */
fdae68
 	dummyset = set_alloc(monh->loc);
fdae68
 	dummyset->key = expr_clone(set->key);
fdae68
-	dummyset->datatype = set->datatype;
fdae68
+	dummyset->data = set->data;
fdae68
 	dummyset->flags = set->flags;
fdae68
 	dummyset->init = set_expr_alloc(monh->loc, set);
fdae68
 
fdae68
diff --git a/src/netlink.c b/src/netlink.c
fdae68
index e0ba903..64e51e5 100644
fdae68
--- a/src/netlink.c
fdae68
+++ b/src/netlink.c
fdae68
@@ -575,7 +575,7 @@ enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype)
fdae68
 	}
fdae68
 }
fdae68
 
fdae68
-const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
fdae68
+static const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
fdae68
 {
fdae68
 	switch (type) {
fdae68
 	case NFT_DATA_VERDICT:
fdae68
@@ -622,10 +622,10 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
fdae68
 				    const struct nftnl_set *nls)
fdae68
 {
fdae68
 	const struct nftnl_udata *ud[NFTNL_UDATA_SET_MAX + 1] = {};
fdae68
-	uint32_t flags, key, data, data_len, objtype = 0;
fdae68
 	enum byteorder keybyteorder = BYTEORDER_INVALID;
fdae68
 	enum byteorder databyteorder = BYTEORDER_INVALID;
fdae68
-	const struct datatype *keytype, *datatype;
fdae68
+	const struct datatype *keytype, *datatype = NULL;
fdae68
+	uint32_t flags, key, objtype = 0;
fdae68
 	bool automerge = false;
fdae68
 	const char *udata;
fdae68
 	struct set *set;
fdae68
@@ -659,6 +659,8 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
fdae68
 
fdae68
 	flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
fdae68
 	if (set_is_datamap(flags)) {
fdae68
+		uint32_t data;
fdae68
+
fdae68
 		data = nftnl_set_get_u32(nls, NFTNL_SET_DATA_TYPE);
fdae68
 		datatype = dtype_map_from_kernel(data);
fdae68
 		if (datatype == NULL) {
fdae68
@@ -667,8 +669,7 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
fdae68
 					 data);
fdae68
 			return NULL;
fdae68
 		}
fdae68
-	} else
fdae68
-		datatype = NULL;
fdae68
+	}
fdae68
 
fdae68
 	if (set_is_objmap(flags)) {
fdae68
 		objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
fdae68
@@ -691,16 +692,13 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
fdae68
 
fdae68
 	set->objtype = objtype;
fdae68
 
fdae68
+	set->data = NULL;
fdae68
 	if (datatype)
fdae68
-		set->datatype = datatype_get(set_datatype_alloc(datatype,
fdae68
-								databyteorder));
fdae68
-	else
fdae68
-		set->datatype = NULL;
fdae68
-
fdae68
-	if (nftnl_set_is_set(nls, NFTNL_SET_DATA_LEN)) {
fdae68
-		data_len = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN);
fdae68
-		set->datalen = data_len * BITS_PER_BYTE;
fdae68
-	}
fdae68
+		set->data = constant_expr_alloc(&netlink_location,
fdae68
+						set_datatype_alloc(datatype, databyteorder),
fdae68
+						databyteorder,
fdae68
+						nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE,
fdae68
+						NULL);
fdae68
 
fdae68
 	if (nftnl_set_is_set(nls, NFTNL_SET_TIMEOUT))
fdae68
 		set->timeout = nftnl_set_get_u64(nls, NFTNL_SET_TIMEOUT);
fdae68
@@ -897,10 +895,10 @@ key_end:
fdae68
 			goto out;
fdae68
 
fdae68
 		data = netlink_alloc_data(&netlink_location, &nld,
fdae68
-					  set->datatype->type == TYPE_VERDICT ?
fdae68
+					  set->data->dtype->type == TYPE_VERDICT ?
fdae68
 					  NFT_REG_VERDICT : NFT_REG_1);
fdae68
-		datatype_set(data, set->datatype);
fdae68
-		data->byteorder = set->datatype->byteorder;
fdae68
+		datatype_set(data, set->data->dtype);
fdae68
+		data->byteorder = set->data->byteorder;
fdae68
 		if (data->byteorder == BYTEORDER_HOST_ENDIAN)
fdae68
 			mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
fdae68
 
fdae68
diff --git a/src/parser_bison.y b/src/parser_bison.y
fdae68
index ea83f52..4cca31b 100644
fdae68
--- a/src/parser_bison.y
fdae68
+++ b/src/parser_bison.y
fdae68
@@ -1749,9 +1749,8 @@ map_block		:	/* empty */	{ $$ = $<set>-1; }
fdae68
 						stmt_separator
fdae68
 			{
fdae68
 				$1->key = $3;
fdae68
-				$1->datatype = $5->dtype;
fdae68
+				$1->data = $5;
fdae68
 
fdae68
-				expr_free($5);
fdae68
 				$1->flags |= NFT_SET_MAP;
fdae68
 				$$ = $1;
fdae68
 			}
fdae68
diff --git a/src/parser_json.c b/src/parser_json.c
fdae68
index ce8e566..ddc694f 100644
fdae68
--- a/src/parser_json.c
fdae68
+++ b/src/parser_json.c
fdae68
@@ -2833,11 +2833,15 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
fdae68
 	}
fdae68
 
fdae68
 	if (!json_unpack(root, "{s:s}", "map", &dtype_ext)) {
fdae68
+		const struct datatype *dtype;
fdae68
+
fdae68
 		set->objtype = string_to_nft_object(dtype_ext);
fdae68
 		if (set->objtype) {
fdae68
 			set->flags |= NFT_SET_OBJECT;
fdae68
-		} else if (datatype_lookup_byname(dtype_ext)) {
fdae68
-			set->datatype = datatype_lookup_byname(dtype_ext);
fdae68
+		} else if ((dtype = datatype_lookup_byname(dtype_ext))) {
fdae68
+			set->data = constant_expr_alloc(&netlink_location,
fdae68
+							dtype, dtype->byteorder,
fdae68
+							dtype->size, NULL);
fdae68
 			set->flags |= NFT_SET_MAP;
fdae68
 		} else {
fdae68
 			json_error(ctx, "Invalid map type '%s'.", dtype_ext);
fdae68
diff --git a/src/rule.c b/src/rule.c
fdae68
index e18237b..f7d888b 100644
fdae68
--- a/src/rule.c
fdae68
+++ b/src/rule.c
fdae68
@@ -332,8 +332,8 @@ struct set *set_clone(const struct set *set)
fdae68
 	new_set->gc_int		= set->gc_int;
fdae68
 	new_set->timeout	= set->timeout;
fdae68
 	new_set->key		= expr_clone(set->key);
fdae68
-	new_set->datatype	= datatype_get(set->datatype);
fdae68
-	new_set->datalen	= set->datalen;
fdae68
+	if (set->data)
fdae68
+		new_set->data	= expr_clone(set->data);
fdae68
 	new_set->objtype	= set->objtype;
fdae68
 	new_set->policy		= set->policy;
fdae68
 	new_set->automerge	= set->automerge;
fdae68
@@ -356,7 +356,7 @@ void set_free(struct set *set)
fdae68
 		expr_free(set->init);
fdae68
 	handle_free(&set->handle);
fdae68
 	expr_free(set->key);
fdae68
-	set_datatype_destroy(set->datatype);
fdae68
+	expr_free(set->data);
fdae68
 	xfree(set);
fdae68
 }
fdae68
 
fdae68
@@ -469,7 +469,7 @@ static void set_print_declaration(const struct set *set,
fdae68
 	nft_print(octx, "%s%stype %s",
fdae68
 		  opts->tab, opts->tab, set->key->dtype->name);
fdae68
 	if (set_is_datamap(set->flags))
fdae68
-		nft_print(octx, " : %s", set->datatype->name);
fdae68
+		nft_print(octx, " : %s", set->data->dtype->name);
fdae68
 	else if (set_is_objmap(set->flags))
fdae68
 		nft_print(octx, " : %s", obj_type_name(set->objtype));
fdae68
 
fdae68
diff --git a/src/segtree.c b/src/segtree.c
fdae68
index 073c6ec..d6e3ce2 100644
fdae68
--- a/src/segtree.c
fdae68
+++ b/src/segtree.c
fdae68
@@ -79,8 +79,12 @@ static void seg_tree_init(struct seg_tree *tree, const struct set *set,
fdae68
 	tree->root	= RB_ROOT;
fdae68
 	tree->keytype	= set->key->dtype;
fdae68
 	tree->keylen	= set->key->len;
fdae68
-	tree->datatype	= set->datatype;
fdae68
-	tree->datalen	= set->datalen;
fdae68
+	tree->datatype	= NULL;
fdae68
+	tree->datalen	= 0;
fdae68
+	if (set->data) {
fdae68
+		tree->datatype	= set->data->dtype;
fdae68
+		tree->datalen	= set->data->len;
fdae68
+	}
fdae68
 	tree->byteorder	= first->byteorder;
fdae68
 	tree->debug_mask = debug_mask;
fdae68
 }
fdae68
-- 
252916
2.31.1
fdae68