提交 6ed9ec24 编写于 作者: P Pablo Neira Ayuso 提交者: Zheng Zengkai

netfilter: nf_tables: bail out early if hardware offload is not supported

stable inclusion
from stable-v5.10.122
commit 86c87d2c0338a5e84e50a312943bca1f33bd8164
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5W6OE

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=86c87d2c0338a5e84e50a312943bca1f33bd8164

--------------------------------

[ Upstream commit 3a41c64d ]

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: c9626a2c ("netfilter: nf_tables: add hardware offload support")
Signed-off-by: NPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 8ebdb93a
...@@ -568,5 +568,6 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch, ...@@ -568,5 +568,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 */
...@@ -91,7 +91,7 @@ int nft_flow_rule_offload_commit(struct net *net); ...@@ -91,7 +91,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);
......
...@@ -566,3 +566,9 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch, ...@@ -566,3 +566,9 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
return list_empty(&bo->cb_list) ? -EOPNOTSUPP : 0; return list_empty(&bo->cb_list) ? -EOPNOTSUPP : 0;
} }
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);
...@@ -1963,7 +1963,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family, ...@@ -1963,7 +1963,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, ...@@ -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) ...@@ -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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册