Skip to content

Commit 3a41c64

Browse files
committed
netfilter: nf_tables: bail out early if hardware offload is not supported
If user requests for NFT_CHAIN_HW_OFFLOAD, then check if either device provides the .ndo_setup_tc interface or there is an indirect flow block that has been registered. Otherwise, bail out early from the preparation phase. Moreover, validate that family == NFPROTO_NETDEV and hook is NF_NETDEV_INGRESS. Fixes: c9626a2 ("netfilter: nf_tables: add hardware offload support") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 9dd732e commit 3a41c64

5 files changed

Lines changed: 31 additions & 3 deletions

File tree

include/net/flow_offload.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,5 +612,6 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
612612
enum tc_setup_type type, void *data,
613613
struct flow_block_offload *bo,
614614
void (*cleanup)(struct flow_block_cb *block_cb));
615+
bool flow_indr_dev_exists(void);
615616

616617
#endif /* _NET_FLOW_OFFLOAD_H */

include/net/netfilter/nf_tables_offload.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ int nft_flow_rule_offload_commit(struct net *net);
9292
NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \
9393
memset(&(__reg)->mask, 0xff, (__reg)->len);
9494

95-
int nft_chain_offload_priority(struct nft_base_chain *basechain);
95+
bool nft_chain_offload_support(const struct nft_base_chain *basechain);
9696

9797
int nft_offload_init(void);
9898
void nft_offload_exit(void);

net/core/flow_offload.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,9 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
595595
return (bo && list_empty(&bo->cb_list)) ? -EOPNOTSUPP : count;
596596
}
597597
EXPORT_SYMBOL(flow_indr_dev_setup_offload);
598+
599+
bool flow_indr_dev_exists(void)
600+
{
601+
return !list_empty(&flow_block_indr_dev_list);
602+
}
603+
EXPORT_SYMBOL(flow_indr_dev_exists);

net/netfilter/nf_tables_api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
21662166
chain->flags |= NFT_CHAIN_BASE | flags;
21672167
basechain->policy = NF_ACCEPT;
21682168
if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
2169-
nft_chain_offload_priority(basechain) < 0)
2169+
!nft_chain_offload_support(basechain))
21702170
return -EOPNOTSUPP;
21712171

21722172
flow_block_init(&basechain->flow_block);

net/netfilter/nf_tables_offload.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ static int nft_setup_cb_call(enum tc_setup_type type, void *type_data,
208208
return 0;
209209
}
210210

211-
int nft_chain_offload_priority(struct nft_base_chain *basechain)
211+
static int nft_chain_offload_priority(const struct nft_base_chain *basechain)
212212
{
213213
if (basechain->ops.priority <= 0 ||
214214
basechain->ops.priority > USHRT_MAX)
@@ -217,6 +217,27 @@ int nft_chain_offload_priority(struct nft_base_chain *basechain)
217217
return 0;
218218
}
219219

220+
bool nft_chain_offload_support(const struct nft_base_chain *basechain)
221+
{
222+
struct net_device *dev;
223+
struct nft_hook *hook;
224+
225+
if (nft_chain_offload_priority(basechain) < 0)
226+
return false;
227+
228+
list_for_each_entry(hook, &basechain->hook_list, list) {
229+
if (hook->ops.pf != NFPROTO_NETDEV ||
230+
hook->ops.hooknum != NF_NETDEV_INGRESS)
231+
return false;
232+
233+
dev = hook->ops.dev;
234+
if (!dev->netdev_ops->ndo_setup_tc && !flow_indr_dev_exists())
235+
return false;
236+
}
237+
238+
return true;
239+
}
240+
220241
static void nft_flow_cls_offload_setup(struct flow_cls_offload *cls_flow,
221242
const struct nft_base_chain *basechain,
222243
const struct nft_rule *rule,

0 commit comments

Comments
 (0)