mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +00:00
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: c9626a2cbd
("netfilter: nf_tables: add hardware offload support")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
9dd732e0bd
commit
3a41c64d9c
@ -612,5 +612,6 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
|
|||||||
enum tc_setup_type type, void *data,
|
enum tc_setup_type type, void *data,
|
||||||
struct flow_block_offload *bo,
|
struct flow_block_offload *bo,
|
||||||
void (*cleanup)(struct flow_block_cb *block_cb));
|
void (*cleanup)(struct flow_block_cb *block_cb));
|
||||||
|
bool flow_indr_dev_exists(void);
|
||||||
|
|
||||||
#endif /* _NET_FLOW_OFFLOAD_H */
|
#endif /* _NET_FLOW_OFFLOAD_H */
|
||||||
|
@ -92,7 +92,7 @@ int nft_flow_rule_offload_commit(struct net *net);
|
|||||||
NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \
|
NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \
|
||||||
memset(&(__reg)->mask, 0xff, (__reg)->len);
|
memset(&(__reg)->mask, 0xff, (__reg)->len);
|
||||||
|
|
||||||
int nft_chain_offload_priority(struct nft_base_chain *basechain);
|
bool nft_chain_offload_support(const struct nft_base_chain *basechain);
|
||||||
|
|
||||||
int nft_offload_init(void);
|
int nft_offload_init(void);
|
||||||
void nft_offload_exit(void);
|
void nft_offload_exit(void);
|
||||||
|
@ -595,3 +595,9 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
|
|||||||
return (bo && list_empty(&bo->cb_list)) ? -EOPNOTSUPP : count;
|
return (bo && list_empty(&bo->cb_list)) ? -EOPNOTSUPP : count;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(flow_indr_dev_setup_offload);
|
EXPORT_SYMBOL(flow_indr_dev_setup_offload);
|
||||||
|
|
||||||
|
bool flow_indr_dev_exists(void)
|
||||||
|
{
|
||||||
|
return !list_empty(&flow_block_indr_dev_list);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(flow_indr_dev_exists);
|
||||||
|
@ -2166,7 +2166,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
|
|||||||
chain->flags |= NFT_CHAIN_BASE | flags;
|
chain->flags |= NFT_CHAIN_BASE | flags;
|
||||||
basechain->policy = NF_ACCEPT;
|
basechain->policy = NF_ACCEPT;
|
||||||
if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
|
if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
|
||||||
nft_chain_offload_priority(basechain) < 0)
|
!nft_chain_offload_support(basechain))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
flow_block_init(&basechain->flow_block);
|
flow_block_init(&basechain->flow_block);
|
||||||
|
@ -208,7 +208,7 @@ static int nft_setup_cb_call(enum tc_setup_type type, void *type_data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nft_chain_offload_priority(struct nft_base_chain *basechain)
|
static int nft_chain_offload_priority(const struct nft_base_chain *basechain)
|
||||||
{
|
{
|
||||||
if (basechain->ops.priority <= 0 ||
|
if (basechain->ops.priority <= 0 ||
|
||||||
basechain->ops.priority > USHRT_MAX)
|
basechain->ops.priority > USHRT_MAX)
|
||||||
@ -217,6 +217,27 @@ int nft_chain_offload_priority(struct nft_base_chain *basechain)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nft_chain_offload_support(const struct nft_base_chain *basechain)
|
||||||
|
{
|
||||||
|
struct net_device *dev;
|
||||||
|
struct nft_hook *hook;
|
||||||
|
|
||||||
|
if (nft_chain_offload_priority(basechain) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list_for_each_entry(hook, &basechain->hook_list, list) {
|
||||||
|
if (hook->ops.pf != NFPROTO_NETDEV ||
|
||||||
|
hook->ops.hooknum != NF_NETDEV_INGRESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dev = hook->ops.dev;
|
||||||
|
if (!dev->netdev_ops->ndo_setup_tc && !flow_indr_dev_exists())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void nft_flow_cls_offload_setup(struct flow_cls_offload *cls_flow,
|
static void nft_flow_cls_offload_setup(struct flow_cls_offload *cls_flow,
|
||||||
const struct nft_base_chain *basechain,
|
const struct nft_base_chain *basechain,
|
||||||
const struct nft_rule *rule,
|
const struct nft_rule *rule,
|
||||||
|
Loading…
Reference in New Issue
Block a user