1818#include <net/netfilter/nf_flow_table.h>
1919#include <net/netfilter/nf_tables_core.h>
2020#include <net/netfilter/nf_tables.h>
21+ #include <net/netfilter/nf_tables_offload.h>
2122#include <net/net_namespace.h>
2223#include <net/sock.h>
2324
@@ -97,6 +98,7 @@ static void nft_ctx_init(struct nft_ctx *ctx,
9798 ctx -> nla = nla ;
9899 ctx -> portid = NETLINK_CB (skb ).portid ;
99100 ctx -> report = nlmsg_report (nlh );
101+ ctx -> flags = nlh -> nlmsg_flags ;
100102 ctx -> seq = nlh -> nlmsg_seq ;
101103}
102104
@@ -1169,6 +1171,7 @@ static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
11691171 [NFTA_CHAIN_POLICY ] = { .type = NLA_U32 },
11701172 [NFTA_CHAIN_TYPE ] = { .type = NLA_STRING },
11711173 [NFTA_CHAIN_COUNTERS ] = { .type = NLA_NESTED },
1174+ [NFTA_CHAIN_FLAGS ] = { .type = NLA_U32 },
11721175};
11731176
11741177static const struct nla_policy nft_hook_policy [NFTA_HOOK_MAX + 1 ] = {
@@ -1603,7 +1606,7 @@ static struct nft_rule **nf_tables_chain_alloc_rules(const struct nft_chain *cha
16031606}
16041607
16051608static int nf_tables_addchain (struct nft_ctx * ctx , u8 family , u8 genmask ,
1606- u8 policy )
1609+ u8 policy , u32 flags )
16071610{
16081611 const struct nlattr * const * nla = ctx -> nla ;
16091612 struct nft_table * table = ctx -> table ;
@@ -1657,8 +1660,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
16571660 ops -> hook = hook .type -> hooks [ops -> hooknum ];
16581661 ops -> dev = hook .dev ;
16591662
1660- chain -> flags |= NFT_BASE_CHAIN ;
1663+ chain -> flags |= NFT_BASE_CHAIN | flags ;
16611664 basechain -> policy = NF_ACCEPT ;
1665+ INIT_LIST_HEAD (& basechain -> cb_list );
16621666 } else {
16631667 chain = kzalloc (sizeof (* chain ), GFP_KERNEL );
16641668 if (chain == NULL )
@@ -1718,7 +1722,8 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
17181722 return err ;
17191723}
17201724
1721- static int nf_tables_updchain (struct nft_ctx * ctx , u8 genmask , u8 policy )
1725+ static int nf_tables_updchain (struct nft_ctx * ctx , u8 genmask , u8 policy ,
1726+ u32 flags )
17221727{
17231728 const struct nlattr * const * nla = ctx -> nla ;
17241729 struct nft_table * table = ctx -> table ;
@@ -1730,6 +1735,9 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy)
17301735 struct nft_trans * trans ;
17311736 int err ;
17321737
1738+ if (chain -> flags ^ flags )
1739+ return - EOPNOTSUPP ;
1740+
17331741 if (nla [NFTA_CHAIN_HOOK ]) {
17341742 if (!nft_is_base_chain (chain ))
17351743 return - EBUSY ;
@@ -1835,6 +1843,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
18351843 u8 policy = NF_ACCEPT ;
18361844 struct nft_ctx ctx ;
18371845 u64 handle = 0 ;
1846+ u32 flags = 0 ;
18381847
18391848 lockdep_assert_held (& net -> nft .commit_mutex );
18401849
@@ -1889,6 +1898,9 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
18891898 }
18901899 }
18911900
1901+ if (nla [NFTA_CHAIN_FLAGS ])
1902+ flags = ntohl (nla_get_be32 (nla [NFTA_CHAIN_FLAGS ]));
1903+
18921904 nft_ctx_init (& ctx , net , skb , nlh , family , table , chain , nla );
18931905
18941906 if (chain != NULL ) {
@@ -1899,10 +1911,10 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
18991911 if (nlh -> nlmsg_flags & NLM_F_REPLACE )
19001912 return - EOPNOTSUPP ;
19011913
1902- return nf_tables_updchain (& ctx , genmask , policy );
1914+ return nf_tables_updchain (& ctx , genmask , policy , flags );
19031915 }
19041916
1905- return nf_tables_addchain (& ctx , family , genmask , policy );
1917+ return nf_tables_addchain (& ctx , family , genmask , policy , flags );
19061918}
19071919
19081920static int nf_tables_delchain (struct net * net , struct sock * nlsk ,
@@ -2658,6 +2670,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
26582670 u8 genmask = nft_genmask_next (net );
26592671 struct nft_expr_info * info = NULL ;
26602672 int family = nfmsg -> nfgen_family ;
2673+ struct nft_flow_rule * flow ;
26612674 struct nft_table * table ;
26622675 struct nft_chain * chain ;
26632676 struct nft_rule * rule , * old_rule = NULL ;
@@ -2804,7 +2817,8 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
28042817
28052818 list_add_tail_rcu (& rule -> list , & old_rule -> list );
28062819 } else {
2807- if (nft_trans_rule_add (& ctx , NFT_MSG_NEWRULE , rule ) == NULL ) {
2820+ trans = nft_trans_rule_add (& ctx , NFT_MSG_NEWRULE , rule );
2821+ if (!trans ) {
28082822 err = - ENOMEM ;
28092823 goto err2 ;
28102824 }
@@ -2827,6 +2841,14 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
28272841 if (net -> nft .validate_state == NFT_VALIDATE_DO )
28282842 return nft_table_validate (net , table );
28292843
2844+ if (chain -> flags & NFT_CHAIN_HW_OFFLOAD ) {
2845+ flow = nft_flow_rule_create (rule );
2846+ if (IS_ERR (flow ))
2847+ return PTR_ERR (flow );
2848+
2849+ nft_trans_flow_rule (trans ) = flow ;
2850+ }
2851+
28302852 return 0 ;
28312853err2 :
28322854 nf_tables_rule_release (& ctx , rule );
@@ -6624,6 +6646,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
66246646 struct nft_trans_elem * te ;
66256647 struct nft_chain * chain ;
66266648 struct nft_table * table ;
6649+ int err ;
66276650
66286651 if (list_empty (& net -> nft .commit_list )) {
66296652 mutex_unlock (& net -> nft .commit_mutex );
@@ -6634,6 +6657,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
66346657 if (nf_tables_validate (net ) < 0 )
66356658 return - EAGAIN ;
66366659
6660+ err = nft_flow_rule_offload_commit (net );
6661+ if (err < 0 )
6662+ return err ;
6663+
66376664 /* 1. Allocate space for next generation rules_gen_X[] */
66386665 list_for_each_entry_safe (trans , next , & net -> nft .commit_list , list ) {
66396666 int ret ;
0 commit comments