Blame SOURCES/0020-src-Add-support-for-NFTNL_SET_DESC_CONCAT.patch

f1d1c0
From c8a5da2f527c85ab7c392cd293ff37d02a3f93a7 Mon Sep 17 00:00:00 2001
f1d1c0
From: Phil Sutter <psutter@redhat.com>
f1d1c0
Date: Thu, 13 Feb 2020 17:48:18 +0100
f1d1c0
Subject: [PATCH] src: Add support for NFTNL_SET_DESC_CONCAT
f1d1c0
f1d1c0
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795224
f1d1c0
Upstream Status: nftables commit 6156ba34018dd
f1d1c0
Conflicts: Context change in src/mnl.c due to missing commit
f1d1c0
	   6e48df5329eab ("src: add "typeof" build/parse/print support")
f1d1c0
f1d1c0
commit 6156ba34018dddd59cb6737cfd5a69a0cbc5eaa4
f1d1c0
Author: Stefano Brivio <sbrivio@redhat.com>
f1d1c0
Date:   Thu Jan 30 01:16:56 2020 +0100
f1d1c0
f1d1c0
    src: Add support for NFTNL_SET_DESC_CONCAT
f1d1c0
f1d1c0
    To support arbitrary range concatenations, the kernel needs to know
f1d1c0
    how long each field in the concatenation is. The new libnftnl
f1d1c0
    NFTNL_SET_DESC_CONCAT set attribute describes this as an array of
f1d1c0
    lengths, in bytes, of concatenated fields.
f1d1c0
f1d1c0
    While evaluating concatenated expressions, export the datatype size
f1d1c0
    into the new field_len array, and hand the data over via libnftnl.
f1d1c0
f1d1c0
    Similarly, when data is passed back from libnftnl, parse it into
f1d1c0
    the set description.
f1d1c0
f1d1c0
    When set data is cloned, we now need to copy the additional fields
f1d1c0
    in set_clone(), too.
f1d1c0
f1d1c0
    This change depends on the libnftnl patch with title:
f1d1c0
      set: Add support for NFTA_SET_DESC_CONCAT attributes
f1d1c0
f1d1c0
    v4: No changes
f1d1c0
    v3: Rework to use set description data instead of a stand-alone
f1d1c0
        attribute
f1d1c0
    v2: No changes
f1d1c0
f1d1c0
    Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
f1d1c0
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
f1d1c0
---
f1d1c0
 include/expression.h |  2 ++
f1d1c0
 include/rule.h       |  6 +++++-
f1d1c0
 src/evaluate.c       | 14 +++++++++++---
f1d1c0
 src/mnl.c            |  7 +++++++
f1d1c0
 src/netlink.c        | 11 +++++++++++
f1d1c0
 src/rule.c           |  2 +-
f1d1c0
 6 files changed, 37 insertions(+), 5 deletions(-)
f1d1c0
f1d1c0
diff --git a/include/expression.h b/include/expression.h
f1d1c0
index 717b675..ee726aa 100644
f1d1c0
--- a/include/expression.h
f1d1c0
+++ b/include/expression.h
f1d1c0
@@ -256,6 +256,8 @@ struct expr {
f1d1c0
 			struct list_head	expressions;
f1d1c0
 			unsigned int		size;
f1d1c0
 			uint32_t		set_flags;
f1d1c0
+			uint8_t			field_len[NFT_REG32_COUNT];
f1d1c0
+			uint8_t			field_count;
f1d1c0
 		};
