You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
netfilter: nf_flow_table: hardware offload support
This patch adds the dataplane hardware offload to the flowtable infrastructure. Three new flags represent the hardware state of this flow: * FLOW_OFFLOAD_HW: This flow entry resides in the hardware. * FLOW_OFFLOAD_HW_DYING: This flow entry has been scheduled to be remove from hardware. This might be triggered by either packet path (via TCP RST/FIN packet) or via aging. * FLOW_OFFLOAD_HW_DEAD: This flow entry has been already removed from the hardware, the software garbage collector can remove it from the software flowtable. This patch supports for: * IPv4 only. * Aging via FLOW_CLS_STATS, no packet and byte counter synchronization at this stage. This patch also adds the action callback that specifies how to convert the flow entry into the flow_rule object that is passed to the driver. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
8bb69f3b29
commit
c29f74e0df
@@ -848,6 +848,7 @@ enum tc_setup_type {
|
||||
TC_SETUP_ROOT_QDISC,
|
||||
TC_SETUP_QDISC_GRED,
|
||||
TC_SETUP_QDISC_TAPRIO,
|
||||
TC_SETUP_FT,
|
||||
};
|
||||
|
||||
/* These structures hold the attributes of bpf state that are being passed
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include <net/dst.h>
|
||||
|
||||
struct nf_flowtable;
|
||||
struct nf_flow_rule;
|
||||
struct flow_offload;
|
||||
enum flow_offload_tuple_dir;
|
||||
|
||||
struct nf_flowtable_type {
|
||||
struct list_head list;
|
||||
@@ -20,6 +23,10 @@ struct nf_flowtable_type {
|
||||
int (*setup)(struct nf_flowtable *ft,
|
||||
struct net_device *dev,
|
||||
enum flow_block_command cmd);
|
||||
int (*action)(struct net *net,
|
||||
const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule);
|
||||
void (*free)(struct nf_flowtable *ft);
|
||||
nf_hookfn *hook;
|
||||
struct module *owner;
|
||||
@@ -80,6 +87,9 @@ struct flow_offload_tuple_rhash {
|
||||
#define FLOW_OFFLOAD_DNAT 0x2
|
||||
#define FLOW_OFFLOAD_DYING 0x4
|
||||
#define FLOW_OFFLOAD_TEARDOWN 0x8
|
||||
#define FLOW_OFFLOAD_HW 0x10
|
||||
#define FLOW_OFFLOAD_HW_DYING 0x20
|
||||
#define FLOW_OFFLOAD_HW_DEAD 0x40
|
||||
|
||||
enum flow_offload_type {
|
||||
NF_FLOW_OFFLOAD_UNSPEC = 0,
|
||||
@@ -142,11 +152,22 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
#define MODULE_ALIAS_NF_FLOWTABLE(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;
|
||||
}
|
||||
void nf_flow_offload_add(struct nf_flowtable *flowtable,
|
||||
struct flow_offload *flow);
|
||||
void nf_flow_offload_del(struct nf_flowtable *flowtable,
|
||||
struct flow_offload *flow);
|
||||
void nf_flow_offload_stats(struct nf_flowtable *flowtable,
|
||||
struct flow_offload *flow);
|
||||
|
||||
void nf_flow_table_offload_flush(struct nf_flowtable *flowtable);
|
||||
int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
|
||||
struct net_device *dev,
|
||||
enum flow_block_command cmd);
|
||||
int nf_flow_rule_route(struct net *net, const struct flow_offload *flow,
|
||||
enum flow_offload_tuple_dir dir,
|
||||
struct nf_flow_rule *flow_rule);
|
||||
|
||||
int nf_flow_table_offload_init(void);
|
||||
void nf_flow_table_offload_exit(void);
|
||||
|
||||
#endif /* _NF_FLOW_TABLE_H */
|
||||
|
||||
@@ -10,6 +10,7 @@ static struct nf_flowtable_type flowtable_ipv4 = {
|
||||
.family = NFPROTO_IPV4,
|
||||
.init = nf_flow_table_init,
|
||||
.setup = nf_flow_table_offload_setup,
|
||||
.action = nf_flow_rule_route,
|
||||
.free = nf_flow_table_free,
|
||||
.hook = nf_flow_offload_ip_hook,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
@@ -11,6 +11,7 @@ static struct nf_flowtable_type flowtable_ipv6 = {
|
||||
.family = NFPROTO_IPV6,
|
||||
.init = nf_flow_table_init,
|
||||
.setup = nf_flow_table_offload_setup,
|
||||
.action = nf_flow_rule_route,
|
||||
.free = nf_flow_table_free,
|
||||
.hook = nf_flow_offload_ipv6_hook,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
@@ -120,7 +120,8 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o
|
||||
|
||||
# flow table infrastructure
|
||||
obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o
|
||||
nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o
|
||||
nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o \
|
||||
nf_flow_table_offload.o
|
||||
|
||||
obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o
|
||||
|
||||
|
||||
@@ -250,6 +250,9 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (flow_table->flags & NF_FLOWTABLE_HW_OFFLOAD)
|
||||
nf_flow_offload_add(flow_table, flow);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(flow_offload_add);
|
||||
@@ -350,9 +353,20 @@ static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
|
||||
{
|
||||
struct nf_flowtable *flow_table = data;
|
||||
|
||||
if (flow->flags & FLOW_OFFLOAD_HW)
|
||||
nf_flow_offload_stats(flow_table, flow);
|
||||
|
||||
if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct) ||
|
||||
(flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN)))
|
||||
flow_offload_del(flow_table, flow);
|
||||
(flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN))) {
|
||||
if (flow->flags & FLOW_OFFLOAD_HW) {
|
||||
if (!(flow->flags & FLOW_OFFLOAD_HW_DYING))
|
||||
nf_flow_offload_del(flow_table, flow);
|
||||
else if (flow->flags & FLOW_OFFLOAD_HW_DEAD)
|
||||
flow_offload_del(flow_table, flow);
|
||||
} else {
|
||||
flow_offload_del(flow_table, flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nf_flow_offload_work_gc(struct work_struct *work)
|
||||
@@ -485,6 +499,7 @@ int nf_flow_table_init(struct nf_flowtable *flowtable)
|
||||
int err;
|
||||
|
||||
INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc);
|
||||
flow_block_init(&flowtable->flow_block);
|
||||
|
||||
err = rhashtable_init(&flowtable->rhashtable,
|
||||
&nf_flow_offload_rhash_params);
|
||||
@@ -520,6 +535,7 @@ static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data)
|
||||
static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable,
|
||||
struct net_device *dev)
|
||||
{
|
||||
nf_flow_table_offload_flush(flowtable);
|
||||
nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev);
|
||||
flush_delayed_work(&flowtable->gc_work);
|
||||
}
|
||||
@@ -547,5 +563,18 @@ void nf_flow_table_free(struct nf_flowtable *flow_table)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_flow_table_free);
|
||||
|
||||
static int __init nf_flow_table_module_init(void)
|
||||
{
|
||||
return nf_flow_table_offload_init();
|
||||
}
|
||||
|
||||
static void __exit nf_flow_table_module_exit(void)
|
||||
{
|
||||
nf_flow_table_offload_exit();
|
||||
}
|
||||
|
||||
module_init(nf_flow_table_module_init);
|
||||
module_exit(nf_flow_table_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
|
||||
|
||||
@@ -25,6 +25,7 @@ static struct nf_flowtable_type flowtable_inet = {
|
||||
.family = NFPROTO_INET,
|
||||
.init = nf_flow_table_init,
|
||||
.setup = nf_flow_table_offload_setup,
|
||||
.action = nf_flow_rule_route,
|
||||
.free = nf_flow_table_free,
|
||||
.hook = nf_flow_offload_inet_hook,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
758
net/netfilter/nf_flow_table_offload.c
Normal file
758
net/netfilter/nf_flow_table_offload.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user