From patchwork Thu May 25 15:40:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 1786205 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QRshR24x8z20QL for ; Fri, 26 May 2023 01:40:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241186AbjEYPki (ORCPT ); Thu, 25 May 2023 11:40:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37328 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241800AbjEYPke (ORCPT ); Thu, 25 May 2023 11:40:34 -0400 Received: from mail.netfilter.org (mail.netfilter.org [217.70.188.207]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 17879D8 for ; Thu, 25 May 2023 08:40:29 -0700 (PDT) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nf-next,v1 1/6] netfilter: nf_tables: remove expression reduce infrastructure Date: Thu, 25 May 2023 17:40:19 +0200 Message-Id: <20230525154024.222338-2-pablo@netfilter.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230525154024.222338-1-pablo@netfilter.org> References: <20230525154024.222338-1-pablo@netfilter.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This infrastructure is disabled since 9e539c5b6d9c ("netfilter: nf_tables: disable expression reduction infra") and the combo match infrastructure provides an alternative to this approach, remove it. Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 36 -------- include/net/netfilter/nft_fib.h | 2 - include/net/netfilter/nft_meta.h | 3 - net/bridge/netfilter/nft_meta_bridge.c | 20 ----- net/bridge/netfilter/nft_reject_bridge.c | 1 - net/ipv4/netfilter/nft_dup_ipv4.c | 1 - net/ipv4/netfilter/nft_fib_ipv4.c | 2 - net/ipv4/netfilter/nft_reject_ipv4.c | 1 - net/ipv6/netfilter/nft_dup_ipv6.c | 1 - net/ipv6/netfilter/nft_fib_ipv6.c | 2 - net/ipv6/netfilter/nft_reject_ipv6.c | 1 - net/netfilter/nf_tables_api.c | 66 --------------- net/netfilter/nft_bitwise.c | 103 ----------------------- net/netfilter/nft_byteorder.c | 11 --- net/netfilter/nft_cmp.c | 3 - net/netfilter/nft_compat.c | 10 --- net/netfilter/nft_connlimit.c | 1 - net/netfilter/nft_counter.c | 1 - net/netfilter/nft_ct.c | 46 ---------- net/netfilter/nft_dup_netdev.c | 1 - net/netfilter/nft_dynset.c | 1 - net/netfilter/nft_exthdr.c | 34 -------- net/netfilter/nft_fib.c | 42 --------- net/netfilter/nft_fib_inet.c | 1 - net/netfilter/nft_fib_netdev.c | 1 - net/netfilter/nft_flow_offload.c | 1 - net/netfilter/nft_fwd_netdev.c | 2 - net/netfilter/nft_hash.c | 36 -------- net/netfilter/nft_immediate.c | 12 --- net/netfilter/nft_last.c | 1 - net/netfilter/nft_limit.c | 2 - net/netfilter/nft_log.c | 1 - net/netfilter/nft_lookup.c | 12 --- net/netfilter/nft_masq.c | 3 - net/netfilter/nft_meta.c | 45 ---------- net/netfilter/nft_nat.c | 2 - net/netfilter/nft_numgen.c | 22 ----- net/netfilter/nft_objref.c | 2 - net/netfilter/nft_osf.c | 25 ------ net/netfilter/nft_payload.c | 47 ----------- net/netfilter/nft_queue.c | 2 - net/netfilter/nft_quota.c | 1 - net/netfilter/nft_range.c | 1 - net/netfilter/nft_redir.c | 3 - net/netfilter/nft_reject_inet.c | 1 - net/netfilter/nft_reject_netdev.c | 1 - net/netfilter/nft_rt.c | 1 - net/netfilter/nft_socket.c | 26 ------ net/netfilter/nft_synproxy.c | 1 - net/netfilter/nft_tproxy.c | 1 - net/netfilter/nft_tunnel.c | 26 ------ net/netfilter/nft_xfrm.c | 27 ------ 52 files changed, 695 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 2e24ea1d744c..588b1904e411 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -123,17 +123,6 @@ struct nft_regs { }; }; -struct nft_regs_track { - struct { - const struct nft_expr *selector; - const struct nft_expr *bitwise; - u8 num_reg; - } regs[NFT_REG32_NUM]; - - const struct nft_expr *cur; - const struct nft_expr *last; -}; - /* Store/load an u8, u16 or u64 integer to/from the u32 data register. * * Note, when using concatenations, register allocation happens at 32-bit @@ -396,8 +385,6 @@ int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src); void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr); int nft_expr_dump(struct sk_buff *skb, unsigned int attr, const struct nft_expr *expr, bool reset); -bool nft_expr_reduce_bitwise(struct nft_regs_track *track, - const struct nft_expr *expr); struct nft_set_ext; @@ -947,8 +934,6 @@ struct nft_expr_ops { int (*validate)(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data); - bool (*reduce)(struct nft_regs_track *track, - const struct nft_expr *expr); bool (*gc)(struct net *net, const struct nft_expr *expr); int (*offload)(struct nft_offload_ctx *ctx, @@ -1712,25 +1697,4 @@ static inline struct nftables_pernet *nft_pernet(const struct net *net) return net_generic(net, nf_tables_net_id); } -#define __NFT_REDUCE_READONLY 1UL -#define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY - -static inline bool nft_reduce_is_readonly(const struct nft_expr *expr) -{ - return expr->ops->reduce == NFT_REDUCE_READONLY; -} - -void nft_reg_track_update(struct nft_regs_track *track, - const struct nft_expr *expr, u8 dreg, u8 len); -void nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg, u8 len); -void __nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg); - -static inline bool nft_reg_track_cmp(struct nft_regs_track *track, - const struct nft_expr *expr, u8 dreg) -{ - return track->regs[dreg].selector && - track->regs[dreg].selector->ops == expr->ops && - track->regs[dreg].num_reg == 0; -} - #endif /* _NET_NF_TABLES_H */ diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h index 167640b843ef..2e434ba41b97 100644 --- a/include/net/netfilter/nft_fib.h +++ b/include/net/netfilter/nft_fib.h @@ -38,6 +38,4 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs, void nft_fib_store_result(void *reg, const struct nft_fib *priv, const struct net_device *dev); -bool nft_fib_reduce(struct nft_regs_track *track, - const struct nft_expr *expr); #endif diff --git a/include/net/netfilter/nft_meta.h b/include/net/netfilter/nft_meta.h index ba1238f12a48..690f6245026c 100644 --- a/include/net/netfilter/nft_meta.h +++ b/include/net/netfilter/nft_meta.h @@ -44,9 +44,6 @@ int nft_meta_set_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data); -bool nft_meta_get_reduce(struct nft_regs_track *track, - const struct nft_expr *expr); - struct nft_inner_tun_ctx; void nft_meta_inner_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt, diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c index bd4d1b4d745f..93e8a8dadd80 100644 --- a/net/bridge/netfilter/nft_meta_bridge.c +++ b/net/bridge/netfilter/nft_meta_bridge.c @@ -102,7 +102,6 @@ static const struct nft_expr_ops nft_meta_bridge_get_ops = { .eval = nft_meta_bridge_get_eval, .init = nft_meta_bridge_get_init, .dump = nft_meta_get_dump, - .reduce = nft_meta_get_reduce, }; static void nft_meta_bridge_set_eval(const struct nft_expr *expr, @@ -149,24 +148,6 @@ static int nft_meta_bridge_set_init(const struct nft_ctx *ctx, return 0; } -static bool nft_meta_bridge_set_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - int i; - - for (i = 0; i < NFT_REG32_NUM; i++) { - if (!track->regs[i].selector) - continue; - - if (track->regs[i].selector->ops != &nft_meta_bridge_get_ops) - continue; - - __nft_reg_track_cancel(track, i); - } - - return false; -} - static int nft_meta_bridge_set_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) @@ -192,7 +173,6 @@ static const struct nft_expr_ops nft_meta_bridge_set_ops = { .init = nft_meta_bridge_set_init, .destroy = nft_meta_set_destroy, .dump = nft_meta_set_dump, - .reduce = nft_meta_bridge_set_reduce, .validate = nft_meta_bridge_set_validate, }; diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index 71b54fed7263..fbf858ddec35 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c @@ -185,7 +185,6 @@ static const struct nft_expr_ops nft_reject_bridge_ops = { .init = nft_reject_init, .dump = nft_reject_dump, .validate = nft_reject_bridge_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_reject_bridge_type __read_mostly = { diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c index a522c3a3be52..cae5b38335b3 100644 --- a/net/ipv4/netfilter/nft_dup_ipv4.c +++ b/net/ipv4/netfilter/nft_dup_ipv4.c @@ -76,7 +76,6 @@ static const struct nft_expr_ops nft_dup_ipv4_ops = { .eval = nft_dup_ipv4_eval, .init = nft_dup_ipv4_init, .dump = nft_dup_ipv4_dump, - .reduce = NFT_REDUCE_READONLY, }; static const struct nla_policy nft_dup_ipv4_policy[NFTA_DUP_MAX + 1] = { diff --git a/net/ipv4/netfilter/nft_fib_ipv4.c b/net/ipv4/netfilter/nft_fib_ipv4.c index 9eee535c64dd..55c4b73265ed 100644 --- a/net/ipv4/netfilter/nft_fib_ipv4.c +++ b/net/ipv4/netfilter/nft_fib_ipv4.c @@ -159,7 +159,6 @@ static const struct nft_expr_ops nft_fib4_type_ops = { .init = nft_fib_init, .dump = nft_fib_dump, .validate = nft_fib_validate, - .reduce = nft_fib_reduce, }; static const struct nft_expr_ops nft_fib4_ops = { @@ -169,7 +168,6 @@ static const struct nft_expr_ops nft_fib4_ops = { .init = nft_fib_init, .dump = nft_fib_dump, .validate = nft_fib_validate, - .reduce = nft_fib_reduce, }; static const struct nft_expr_ops * diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index 6cb213bb7256..55fc23a8f7a7 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c @@ -45,7 +45,6 @@ static const struct nft_expr_ops nft_reject_ipv4_ops = { .init = nft_reject_init, .dump = nft_reject_dump, .validate = nft_reject_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_reject_ipv4_type __read_mostly = { diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c index c82f3fdd4a65..e859beb29bb1 100644 --- a/net/ipv6/netfilter/nft_dup_ipv6.c +++ b/net/ipv6/netfilter/nft_dup_ipv6.c @@ -74,7 +74,6 @@ static const struct nft_expr_ops nft_dup_ipv6_ops = { .eval = nft_dup_ipv6_eval, .init = nft_dup_ipv6_init, .dump = nft_dup_ipv6_dump, - .reduce = NFT_REDUCE_READONLY, }; static const struct nla_policy nft_dup_ipv6_policy[NFTA_DUP_MAX + 1] = { diff --git a/net/ipv6/netfilter/nft_fib_ipv6.c b/net/ipv6/netfilter/nft_fib_ipv6.c index 36dc14b34388..6ae17f530994 100644 --- a/net/ipv6/netfilter/nft_fib_ipv6.c +++ b/net/ipv6/netfilter/nft_fib_ipv6.c @@ -220,7 +220,6 @@ static const struct nft_expr_ops nft_fib6_type_ops = { .init = nft_fib_init, .dump = nft_fib_dump, .validate = nft_fib_validate, - .reduce = nft_fib_reduce, }; static const struct nft_expr_ops nft_fib6_ops = { @@ -230,7 +229,6 @@ static const struct nft_expr_ops nft_fib6_ops = { .init = nft_fib_init, .dump = nft_fib_dump, .validate = nft_fib_validate, - .reduce = nft_fib_reduce, }; static const struct nft_expr_ops * diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c index 5c61294f410e..ed69c768797e 100644 --- a/net/ipv6/netfilter/nft_reject_ipv6.c +++ b/net/ipv6/netfilter/nft_reject_ipv6.c @@ -46,7 +46,6 @@ static const struct nft_expr_ops nft_reject_ipv6_ops = { .init = nft_reject_init, .dump = nft_reject_dump, .validate = nft_reject_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_reject_ipv6_type __read_mostly = { diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 0396fd8f4e71..80932407b9a6 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -576,58 +576,6 @@ static int nft_delflowtable(struct nft_ctx *ctx, return err; } -static void __nft_reg_track_clobber(struct nft_regs_track *track, u8 dreg) -{ - int i; - - for (i = track->regs[dreg].num_reg; i > 0; i--) - __nft_reg_track_cancel(track, dreg - i); -} - -static void __nft_reg_track_update(struct nft_regs_track *track, - const struct nft_expr *expr, - u8 dreg, u8 num_reg) -{ - track->regs[dreg].selector = expr; - track->regs[dreg].bitwise = NULL; - track->regs[dreg].num_reg = num_reg; -} - -void nft_reg_track_update(struct nft_regs_track *track, - const struct nft_expr *expr, u8 dreg, u8 len) -{ - unsigned int regcount; - int i; - - __nft_reg_track_clobber(track, dreg); - - regcount = DIV_ROUND_UP(len, NFT_REG32_SIZE); - for (i = 0; i < regcount; i++, dreg++) - __nft_reg_track_update(track, expr, dreg, i); -} -EXPORT_SYMBOL_GPL(nft_reg_track_update); - -void nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg, u8 len) -{ - unsigned int regcount; - int i; - - __nft_reg_track_clobber(track, dreg); - - regcount = DIV_ROUND_UP(len, NFT_REG32_SIZE); - for (i = 0; i < regcount; i++, dreg++) - __nft_reg_track_cancel(track, dreg); -} -EXPORT_SYMBOL_GPL(nft_reg_track_cancel); - -void __nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg) -{ - track->regs[dreg].selector = NULL; - track->regs[dreg].bitwise = NULL; - track->regs[dreg].num_reg = 0; -} -EXPORT_SYMBOL_GPL(__nft_reg_track_cancel); - /* * Tables */ @@ -8953,16 +8901,9 @@ void nf_tables_trans_destroy_flush_work(void) } EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work); -static bool nft_expr_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - return false; -} - static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain) { const struct nft_expr *expr, *last; - struct nft_regs_track track = {}; unsigned int size, data_size; void *data, *data_boundary; struct nft_rule_dp *prule; @@ -8999,14 +8940,7 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha return -ENOMEM; size = 0; - track.last = nft_expr_last(rule); nft_rule_for_each_expr(expr, last, rule) { - track.cur = expr; - - if (nft_expr_reduce(&track, expr)) { - expr = track.cur; - continue; - } if (WARN_ON_ONCE(data + expr->ops->size > data_boundary)) return -ENOMEM; diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 84eae7cabc67..8d2b9249078a 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -281,60 +281,12 @@ static int nft_bitwise_offload(struct nft_offload_ctx *ctx, return 0; } -static bool nft_bitwise_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_bitwise *priv = nft_expr_priv(expr); - const struct nft_bitwise *bitwise; - unsigned int regcount; - u8 dreg; - int i; - - if (!track->regs[priv->sreg].selector) - return false; - - bitwise = nft_expr_priv(track->regs[priv->dreg].selector); - if (track->regs[priv->sreg].selector == track->regs[priv->dreg].selector && - track->regs[priv->sreg].num_reg == 0 && - track->regs[priv->dreg].bitwise && - track->regs[priv->dreg].bitwise->ops == expr->ops && - priv->sreg == bitwise->sreg && - priv->dreg == bitwise->dreg && - priv->op == bitwise->op && - priv->len == bitwise->len && - !memcmp(&priv->mask, &bitwise->mask, sizeof(priv->mask)) && - !memcmp(&priv->xor, &bitwise->xor, sizeof(priv->xor)) && - !memcmp(&priv->data, &bitwise->data, sizeof(priv->data))) { - track->cur = expr; - return true; - } - - if (track->regs[priv->sreg].bitwise || - track->regs[priv->sreg].num_reg != 0) { - nft_reg_track_cancel(track, priv->dreg, priv->len); - return false; - } - - if (priv->sreg != priv->dreg) { - nft_reg_track_update(track, track->regs[priv->sreg].selector, - priv->dreg, priv->len); - } - - dreg = priv->dreg; - regcount = DIV_ROUND_UP(priv->len, NFT_REG32_SIZE); - for (i = 0; i < regcount; i++, dreg++) - track->regs[priv->dreg].bitwise = expr; - - return false; -} - static const struct nft_expr_ops nft_bitwise_ops = { .type = &nft_bitwise_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise)), .eval = nft_bitwise_eval, .init = nft_bitwise_init, .dump = nft_bitwise_dump, - .reduce = nft_bitwise_reduce, .offload = nft_bitwise_offload, }; @@ -436,48 +388,12 @@ static int nft_bitwise_fast_offload(struct nft_offload_ctx *ctx, return 0; } -static bool nft_bitwise_fast_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); - const struct nft_bitwise_fast_expr *bitwise; - - if (!track->regs[priv->sreg].selector) - return false; - - bitwise = nft_expr_priv(track->regs[priv->dreg].selector); - if (track->regs[priv->sreg].selector == track->regs[priv->dreg].selector && - track->regs[priv->dreg].bitwise && - track->regs[priv->dreg].bitwise->ops == expr->ops && - priv->sreg == bitwise->sreg && - priv->dreg == bitwise->dreg && - priv->mask == bitwise->mask && - priv->xor == bitwise->xor) { - track->cur = expr; - return true; - } - - if (track->regs[priv->sreg].bitwise) { - nft_reg_track_cancel(track, priv->dreg, NFT_REG32_SIZE); - return false; - } - - if (priv->sreg != priv->dreg) { - track->regs[priv->dreg].selector = - track->regs[priv->sreg].selector; - } - track->regs[priv->dreg].bitwise = expr; - - return false; -} - const struct nft_expr_ops nft_bitwise_fast_ops = { .type = &nft_bitwise_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise_fast_expr)), .eval = NULL, /* inlined */ .init = nft_bitwise_fast_init, .dump = nft_bitwise_fast_dump, - .reduce = nft_bitwise_fast_reduce, .offload = nft_bitwise_fast_offload, }; @@ -514,22 +430,3 @@ struct nft_expr_type nft_bitwise_type __read_mostly = { .maxattr = NFTA_BITWISE_MAX, .owner = THIS_MODULE, }; - -bool nft_expr_reduce_bitwise(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_expr *last = track->last; - const struct nft_expr *next; - - if (expr == last) - return false; - - next = nft_expr_next(expr); - if (next->ops == &nft_bitwise_ops) - return nft_bitwise_reduce(track, next); - else if (next->ops == &nft_bitwise_fast_ops) - return nft_bitwise_fast_reduce(track, next); - - return false; -} -EXPORT_SYMBOL_GPL(nft_expr_reduce_bitwise); diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index b66647a5a171..a42d03741bb3 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c @@ -169,23 +169,12 @@ static int nft_byteorder_dump(struct sk_buff *skb, return -1; } -static bool nft_byteorder_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - struct nft_byteorder *priv = nft_expr_priv(expr); - - nft_reg_track_cancel(track, priv->dreg, priv->len); - - return false; -} - static const struct nft_expr_ops nft_byteorder_ops = { .type = &nft_byteorder_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_byteorder)), .eval = nft_byteorder_eval, .init = nft_byteorder_init, .dump = nft_byteorder_dump, - .reduce = nft_byteorder_reduce, }; struct nft_expr_type nft_byteorder_type __read_mostly = { diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c index 6eb21a4f5698..75a7b24eeefc 100644 --- a/net/netfilter/nft_cmp.c +++ b/net/netfilter/nft_cmp.c @@ -190,7 +190,6 @@ static const struct nft_expr_ops nft_cmp_ops = { .eval = nft_cmp_eval, .init = nft_cmp_init, .dump = nft_cmp_dump, - .reduce = NFT_REDUCE_READONLY, .offload = nft_cmp_offload, }; @@ -282,7 +281,6 @@ const struct nft_expr_ops nft_cmp_fast_ops = { .eval = NULL, /* inlined */ .init = nft_cmp_fast_init, .dump = nft_cmp_fast_dump, - .reduce = NFT_REDUCE_READONLY, .offload = nft_cmp_fast_offload, }; @@ -376,7 +374,6 @@ const struct nft_expr_ops nft_cmp16_fast_ops = { .eval = NULL, /* inlined */ .init = nft_cmp16_fast_init, .dump = nft_cmp16_fast_dump, - .reduce = NFT_REDUCE_READONLY, .offload = nft_cmp16_fast_offload, }; diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 5284cd2ad532..e178b479dfaf 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -734,14 +734,6 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = { static struct nft_expr_type nft_match_type; -static bool nft_match_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct xt_match *match = expr->ops->data; - - return strcmp(match->name, "comment") == 0; -} - static const struct nft_expr_ops * nft_match_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) @@ -784,7 +776,6 @@ nft_match_select_ops(const struct nft_ctx *ctx, ops->dump = nft_match_dump; ops->validate = nft_match_validate; ops->data = match; - ops->reduce = nft_match_reduce; matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize)); if (matchsize > NFT_MATCH_LARGE_THRESH) { @@ -874,7 +865,6 @@ nft_target_select_ops(const struct nft_ctx *ctx, ops->dump = nft_target_dump; ops->validate = nft_target_validate; ops->data = target; - ops->reduce = NFT_REDUCE_READONLY; if (family == NFPROTO_BRIDGE) ops->eval = nft_target_eval_bridge; diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c index de9d1980df69..53ef6854f8e6 100644 --- a/net/netfilter/nft_connlimit.c +++ b/net/netfilter/nft_connlimit.c @@ -258,7 +258,6 @@ static const struct nft_expr_ops nft_connlimit_ops = { .destroy_clone = nft_connlimit_destroy_clone, .dump = nft_connlimit_dump, .gc = nft_connlimit_gc, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_connlimit_type __read_mostly = { diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c index dccc68a5135a..446406631c9a 100644 --- a/net/netfilter/nft_counter.c +++ b/net/netfilter/nft_counter.c @@ -294,7 +294,6 @@ static const struct nft_expr_ops nft_counter_ops = { .destroy_clone = nft_counter_destroy, .dump = nft_counter_dump, .clone = nft_counter_clone, - .reduce = NFT_REDUCE_READONLY, .offload = nft_counter_offload, .offload_stats = nft_counter_offload_stats, }; diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index b9c84499438b..fe25ce6fa0bd 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -671,29 +671,6 @@ static int nft_ct_get_dump(struct sk_buff *skb, return -1; } -static bool nft_ct_get_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_ct *priv = nft_expr_priv(expr); - const struct nft_ct *ct; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - ct = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->key != ct->key) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return nft_expr_reduce_bitwise(track, expr); -} - static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr, bool reset) { @@ -728,27 +705,8 @@ static const struct nft_expr_ops nft_ct_get_ops = { .init = nft_ct_get_init, .destroy = nft_ct_get_destroy, .dump = nft_ct_get_dump, - .reduce = nft_ct_get_reduce, }; -static bool nft_ct_set_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - int i; - - for (i = 0; i < NFT_REG32_NUM; i++) { - if (!track->regs[i].selector) - continue; - - if (track->regs[i].selector->ops != &nft_ct_get_ops) - continue; - - __nft_reg_track_cancel(track, i); - } - - return false; -} - #ifdef CONFIG_RETPOLINE static const struct nft_expr_ops nft_ct_get_fast_ops = { .type = &nft_ct_type, @@ -757,7 +715,6 @@ static const struct nft_expr_ops nft_ct_get_fast_ops = { .init = nft_ct_get_init, .destroy = nft_ct_get_destroy, .dump = nft_ct_get_dump, - .reduce = nft_ct_set_reduce, }; #endif @@ -768,7 +725,6 @@ static const struct nft_expr_ops nft_ct_set_ops = { .init = nft_ct_set_init, .destroy = nft_ct_set_destroy, .dump = nft_ct_set_dump, - .reduce = nft_ct_set_reduce, }; #ifdef CONFIG_NF_CONNTRACK_ZONES @@ -779,7 +735,6 @@ static const struct nft_expr_ops nft_ct_set_zone_ops = { .init = nft_ct_set_init, .destroy = nft_ct_set_destroy, .dump = nft_ct_set_dump, - .reduce = nft_ct_set_reduce, }; #endif @@ -849,7 +804,6 @@ static const struct nft_expr_ops nft_notrack_ops = { .type = &nft_notrack_type, .size = NFT_EXPR_SIZE(0), .eval = nft_notrack_eval, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_notrack_type __read_mostly = { diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c index e5739a59ebf1..2007700bef8e 100644 --- a/net/netfilter/nft_dup_netdev.c +++ b/net/netfilter/nft_dup_netdev.c @@ -80,7 +80,6 @@ static const struct nft_expr_ops nft_dup_netdev_ops = { .eval = nft_dup_netdev_eval, .init = nft_dup_netdev_init, .dump = nft_dup_netdev_dump, - .reduce = NFT_REDUCE_READONLY, .offload = nft_dup_netdev_offload, .offload_action = nft_dup_netdev_offload_action, }; diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index bd19c7aec92e..c3bd57be2ee8 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -414,7 +414,6 @@ static const struct nft_expr_ops nft_dynset_ops = { .activate = nft_dynset_activate, .deactivate = nft_dynset_deactivate, .dump = nft_dynset_dump, - .reduce = NFT_REDUCE_READONLY, }; struct nft_expr_type nft_dynset_type __read_mostly = { diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c index 671474e59817..41e8ae77b823 100644 --- a/net/netfilter/nft_exthdr.c +++ b/net/netfilter/nft_exthdr.c @@ -698,40 +698,12 @@ static int nft_exthdr_dump_strip(struct sk_buff *skb, return nft_exthdr_dump_common(skb, priv); } -static bool nft_exthdr_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_exthdr *priv = nft_expr_priv(expr); - const struct nft_exthdr *exthdr; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - exthdr = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->type != exthdr->type || - priv->op != exthdr->op || - priv->flags != exthdr->flags || - priv->offset != exthdr->offset || - priv->len != exthdr->len) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return nft_expr_reduce_bitwise(track, expr); -} - static const struct nft_expr_ops nft_exthdr_ipv6_ops = { .type = &nft_exthdr_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_exthdr)), .eval = nft_exthdr_ipv6_eval, .init = nft_exthdr_init, .dump = nft_exthdr_dump, - .reduce = nft_exthdr_reduce, }; static const struct nft_expr_ops nft_exthdr_ipv4_ops = { @@ -740,7 +712,6 @@ static const struct nft_expr_ops nft_exthdr_ipv4_ops = { .eval = nft_exthdr_ipv4_eval, .init = nft_exthdr_ipv4_init, .dump = nft_exthdr_dump, - .reduce = nft_exthdr_reduce, }; static const struct nft_expr_ops nft_exthdr_tcp_ops = { @@ -749,7 +720,6 @@ static const struct nft_expr_ops nft_exthdr_tcp_ops = { .eval = nft_exthdr_tcp_eval, .init = nft_exthdr_init, .dump = nft_exthdr_dump, - .reduce = nft_exthdr_reduce, }; static const struct nft_expr_ops nft_exthdr_tcp_set_ops = { @@ -758,7 +728,6 @@ static const struct nft_expr_ops nft_exthdr_tcp_set_ops = { .eval = nft_exthdr_tcp_set_eval, .init = nft_exthdr_tcp_set_init, .dump = nft_exthdr_dump_set, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops nft_exthdr_tcp_strip_ops = { @@ -767,7 +736,6 @@ static const struct nft_expr_ops nft_exthdr_tcp_strip_ops = { .eval = nft_exthdr_tcp_strip_eval, .init = nft_exthdr_tcp_strip_init, .dump = nft_exthdr_dump_strip, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops nft_exthdr_sctp_ops = { @@ -776,7 +744,6 @@ static const struct nft_expr_ops nft_exthdr_sctp_ops = { .eval = nft_exthdr_sctp_eval, .init = nft_exthdr_init, .dump = nft_exthdr_dump, - .reduce = nft_exthdr_reduce, }; static const struct nft_expr_ops nft_exthdr_dccp_ops = { @@ -785,7 +752,6 @@ static const struct nft_expr_ops nft_exthdr_dccp_ops = { .eval = nft_exthdr_dccp_eval, .init = nft_exthdr_dccp_init, .dump = nft_exthdr_dump, - .reduce = nft_exthdr_reduce, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_fib.c b/net/netfilter/nft_fib.c index 6e049fd48760..e7cb42c9c175 100644 --- a/net/netfilter/nft_fib.c +++ b/net/netfilter/nft_fib.c @@ -160,47 +160,5 @@ void nft_fib_store_result(void *reg, const struct nft_fib *priv, } EXPORT_SYMBOL_GPL(nft_fib_store_result); -bool nft_fib_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_fib *priv = nft_expr_priv(expr); - unsigned int len = NFT_REG32_SIZE; - const struct nft_fib *fib; - - switch (priv->result) { - case NFT_FIB_RESULT_OIF: - break; - case NFT_FIB_RESULT_OIFNAME: - if (priv->flags & NFTA_FIB_F_PRESENT) - len = NFT_REG32_SIZE; - else - len = IFNAMSIZ; - break; - case NFT_FIB_RESULT_ADDRTYPE: - break; - default: - WARN_ON_ONCE(1); - break; - } - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, len); - return false; - } - - fib = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->result != fib->result || - priv->flags != fib->flags) { - nft_reg_track_update(track, expr, priv->dreg, len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return false; -} -EXPORT_SYMBOL_GPL(nft_fib_reduce); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Florian Westphal "); diff --git a/net/netfilter/nft_fib_inet.c b/net/netfilter/nft_fib_inet.c index 666a3741d20b..a88d44e163d1 100644 --- a/net/netfilter/nft_fib_inet.c +++ b/net/netfilter/nft_fib_inet.c @@ -49,7 +49,6 @@ static const struct nft_expr_ops nft_fib_inet_ops = { .init = nft_fib_init, .dump = nft_fib_dump, .validate = nft_fib_validate, - .reduce = nft_fib_reduce, }; static struct nft_expr_type nft_fib_inet_type __read_mostly = { diff --git a/net/netfilter/nft_fib_netdev.c b/net/netfilter/nft_fib_netdev.c index 9121ec64e918..3f3478abd845 100644 --- a/net/netfilter/nft_fib_netdev.c +++ b/net/netfilter/nft_fib_netdev.c @@ -58,7 +58,6 @@ static const struct nft_expr_ops nft_fib_netdev_ops = { .init = nft_fib_init, .dump = nft_fib_dump, .validate = nft_fib_validate, - .reduce = nft_fib_reduce, }; static struct nft_expr_type nft_fib_netdev_type __read_mostly = { diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index 5ef9146e74ad..59c468261134 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c @@ -462,7 +462,6 @@ static const struct nft_expr_ops nft_flow_offload_ops = { .destroy = nft_flow_offload_destroy, .validate = nft_flow_offload_validate, .dump = nft_flow_offload_dump, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_flow_offload_type __read_mostly = { diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c index 7b9d4d1bd17c..a534d060ce1b 100644 --- a/net/netfilter/nft_fwd_netdev.c +++ b/net/netfilter/nft_fwd_netdev.c @@ -219,7 +219,6 @@ static const struct nft_expr_ops nft_fwd_neigh_netdev_ops = { .init = nft_fwd_neigh_init, .dump = nft_fwd_neigh_dump, .validate = nft_fwd_validate, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops nft_fwd_netdev_ops = { @@ -229,7 +228,6 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = { .init = nft_fwd_netdev_init, .dump = nft_fwd_netdev_dump, .validate = nft_fwd_validate, - .reduce = NFT_REDUCE_READONLY, .offload = nft_fwd_netdev_offload, .offload_action = nft_fwd_netdev_offload_action, }; diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index ee8d487b69c0..4fc99c80b28e 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c @@ -165,16 +165,6 @@ static int nft_jhash_dump(struct sk_buff *skb, return -1; } -static bool nft_jhash_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_jhash *priv = nft_expr_priv(expr); - - nft_reg_track_cancel(track, priv->dreg, sizeof(u32)); - - return false; -} - static int nft_symhash_dump(struct sk_buff *skb, const struct nft_expr *expr, bool reset) { @@ -195,30 +185,6 @@ static int nft_symhash_dump(struct sk_buff *skb, return -1; } -static bool nft_symhash_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - struct nft_symhash *priv = nft_expr_priv(expr); - struct nft_symhash *symhash; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, sizeof(u32)); - return false; - } - - symhash = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->offset != symhash->offset || - priv->modulus != symhash->modulus) { - nft_reg_track_update(track, expr, priv->dreg, sizeof(u32)); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return false; -} - static struct nft_expr_type nft_hash_type; static const struct nft_expr_ops nft_jhash_ops = { .type = &nft_hash_type, @@ -226,7 +192,6 @@ static const struct nft_expr_ops nft_jhash_ops = { .eval = nft_jhash_eval, .init = nft_jhash_init, .dump = nft_jhash_dump, - .reduce = nft_jhash_reduce, }; static const struct nft_expr_ops nft_symhash_ops = { @@ -235,7 +200,6 @@ static const struct nft_expr_ops nft_symhash_ops = { .eval = nft_symhash_eval, .init = nft_symhash_init, .dump = nft_symhash_dump, - .reduce = nft_symhash_reduce, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c index c9d2f7c29f53..0d744c3f73b3 100644 --- a/net/netfilter/nft_immediate.c +++ b/net/netfilter/nft_immediate.c @@ -240,17 +240,6 @@ static bool nft_immediate_offload_action(const struct nft_expr *expr) return false; } -static bool nft_immediate_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_immediate_expr *priv = nft_expr_priv(expr); - - if (priv->dreg != NFT_REG_VERDICT) - nft_reg_track_cancel(track, priv->dreg, priv->dlen); - - return false; -} - static const struct nft_expr_ops nft_imm_ops = { .type = &nft_imm_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), @@ -261,7 +250,6 @@ static const struct nft_expr_ops nft_imm_ops = { .destroy = nft_immediate_destroy, .dump = nft_immediate_dump, .validate = nft_immediate_validate, - .reduce = nft_immediate_reduce, .offload = nft_immediate_offload, .offload_action = nft_immediate_offload_action, }; diff --git a/net/netfilter/nft_last.c b/net/netfilter/nft_last.c index 8e6d7eaf9dc8..5d44d45ca4ef 100644 --- a/net/netfilter/nft_last.c +++ b/net/netfilter/nft_last.c @@ -125,7 +125,6 @@ static const struct nft_expr_ops nft_last_ops = { .destroy = nft_last_destroy, .clone = nft_last_clone, .dump = nft_last_dump, - .reduce = NFT_REDUCE_READONLY, }; struct nft_expr_type nft_last_type __read_mostly = { diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c index 145dc62c6247..10752da5bd16 100644 --- a/net/netfilter/nft_limit.c +++ b/net/netfilter/nft_limit.c @@ -228,7 +228,6 @@ static const struct nft_expr_ops nft_limit_pkts_ops = { .destroy = nft_limit_pkts_destroy, .clone = nft_limit_pkts_clone, .dump = nft_limit_pkts_dump, - .reduce = NFT_REDUCE_READONLY, }; static void nft_limit_bytes_eval(const struct nft_expr *expr, @@ -283,7 +282,6 @@ static const struct nft_expr_ops nft_limit_bytes_ops = { .dump = nft_limit_bytes_dump, .clone = nft_limit_bytes_clone, .destroy = nft_limit_bytes_destroy, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 5defe6e4fd98..84e374411877 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c @@ -291,7 +291,6 @@ static const struct nft_expr_ops nft_log_ops = { .init = nft_log_init, .destroy = nft_log_destroy, .dump = nft_log_dump, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_log_type __read_mostly = { diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index 29ac48cdd6db..5ba799a7722d 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c @@ -233,17 +233,6 @@ static int nft_lookup_validate(const struct nft_ctx *ctx, return 0; } -static bool nft_lookup_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_lookup *priv = nft_expr_priv(expr); - - if (priv->set->flags & NFT_SET_MAP) - nft_reg_track_cancel(track, priv->dreg, priv->set->dlen); - - return false; -} - static const struct nft_expr_ops nft_lookup_ops = { .type = &nft_lookup_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)), @@ -254,7 +243,6 @@ static const struct nft_expr_ops nft_lookup_ops = { .destroy = nft_lookup_destroy, .dump = nft_lookup_dump, .validate = nft_lookup_validate, - .reduce = nft_lookup_reduce, }; struct nft_expr_type nft_lookup_type __read_mostly = { diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c index b115d77fbbc7..b6cd11fd596b 100644 --- a/net/netfilter/nft_masq.c +++ b/net/netfilter/nft_masq.c @@ -146,7 +146,6 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = { .destroy = nft_masq_ipv4_destroy, .dump = nft_masq_dump, .validate = nft_masq_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { @@ -174,7 +173,6 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = { .destroy = nft_masq_ipv6_destroy, .dump = nft_masq_dump, .validate = nft_masq_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { @@ -216,7 +214,6 @@ static const struct nft_expr_ops nft_masq_inet_ops = { .destroy = nft_masq_inet_destroy, .dump = nft_masq_dump, .validate = nft_masq_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_masq_inet_type __read_mostly = { diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index e384e0de7a54..73128d73fc99 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -744,60 +744,16 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx, return 0; } -bool nft_meta_get_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_meta *priv = nft_expr_priv(expr); - const struct nft_meta *meta; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - meta = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->key != meta->key || - priv->dreg != meta->dreg) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return nft_expr_reduce_bitwise(track, expr); -} -EXPORT_SYMBOL_GPL(nft_meta_get_reduce); - static const struct nft_expr_ops nft_meta_get_ops = { .type = &nft_meta_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), .eval = nft_meta_get_eval, .init = nft_meta_get_init, .dump = nft_meta_get_dump, - .reduce = nft_meta_get_reduce, .validate = nft_meta_get_validate, .offload = nft_meta_get_offload, }; -static bool nft_meta_set_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - int i; - - for (i = 0; i < NFT_REG32_NUM; i++) { - if (!track->regs[i].selector) - continue; - - if (track->regs[i].selector->ops != &nft_meta_get_ops) - continue; - - __nft_reg_track_cancel(track, i); - } - - return false; -} - static const struct nft_expr_ops nft_meta_set_ops = { .type = &nft_meta_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), @@ -805,7 +761,6 @@ static const struct nft_expr_ops nft_meta_set_ops = { .init = nft_meta_set_init, .destroy = nft_meta_set_destroy, .dump = nft_meta_set_dump, - .reduce = nft_meta_set_reduce, .validate = nft_meta_set_validate, }; diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index 5c29915ab028..296667e25420 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c @@ -318,7 +318,6 @@ static const struct nft_expr_ops nft_nat_ops = { .destroy = nft_nat_destroy, .dump = nft_nat_dump, .validate = nft_nat_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_nat_type __read_mostly = { @@ -349,7 +348,6 @@ static const struct nft_expr_ops nft_nat_inet_ops = { .destroy = nft_nat_destroy, .dump = nft_nat_dump, .validate = nft_nat_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_inet_nat_type __read_mostly = { diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c index 7d29db7c2ac0..c46534347405 100644 --- a/net/netfilter/nft_numgen.c +++ b/net/netfilter/nft_numgen.c @@ -84,16 +84,6 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx, return err; } -static bool nft_ng_inc_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_ng_inc *priv = nft_expr_priv(expr); - - nft_reg_track_cancel(track, priv->dreg, NFT_REG32_SIZE); - - return false; -} - static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg, u32 modulus, enum nft_ng_types type, u32 offset) { @@ -178,16 +168,6 @@ static int nft_ng_random_dump(struct sk_buff *skb, priv->offset); } -static bool nft_ng_random_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_ng_random *priv = nft_expr_priv(expr); - - nft_reg_track_cancel(track, priv->dreg, NFT_REG32_SIZE); - - return false; -} - static struct nft_expr_type nft_ng_type; static const struct nft_expr_ops nft_ng_inc_ops = { .type = &nft_ng_type, @@ -196,7 +176,6 @@ static const struct nft_expr_ops nft_ng_inc_ops = { .init = nft_ng_inc_init, .destroy = nft_ng_inc_destroy, .dump = nft_ng_inc_dump, - .reduce = nft_ng_inc_reduce, }; static const struct nft_expr_ops nft_ng_random_ops = { @@ -205,7 +184,6 @@ static const struct nft_expr_ops nft_ng_random_ops = { .eval = nft_ng_random_eval, .init = nft_ng_random_init, .dump = nft_ng_random_dump, - .reduce = nft_ng_random_reduce, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c index a48dd5b5d45b..0db12fe25d16 100644 --- a/net/netfilter/nft_objref.c +++ b/net/netfilter/nft_objref.c @@ -91,7 +91,6 @@ static const struct nft_expr_ops nft_objref_ops = { .activate = nft_objref_activate, .deactivate = nft_objref_deactivate, .dump = nft_objref_dump, - .reduce = NFT_REDUCE_READONLY, }; struct nft_objref_map { @@ -205,7 +204,6 @@ static const struct nft_expr_ops nft_objref_map_ops = { .deactivate = nft_objref_map_deactivate, .destroy = nft_objref_map_destroy, .dump = nft_objref_map_dump, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c index 70820c66b591..093ec7f96a77 100644 --- a/net/netfilter/nft_osf.c +++ b/net/netfilter/nft_osf.c @@ -133,30 +133,6 @@ static int nft_osf_validate(const struct nft_ctx *ctx, return nft_chain_validate_hooks(ctx->chain, hooks); } -static bool nft_osf_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - struct nft_osf *priv = nft_expr_priv(expr); - struct nft_osf *osf; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, NFT_OSF_MAXGENRELEN); - return false; - } - - osf = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->flags != osf->flags || - priv->ttl != osf->ttl) { - nft_reg_track_update(track, expr, priv->dreg, NFT_OSF_MAXGENRELEN); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return false; -} - static struct nft_expr_type nft_osf_type; static const struct nft_expr_ops nft_osf_op = { .eval = nft_osf_eval, @@ -165,7 +141,6 @@ static const struct nft_expr_ops nft_osf_op = { .dump = nft_osf_dump, .type = &nft_osf_type, .validate = nft_osf_validate, - .reduce = nft_osf_reduce, }; static struct nft_expr_type nft_osf_type __read_mostly = { diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 3a3c7746e88f..2c06aca301cb 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -247,31 +247,6 @@ static int nft_payload_dump(struct sk_buff *skb, return -1; } -static bool nft_payload_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_payload *priv = nft_expr_priv(expr); - const struct nft_payload *payload; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - payload = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->base != payload->base || - priv->offset != payload->offset || - priv->len != payload->len) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return nft_expr_reduce_bitwise(track, expr); -} - static bool nft_payload_offload_mask(struct nft_offload_reg *reg, u32 priv_len, u32 field_len) { @@ -575,7 +550,6 @@ static const struct nft_expr_ops nft_payload_ops = { .eval = nft_payload_eval, .init = nft_payload_init, .dump = nft_payload_dump, - .reduce = nft_payload_reduce, .offload = nft_payload_offload, }; @@ -585,7 +559,6 @@ const struct nft_expr_ops nft_payload_fast_ops = { .eval = nft_payload_eval, .init = nft_payload_init, .dump = nft_payload_dump, - .reduce = nft_payload_reduce, .offload = nft_payload_offload, }; @@ -940,32 +913,12 @@ static int nft_payload_set_dump(struct sk_buff *skb, return -1; } -static bool nft_payload_set_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - int i; - - for (i = 0; i < NFT_REG32_NUM; i++) { - if (!track->regs[i].selector) - continue; - - if (track->regs[i].selector->ops != &nft_payload_ops && - track->regs[i].selector->ops != &nft_payload_fast_ops) - continue; - - __nft_reg_track_cancel(track, i); - } - - return false; -} - static const struct nft_expr_ops nft_payload_set_ops = { .type = &nft_payload_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)), .eval = nft_payload_set_eval, .init = nft_payload_set_init, .dump = nft_payload_set_dump, - .reduce = nft_payload_set_reduce, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index b2b8127c8d43..160541791939 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c @@ -192,7 +192,6 @@ static const struct nft_expr_ops nft_queue_ops = { .init = nft_queue_init, .dump = nft_queue_dump, .validate = nft_queue_validate, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops nft_queue_sreg_ops = { @@ -202,7 +201,6 @@ static const struct nft_expr_ops nft_queue_sreg_ops = { .init = nft_queue_sreg_init, .dump = nft_queue_sreg_dump, .validate = nft_queue_validate, - .reduce = NFT_REDUCE_READONLY, }; static const struct nft_expr_ops * diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c index 3ba12a7471b0..5453056f07df 100644 --- a/net/netfilter/nft_quota.c +++ b/net/netfilter/nft_quota.c @@ -259,7 +259,6 @@ static const struct nft_expr_ops nft_quota_ops = { .destroy = nft_quota_destroy, .clone = nft_quota_clone, .dump = nft_quota_dump, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_quota_type __read_mostly = { diff --git a/net/netfilter/nft_range.c b/net/netfilter/nft_range.c index 0566d6aaf1e5..f8258d520229 100644 --- a/net/netfilter/nft_range.c +++ b/net/netfilter/nft_range.c @@ -138,7 +138,6 @@ static const struct nft_expr_ops nft_range_ops = { .eval = nft_range_eval, .init = nft_range_init, .dump = nft_range_dump, - .reduce = NFT_REDUCE_READONLY, }; struct nft_expr_type nft_range_type __read_mostly = { diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c index a70196ffcb1e..ab8dfaa34230 100644 --- a/net/netfilter/nft_redir.c +++ b/net/netfilter/nft_redir.c @@ -149,7 +149,6 @@ static const struct nft_expr_ops nft_redir_ipv4_ops = { .destroy = nft_redir_ipv4_destroy, .dump = nft_redir_dump, .validate = nft_redir_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_redir_ipv4_type __read_mostly = { @@ -177,7 +176,6 @@ static const struct nft_expr_ops nft_redir_ipv6_ops = { .destroy = nft_redir_ipv6_destroy, .dump = nft_redir_dump, .validate = nft_redir_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_redir_ipv6_type __read_mostly = { @@ -206,7 +204,6 @@ static const struct nft_expr_ops nft_redir_inet_ops = { .destroy = nft_redir_inet_destroy, .dump = nft_redir_dump, .validate = nft_redir_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_redir_inet_type __read_mostly = { diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 973fa31a9dd6..554caf967baa 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c @@ -80,7 +80,6 @@ static const struct nft_expr_ops nft_reject_inet_ops = { .init = nft_reject_init, .dump = nft_reject_dump, .validate = nft_reject_inet_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_reject_inet_type __read_mostly = { diff --git a/net/netfilter/nft_reject_netdev.c b/net/netfilter/nft_reject_netdev.c index 7865cd8b11bb..61cd8c4ac385 100644 --- a/net/netfilter/nft_reject_netdev.c +++ b/net/netfilter/nft_reject_netdev.c @@ -159,7 +159,6 @@ static const struct nft_expr_ops nft_reject_netdev_ops = { .init = nft_reject_init, .dump = nft_reject_dump, .validate = nft_reject_netdev_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_reject_netdev_type __read_mostly = { diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c index 5990fdd7b3cc..63a6069aa02b 100644 --- a/net/netfilter/nft_rt.c +++ b/net/netfilter/nft_rt.c @@ -191,7 +191,6 @@ static const struct nft_expr_ops nft_rt_get_ops = { .init = nft_rt_get_init, .dump = nft_rt_get_dump, .validate = nft_rt_validate, - .reduce = NFT_REDUCE_READONLY, }; struct nft_expr_type nft_rt_type __read_mostly = { diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c index 85f8df87efda..3bfcfe3ee5aa 100644 --- a/net/netfilter/nft_socket.c +++ b/net/netfilter/nft_socket.c @@ -213,31 +213,6 @@ static int nft_socket_dump(struct sk_buff *skb, return 0; } -static bool nft_socket_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_socket *priv = nft_expr_priv(expr); - const struct nft_socket *socket; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - socket = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->key != socket->key || - priv->dreg != socket->dreg || - priv->level != socket->level) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return nft_expr_reduce_bitwise(track, expr); -} - static int nft_socket_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data) @@ -256,7 +231,6 @@ static const struct nft_expr_ops nft_socket_ops = { .init = nft_socket_init, .dump = nft_socket_dump, .validate = nft_socket_validate, - .reduce = nft_socket_reduce, }; static struct nft_expr_type nft_socket_type __read_mostly = { diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c index 13da882669a4..bf7268908154 100644 --- a/net/netfilter/nft_synproxy.c +++ b/net/netfilter/nft_synproxy.c @@ -289,7 +289,6 @@ static const struct nft_expr_ops nft_synproxy_ops = { .dump = nft_synproxy_dump, .type = &nft_synproxy_type, .validate = nft_synproxy_validate, - .reduce = NFT_REDUCE_READONLY, }; static struct nft_expr_type nft_synproxy_type __read_mostly = { diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c index ea83f661417e..089d608f6b32 100644 --- a/net/netfilter/nft_tproxy.c +++ b/net/netfilter/nft_tproxy.c @@ -327,7 +327,6 @@ static const struct nft_expr_ops nft_tproxy_ops = { .init = nft_tproxy_init, .destroy = nft_tproxy_destroy, .dump = nft_tproxy_dump, - .reduce = NFT_REDUCE_READONLY, .validate = nft_tproxy_validate, }; diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index b059aa541798..ddd698332730 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -124,31 +124,6 @@ static int nft_tunnel_get_dump(struct sk_buff *skb, return -1; } -static bool nft_tunnel_get_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_tunnel *priv = nft_expr_priv(expr); - const struct nft_tunnel *tunnel; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - tunnel = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->key != tunnel->key || - priv->dreg != tunnel->dreg || - priv->mode != tunnel->mode) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return false; -} - static struct nft_expr_type nft_tunnel_type; static const struct nft_expr_ops nft_tunnel_get_ops = { .type = &nft_tunnel_type, @@ -156,7 +131,6 @@ static const struct nft_expr_ops nft_tunnel_get_ops = { .eval = nft_tunnel_get_eval, .init = nft_tunnel_get_init, .dump = nft_tunnel_get_dump, - .reduce = nft_tunnel_get_reduce, }; static struct nft_expr_type nft_tunnel_type __read_mostly = { diff --git a/net/netfilter/nft_xfrm.c b/net/netfilter/nft_xfrm.c index c88fd078a9ae..6252e1d9def8 100644 --- a/net/netfilter/nft_xfrm.c +++ b/net/netfilter/nft_xfrm.c @@ -254,32 +254,6 @@ static int nft_xfrm_validate(const struct nft_ctx *ctx, const struct nft_expr *e return nft_chain_validate_hooks(ctx->chain, hooks); } -static bool nft_xfrm_reduce(struct nft_regs_track *track, - const struct nft_expr *expr) -{ - const struct nft_xfrm *priv = nft_expr_priv(expr); - const struct nft_xfrm *xfrm; - - if (!nft_reg_track_cmp(track, expr, priv->dreg)) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - xfrm = nft_expr_priv(track->regs[priv->dreg].selector); - if (priv->key != xfrm->key || - priv->dreg != xfrm->dreg || - priv->dir != xfrm->dir || - priv->spnum != xfrm->spnum) { - nft_reg_track_update(track, expr, priv->dreg, priv->len); - return false; - } - - if (!track->regs[priv->dreg].bitwise) - return true; - - return nft_expr_reduce_bitwise(track, expr); -} - static struct nft_expr_type nft_xfrm_type; static const struct nft_expr_ops nft_xfrm_get_ops = { .type = &nft_xfrm_type, @@ -288,7 +262,6 @@ static const struct nft_expr_ops nft_xfrm_get_ops = { .init = nft_xfrm_get_init, .dump = nft_xfrm_get_dump, .validate = nft_xfrm_validate, - .reduce = nft_xfrm_reduce, }; static struct nft_expr_type nft_xfrm_type __read_mostly = { From patchwork Thu May 25 15:40:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 1786200 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QRshL3Rppz20QM for ; Fri, 26 May 2023 01:40:34 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241540AbjEYPkc (ORCPT ); Thu, 25 May 2023 11:40:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37306 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241186AbjEYPkb (ORCPT ); Thu, 25 May 2023 11:40:31 -0400 Received: from mail.netfilter.org (mail.netfilter.org [217.70.188.207]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8D54E18D for ; Thu, 25 May 2023 08:40:29 -0700 (PDT) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nf-next,v1 2/6] netfilter: nf_tables: remove fast bitwise and cmp operations Date: Thu, 25 May 2023 17:40:20 +0200 Message-Id: <20230525154024.222338-3-pablo@netfilter.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230525154024.222338-1-pablo@netfilter.org> References: <20230525154024.222338-1-pablo@netfilter.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch removes r10fdd6d80e4c ("netfilter: nf_tables: Implement fast bitwise expression") and 23f68d462984 ("netfilter: nft_cmp: optimize comparison for 16-bytes") which aim to speed up matching on 128-bits and <= 32-bits fields with bitwise operations in favour of the new combo match approach. Signed-off-by: Pablo Neira Ayuso Acked-by: Florian Westphal --- include/net/netfilter/nf_tables_core.h | 28 ---- net/netfilter/nf_tables_core.c | 44 +----- net/netfilter/nft_bitwise.c | 116 +-------------- net/netfilter/nft_cmp.c | 192 ------------------------- 4 files changed, 3 insertions(+), 377 deletions(-) diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index 780a5f6ad4a6..e98b7c244d36 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -29,38 +29,12 @@ extern struct nft_object_type nft_counter_obj_type; int nf_tables_core_module_init(void); void nf_tables_core_module_exit(void); -struct nft_bitwise_fast_expr { - u32 mask; - u32 xor; - u8 sreg; - u8 dreg; -}; - -struct nft_cmp_fast_expr { - u32 data; - u32 mask; - u8 sreg; - u8 len; - bool inv; -}; - -struct nft_cmp16_fast_expr { - struct nft_data data; - struct nft_data mask; - u8 sreg; - u8 len; - bool inv; -}; - struct nft_immediate_expr { struct nft_data data; u8 dreg; u8 dlen; }; -extern const struct nft_expr_ops nft_cmp_fast_ops; -extern const struct nft_expr_ops nft_cmp16_fast_ops; - struct nft_ct { enum nft_ct_keys key:8; enum ip_conntrack_dir dir:8; @@ -80,8 +54,6 @@ struct nft_payload { extern const struct nft_expr_ops nft_payload_fast_ops; -extern const struct nft_expr_ops nft_bitwise_fast_ops; - extern struct static_key_false nft_counters_enabled; extern struct static_key_false nft_trace_enabled; diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 4d0ce12221f6..f7270195db9b 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -74,40 +74,6 @@ static inline void nft_trace_copy_nftrace(const struct nft_pktinfo *pkt, info->nf_trace = pkt->skb->nf_trace; } -static void nft_bitwise_fast_eval(const struct nft_expr *expr, - struct nft_regs *regs) -{ - const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); - u32 *src = ®s->data[priv->sreg]; - u32 *dst = ®s->data[priv->dreg]; - - *dst = (*src & priv->mask) ^ priv->xor; -} - -static void nft_cmp_fast_eval(const struct nft_expr *expr, - struct nft_regs *regs) -{ - const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); - - if (((regs->data[priv->sreg] & priv->mask) == priv->data) ^ priv->inv) - return; - regs->verdict.code = NFT_BREAK; -} - -static void nft_cmp16_fast_eval(const struct nft_expr *expr, - struct nft_regs *regs) -{ - const struct nft_cmp16_fast_expr *priv = nft_expr_priv(expr); - const u64 *reg_data = (const u64 *)®s->data[priv->sreg]; - const u64 *mask = (const u64 *)&priv->mask; - const u64 *data = (const u64 *)&priv->data; - - if (((reg_data[0] & mask[0]) == data[0] && - ((reg_data[1] & mask[1]) == data[1])) ^ priv->inv) - return; - regs->verdict.code = NFT_BREAK; -} - static noinline void __nft_trace_verdict(const struct nft_pktinfo *pkt, struct nft_traceinfo *info, const struct nft_rule_dp *rule, @@ -277,14 +243,8 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) regs.verdict.code = NFT_CONTINUE; for (; !rule->is_last ; rule = nft_rule_next(rule)) { nft_rule_dp_for_each_expr(expr, last, rule) { - if (expr->ops == &nft_cmp_fast_ops) - nft_cmp_fast_eval(expr, ®s); - else if (expr->ops == &nft_cmp16_fast_ops) - nft_cmp16_fast_eval(expr, ®s); - else if (expr->ops == &nft_bitwise_fast_ops) - nft_bitwise_fast_eval(expr, ®s); - else if (expr->ops != &nft_payload_fast_ops || - !nft_payload_fast_eval(expr, ®s, pkt)) + if (expr->ops != &nft_payload_fast_ops || + !nft_payload_fast_eval(expr, ®s, pkt)) expr_call_ops_eval(expr, ®s, pkt); if (regs.verdict.code != NFT_CONTINUE) diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index 8d2b9249078a..b358c03bdb04 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -290,113 +290,6 @@ static const struct nft_expr_ops nft_bitwise_ops = { .offload = nft_bitwise_offload, }; -static int -nft_bitwise_extract_u32_data(const struct nlattr * const tb, u32 *out) -{ - struct nft_data data; - struct nft_data_desc desc = { - .type = NFT_DATA_VALUE, - .size = sizeof(data), - .len = sizeof(u32), - }; - int err; - - err = nft_data_init(NULL, &data, &desc, tb); - if (err < 0) - return err; - - *out = data.data[0]; - - return 0; -} - -static int nft_bitwise_fast_init(const struct nft_ctx *ctx, - const struct nft_expr *expr, - const struct nlattr * const tb[]) -{ - struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); - int err; - - err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg, - sizeof(u32)); - if (err < 0) - return err; - - err = nft_parse_register_store(ctx, tb[NFTA_BITWISE_DREG], &priv->dreg, - NULL, NFT_DATA_VALUE, sizeof(u32)); - if (err < 0) - return err; - - if (tb[NFTA_BITWISE_DATA]) - return -EINVAL; - - if (!tb[NFTA_BITWISE_MASK] || - !tb[NFTA_BITWISE_XOR]) - return -EINVAL; - - err = nft_bitwise_extract_u32_data(tb[NFTA_BITWISE_MASK], &priv->mask); - if (err < 0) - return err; - - err = nft_bitwise_extract_u32_data(tb[NFTA_BITWISE_XOR], &priv->xor); - if (err < 0) - return err; - - return 0; -} - -static int -nft_bitwise_fast_dump(struct sk_buff *skb, - const struct nft_expr *expr, bool reset) -{ - const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); - struct nft_data data; - - if (nft_dump_register(skb, NFTA_BITWISE_SREG, priv->sreg)) - return -1; - if (nft_dump_register(skb, NFTA_BITWISE_DREG, priv->dreg)) - return -1; - if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(sizeof(u32)))) - return -1; - if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_BOOL))) - return -1; - - data.data[0] = priv->mask; - if (nft_data_dump(skb, NFTA_BITWISE_MASK, &data, - NFT_DATA_VALUE, sizeof(u32)) < 0) - return -1; - - data.data[0] = priv->xor; - if (nft_data_dump(skb, NFTA_BITWISE_XOR, &data, - NFT_DATA_VALUE, sizeof(u32)) < 0) - return -1; - - return 0; -} - -static int nft_bitwise_fast_offload(struct nft_offload_ctx *ctx, - struct nft_flow_rule *flow, - const struct nft_expr *expr) -{ - const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); - struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; - - if (priv->xor || priv->sreg != priv->dreg || reg->len != sizeof(u32)) - return -EOPNOTSUPP; - - reg->mask.data[0] = priv->mask; - return 0; -} - -const struct nft_expr_ops nft_bitwise_fast_ops = { - .type = &nft_bitwise_type, - .size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise_fast_expr)), - .eval = NULL, /* inlined */ - .init = nft_bitwise_fast_init, - .dump = nft_bitwise_fast_dump, - .offload = nft_bitwise_fast_offload, -}; - static const struct nft_expr_ops * nft_bitwise_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) @@ -413,14 +306,7 @@ nft_bitwise_select_ops(const struct nft_ctx *ctx, if (err < 0) return ERR_PTR(err); - if (len != sizeof(u32)) - return &nft_bitwise_ops; - - if (tb[NFTA_BITWISE_OP] && - ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_BOOL) - return &nft_bitwise_ops; - - return &nft_bitwise_fast_ops; + return &nft_bitwise_ops; } struct nft_expr_type nft_bitwise_type __read_mostly = { diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c index 75a7b24eeefc..64856ceb60ea 100644 --- a/net/netfilter/nft_cmp.c +++ b/net/netfilter/nft_cmp.c @@ -193,190 +193,6 @@ static const struct nft_expr_ops nft_cmp_ops = { .offload = nft_cmp_offload, }; -/* Calculate the mask for the nft_cmp_fast expression. On big endian the - * mask needs to include the *upper* bytes when interpreting that data as - * something smaller than the full u32, therefore a cpu_to_le32 is done. - */ -static u32 nft_cmp_fast_mask(unsigned int len) -{ - __le32 mask = cpu_to_le32(~0U >> (sizeof_field(struct nft_cmp_fast_expr, - data) * BITS_PER_BYTE - len)); - - return (__force u32)mask; -} - -static int nft_cmp_fast_init(const struct nft_ctx *ctx, - const struct nft_expr *expr, - const struct nlattr * const tb[]) -{ - struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); - struct nft_data data; - struct nft_data_desc desc = { - .type = NFT_DATA_VALUE, - .size = sizeof(data), - }; - int err; - - err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); - if (err < 0) - return err; - - err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); - if (err < 0) - return err; - - desc.len *= BITS_PER_BYTE; - - priv->mask = nft_cmp_fast_mask(desc.len); - priv->data = data.data[0] & priv->mask; - priv->len = desc.len; - priv->inv = ntohl(nla_get_be32(tb[NFTA_CMP_OP])) != NFT_CMP_EQ; - return 0; -} - -static int nft_cmp_fast_offload(struct nft_offload_ctx *ctx, - struct nft_flow_rule *flow, - const struct nft_expr *expr) -{ - const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); - struct nft_cmp_expr cmp = { - .data = { - .data = { - [0] = priv->data, - }, - }, - .sreg = priv->sreg, - .len = priv->len / BITS_PER_BYTE, - .op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ, - }; - - return __nft_cmp_offload(ctx, flow, &cmp); -} - -static int nft_cmp_fast_dump(struct sk_buff *skb, - const struct nft_expr *expr, bool reset) -{ - const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); - enum nft_cmp_ops op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ; - struct nft_data data; - - if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg)) - goto nla_put_failure; - if (nla_put_be32(skb, NFTA_CMP_OP, htonl(op))) - goto nla_put_failure; - - data.data[0] = priv->data; - if (nft_data_dump(skb, NFTA_CMP_DATA, &data, - NFT_DATA_VALUE, priv->len / BITS_PER_BYTE) < 0) - goto nla_put_failure; - return 0; - -nla_put_failure: - return -1; -} - -const struct nft_expr_ops nft_cmp_fast_ops = { - .type = &nft_cmp_type, - .size = NFT_EXPR_SIZE(sizeof(struct nft_cmp_fast_expr)), - .eval = NULL, /* inlined */ - .init = nft_cmp_fast_init, - .dump = nft_cmp_fast_dump, - .offload = nft_cmp_fast_offload, -}; - -static u32 nft_cmp_mask(u32 bitlen) -{ - return (__force u32)cpu_to_le32(~0U >> (sizeof(u32) * BITS_PER_BYTE - bitlen)); -} - -static void nft_cmp16_fast_mask(struct nft_data *data, unsigned int bitlen) -{ - int len = bitlen / BITS_PER_BYTE; - int i, words = len / sizeof(u32); - - for (i = 0; i < words; i++) { - data->data[i] = 0xffffffff; - bitlen -= sizeof(u32) * BITS_PER_BYTE; - } - - if (len % sizeof(u32)) - data->data[i++] = nft_cmp_mask(bitlen); - - for (; i < 4; i++) - data->data[i] = 0; -} - -static int nft_cmp16_fast_init(const struct nft_ctx *ctx, - const struct nft_expr *expr, - const struct nlattr * const tb[]) -{ - struct nft_cmp16_fast_expr *priv = nft_expr_priv(expr); - struct nft_data_desc desc = { - .type = NFT_DATA_VALUE, - .size = sizeof(priv->data), - }; - int err; - - err = nft_data_init(NULL, &priv->data, &desc, tb[NFTA_CMP_DATA]); - if (err < 0) - return err; - - err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); - if (err < 0) - return err; - - nft_cmp16_fast_mask(&priv->mask, desc.len * BITS_PER_BYTE); - priv->inv = ntohl(nla_get_be32(tb[NFTA_CMP_OP])) != NFT_CMP_EQ; - priv->len = desc.len; - - return 0; -} - -static int nft_cmp16_fast_offload(struct nft_offload_ctx *ctx, - struct nft_flow_rule *flow, - const struct nft_expr *expr) -{ - const struct nft_cmp16_fast_expr *priv = nft_expr_priv(expr); - struct nft_cmp_expr cmp = { - .data = priv->data, - .sreg = priv->sreg, - .len = priv->len, - .op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ, - }; - - return __nft_cmp_offload(ctx, flow, &cmp); -} - -static int nft_cmp16_fast_dump(struct sk_buff *skb, - const struct nft_expr *expr, bool reset) -{ - const struct nft_cmp16_fast_expr *priv = nft_expr_priv(expr); - enum nft_cmp_ops op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ; - - if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg)) - goto nla_put_failure; - if (nla_put_be32(skb, NFTA_CMP_OP, htonl(op))) - goto nla_put_failure; - - if (nft_data_dump(skb, NFTA_CMP_DATA, &priv->data, - NFT_DATA_VALUE, priv->len) < 0) - goto nla_put_failure; - return 0; - -nla_put_failure: - return -1; -} - - -const struct nft_expr_ops nft_cmp16_fast_ops = { - .type = &nft_cmp_type, - .size = NFT_EXPR_SIZE(sizeof(struct nft_cmp16_fast_expr)), - .eval = NULL, /* inlined */ - .init = nft_cmp16_fast_init, - .dump = nft_cmp16_fast_dump, - .offload = nft_cmp16_fast_offload, -}; - static const struct nft_expr_ops * nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) { @@ -413,14 +229,6 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); - if (op == NFT_CMP_EQ || op == NFT_CMP_NEQ) { - if (desc.len <= sizeof(u32)) - return &nft_cmp_fast_ops; - else if (desc.len <= sizeof(data) && - ((sreg >= NFT_REG_1 && sreg <= NFT_REG_4) || - (sreg >= NFT_REG32_00 && sreg <= NFT_REG32_12 && sreg % 2 == 0))) - return &nft_cmp16_fast_ops; - } return &nft_cmp_ops; } From patchwork Thu May 25 15:40:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 1786201 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QRshN199Rz20QL for ; Fri, 26 May 2023 01:40:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241782AbjEYPkd (ORCPT ); Thu, 25 May 2023 11:40:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37310 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241327AbjEYPkc (ORCPT ); Thu, 25 May 2023 11:40:32 -0400 Received: from mail.netfilter.org (mail.netfilter.org [217.70.188.207]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2F47F195 for ; Thu, 25 May 2023 08:40:30 -0700 (PDT) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nf-next,v1 3/6] netfilter: nf_tables: add payload combo match Date: Thu, 25 May 2023 17:40:21 +0200 Message-Id: <20230525154024.222338-4-pablo@netfilter.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230525154024.222338-1-pablo@netfilter.org> References: <20230525154024.222338-1-pablo@netfilter.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch adds the expression tracking infrastructure to search for expressions that can be coalesced into one single operation. This patch allows to coalesce payload + cmp expression into a single combo expression if matching length is <= 4 bytes or 16 bytes when building the ruleset blob. If .track returns 0, the expression added to the expression stack, this means that it does not know what to do with this expression yet. If .track returns 1, then the expressions in the stack are built into the ruleset blob. A later patch introduces -1 return value to skip such expression, which is useful to skip the comment match. Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 51 ++++++++++++++ include/net/netfilter/nf_tables_core.h | 4 ++ net/netfilter/nf_tables_api.c | 92 +++++++++++++++++++++++--- net/netfilter/nf_tables_core.c | 46 ++++++++++++- net/netfilter/nft_cmp.c | 20 ++++++ net/netfilter/nft_payload.c | 61 +++++++++++++++++ 6 files changed, 264 insertions(+), 10 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 588b1904e411..d061777ae860 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -123,6 +123,55 @@ struct nft_regs { }; }; +enum nft_expr_track_type { + NFT_EXPR_UNSET = 0, + NFT_EXPR_PAYLOAD, + NFT_EXPR_CMP +}; + +struct nft_expr_track { + enum nft_expr_track_type type; + union { + struct { + u8 dreg; + u8 base; + u8 offset; + u8 len; + u32 mask; + } payload; + struct { + u8 sreg; + u8 op; + u8 len; + bool inv; + struct nft_data data; + } cmp; + }; +}; + +struct nft_payload_combo { + u8 offset; + u8 len; + bool inv; + struct nft_data data; + struct nft_data mask; +}; + +/* Same layout as nft_expr but it embeds the private expression data area. */ +struct nft_combo_expr { + const struct nft_expr_ops *ops; + union { + struct nft_payload_combo payload; + } __attribute__((aligned(__alignof__(u64)))); +}; + +struct nft_exprs_track { + int num_exprs; + struct nft_expr_track expr[2]; + const struct nft_expr *saved_expr[2]; + struct nft_combo_expr _expr; +}; + /* Store/load an u8, u16 or u64 integer to/from the u32 data register. * * Note, when using concatenations, register allocation happens at 32-bit @@ -934,6 +983,8 @@ struct nft_expr_ops { int (*validate)(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nft_data **data); + int (*track)(struct nft_expr_track *track, + const struct nft_expr *expr); bool (*gc)(struct net *net, const struct nft_expr *expr); int (*offload)(struct nft_offload_ctx *ctx, diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index e98b7c244d36..6eb5cf980e66 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -53,6 +53,7 @@ struct nft_payload { }; extern const struct nft_expr_ops nft_payload_fast_ops; +extern const struct nft_expr_ops nft_payload_combo_ops; extern struct static_key_false nft_counters_enabled; extern struct static_key_false nft_trace_enabled; @@ -152,4 +153,7 @@ void nft_objref_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt); void nft_objref_map_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt); + +void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track); + #endif /* _NET_NF_TABLES_CORE_H */ diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 80932407b9a6..00bbf8c2fdfd 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8901,13 +8901,67 @@ void nf_tables_trans_destroy_flush_work(void) } EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work); +static int nft_expr_track(struct nft_exprs_track *expr_track, + const struct nft_expr *expr) +{ + int ret; + + expr_track->saved_expr[expr_track->num_exprs] = expr; + + if (!expr->ops->track) { + expr_track->num_exprs++; + return 1; + } + + ret = expr->ops->track(&expr_track->expr[expr_track->num_exprs], expr); + if (ret > 0) { + expr_track->num_exprs++; + return 1; + } + + switch (expr_track->num_exprs) { + case 0: + switch (expr_track->expr[0].type) { + case NFT_EXPR_PAYLOAD: + expr_track->num_exprs++; + return 0; + default: + return 1; + } + break; + case 1: + switch (expr_track->expr[0].type) { + case NFT_EXPR_PAYLOAD: + if (expr_track->expr[1].type == NFT_EXPR_CMP) { + nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track); + expr_track->saved_expr[0] = (struct nft_expr *)&expr_track->_expr; + expr_track->num_exprs = 1; + return 1; + } + break; + default: + return 1; + } + break; + default: + WARN_ON_ONCE(1); + break; + } + + expr_track->num_exprs++; + + return 1; +} + static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain) { + struct nft_exprs_track expr_track = {}; const struct nft_expr *expr, *last; unsigned int size, data_size; void *data, *data_boundary; struct nft_rule_dp *prule; struct nft_rule *rule; + int i; /* already handled or inactive chain? */ if (chain->blob_next || !nft_is_active_next(net, chain)) @@ -8915,11 +8969,26 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha data_size = 0; list_for_each_entry(rule, &chain->rules, list) { - if (nft_is_active_next(net, rule)) { - data_size += sizeof(*prule) + rule->dlen; - if (data_size > INT_MAX) - return -ENOMEM; + if (!nft_is_active_next(net, rule)) + continue; + + size = 0; + nft_rule_for_each_expr(expr, last, rule) { + if (!nft_expr_track(&expr_track, expr)) + continue; + + for (i = 0; i < expr_track.num_exprs; i++) + size += expr_track.saved_expr[i]->ops->size; + + expr_track.num_exprs = 0; } + + if (WARN_ON_ONCE(size >= 1 << 12)) + return -ENOMEM; + + data_size += sizeof(*prule) + size; + if (data_size > INT_MAX) + return -ENOMEM; } chain->blob_next = nf_tables_chain_alloc_rules(chain, data_size); @@ -8929,6 +8998,7 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha data = (void *)chain->blob_next->data; data_boundary = data + data_size; size = 0; + expr_track.num_exprs = 0; list_for_each_entry(rule, &chain->rules, list) { if (!nft_is_active_next(net, rule)) @@ -8941,12 +9011,18 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha size = 0; nft_rule_for_each_expr(expr, last, rule) { + if (!nft_expr_track(&expr_track, expr)) + continue; - if (WARN_ON_ONCE(data + expr->ops->size > data_boundary)) - return -ENOMEM; + for (i = 0; i < expr_track.num_exprs; i++) { + if (WARN_ON_ONCE(data + expr_track.saved_expr[i]->ops->size > data_boundary)) + return -ENOMEM; - memcpy(data + size, expr, expr->ops->size); - size += expr->ops->size; + memcpy(data + size, expr_track.saved_expr[i], + expr_track.saved_expr[i]->ops->size); + size += expr_track.saved_expr[i]->ops->size; + } + expr_track.num_exprs = 0; } if (WARN_ON_ONCE(size >= 1 << 12)) return -ENOMEM; diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index f7270195db9b..db0c667ea5d0 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -142,6 +142,46 @@ static bool nft_payload_fast_eval(const struct nft_expr *expr, return true; } +static inline int nft_payload_combo_match16(const u64 *x, + struct nft_payload_combo *priv) +{ + const u64 *mask = (const u64 *)&priv->mask; + const u64 *data = (const u64 *)&priv->data; + + return ((x[0] & mask[0]) == data[0] && + (x[1] & mask[1]) == data[1]) ^ priv->inv; +} + +static inline int nft_payload_combo_match4(const u32 *x, + const struct nft_payload_combo *priv) +{ + return ((*x & priv->mask.data[0]) == priv->data.data[0]) ^ priv->inv; +} + +static inline void nft_payload_combo_eval(const struct nft_expr *expr, + struct nft_regs *regs, + const struct nft_pktinfo *pkt) +{ + struct nft_payload_combo *priv = nft_expr_priv(expr); + char __buf[16]; + void *ptr; + bool ret; + + ptr = skb_header_pointer(pkt->skb, priv->offset, priv->len, __buf); + if (!ptr) + goto err; + + if (priv->len == 16) + ret = nft_payload_combo_match16(ptr, priv); + else + ret = nft_payload_combo_match4(ptr, priv); + + if (ret) + return; +err: + regs->verdict.code = NFT_BREAK; +} + DEFINE_STATIC_KEY_FALSE(nft_counters_enabled); static noinline void nft_update_chain_stats(const struct nft_chain *chain, @@ -243,8 +283,10 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) regs.verdict.code = NFT_CONTINUE; for (; !rule->is_last ; rule = nft_rule_next(rule)) { nft_rule_dp_for_each_expr(expr, last, rule) { - if (expr->ops != &nft_payload_fast_ops || - !nft_payload_fast_eval(expr, ®s, pkt)) + if (expr->ops == &nft_payload_combo_ops) + nft_payload_combo_eval(expr, ®s, pkt); + else if (expr->ops != &nft_payload_fast_ops || + !nft_payload_fast_eval(expr, ®s, pkt)) expr_call_ops_eval(expr, ®s, pkt); if (regs.verdict.code != NFT_CONTINUE) diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c index 64856ceb60ea..800c3ec76b59 100644 --- a/net/netfilter/nft_cmp.c +++ b/net/netfilter/nft_cmp.c @@ -184,12 +184,32 @@ static int nft_cmp_offload(struct nft_offload_ctx *ctx, return __nft_cmp_offload(ctx, flow, priv); } +static int nft_cmp_track(struct nft_expr_track *track, + const struct nft_expr *expr) +{ + const struct nft_cmp_expr *priv = nft_expr_priv(expr); + + if (priv->op != NFT_CMP_EQ && + priv->op != NFT_CMP_NEQ) + return 1; + + track->type = NFT_EXPR_CMP; + track->cmp.sreg = priv->sreg; + track->cmp.op = priv->op; + track->cmp.len = priv->len; + track->cmp.inv = (priv->op == NFT_CMP_NEQ); + memcpy(&track->cmp.data, &priv->data, sizeof(priv->data)); + + return 0; +} + static const struct nft_expr_ops nft_cmp_ops = { .type = &nft_cmp_type, .size = NFT_EXPR_SIZE(sizeof(struct nft_cmp_expr)), .eval = nft_cmp_eval, .init = nft_cmp_init, .dump = nft_cmp_dump, + .track = nft_cmp_track, .offload = nft_cmp_offload, }; diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 2c06aca301cb..5b6affe18ffc 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -247,6 +247,23 @@ static int nft_payload_dump(struct sk_buff *skb, return -1; } +static int nft_payload_track(struct nft_expr_track *track, + const struct nft_expr *expr) +{ + const struct nft_payload *priv = nft_expr_priv(expr); + + if (priv->len > 4 && priv->len < 16) + return 1; + + track->type = NFT_EXPR_PAYLOAD; + track->payload.dreg = priv->dreg; + track->payload.base = priv->base; + track->payload.offset = priv->offset; + track->payload.len = priv->len; + + return 0; +} + static bool nft_payload_offload_mask(struct nft_offload_reg *reg, u32 priv_len, u32 field_len) { @@ -550,6 +567,7 @@ static const struct nft_expr_ops nft_payload_ops = { .eval = nft_payload_eval, .init = nft_payload_init, .dump = nft_payload_dump, + .track = nft_payload_track, .offload = nft_payload_offload, }; @@ -559,6 +577,7 @@ const struct nft_expr_ops nft_payload_fast_ops = { .eval = nft_payload_eval, .init = nft_payload_init, .dump = nft_payload_dump, + .track = nft_payload_track, .offload = nft_payload_offload, }; @@ -977,3 +996,45 @@ struct nft_expr_type nft_payload_type __read_mostly = { .maxattr = NFTA_PAYLOAD_MAX, .owner = THIS_MODULE, }; + +/* Calculate the mask for the nft_cmp_fast expression. On big endian the + * mask needs to include the *upper* bytes when interpreting that data as + * something smaller than the full u32, therefore a cpu_to_le32 is done. + */ +static u32 nft_cmp_mask(u32 bitlen) +{ + return (__force u32)cpu_to_le32(~0U >> (sizeof(u32) * BITS_PER_BYTE - bitlen)); +} + +static void nft_cmp16_mask(struct nft_data *data, unsigned int len) +{ + unsigned int bitlen = len * BITS_PER_BYTE; + int i, words = len / sizeof(u32); + + for (i = 0; i < words; i++) { + data->data[i] = 0xffffffff; + bitlen -= sizeof(u32) * BITS_PER_BYTE; + } + + if (len % sizeof(u32)) + data->data[i++] = nft_cmp_mask(bitlen); + + for (; i < 4; i++) + data->data[i] = 0; +} + +void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track) +{ + struct nft_payload_combo *priv = nft_expr_priv(expr); + + expr->ops = &nft_payload_combo_ops; + priv->offset = track->expr[0].payload.offset; + priv->len = track->expr[0].payload.len; + memcpy(&priv->data, &track->expr[1].cmp.data, sizeof(priv->data)); + priv->inv = track->expr[1].cmp.inv; + nft_cmp16_mask(&priv->mask, track->expr[1].cmp.len); +} + +const struct nft_expr_ops nft_payload_combo_ops = { + .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_combo)), +}; From patchwork Thu May 25 15:40:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 1786204 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QRshQ56snz20QL for ; Fri, 26 May 2023 01:40:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241327AbjEYPkh (ORCPT ); Thu, 25 May 2023 11:40:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37320 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241186AbjEYPkc (ORCPT ); Thu, 25 May 2023 11:40:32 -0400 Received: from mail.netfilter.org (mail.netfilter.org [217.70.188.207]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B1DDA99 for ; Thu, 25 May 2023 08:40:30 -0700 (PDT) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nf-next,v1 4/6] netfilter: nf_tables: add meta combo match Date: Thu, 25 May 2023 17:40:22 +0200 Message-Id: <20230525154024.222338-5-pablo@netfilter.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230525154024.222338-1-pablo@netfilter.org> References: <20230525154024.222338-1-pablo@netfilter.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch allows to coalesce meta iifname,oifname + cmp into one combo expression. Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 16 +++++++++++ include/net/netfilter/nf_tables_core.h | 2 ++ net/netfilter/nf_tables_api.c | 9 ++++++ net/netfilter/nf_tables_core.c | 40 ++++++++++++++++++++++++++ net/netfilter/nft_meta.c | 32 +++++++++++++++++++++ net/netfilter/nft_payload.c | 2 +- 6 files changed, 100 insertions(+), 1 deletion(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index d061777ae860..6ae056dde789 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -126,6 +126,7 @@ struct nft_regs { enum nft_expr_track_type { NFT_EXPR_UNSET = 0, NFT_EXPR_PAYLOAD, + NFT_EXPR_META, NFT_EXPR_CMP }; @@ -139,6 +140,11 @@ struct nft_expr_track { u8 len; u32 mask; } payload; + struct { + u8 dreg; + u8 key; + bool inv; + } meta; struct { u8 sreg; u8 op; @@ -157,11 +163,21 @@ struct nft_payload_combo { struct nft_data mask; }; +struct nft_meta_combo { + u8 key; + bool inv; + struct nft_data data; + struct nft_data mask; +}; + +void nft_cmp16_mask(struct nft_data *data, unsigned int len); + /* Same layout as nft_expr but it embeds the private expression data area. */ struct nft_combo_expr { const struct nft_expr_ops *ops; union { struct nft_payload_combo payload; + struct nft_meta_combo meta; } __attribute__((aligned(__alignof__(u64)))); }; diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index 6eb5cf980e66..424aca2f54e0 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -54,6 +54,7 @@ struct nft_payload { extern const struct nft_expr_ops nft_payload_fast_ops; extern const struct nft_expr_ops nft_payload_combo_ops; +extern const struct nft_expr_ops nft_meta_combo_ops; extern struct static_key_false nft_counters_enabled; extern struct static_key_false nft_trace_enabled; @@ -155,5 +156,6 @@ void nft_objref_map_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt); void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track); +void nft_meta_combo_init(struct nft_expr *expr, struct nft_exprs_track *track); #endif /* _NET_NF_TABLES_CORE_H */ diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 00bbf8c2fdfd..ceae7a9bb989 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8923,6 +8923,7 @@ static int nft_expr_track(struct nft_exprs_track *expr_track, case 0: switch (expr_track->expr[0].type) { case NFT_EXPR_PAYLOAD: + case NFT_EXPR_META: expr_track->num_exprs++; return 0; default: @@ -8939,6 +8940,14 @@ static int nft_expr_track(struct nft_exprs_track *expr_track, return 1; } break; + case NFT_EXPR_META: + if (expr_track->expr[1].type == NFT_EXPR_CMP) { + nft_meta_combo_init((struct nft_expr *)&expr_track->_expr, expr_track); + expr_track->saved_expr[0] = (struct nft_expr *)&expr_track->_expr; + expr_track->num_exprs = 1; + return 1; + } + break; default: return 1; } diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index db0c667ea5d0..417724330538 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -182,6 +182,44 @@ static inline void nft_payload_combo_eval(const struct nft_expr *expr, regs->verdict.code = NFT_BREAK; } +static inline int nft_combo_ifname(const u64 *x, struct nft_meta_combo *priv) +{ + const u64 *mask = (const u64 *)&priv->mask; + const u64 *data = (const u64 *)&priv->data; + + return ((x[0] & mask[0]) == data[0] && + (x[1] & mask[1]) == data[1]) ^ priv->inv; +} + +static inline void nft_meta_combo_eval(const struct nft_expr *expr, + struct nft_regs *regs, + const struct nft_pktinfo *pkt) +{ + struct nft_meta_combo *priv = nft_expr_priv(expr); + const struct net_device *dev; + const void *ptr; + bool ret; + + switch (priv->key) { + case NFT_META_IIFNAME: + dev = nft_in(pkt); + break; + case NFT_META_OIFNAME: + dev = nft_out(pkt); + break; + } + + if (unlikely(!dev)) + goto err; + + ptr = dev->name; + ret = nft_combo_ifname(ptr, priv); + if (ret) + return; +err: + regs->verdict.code = NFT_BREAK; +} + DEFINE_STATIC_KEY_FALSE(nft_counters_enabled); static noinline void nft_update_chain_stats(const struct nft_chain *chain, @@ -285,6 +323,8 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) nft_rule_dp_for_each_expr(expr, last, rule) { if (expr->ops == &nft_payload_combo_ops) nft_payload_combo_eval(expr, ®s, pkt); + else if (expr->ops == &nft_meta_combo_ops) + nft_meta_combo_eval(expr, ®s, pkt); else if (expr->ops != &nft_payload_fast_ops || !nft_payload_fast_eval(expr, ®s, pkt)) expr_call_ops_eval(expr, ®s, pkt); diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index 73128d73fc99..b0e8255cdcd0 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -711,6 +711,22 @@ void nft_meta_set_destroy(const struct nft_ctx *ctx, } EXPORT_SYMBOL_GPL(nft_meta_set_destroy); +static int nft_meta_get_track(struct nft_expr_track *track, + const struct nft_expr *expr) +{ + const struct nft_meta *priv = nft_expr_priv(expr); + + if (priv->key != NFT_META_IIFNAME && + priv->key != NFT_META_OIFNAME) + return 1; + + track->type = NFT_EXPR_META; + track->meta.dreg = priv->dreg; + track->meta.key = priv->key; + + return 0; +} + static int nft_meta_get_offload(struct nft_offload_ctx *ctx, struct nft_flow_rule *flow, const struct nft_expr *expr) @@ -750,6 +766,7 @@ static const struct nft_expr_ops nft_meta_get_ops = { .eval = nft_meta_get_eval, .init = nft_meta_get_init, .dump = nft_meta_get_dump, + .track = nft_meta_get_track, .validate = nft_meta_get_validate, .offload = nft_meta_get_offload, }; @@ -964,3 +981,18 @@ struct nft_object_type nft_secmark_obj_type __read_mostly = { .owner = THIS_MODULE, }; #endif /* CONFIG_NETWORK_SECMARK */ + +void nft_meta_combo_init(struct nft_expr *expr, struct nft_exprs_track *track) +{ + struct nft_meta_combo *priv = nft_expr_priv(expr); + + expr->ops = &nft_meta_combo_ops; + priv->key = track->expr[0].meta.key; + memcpy(&priv->data, &track->expr[1].cmp.data, sizeof(priv->data)); + priv->inv = track->expr[1].cmp.inv; + nft_cmp16_mask(&priv->mask, track->expr[1].cmp.len); +} + +const struct nft_expr_ops nft_meta_combo_ops = { + .size = NFT_EXPR_SIZE(sizeof(struct nft_meta_combo)), +}; diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 5b6affe18ffc..5c99eca32e84 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -1006,7 +1006,7 @@ static u32 nft_cmp_mask(u32 bitlen) return (__force u32)cpu_to_le32(~0U >> (sizeof(u32) * BITS_PER_BYTE - bitlen)); } -static void nft_cmp16_mask(struct nft_data *data, unsigned int len) +void nft_cmp16_mask(struct nft_data *data, unsigned int len) { unsigned int bitlen = len * BITS_PER_BYTE; int i, words = len / sizeof(u32); From patchwork Thu May 25 15:40:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 1786202 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QRshN643Jz20QM for ; Fri, 26 May 2023 01:40:36 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241784AbjEYPke (ORCPT ); Thu, 25 May 2023 11:40:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37316 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241770AbjEYPkc (ORCPT ); Thu, 25 May 2023 11:40:32 -0400 Received: from mail.netfilter.org (mail.netfilter.org [217.70.188.207]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E5805197 for ; Thu, 25 May 2023 08:40:30 -0700 (PDT) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nf-next,v1 5/6] netfilter: nf_tables: add payload bitwise combo match Date: Thu, 25 May 2023 17:40:23 +0200 Message-Id: <20230525154024.222338-6-pablo@netfilter.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230525154024.222338-1-pablo@netfilter.org> References: <20230525154024.222338-1-pablo@netfilter.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This allows to coalesce payload + bitwise + cmp expression into one combo expression. This does not require updates on the datapath, the existing mask field is adjusted based on the bitwise mask. Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 10 ++++++++-- include/net/netfilter/nf_tables_core.h | 2 +- net/netfilter/nf_tables_api.c | 20 +++++++++++++++++++- net/netfilter/nft_bitwise.c | 20 ++++++++++++++++++++ net/netfilter/nft_payload.c | 13 +++++++++---- 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 6ae056dde789..85df4b23264f 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -127,6 +127,7 @@ enum nft_expr_track_type { NFT_EXPR_UNSET = 0, NFT_EXPR_PAYLOAD, NFT_EXPR_META, + NFT_EXPR_BITWISE, NFT_EXPR_CMP }; @@ -152,6 +153,11 @@ struct nft_expr_track { bool inv; struct nft_data data; } cmp; + struct { + u8 sreg; + u8 dreg; + struct nft_data mask; + } bitwise; }; }; @@ -183,8 +189,8 @@ struct nft_combo_expr { struct nft_exprs_track { int num_exprs; - struct nft_expr_track expr[2]; - const struct nft_expr *saved_expr[2]; + struct nft_expr_track expr[3]; + const struct nft_expr *saved_expr[3]; struct nft_combo_expr _expr; }; diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index 424aca2f54e0..2d8c984e3955 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -155,7 +155,7 @@ void nft_objref_eval(const struct nft_expr *expr, struct nft_regs *regs, void nft_objref_map_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt); -void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track); +void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track, bool mask); void nft_meta_combo_init(struct nft_expr *expr, struct nft_exprs_track *track); #endif /* _NET_NF_TABLES_CORE_H */ diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index ceae7a9bb989..3c5c3f3af333 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8934,7 +8934,7 @@ static int nft_expr_track(struct nft_exprs_track *expr_track, switch (expr_track->expr[0].type) { case NFT_EXPR_PAYLOAD: if (expr_track->expr[1].type == NFT_EXPR_CMP) { - nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track); + nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track, false); expr_track->saved_expr[0] = (struct nft_expr *)&expr_track->_expr; expr_track->num_exprs = 1; return 1; @@ -8948,6 +8948,24 @@ static int nft_expr_track(struct nft_exprs_track *expr_track, return 1; } break; + case NFT_EXPR_BITWISE: + expr_track->num_exprs++; + return 0; + default: + return 1; + } + break; + case 2: + switch (expr_track->expr[0].type) { + case NFT_EXPR_PAYLOAD: + if (expr_track->expr[2].type == NFT_EXPR_CMP) { + nft_payload_combo_init((struct nft_expr *)&expr_track->_expr, expr_track, true); + expr_track->saved_expr[0] = (struct nft_expr *)&expr_track->_expr; + expr_track->num_exprs = 1; + pr_info("collapsing\n"); + return 1; + } + break; default: return 1; } diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c index b358c03bdb04..4bea8d36b027 100644 --- a/net/netfilter/nft_bitwise.c +++ b/net/netfilter/nft_bitwise.c @@ -262,6 +262,25 @@ static int nft_bitwise_dump(struct sk_buff *skb, static struct nft_data zero; +static int nft_bitwise_track(struct nft_expr_track *track, + const struct nft_expr *expr) +{ + const struct nft_bitwise *priv = nft_expr_priv(expr); + + if (priv->op != NFT_BITWISE_BOOL) + return 1; + + if (memcmp(&priv->xor, &zero, sizeof(priv->xor))) + return 1; + + track->type = NFT_EXPR_BITWISE; + track->bitwise.sreg = priv->sreg; + track->bitwise.dreg = priv->dreg; + memcpy(&track->bitwise.mask, &priv->mask, sizeof(priv->mask)); + + return 0; +} + static int nft_bitwise_offload(struct nft_offload_ctx *ctx, struct nft_flow_rule *flow, const struct nft_expr *expr) @@ -287,6 +306,7 @@ static const struct nft_expr_ops nft_bitwise_ops = { .eval = nft_bitwise_eval, .init = nft_bitwise_init, .dump = nft_bitwise_dump, + .track = nft_bitwise_track, .offload = nft_bitwise_offload, }; diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 5c99eca32e84..b1910287a0a0 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -1023,16 +1023,21 @@ void nft_cmp16_mask(struct nft_data *data, unsigned int len) data->data[i] = 0; } -void nft_payload_combo_init(struct nft_expr *expr, struct nft_exprs_track *track) +void nft_payload_combo_init(struct nft_expr *expr, + struct nft_exprs_track *track, bool bitmask) { struct nft_payload_combo *priv = nft_expr_priv(expr); + int index = bitmask ? 2 : 1; expr->ops = &nft_payload_combo_ops; priv->offset = track->expr[0].payload.offset; priv->len = track->expr[0].payload.len; - memcpy(&priv->data, &track->expr[1].cmp.data, sizeof(priv->data)); - priv->inv = track->expr[1].cmp.inv; - nft_cmp16_mask(&priv->mask, track->expr[1].cmp.len); + memcpy(&priv->data, &track->expr[index].cmp.data, sizeof(priv->data)); + priv->inv = track->expr[index].cmp.inv; + nft_cmp16_mask(&priv->mask, track->expr[index].cmp.len); + + if (bitmask) + priv->mask.data[0] &= track->expr[1].bitwise.mask.data[0]; } const struct nft_expr_ops nft_payload_combo_ops = { From patchwork Thu May 25 15:40:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 1786203 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QRshP51pzz20QL for ; Fri, 26 May 2023 01:40:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241770AbjEYPkf (ORCPT ); Thu, 25 May 2023 11:40:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37318 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241776AbjEYPkc (ORCPT ); Thu, 25 May 2023 11:40:32 -0400 Received: from mail.netfilter.org (mail.netfilter.org [217.70.188.207]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 74EF9198 for ; Thu, 25 May 2023 08:40:31 -0700 (PDT) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Subject: [PATCH nf-next,v1 6/6] netfilter: nf_tables: skip comment match when building blob Date: Thu, 25 May 2023 17:40:24 +0200 Message-Id: <20230525154024.222338-7-pablo@netfilter.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230525154024.222338-1-pablo@netfilter.org> References: <20230525154024.222338-1-pablo@netfilter.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Use tracking infrastructure to skip the comment match when building the ruleset blob, this restores the comment match suppression done in c828414ac935 ("netfilter: nft_compat: suppress comment match"). If .track returns -1, then skip the expression. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 3 ++- net/netfilter/nft_compat.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 3c5c3f3af333..3fc1a7d30f8b 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8917,7 +8917,8 @@ static int nft_expr_track(struct nft_exprs_track *expr_track, if (ret > 0) { expr_track->num_exprs++; return 1; - } + } else if (ret < 0) + return 0; switch (expr_track->num_exprs) { case 0: diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index e178b479dfaf..89a5e4d2b03d 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -734,6 +734,17 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = { static struct nft_expr_type nft_match_type; +static int nft_match_track(struct nft_expr_track *track, + const struct nft_expr *expr) +{ + const struct xt_match *match = expr->ops->data; + + if (!strcmp(match->name, "comment")) + return -1; + + return 1; +} + static const struct nft_expr_ops * nft_match_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) @@ -776,6 +787,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, ops->dump = nft_match_dump; ops->validate = nft_match_validate; ops->data = match; + ops->track = nft_match_track; matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize)); if (matchsize > NFT_MATCH_LARGE_THRESH) {