netfilter: nft_numgen: add number generator expression
Subsystems (2)
PATCH v4 1/1 netfilter: nft_numgen: add number generator expression
Add support for the number generator expression in netfilter.
---
Changes in V4:
- Rename prandom state identifier
include/uapi/linux/netfilter/nf_tables.h | 25 ++++ net/netfilter/Kconfig | 6 + net/netfilter/Makefile | 1 + net/netfilter/nft_numgen.c | 193 +++++++++++++++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 net/netfilter/nft_numgen.c
include/uapi/linux/netfilter/nf_tables.h +25 -0
@@ -1082,4 +1082,29 @@ enum nft_trace_types {__NFT_TRACETYPE_MAX };#define NFT_TRACETYPE_MAX (__NFT_TRACETYPE_MAX - 1) + +/** +* enum nft_ng_attributes - nf_tables number generator expression netlink +* attributes +* +* @NFTA_NG_DREG: destination register (NLA_U32) +* @NFTA_NG_UNTIL: source value to increment the counter until reset (NLA_U32) +* @NFTA_NG_TYPE: operation type (NLA_U32) +*/ +enum nft_ng_attributes { +NFTA_NG_UNSPEC , +NFTA_NG_DREG , +NFTA_NG_UNTIL , +NFTA_NG_TYPE , + __NFTA_NG_MAX +}; +#define NFTA_NG_MAX (__NFTA_NG_MAX - 1) + +enum nft_ng_types { +NFT_NG_INCREMENTAL , +NFT_NG_RANDOM , + __NFT_NG_MAX +}; +#define NFT_NG_MAX (__NFT_NG_MAX - 1) +#endif /* _LINUX_NF_TABLES_H */
net/netfilter/Kconfig +6 -0
@@ -474,6 +474,12 @@ config NFT_META This option adds the "meta" expression that you can use to match and to set packet metainformation such as the packet mark. +config NFT_NUMGEN + tristate "Netfilter nf_tables number generator module" + help + This option adds the number generator expression used to perform + operations like the incremental counter until a reset value or random. + config NFT_CT depends on NF_CONNTRACK tristate "Netfilter nf_tables conntrack module"
net/netfilter/Makefile +1 -0
@@ -80,6 +80,7 @@ obj-$(CONFIG_NF_TABLES_NETDEV) += nf_tables_netdev.o obj-$(CONFIG_NFT_COMPAT) += nft_compat.o obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o obj-$(CONFIG_NFT_META) += nft_meta.o +obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o obj-$(CONFIG_NFT_CT) += nft_ct.o obj-$(CONFIG_NFT_LIMIT) += nft_limit.o obj-$(CONFIG_NFT_NAT) += nft_nat.o
net/netfilter/nft_numgen.c new file +193 -0
193 lines not on this page · raw message
Signature · 1 line
2.8.1
Pablo Neira Ayuso
maintainerMostly comestic changes, see below.
Quoted 39 lines · Laura Garcia Liebana
net/netfilter/Makefile +1
-0@@ -80,6 +80,7 @@ obj-$(CONFIG_NF_TABLES_NETDEV) += nf_tables_netdev.o obj-$(CONFIG_NFT_COMPAT) += nft_compat.o obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o obj-$(CONFIG_NFT_META) += nft_meta.o +obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o obj-$(CONFIG_NFT_CT) += nft_ct.o obj-$(CONFIG_NFT_LIMIT) += nft_limit.o obj-$(CONFIG_NFT_NAT) += nft_nat.onet/netfilter/nft_numgen.c new file +21
-0@@ -0,0 +1,193 @@ +/* +* Copyright (c) 2016 Laura Garcia <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/netlink.h> +#include <linux/netfilter.h> +#include <linux/netfilter/nf_tables.h> +#include <linux/static_key.h> +#include <net/netfilter/nf_tables.h> +#include <net/netfilter/nf_tables_core.h> + +static DEFINE_PER_CPU(struct rnd_state, nft_numgen_prandom_state); +
net/netfilter/nft_numgen.c line 31
Quoted 10 lines
net/netfilter/nft_numgen.c new file +10
-0+struct nft_ng_inc { +enum nft_registers dreg:8 ; +u32 until; +atomic_t counter; +}; + +struct nft_ng_random { +enum nft_registers dreg:8 ; +u32 until; +};
It is strange that you mix the code of both methods. I mean, I would be expecting to see:
struct nft_ng_inc {
...
};static void nft_ng_inc_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt)
{
...
}static int nft_ng_inc_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
...
}And so on, I mean, everything that relates to _inc_ all together.
This makes the code more readable as I don't need to scroll up and down to see all what refers to the _inc_ mode.
More comments below.
Quoted 16 lines
net/netfilter/nft_numgen.c new file +16
-0+static void nft_ng_inc_eval (const struct nft_expr *expr, +struct nft_regs *regs, +const struct nft_pktinfo *pkt) +{ +struct nft_ng_inc *priv =nft_expr_priv (expr); +u32 nval, oval; + +do { + oval =atomic_read (&priv->counter); + nval = (oval +1 < priv->until) ? oval +1 :0 ; + }while (atomic_cmpxchg (&priv->counter, oval, nval) != oval); + +memcpy (®s->data[priv->dreg], &priv->counter,sizeof (u32)); +} + +static void nft_ng_random_eval(const struct nft_expr *expr,
net/netfilter/nft_numgen.c line 58
Quoted 10 lines
net/netfilter/nft_numgen.c new file +10
-0+struct nft_regs *regs, + const struct nft_pktinfo *pkt) +{ + struct nft_ng_random *priv = nft_expr_priv(expr); +struct rnd_state *state =this_cpu_ptr (&nft_numgen_prandom_state); +u32 p; + + p =reciprocal_scale (prandom_u32_state (state), priv->until); + + regs->data[priv->dreg] = p;
You can place this in one single line and get rid of p:
regs->data[priv->dreg] =
reciprocal_scale(prandom_u32_state(state), priv->until);Quoted 23 lines
net/netfilter/nft_numgen.c new file +23
-0+} + +const struct nla_policy nft_ng_policy[NFTA_NG_MAX +1 ] = { + [NFTA_NG_DREG ] = { .type =NLA_U32 }, + [NFTA_NG_UNTIL ] = { .type =NLA_U32 }, + [NFTA_NG_TYPE ] = { .type =NLA_U32 }, +}; + +static int nft_ng_inc_init (const struct nft_ctx *ctx, +const struct nft_expr *expr, +const struct nlattr *const tb[]) +{ +struct nft_ng_inc *priv =nft_expr_priv (expr); + + priv->until =ntohl (nla_get_be32 (tb[NFTA_NG_UNTIL ])); +if (priv->until ==0 ) +return -EINVAL ; + + priv->dreg =nft_parse_register (tb[NFTA_NG_DREG ]); +atomic_set (&priv->counter,0 ); + +return nft_validate_register_store (ctx, priv->dreg,NULL , +NFT_DATA_VALUE ,sizeof (u32));
net/netfilter/nft_numgen.c line 91
Quoted 10 lines
net/netfilter/nft_numgen.c new file +10
-0+} + +static int nft_ng_random_init (const struct nft_ctx *ctx, +const struct nft_expr *expr, +const struct nlattr *const tb[]) +{ +struct nft_ng_random *priv =nft_expr_priv (expr); +u32 len; + + priv->until =ntohl (nla_get_be32 (tb[NFTA_NG_UNTIL ]));
No check for priv->until == 0 here?
net/netfilter/nft_numgen.c line 94
Quoted 2 lines
net/netfilter/nft_numgen.c new file +2
-0+prandom_init_once (&nft_numgen_prandom_state); + len =sizeof (u32);
We don't need len here.
Quoted 60 lines
net/netfilter/nft_numgen.c new file +60
-0+ priv->dreg =nft_parse_register (tb[NFTA_NG_DREG ]); + +return nft_validate_register_store (ctx, priv->dreg,NULL , +NFT_DATA_VALUE , len); +} + +static int nft_ng_dump (struct sk_buff *skb,enum nft_registers dreg, +u32 until,enum nft_ng_types type) +{ +if (nft_dump_register (skb,NFTA_NG_DREG , dreg)) + goto nla_put_failure; +if (nft_dump_register (skb,NFTA_NG_UNTIL , until)) + goto nla_put_failure; +if (nft_dump_register (skb,NFTA_NG_TYPE , type)) + goto nla_put_failure; + +return 0 ; + +nla_put_failure: +return -1 ; +} + +static int nft_ng_inc_dump (struct sk_buff *skb,const struct nft_expr *expr) +{ +const struct nft_ng_inc *priv =nft_expr_priv (expr); + +return nft_ng_dump (skb, priv->dreg, priv->until,NFT_NG_INCREMENTAL ); +} + +static int nft_ng_random_dump (struct sk_buff *skb,const struct nft_expr *expr) +{ +const struct nft_ng_random *priv =nft_expr_priv (expr); + +return nft_ng_dump (skb, priv->dreg, priv->until,NFT_NG_RANDOM ); +} + +static struct nft_expr_type nft_ng_type; +static const struct nft_expr_ops nft_ng_inc_ops = { + .type = &nft_ng_type, + .size =NFT_EXPR_SIZE (sizeof (struct nft_ng_inc )), + .eval = nft_ng_inc_eval, + .init = nft_ng_inc_init, + .dump = nft_ng_inc_dump, +}; + +static const struct nft_expr_ops nft_ng_random_ops = { + .type = &nft_ng_type, + .size =NFT_EXPR_SIZE (sizeof (struct nft_ng_random )), + .eval = nft_ng_random_eval, + .init = nft_ng_random_init, + .dump = nft_ng_random_dump, +}; + +static const struct nft_expr_ops * +nft_ng_select_ops (const struct nft_ctx *ctx,const struct nlattr *const tb[]) +{ +u32 type; + + if (!tb[NFTA_NG_DREG] || + !tb[NFTA_NG_UNTIL] ||
net/netfilter/nft_numgen.c line 165
Quoted 10 lines
net/netfilter/nft_numgen.c new file +10
-0+ !tb[NFTA_NG_TYPE]) +return ERR_PTR (-EINVAL ); + + type =ntohl (nla_get_be32 (tb[NFTA_NG_TYPE ])); + +if (type ==NFT_NG_INCREMENTAL ) +return &nft_ng_inc_ops; + +if (type ==NFT_NG_RANDOM ) +return &nft_ng_random_ops;
Better a switch for this?
switch (type) {
case NFT_NG_INCREMENTAL:
return &nft_ng_inc_ops;
case NFT_NG_RANDOM:
return &nft_ng_random_ops;
}
return ERR_PTR(-EINVAL);Quoted 35 lines
net/netfilter/nft_numgen.c new file +28
-0+ +return ERR_PTR (-EINVAL ); +} + +static struct nft_expr_type nft_ng_type__read_mostly = { + .name ="numgen" , + .select_ops = &nft_ng_select_ops, + .policy = nft_ng_policy, + .maxattr =NFTA_NG_MAX , + .owner =THIS_MODULE , +}; + +static int __init nft_ng_module_init (void ) +{ +return nft_register_expr (&nft_ng_type); +} + +static void __exit nft_ng_module_exit(void) +{ +nft_unregister_expr (&nft_ng_type); +} + +module_init (nft_ng_module_init); +module_exit (nft_ng_module_exit); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Laura Garcia <[email protected]>" ); +MODULE_ALIAS_NFT_EXPR ("numgen" );Signature · 6 lines
2.8.1 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html