netfilter: nf_tables: add hardware offload support
This patch adds hardware offload support for nftables through the existing netdev_ops->ndo_setup_tc() interface, the TC_SETUP_CLSFLOWER classifier and the flow rule API. This hardware offload support is available for the NFPROTO_NETDEV family and the ingress hook. Each nftables expression has a new ->offload interface, that is used to populate the flow rule object that is attached to the transaction object. There is a new per-table NFT_TABLE_F_HW flag, that is set on to offload an entire table, including all of its chains. This patch supports for basic metadata (layer 3 and 4 protocol numbers), 5-tuple payload matching and the accept/drop actions; this also includes basechain hardware offload only. 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
f9e30088d2
commit
c9626a2cbd
@@ -161,6 +161,7 @@ struct nft_ctx {
|
||||
const struct nlattr * const *nla;
|
||||
u32 portid;
|
||||
u32 seq;
|
||||
u16 flags;
|
||||
u8 family;
|
||||
u8 level;
|
||||
bool report;
|
||||
@@ -735,6 +736,9 @@ enum nft_trans_phase {
|
||||
NFT_TRANS_RELEASE
|
||||
};
|
||||
|
||||
struct nft_flow_rule;
|
||||
struct nft_offload_ctx;
|
||||
|
||||
/**
|
||||
* struct nft_expr_ops - nf_tables expression operations
|
||||
*
|
||||
@@ -777,6 +781,10 @@ struct nft_expr_ops {
|
||||
const struct nft_data **data);
|
||||
bool (*gc)(struct net *net,
|
||||
const struct nft_expr *expr);
|
||||
int (*offload)(struct nft_offload_ctx *ctx,
|
||||
struct nft_flow_rule *flow,
|
||||
const struct nft_expr *expr);
|
||||
u32 offload_flags;
|
||||
const struct nft_expr_type *type;
|
||||
void *data;
|
||||
};
|
||||
@@ -859,6 +867,7 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
|
||||
|
||||
enum nft_chain_flags {
|
||||
NFT_BASE_CHAIN = 0x1,
|
||||
NFT_CHAIN_HW_OFFLOAD = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -942,6 +951,7 @@ struct nft_stats {
|
||||
* @stats: per-cpu chain stats
|
||||
* @chain: the chain
|
||||
* @dev_name: device name that this base chain is attached to (if any)
|
||||
* @cb_list: list of flow block callbacks (for hardware offload)
|
||||
*/
|
||||
struct nft_base_chain {
|
||||
struct nf_hook_ops ops;
|
||||
@@ -951,6 +961,7 @@ struct nft_base_chain {
|
||||
struct nft_stats __percpu *stats;
|
||||
struct nft_chain chain;
|
||||
char dev_name[IFNAMSIZ];
|
||||
struct list_head cb_list;
|
||||
};
|
||||
|
||||
static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
|
||||
@@ -1322,11 +1333,14 @@ struct nft_trans {
|
||||
|
||||
struct nft_trans_rule {
|
||||
struct nft_rule *rule;
|
||||
struct nft_flow_rule *flow;
|
||||
u32 rule_id;
|
||||
};
|
||||
|
||||
#define nft_trans_rule(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->rule)
|
||||
#define nft_trans_flow_rule(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->flow)
|
||||
#define nft_trans_rule_id(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->rule_id)
|
||||
|
||||
|
76
include/net/netfilter/nf_tables_offload.h
Normal file
76
include/net/netfilter/nf_tables_offload.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef _NET_NF_TABLES_OFFLOAD_H
|
||||
#define _NET_NF_TABLES_OFFLOAD_H
|
||||
|
||||
#include <net/flow_offload.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
|
||||
struct nft_offload_reg {
|
||||
u32 key;
|
||||
u32 len;
|
||||
u32 base_offset;
|
||||
u32 offset;
|
||||
struct nft_data mask;
|
||||
};
|
||||
|
||||
enum nft_offload_dep_type {
|
||||
NFT_OFFLOAD_DEP_UNSPEC = 0,
|
||||
NFT_OFFLOAD_DEP_NETWORK,
|
||||
NFT_OFFLOAD_DEP_TRANSPORT,
|
||||
};
|
||||
|
||||
struct nft_offload_ctx {
|
||||
struct {
|
||||
enum nft_offload_dep_type type;
|
||||
__be16 l3num;
|
||||
u8 protonum;
|
||||
} dep;
|
||||
unsigned int num_actions;
|
||||
struct nft_offload_reg regs[NFT_REG32_15 + 1];
|
||||
};
|
||||
|
||||
void nft_offload_set_dependency(struct nft_offload_ctx *ctx,
|
||||
enum nft_offload_dep_type type);
|
||||
void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
|
||||
const void *data, u32 len);
|
||||
|
||||
struct nft_flow_key {
|
||||
struct flow_dissector_key_basic basic;
|
||||
union {
|
||||
struct flow_dissector_key_ipv4_addrs ipv4;
|
||||
struct flow_dissector_key_ipv6_addrs ipv6;
|
||||
};
|
||||
struct flow_dissector_key_ports tp;
|
||||
struct flow_dissector_key_ip ip;
|
||||
struct flow_dissector_key_vlan vlan;
|
||||
struct flow_dissector_key_eth_addrs eth_addrs;
|
||||
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
|
||||
|
||||
struct nft_flow_match {
|
||||
struct flow_dissector dissector;
|
||||
struct nft_flow_key key;
|
||||
struct nft_flow_key mask;
|
||||
};
|
||||
|
||||
struct nft_flow_rule {
|
||||
__be16 proto;
|
||||
struct nft_flow_match match;
|
||||
struct flow_rule *rule;
|
||||
};
|
||||
|
||||
#define NFT_OFFLOAD_F_ACTION (1 << 0)
|
||||
|
||||
struct nft_rule;
|
||||
struct nft_flow_rule *nft_flow_rule_create(const struct nft_rule *rule);
|
||||
void nft_flow_rule_destroy(struct nft_flow_rule *flow);
|
||||
int nft_flow_rule_offload_commit(struct net *net);
|
||||
|
||||
#define NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \
|
||||
(__reg)->base_offset = \
|
||||
offsetof(struct nft_flow_key, __base); \
|
||||
(__reg)->offset = \
|
||||
offsetof(struct nft_flow_key, __base.__field); \
|
||||
(__reg)->len = __len; \
|
||||
(__reg)->key = __key; \
|
||||
memset(&(__reg)->mask, 0xff, (__reg)->len);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user