Commit 8bb69f3b authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by David S. Miller

netfilter: nf_tables: add flowtable offload control plane

This patch adds the NFTA_FLOWTABLE_FLAGS attribute that allows users to
specify the NF_FLOWTABLE_HW_OFFLOAD flag. This patch also adds a new
setup interface for the flowtable type to perform the flowtable offload
block callback configuration.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f1363e05
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h> #include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/flow_offload.h>
#include <net/dst.h> #include <net/dst.h>
struct nf_flowtable; struct nf_flowtable;
...@@ -16,17 +17,27 @@ struct nf_flowtable_type { ...@@ -16,17 +17,27 @@ struct nf_flowtable_type {
struct list_head list; struct list_head list;
int family; int family;
int (*init)(struct nf_flowtable *ft); int (*init)(struct nf_flowtable *ft);
int (*setup)(struct nf_flowtable *ft,
struct net_device *dev,
enum flow_block_command cmd);
void (*free)(struct nf_flowtable *ft); void (*free)(struct nf_flowtable *ft);
nf_hookfn *hook; nf_hookfn *hook;
struct module *owner; struct module *owner;
}; };
enum nf_flowtable_flags {
NF_FLOWTABLE_HW_OFFLOAD = 0x1,
};
struct nf_flowtable { struct nf_flowtable {
struct list_head list; struct list_head list;
struct rhashtable rhashtable; struct rhashtable rhashtable;
int priority; int priority;
const struct nf_flowtable_type *type; const struct nf_flowtable_type *type;
struct delayed_work gc_work; struct delayed_work gc_work;
unsigned int flags;
struct flow_block flow_block;
possible_net_t net;
}; };
enum flow_offload_tuple_dir { enum flow_offload_tuple_dir {
...@@ -131,4 +142,11 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ...@@ -131,4 +142,11 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
#define MODULE_ALIAS_NF_FLOWTABLE(family) \ #define MODULE_ALIAS_NF_FLOWTABLE(family) \
MODULE_ALIAS("nf-flowtable-" __stringify(family)) MODULE_ALIAS("nf-flowtable-" __stringify(family))
static inline int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
struct net_device *dev,
enum flow_block_command cmd)
{
return 0;
}
#endif /* _NF_FLOW_TABLE_H */ #endif /* _NF_FLOW_TABLE_H */
...@@ -1518,6 +1518,7 @@ enum nft_object_attributes { ...@@ -1518,6 +1518,7 @@ enum nft_object_attributes {
* @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
* @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
* @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
* @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)
*/ */
enum nft_flowtable_attributes { enum nft_flowtable_attributes {
NFTA_FLOWTABLE_UNSPEC, NFTA_FLOWTABLE_UNSPEC,
...@@ -1527,6 +1528,7 @@ enum nft_flowtable_attributes { ...@@ -1527,6 +1528,7 @@ enum nft_flowtable_attributes {
NFTA_FLOWTABLE_USE, NFTA_FLOWTABLE_USE,
NFTA_FLOWTABLE_HANDLE, NFTA_FLOWTABLE_HANDLE,
NFTA_FLOWTABLE_PAD, NFTA_FLOWTABLE_PAD,
NFTA_FLOWTABLE_FLAGS,
__NFTA_FLOWTABLE_MAX __NFTA_FLOWTABLE_MAX
}; };
#define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
static struct nf_flowtable_type flowtable_ipv4 = { static struct nf_flowtable_type flowtable_ipv4 = {
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
.init = nf_flow_table_init, .init = nf_flow_table_init,
.setup = nf_flow_table_offload_setup,
.free = nf_flow_table_free, .free = nf_flow_table_free,
.hook = nf_flow_offload_ip_hook, .hook = nf_flow_offload_ip_hook,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
static struct nf_flowtable_type flowtable_ipv6 = { static struct nf_flowtable_type flowtable_ipv6 = {
.family = NFPROTO_IPV6, .family = NFPROTO_IPV6,
.init = nf_flow_table_init, .init = nf_flow_table_init,
.setup = nf_flow_table_offload_setup,
.free = nf_flow_table_free, .free = nf_flow_table_free,
.hook = nf_flow_offload_ipv6_hook, .hook = nf_flow_offload_ipv6_hook,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -24,6 +24,7 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, ...@@ -24,6 +24,7 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
static struct nf_flowtable_type flowtable_inet = { static struct nf_flowtable_type flowtable_inet = {
.family = NFPROTO_INET, .family = NFPROTO_INET,
.init = nf_flow_table_init, .init = nf_flow_table_init,
.setup = nf_flow_table_offload_setup,
.free = nf_flow_table_free, .free = nf_flow_table_free,
.hook = nf_flow_offload_inet_hook, .hook = nf_flow_offload_inet_hook,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -5835,6 +5835,7 @@ static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = { ...@@ -5835,6 +5835,7 @@ static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = {
.len = NFT_NAME_MAXLEN - 1 }, .len = NFT_NAME_MAXLEN - 1 },
[NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED },
[NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 },
[NFTA_FLOWTABLE_FLAGS] = { .type = NLA_U32 },
}; };
struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table, struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table,
...@@ -5968,8 +5969,11 @@ static void nft_unregister_flowtable_net_hooks(struct net *net, ...@@ -5968,8 +5969,11 @@ static void nft_unregister_flowtable_net_hooks(struct net *net,
{ {
struct nft_hook *hook; struct nft_hook *hook;
list_for_each_entry(hook, &flowtable->hook_list, list) list_for_each_entry(hook, &flowtable->hook_list, list) {
nf_unregister_net_hook(net, &hook->ops); nf_unregister_net_hook(net, &hook->ops);
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
FLOW_BLOCK_UNBIND);
}
} }
static int nft_register_flowtable_net_hooks(struct net *net, static int nft_register_flowtable_net_hooks(struct net *net,
...@@ -5991,6 +5995,8 @@ static int nft_register_flowtable_net_hooks(struct net *net, ...@@ -5991,6 +5995,8 @@ static int nft_register_flowtable_net_hooks(struct net *net,
} }
} }
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
FLOW_BLOCK_BIND);
err = nf_register_net_hook(net, &hook->ops); err = nf_register_net_hook(net, &hook->ops);
if (err < 0) if (err < 0)
goto err_unregister_net_hooks; goto err_unregister_net_hooks;
...@@ -6006,6 +6012,8 @@ static int nft_register_flowtable_net_hooks(struct net *net, ...@@ -6006,6 +6012,8 @@ static int nft_register_flowtable_net_hooks(struct net *net,
break; break;
nf_unregister_net_hook(net, &hook->ops); nf_unregister_net_hook(net, &hook->ops);
flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
FLOW_BLOCK_UNBIND);
list_del_rcu(&hook->list); list_del_rcu(&hook->list);
kfree_rcu(hook, rcu); kfree_rcu(hook, rcu);
} }
...@@ -6080,6 +6088,14 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, ...@@ -6080,6 +6088,14 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
goto err2; goto err2;
} }
if (nla[NFTA_FLOWTABLE_FLAGS]) {
flowtable->data.flags =
ntohl(nla_get_be32(nla[NFTA_FLOWTABLE_FLAGS]));
if (flowtable->data.flags & ~NF_FLOWTABLE_HW_OFFLOAD)
goto err3;
}
write_pnet(&flowtable->data.net, net);
flowtable->data.type = type; flowtable->data.type = type;
err = type->init(&flowtable->data); err = type->init(&flowtable->data);
if (err < 0) if (err < 0)
...@@ -6191,7 +6207,8 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, ...@@ -6191,7 +6207,8 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) ||
nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle),
NFTA_FLOWTABLE_PAD)) NFTA_FLOWTABLE_PAD) ||
nla_put_be32(skb, NFTA_FLOWTABLE_FLAGS, htonl(flowtable->data.flags)))
goto nla_put_failure; goto nla_put_failure;
nest = nla_nest_start_noflag(skb, NFTA_FLOWTABLE_HOOK); nest = nla_nest_start_noflag(skb, NFTA_FLOWTABLE_HOOK);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment