Commit 0320d1e7 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'netfilter-flowtable-hardware-offload'



Pablo Neira Ayuso says:

====================
netfilter flowtable hardware offload

The following patchset adds hardware offload support for the flowtable
infrastructure [1]. This infrastructure provides a fast datapath for
the classic Linux forwarding path that users can enable through policy,
eg.

 table inet x {
      flowtable f {
               hook ingress priority 10 devices = { eth0, eth1 }
	       flags offload
      }
      chain y {
               type filter hook forward priority 0; policy accept;
               ip protocol tcp flow offload @f
      }
 }

This example above enables the fastpath for TCP traffic between devices
eth0 and eth1. Users can turn on the hardware offload through the
'offload' flag from the flowtable definition. If this new flag is not
specified, the software flowtable datapath is used.

This patchset is composed of 4 preparation patches:

   room to extend this infrastructure, eg. accelerate bridge forwarding.

And 2 patches to add the hardware offload control and data planes:

   hardware offload. This includes a new NFTA_FLOWTABLE_FLAGS netlink
   attribute to convey the optional NF_FLOWTABLE_HW_OFFLOAD flag.
   API available at net/core/flow_offload.h to represent the flow
   through two flow_rule objects to configure an exact 5-tuple matching
   on each direction plus the corresponding forwarding actions, that is,
   the MAC address, NAT and checksum updates; and port redirection in
   order to configure the hardware datapath. This patch only supports
   for IPv4 support and statistics collection for flow aging as an initial
   step.

This patchset introduces a new flow_block callback type that needs to be
set up to configure the flowtable hardware offload.

The first client of this infrastructure follows up after this batch.
I would like to thank Mellanox for developing the first upstream driver
to use this infrastructure.

[1] Documentation/networking/nf_flowtable.txt
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4717b053 c29f74e0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+53 −7
Original line number Diff line number Diff line
@@ -8,25 +8,43 @@
#include <linux/rcupdate.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/flow_offload.h>
#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;
	int				family;
	int				(*init)(struct nf_flowtable *ft);
	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;
};

enum nf_flowtable_flags {
	NF_FLOWTABLE_HW_OFFLOAD		= 0x1,
};

struct nf_flowtable {
	struct list_head		list;
	struct rhashtable		rhashtable;
	int				priority;
	const struct nf_flowtable_type	*type;
	struct delayed_work		gc_work;
	unsigned int			flags;
	struct flow_block		flow_block;
	possible_net_t			net;
};

enum flow_offload_tuple_dir {
@@ -69,14 +87,22 @@ 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,
	NF_FLOW_OFFLOAD_ROUTE,
};

struct flow_offload {
	struct flow_offload_tuple_rhash		tuplehash[FLOW_OFFLOAD_DIR_MAX];
	u32					flags;
	union {
		/* Your private driver data here. */
	struct nf_conn				*ct;
	u16					flags;
	u16					type;
	u32					timeout;
	};
	struct rcu_head				rcu_head;
};

#define NF_FLOW_TIMEOUT (30 * HZ)
@@ -87,10 +113,12 @@ struct nf_flow_route {
	} tuple[FLOW_OFFLOAD_DIR_MAX];
};

struct flow_offload *flow_offload_alloc(struct nf_conn *ct,
					struct nf_flow_route *route);
struct flow_offload *flow_offload_alloc(struct nf_conn *ct);
void flow_offload_free(struct flow_offload *flow);

int flow_offload_route_init(struct flow_offload *flow,
			    const struct nf_flow_route *route);

int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table,
						     struct flow_offload_tuple *tuple);
@@ -124,4 +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))

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 */
+2 −0
Original line number Diff line number Diff line
@@ -1518,6 +1518,7 @@ enum nft_object_attributes {
 * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
 * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
 * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
 * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)
 */
enum nft_flowtable_attributes {
	NFTA_FLOWTABLE_UNSPEC,
@@ -1527,6 +1528,7 @@ enum nft_flowtable_attributes {
	NFTA_FLOWTABLE_USE,
	NFTA_FLOWTABLE_HANDLE,
	NFTA_FLOWTABLE_PAD,
	NFTA_FLOWTABLE_FLAGS,
	__NFTA_FLOWTABLE_MAX
};
#define NFTA_FLOWTABLE_MAX	(__NFTA_FLOWTABLE_MAX - 1)
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
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,
+2 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
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,
Loading