diff mbox series

[nft,v2,1/3] src: Add support for and export NFT_SET_SUBKEY attributes

Message ID 3982a275e0a29b00b742d5b5322163cae8e6c046.1574353687.git.sbrivio@redhat.com
State Changes Requested
Delegated to: Pablo Neira
Headers show
Series Introduce support for concatenated ranges | expand

Commit Message

Stefano Brivio Nov. 21, 2019, 5:10 p.m. UTC
To support arbitrary range concatenations, the kernel needs to know
how long each field in the concatenation is.

While evaluating concatenated expressions, export the datatype size,
in bits, into the new subkey_len array, and hand the data over via
libnftnl.

Note that, while the subkey length is expressed in bits, and the
kernel attribute is 32-bit long to make UAPI more future-proof, we
just reserve 8 bits for it, at the moment, and still store this data
in bits.

As we don't have subkeys exceeding 128 bits in length, this should be
fine, at least for a while, but it can be easily changed later on to
use the full 32 bits allowed by the netlink attribute.

This change depends on the UAPI kernel patch with title:
  netfilter: nf_tables: Support for subkeys, set with multiple ranged fields

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
v2: No changes

 include/expression.h |  1 +
 include/rule.h       |  1 +
 src/evaluate.c       | 12 ++++++++----
 src/mnl.c            |  4 ++++
 4 files changed, 14 insertions(+), 4 deletions(-)

Comments

Phil Sutter Nov. 21, 2019, 5:51 p.m. UTC | #1
On Thu, Nov 21, 2019 at 06:10:04PM +0100, Stefano Brivio wrote:
> To support arbitrary range concatenations, the kernel needs to know
> how long each field in the concatenation is.
> 
> While evaluating concatenated expressions, export the datatype size,
> in bits, into the new subkey_len array, and hand the data over via
> libnftnl.
> 
> Note that, while the subkey length is expressed in bits, and the
> kernel attribute is 32-bit long to make UAPI more future-proof, we
> just reserve 8 bits for it, at the moment, and still store this data
> in bits.
> 
> As we don't have subkeys exceeding 128 bits in length, this should be
> fine, at least for a while, but it can be easily changed later on to
> use the full 32 bits allowed by the netlink attribute.
> 
> This change depends on the UAPI kernel patch with title:
>   netfilter: nf_tables: Support for subkeys, set with multiple ranged fields
> 
> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>

Acked-by: Phil Sutter <phil@nwl.cc>
diff mbox series

Patch

diff --git a/include/expression.h b/include/expression.h
index 717b67550381..b6d5adb2d981 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -256,6 +256,7 @@  struct expr {
 			struct list_head	expressions;
 			unsigned int		size;
 			uint32_t		set_flags;
+			uint8_t			subkey_len[NFT_REG32_COUNT];
 		};
 		struct {
 			/* EXPR_SET_REF */
diff --git a/include/rule.h b/include/rule.h
index 0b2eba37934b..a263947da8fd 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -308,6 +308,7 @@  struct set {
 	struct expr		*rg_cache;
 	uint32_t		policy;
 	bool			automerge;
+	uint8_t			subkey_len[NFT_REG32_COUNT];
 	struct {
 		uint32_t	size;
 	} desc;
diff --git a/src/evaluate.c b/src/evaluate.c
index e54eaf1a7110..e1ecf4de243a 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1211,7 +1211,7 @@  static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
 {
 	const struct datatype *dtype = ctx->ectx.dtype, *tmp;
 	uint32_t type = dtype ? dtype->type : 0, ntype = 0;
-	int off = dtype ? dtype->subtypes : 0;
+	int off = dtype ? dtype->subtypes : 0, subkey_idx = 0;
 	unsigned int flags = EXPR_F_CONSTANT | EXPR_F_SINGLETON;
 	struct expr *i, *next;
 
@@ -1240,6 +1240,8 @@  static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
 						 i->dtype->name);
 
 		ntype = concat_subtype_add(ntype, i->dtype->type);
+
+		(*expr)->subkey_len[subkey_idx++] = i->dtype->size;
 	}
 
 	(*expr)->flags |= flags;
@@ -3301,9 +3303,11 @@  static int set_evaluate(struct eval_ctx *ctx, struct set *set)
 					 "specified in %s definition",
 					 set->key->dtype->name, type);
 	}
-	if (set->flags & NFT_SET_INTERVAL &&
-	    set->key->etype == EXPR_CONCAT)
-		return set_error(ctx, set, "concatenated types not supported in interval sets");
+	if (set->flags & NFT_SET_INTERVAL && set->key->etype == EXPR_CONCAT) {
+		memcpy(&set->subkey_len, &set->key->subkey_len,
+		       sizeof(set->subkey_len));
+		set->flags |= NFT_SET_SUBKEY;
+	}
 
 	if (set_is_datamap(set->flags)) {
 		if (set->datatype == NULL)
diff --git a/src/mnl.c b/src/mnl.c
index aa5b0b4652e8..24480badaecc 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -881,6 +881,10 @@  int mnl_nft_set_add(struct netlink_ctx *ctx, const struct cmd *cmd,
 				 set->automerge))
 		memory_allocation_error();
 
+	if (set->flags & NFT_SET_SUBKEY)
+		nftnl_set_set_data(nls, NFTNL_SET_SUBKEY, &set->subkey_len,
+				   sizeof(set->subkey_len));
+
 	nftnl_set_set_data(nls, NFTNL_SET_USERDATA, nftnl_udata_buf_data(udbuf),
 			   nftnl_udata_buf_len(udbuf));
 	nftnl_udata_buf_free(udbuf);