f1d1c0
 		struct {
f1d1c0
 			/* EXPR_SET_REF */
f1d1c0
diff --git a/include/rule.h b/include/rule.h
f1d1c0
index 47eb29f..c03b0b8 100644
f1d1c0
--- a/include/rule.h
f1d1c0
+++ b/include/rule.h
f1d1c0
@@ -290,7 +290,9 @@ extern struct rule *rule_lookup_by_index(const struct chain *chain,
f1d1c0
  * @rg_cache:	cached range element (left)
f1d1c0
  * @policy:	set mechanism policy
f1d1c0
  * @automerge:	merge adjacents and overlapping elements, if possible
f1d1c0
- * @desc:	set mechanism desc
f1d1c0
+ * @desc.size:		count of set elements
f1d1c0
+ * @desc.field_len:	length of single concatenated fields, bytes
f1d1c0
+ * @desc.field_count:	count of concatenated fields
f1d1c0
  */
f1d1c0
 struct set {
f1d1c0
 	struct list_head	list;
f1d1c0
@@ -310,6 +312,8 @@ struct set {
f1d1c0
 	bool			automerge;
f1d1c0
 	struct {
f1d1c0
 		uint32_t	size;
f1d1c0
+		uint8_t		field_len[NFT_REG32_COUNT];
f1d1c0
+		uint8_t		field_count;
f1d1c0
 	} desc;
f1d1c0
 };
f1d1c0
 
f1d1c0
diff --git a/src/evaluate.c b/src/evaluate.c
f1d1c0
index a865902..58f458d 100644
f1d1c0
--- a/src/evaluate.c
f1d1c0
+++ b/src/evaluate.c
f1d1c0
@@ -1216,6 +1216,8 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
f1d1c0
 	struct expr *i, *next;
f1d1c0
 
f1d1c0
 	list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
f1d1c0
+		unsigned dsize_bytes;
f1d1c0
+
f1d1c0
 		if (expr_is_constant(*expr) && dtype && off == 0)
f1d1c0
 			return expr_binary_error(ctx->msgs, i, *expr,
f1d1c0
 						 "unexpected concat component, "
f1d1c0
@@ -1240,6 +1242,9 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
f1d1c0
 						 i->dtype->name);
f1d1c0
 
f1d1c0
 		ntype = concat_subtype_add(ntype, i->dtype->type);
f1d1c0
+
f1d1c0
+		dsize_bytes = div_round_up(i->dtype->size, BITS_PER_BYTE);
f1d1c0
+		(*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
f1d1c0
 	}
f1d1c0
 
f1d1c0
 	(*expr)->flags |= flags;
f1d1c0
@@ -3321,9 +3326,12 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
f1d1c0
 					 "specified in %s definition",
f1d1c0
 					 set->key->dtype->name, type);
f1d1c0
 	}
f1d1c0
-	if (set->flags & NFT_SET_INTERVAL &&
f1d1c0
-	    set->key->etype == EXPR_CONCAT)
f1d1c0
-		return set_error(ctx, set, "concatenated types not supported in interval sets");
f1d1c0
+
f1d1c0
+	if (set->flags & NFT_SET_INTERVAL && set->key->etype == EXPR_CONCAT) {
f1d1c0
+		memcpy(&set->desc.field_len, &set->key->field_len,
f1d1c0
+		       sizeof(set->desc.field_len));
f1d1c0
+		set->desc.field_count = set->key->field_count;
f1d1c0
+	}
f1d1c0
 
f1d1c0
 	if (set_is_datamap(set->flags)) {
f1d1c0
 		if (set->datatype == NULL)
f1d1c0
diff --git a/src/mnl.c b/src/mnl.c
f1d1c0
index aa5b0b4..221ee05 100644
f1d1c0
--- a/src/mnl.c
f1d1c0
+++ b/src/mnl.c
f1d1c0
@@ -881,6 +881,13 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
f1d1c0
 				 set->automerge))
f1d1c0
 		memory_allocation_error();
f1d1c0
 
f1d1c0
+	if (set->desc.field_len[0]) {
f1d1c0
+		nftnl_set_set_data(nls, NFTNL_SET_DESC_CONCAT,
f1d1c0
+				   set->desc.field_len,
f1d1c0
+				   set->desc.field_count *
f1d1c0
+				   sizeof(set->desc.field_len[0]));
f1d1c0
+	}
f1d1c0
+
f1d1c0
 	nftnl_set_set_data(nls, NFTNL_SET_USERDATA, nftnl_udata_buf_data(udbuf),
f1d1c0
 			   nftnl_udata_buf_len(udbuf));
f1d1c0
 	nftnl_udata_buf_free(udbuf);
f1d1c0
diff --git a/src/netlink.c b/src/netlink.c
f1d1c0
index 486e124..83d863c 100644
f1d1c0
--- a/src/netlink.c
f1d1c0
+++ b/src/netlink.c
f1d1c0
@@ -672,6 +672,17 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
f1d1c0
 	if (nftnl_set_is_set(nls, NFTNL_SET_DESC_SIZE))
f1d1c0
 		set->desc.size = nftnl_set_get_u32(nls, NFTNL_SET_DESC_SIZE);
f1d1c0
 
f1d1c0
+	if (nftnl_set_is_set(nls, NFTNL_SET_DESC_CONCAT)) {
f1d1c0
+		uint32_t len = NFT_REG32_COUNT;
f1d1c0
+		const uint8_t *data;
f1d1c0
+
f1d1c0
+		data = nftnl_set_get_data(nls, NFTNL_SET_DESC_CONCAT, &len;;
f1d1c0
+		if (data) {
f1d1c0
+			memcpy(set->desc.field_len, data, len);
f1d1c0
+			set->desc.field_count = len;
f1d1c0
+		}
f1d1c0
+	}
f1d1c0
+
f1d1c0
 	return set;
f1d1c0
 }
f1d1c0
 
f1d1c0
diff --git a/src/rule.c b/src/rule.c
f1d1c0
index 3ca1805..4669577 100644
f1d1c0
--- a/src/rule.c
f1d1c0
+++ b/src/rule.c
f1d1c0
@@ -337,7 +337,7 @@ struct set *set_clone(const struct set *set)
f1d1c0
 	new_set->objtype	= set->objtype;
f1d1c0
 	new_set->policy		= set->policy;
f1d1c0
 	new_set->automerge	= set->automerge;
f1d1c0
-	new_set->desc.size	= set->desc.size;
f1d1c0
+	new_set->desc		= set->desc;
f1d1c0
 
f1d1c0
 	return new_set;
f1d1c0
 }
f1d1c0
-- 
bfbb76
2.31.1
f1d1c0