lkml.org 
[lkml]   [2022]   [Jun]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 167/298] netfilter: nf_tables: bail out early if hardware offload is not supported
    Date
    From: Pablo Neira Ayuso <pablo@netfilter.org>

    [ Upstream commit 3a41c64d9c1185a2f3a184015e2a9b78bfc99c71 ]

    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: c9626a2cbdb2 ("netfilter: nf_tables: add hardware offload support")
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    include/net/flow_offload.h | 1 +
    include/net/netfilter/nf_tables_offload.h | 2 +-
    net/core/flow_offload.c | 6 ++++++
    net/netfilter/nf_tables_api.c | 2 +-
    net/netfilter/nf_tables_offload.c | 23 ++++++++++++++++++++++-
    5 files changed, 31 insertions(+), 3 deletions(-)

    diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
    index 5b8c54eb7a6b..7a10e4ed5540 100644
    --- a/include/net/flow_offload.h
    +++ b/include/net/flow_offload.h
    @@ -591,5 +591,6 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch,
    enum tc_setup_type type, void *data,
    struct flow_block_offload *bo,
    void (*cleanup)(struct flow_block_cb *block_cb));
    +bool flow_indr_dev_exists(void);

    #endif /* _NET_FLOW_OFFLOAD_H */
    diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h
    index 797147843958..3568b6a2f5f0 100644
    --- a/include/net/netfilter/nf_tables_offload.h
    +++ b/include/net/netfilter/nf_tables_offload.h
    @@ -92,7 +92,7 @@ int nft_flow_rule_offload_commit(struct net *net);
    NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \
    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);
    void nft_offload_exit(void);
    diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
    index 73f68d4625f3..929f6379a279 100644
    --- a/net/core/flow_offload.c
    +++ b/net/core/flow_offload.c
    @@ -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;
    }
    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);
    diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
    index 5a2d585e180c..8eac1915ec73 100644
    --- a/net/netfilter/nf_tables_api.c
    +++ b/net/netfilter/nf_tables_api.c
    @@ -2087,7 +2087,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
    chain->flags |= NFT_CHAIN_BASE | flags;
    basechain->policy = NF_ACCEPT;
    if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
    - nft_chain_offload_priority(basechain) < 0)
    + !nft_chain_offload_support(basechain))
    return -EOPNOTSUPP;

    flow_block_init(&basechain->flow_block);
    diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
    index 2d36952b1392..910ef881c3b8 100644
    --- a/net/netfilter/nf_tables_offload.c
    +++ b/net/netfilter/nf_tables_offload.c
    @@ -208,7 +208,7 @@ static int nft_setup_cb_call(enum tc_setup_type type, void *type_data,
    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 ||
    basechain->ops.priority > USHRT_MAX)
    @@ -217,6 +217,27 @@ int nft_chain_offload_priority(struct nft_base_chain *basechain)
    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,
    const struct nft_base_chain *basechain,
    const struct nft_rule *rule,
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-06-13 16:35    [W:3.985 / U:0.240 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site