diff mbox series

[nf-next] netfilter: nf_tables: export set count and backend name to userspace

Message ID 20241120095236.10532-1-fw@strlen.de
State New
Headers show
Series [nf-next] netfilter: nf_tables: export set count and backend name to userspace | expand

Commit Message

Florian Westphal Nov. 20, 2024, 9:52 a.m. UTC
nf_tables picks a suitable set backend implementation (bitmap, hash,
rbtree..) based on the userspace requirements.

Figuring out the chosen backend requires information about the set flags
and the kernel version.  Export this to userspace so nft can include this
information in debug stats.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/uapi/linux/netfilter/nf_tables.h |  4 ++++
 net/netfilter/nf_tables_api.c            | 19 +++++++++++++++++++
 2 files changed, 23 insertions(+)

Comments

Pablo Neira Ayuso Nov. 20, 2024, 11:34 p.m. UTC | #1
On Wed, Nov 20, 2024 at 10:52:33AM +0100, Florian Westphal wrote:
> nf_tables picks a suitable set backend implementation (bitmap, hash,
> rbtree..) based on the userspace requirements.
> 
> Figuring out the chosen backend requires information about the set flags
> and the kernel version.  Export this to userspace so nft can include this
> information in debug stats.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  include/uapi/linux/netfilter/nf_tables.h |  4 ++++
>  net/netfilter/nf_tables_api.c            | 19 +++++++++++++++++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
> index 49c944e78463..6e87d704d3a8 100644
> --- a/include/uapi/linux/netfilter/nf_tables.h
> +++ b/include/uapi/linux/netfilter/nf_tables.h
> @@ -394,6 +394,8 @@ enum nft_set_field_attributes {
>   * @NFTA_SET_HANDLE: set handle (NLA_U64)
>   * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes)
>   * @NFTA_SET_EXPRESSION: list of expressions (NLA_NESTED: nft_list_attributes)
> + * @NFTA_SET_OPSNAME: set backend type (NLA_STRING)
> + * @NFTA_SET_NELEMS: number of set elements (NLA_U32)
>   */
>  enum nft_set_attributes {
>  	NFTA_SET_UNSPEC,
> @@ -415,6 +417,8 @@ enum nft_set_attributes {
>  	NFTA_SET_HANDLE,
>  	NFTA_SET_EXPR,
>  	NFTA_SET_EXPRESSIONS,
> +	NFTA_SET_OPSNAME,
> +	NFTA_SET_NELEMS,
>  	__NFTA_SET_MAX
>  };
>  #define NFTA_SET_MAX		(__NFTA_SET_MAX - 1)
> diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
> index 21b6f7410a1f..da308e295b95 100644
> --- a/net/netfilter/nf_tables_api.c
> +++ b/net/netfilter/nf_tables_api.c
> @@ -4565,6 +4565,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
>  	[NFTA_SET_HANDLE]		= { .type = NLA_U64 },
>  	[NFTA_SET_EXPR]			= { .type = NLA_NESTED },
>  	[NFTA_SET_EXPRESSIONS]		= NLA_POLICY_NESTED_ARRAY(nft_expr_policy),
> +	[NFTA_SET_OPSNAME]		= { .type = NLA_REJECT },
> +	[NFTA_SET_NELEMS]		= { .type = NLA_REJECT },
>  };
>  
>  static const struct nla_policy nft_concat_policy[NFTA_SET_FIELD_MAX + 1] = {
> @@ -4751,6 +4753,21 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb,
>  	return 0;
>  }
>  
> +/* no error checking: non-essential debug info */
> +static void nf_tables_fill_set_info(struct sk_buff *skb,
> +				    const struct nft_set *set)
> +{
> +	unsigned int nelems = atomic_read(&set->nelems);
> +	const char *str = kasprintf(GFP_ATOMIC, "%ps", set->ops);
> +
> +	nla_put_be32(skb, NFTA_SET_NELEMS, htonl(nelems));
> +
> +	if (str)
> +		nla_put_string(skb, NFTA_SET_OPSNAME, str);
> +
> +	kfree(str);

Can you think of a case where this cannot fit in the skbuff either in
netlink dump or event path? I would check for errors here.

If you like my syntax proposal in userspace:

        size 128        # count 56

maybe rename _NELEMS to _COUNT.

As for NFTA_SET_OPSNAME, I suggest NFTA_SET_TYPE.

Thanks.

> +}
> +
>  static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
>  			      const struct nft_set *set, u16 event, u16 flags)
>  {
> @@ -4830,6 +4847,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
>  
>  	nla_nest_end(skb, nest);
>  
> +	nf_tables_fill_set_info(skb, set);
> +
>  	if (set->num_exprs == 1) {
>  		nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
>  		if (nf_tables_fill_expr_info(skb, set->exprs[0], false) < 0)
> -- 
> 2.45.2
> 
>
Florian Westphal Nov. 20, 2024, 11:38 p.m. UTC | #2
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > +/* no error checking: non-essential debug info */
> > +static void nf_tables_fill_set_info(struct sk_buff *skb,
> > +				    const struct nft_set *set)
> > +{
> > +	unsigned int nelems = atomic_read(&set->nelems);
> > +	const char *str = kasprintf(GFP_ATOMIC, "%ps", set->ops);
> > +
> > +	nla_put_be32(skb, NFTA_SET_NELEMS, htonl(nelems));
> > +
> > +	if (str)
> > +		nla_put_string(skb, NFTA_SET_OPSNAME, str);
> > +
> > +	kfree(str);
> 
> Can you think of a case where this cannot fit in the skbuff either in
> netlink dump or event path? I would check for errors here.

I'll change it, no problem.

> If you like my syntax proposal in userspace:
> 
>         size 128        # count 56
> 
> maybe rename _NELEMS to _COUNT.
> 
> As for NFTA_SET_OPSNAME, I suggest NFTA_SET_TYPE.

OK.
diff mbox series

Patch

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 49c944e78463..6e87d704d3a8 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -394,6 +394,8 @@  enum nft_set_field_attributes {
  * @NFTA_SET_HANDLE: set handle (NLA_U64)
  * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes)
  * @NFTA_SET_EXPRESSION: list of expressions (NLA_NESTED: nft_list_attributes)
+ * @NFTA_SET_OPSNAME: set backend type (NLA_STRING)
+ * @NFTA_SET_NELEMS: number of set elements (NLA_U32)
  */
 enum nft_set_attributes {
 	NFTA_SET_UNSPEC,
@@ -415,6 +417,8 @@  enum nft_set_attributes {
 	NFTA_SET_HANDLE,
 	NFTA_SET_EXPR,
 	NFTA_SET_EXPRESSIONS,
+	NFTA_SET_OPSNAME,
+	NFTA_SET_NELEMS,
 	__NFTA_SET_MAX
 };
 #define NFTA_SET_MAX		(__NFTA_SET_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 21b6f7410a1f..da308e295b95 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -4565,6 +4565,8 @@  static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
 	[NFTA_SET_HANDLE]		= { .type = NLA_U64 },
 	[NFTA_SET_EXPR]			= { .type = NLA_NESTED },
 	[NFTA_SET_EXPRESSIONS]		= NLA_POLICY_NESTED_ARRAY(nft_expr_policy),
+	[NFTA_SET_OPSNAME]		= { .type = NLA_REJECT },
+	[NFTA_SET_NELEMS]		= { .type = NLA_REJECT },
 };
 
 static const struct nla_policy nft_concat_policy[NFTA_SET_FIELD_MAX + 1] = {
@@ -4751,6 +4753,21 @@  static int nf_tables_fill_set_concat(struct sk_buff *skb,
 	return 0;
 }
 
+/* no error checking: non-essential debug info */
+static void nf_tables_fill_set_info(struct sk_buff *skb,
+				    const struct nft_set *set)
+{
+	unsigned int nelems = atomic_read(&set->nelems);
+	const char *str = kasprintf(GFP_ATOMIC, "%ps", set->ops);
+
+	nla_put_be32(skb, NFTA_SET_NELEMS, htonl(nelems));
+
+	if (str)
+		nla_put_string(skb, NFTA_SET_OPSNAME, str);
+
+	kfree(str);
+}
+
 static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
 			      const struct nft_set *set, u16 event, u16 flags)
 {
@@ -4830,6 +4847,8 @@  static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
 
 	nla_nest_end(skb, nest);
 
+	nf_tables_fill_set_info(skb, set);
+
 	if (set->num_exprs == 1) {
 		nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
 		if (nf_tables_fill_expr_info(skb, set->exprs[0], false) < 0)