* [PATCH nf-next,v2 0/7] nf_tables combo match
@ 2023-06-06 16:35 Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 1/7] netfilter: nf_tables: remove expression reduce infrastructure Pablo Neira Ayuso
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
Hi,
This patchset provides the combo match for payload and the iifname and
oifname meta selector. The idea is to track and coalesce expressions in
an internal special combo expression. This batch adds support to
coalesce the following expressions:
payload + cmp
payload + bitwise + cmp
meta {iifname,oifname} + cmp
The coalesce happens when the ruleset blob is built, the expression
tracking is done at rule level, ie. by iterating over the expressions
that represent the rule. The expression tracking happens twice, once to
calculate the ruleset blob (because the combo expression alters the
expected rule data size) and then to build the ruleset blob. If the
register tracking detects an access to uninitialized register,
including recycling a register that has been combo'ed, then combo logic
is disabled and the registers are zeroed at the basechain.
Main changes in v2:
Patch #1 no changes
Patch #2 do not remove 32-bit cmp fast, this helps for usual matching
on 32-bits selectors.
Patch #3 adds register tracking infrastructure for the combo match.
This is new in this series and it is required to detect access
of registers that has been combo'ed.
Patch #4 adds tracking infrastructure and the payload combo expression.
This supports for payload whose size is <= 4 bytes and 16 bytes.
This patch uses the register tracking infrastructure introduced
in #3 to build the chain blob. There is a new skip_track flag
that is set on in case that an expression performs an access
to combo'ed register.
Patch #5 adds meta combo expression for iifname and oifname as noinline
(per Florian). This v2 also fixes incorrect byteoder in the
bitmask calculation that is used to match the interface.
Patch #6 adds bitwise support to the payload combo expression, this
requires no changes to the datapath.
Patch #7 allows to skip comment match when building the ruleset blob.
I'm exploring a patch to perform conditional register initialization
as Florian suggested using this new register tracking infrastructure.
The idea is to add a new flag in case that it detects what it might be
an uninitialized access to register, then add a new internal built-in
expression to the blob to memset register in the basechains, the
mechanism will be defensive, one access to uninitialized register
enables the zeroing in every basechain.
A few numbers in Mb/sec (w/retpoline) with N mismatching rules, then N+1
finds a matching rule bump counter and accept, with iptables-nft.
baseline after
IPv4 address match: 458 673
IPv6 address match: 227 673
interface match: 130[*] 424
ct state match: 275 200[**]
[*] by using IFNAMSIZ in iptables-nft, this should achieve similar
numbers as IPv6 address, ie. 227.
[**] fast bitwise is removed in this batch, one possibility would be
add a generic combo: bitwise + cmp that operates on registers,
but iptables-nft does not use 'ct state', and upcoming nftables
version allows to combine 'ct state' with vmap and counters.
Numbers I collected in v1 were not correct for this one.
Pablo Neira Ayuso (7):
netfilter: nf_tables: remove expression reduce infrastructure
netfilter: nf_tables: remove fast bitwise and fast cmp16
netfilter: nf_tables: track register store and load operations
netfilter: nf_tables: add payload + cmp combo match
netfilter: nf_tables: add meta + cmp combo match
netfilter: nf_tables: add payload + bitwise + cmp combo match
netfilter: nf_tables: skip comment match when building blob
include/net/netfilter/nf_tables.h | 141 +++++++++----
include/net/netfilter/nf_tables_core.h | 25 +--
include/net/netfilter/nft_fib.h | 6 +-
include/net/netfilter/nft_meta.h | 9 +-
net/bridge/netfilter/nft_meta_bridge.c | 22 +-
net/bridge/netfilter/nft_reject_bridge.c | 2 +-
net/ipv4/netfilter/nft_dup_ipv4.c | 15 +-
net/ipv4/netfilter/nft_fib_ipv4.c | 4 +-
net/ipv4/netfilter/nft_reject_ipv4.c | 2 +-
net/ipv6/netfilter/nft_dup_ipv6.c | 15 +-
net/ipv6/netfilter/nft_fib_ipv6.c | 4 +-
net/ipv6/netfilter/nft_reject_ipv6.c | 2 +-
net/netfilter/nf_tables_api.c | 226 ++++++++++++++-------
net/netfilter/nf_tables_core.c | 112 ++++++++---
net/netfilter/nft_bitwise.c | 246 +++--------------------
net/netfilter/nft_byteorder.c | 14 +-
net/netfilter/nft_cmp.c | 138 ++++---------
net/netfilter/nft_compat.c | 14 +-
net/netfilter/nft_connlimit.c | 2 +-
net/netfilter/nft_counter.c | 2 +-
net/netfilter/nft_ct.c | 73 +++----
net/netfilter/nft_dup_netdev.c | 13 +-
net/netfilter/nft_dynset.c | 15 +-
net/netfilter/nft_exthdr.c | 47 ++---
net/netfilter/nft_fib.c | 54 ++---
net/netfilter/nft_fib_inet.c | 2 +-
net/netfilter/nft_fib_netdev.c | 2 +-
net/netfilter/nft_flow_offload.c | 2 +-
net/netfilter/nft_fwd_netdev.c | 38 +++-
net/netfilter/nft_hash.c | 39 ++--
net/netfilter/nft_immediate.c | 24 +--
net/netfilter/nft_inner.c | 10 +
net/netfilter/nft_last.c | 2 +-
net/netfilter/nft_limit.c | 4 +-
net/netfilter/nft_log.c | 2 +-
net/netfilter/nft_lookup.c | 26 +--
net/netfilter/nft_masq.c | 20 +-
net/netfilter/nft_meta.c | 80 ++++----
net/netfilter/nft_nat.c | 34 +++-
net/netfilter/nft_numgen.c | 36 ++--
net/netfilter/nft_objref.c | 15 +-
net/netfilter/nft_osf.c | 37 ++--
net/netfilter/nft_payload.c | 116 +++++++----
net/netfilter/nft_queue.c | 16 +-
net/netfilter/nft_quota.c | 2 +-
net/netfilter/nft_range.c | 13 +-
net/netfilter/nft_redir.c | 20 +-
net/netfilter/nft_reject_inet.c | 2 +-
net/netfilter/nft_reject_netdev.c | 2 +-
net/netfilter/nft_rt.c | 15 +-
net/netfilter/nft_socket.c | 26 +--
net/netfilter/nft_synproxy.c | 2 +-
net/netfilter/nft_tproxy.c | 28 ++-
net/netfilter/nft_tunnel.c | 26 +--
net/netfilter/nft_xfrm.c | 39 ++--
55 files changed, 997 insertions(+), 886 deletions(-)
--
2.22.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 1/7] netfilter: nf_tables: remove expression reduce infrastructure
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 2/7] netfilter: nf_tables: remove fast bitwise and fast cmp16 Pablo Neira Ayuso
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
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 <pablo@netfilter.org>
---
v2: no changes.
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 <fw@strlen.de>");
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 = {
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 2/7] netfilter: nf_tables: remove fast bitwise and fast cmp16
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 1/7] netfilter: nf_tables: remove expression reduce infrastructure Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 3/7] netfilter: nf_tables: track register store and load operations Pablo Neira Ayuso
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
This patch removes 10fdd6d80e4c ("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.
The fast cmp for 32-bits remains in place. As an alternative for the
fast bitwise, it should be possible to implement a generic combo that
reads from the register: sreg + bitwise + cmp.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: leave 32-bit fast cmp in place.
include/net/netfilter/nf_tables_core.h | 18 ----
net/netfilter/nf_tables_core.c | 28 ------
net/netfilter/nft_bitwise.c | 116 +------------------------
net/netfilter/nft_cmp.c | 97 ---------------------
4 files changed, 1 insertion(+), 258 deletions(-)
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index 780a5f6ad4a6..56b60dbe96d1 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -29,13 +29,6 @@ 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;
@@ -44,14 +37,6 @@ struct nft_cmp_fast_expr {
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;
@@ -59,7 +44,6 @@ struct nft_immediate_expr {
};
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;
@@ -80,8 +64,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..0590f377a0fd 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -74,16 +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)
{
@@ -94,20 +84,6 @@ static void nft_cmp_fast_eval(const struct nft_expr *expr,
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,
@@ -279,10 +255,6 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
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))
expr_call_ops_eval(expr, ®s, pkt);
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..7f3f87446683 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -284,99 +284,6 @@ const struct nft_expr_ops nft_cmp_fast_ops = {
.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[])
{
@@ -416,10 +323,6 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
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;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 3/7] netfilter: nf_tables: track register store and load operations
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 1/7] netfilter: nf_tables: remove expression reduce infrastructure Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 2/7] netfilter: nf_tables: remove fast bitwise and fast cmp16 Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 4/7] netfilter: nf_tables: add payload + cmp combo match Pablo Neira Ayuso
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
Add basic register tracking for the combo infrastructure.
Track registers to detect an expression that recycles data from an
expression that has been merged into a combo expression. Skip track
and merge into combo logic in such case. Otherwise userspace might
trigger a combo expression then try to access a register that is
uninitialized.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: new in this series.
include/net/netfilter/nf_tables.h | 35 +++++++++++++++++++++++
include/net/netfilter/nft_fib.h | 4 +++
include/net/netfilter/nft_meta.h | 8 ++++++
net/bridge/netfilter/nft_meta_bridge.c | 2 ++
net/bridge/netfilter/nft_reject_bridge.c | 1 +
net/ipv4/netfilter/nft_dup_ipv4.c | 14 +++++++++
net/ipv4/netfilter/nft_fib_ipv4.c | 2 ++
net/ipv4/netfilter/nft_reject_ipv4.c | 1 +
net/ipv6/netfilter/nft_dup_ipv6.c | 14 +++++++++
net/ipv6/netfilter/nft_fib_ipv6.c | 2 ++
net/ipv6/netfilter/nft_reject_ipv6.c | 1 +
net/netfilter/nft_bitwise.c | 13 +++++++++
net/netfilter/nft_byteorder.c | 13 +++++++++
net/netfilter/nft_cmp.c | 24 ++++++++++++++++
net/netfilter/nft_compat.c | 1 +
net/netfilter/nft_connlimit.c | 1 +
net/netfilter/nft_counter.c | 1 +
net/netfilter/nft_ct.c | 27 ++++++++++++++++++
net/netfilter/nft_dup_netdev.c | 12 ++++++++
net/netfilter/nft_dynset.c | 14 +++++++++
net/netfilter/nft_exthdr.c | 29 +++++++++++++++++++
net/netfilter/nft_fib.c | 12 ++++++++
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 | 36 ++++++++++++++++++++++++
net/netfilter/nft_hash.c | 25 ++++++++++++++++
net/netfilter/nft_immediate.c | 12 ++++++++
net/netfilter/nft_inner.c | 10 +++++++
net/netfilter/nft_last.c | 1 +
net/netfilter/nft_limit.c | 2 ++
net/netfilter/nft_log.c | 1 +
net/netfilter/nft_lookup.c | 14 +++++++++
net/netfilter/nft_masq.c | 17 +++++++++++
net/netfilter/nft_meta.c | 26 +++++++++++++++++
net/netfilter/nft_nat.c | 32 +++++++++++++++++++++
net/netfilter/nft_numgen.c | 24 ++++++++++++++++
net/netfilter/nft_objref.c | 13 +++++++++
net/netfilter/nft_osf.c | 12 ++++++++
net/netfilter/nft_payload.c | 26 +++++++++++++++++
net/netfilter/nft_queue.c | 14 +++++++++
net/netfilter/nft_quota.c | 1 +
net/netfilter/nft_range.c | 12 ++++++++
net/netfilter/nft_redir.c | 17 +++++++++++
net/netfilter/nft_reject_inet.c | 1 +
net/netfilter/nft_reject_netdev.c | 1 +
net/netfilter/nft_rt.c | 14 +++++++++
net/netfilter/nft_socket.c | 12 ++++++++
net/netfilter/nft_synproxy.c | 1 +
net/netfilter/nft_tproxy.c | 27 ++++++++++++++++++
net/netfilter/nft_tunnel.c | 12 ++++++++
net/netfilter/nft_xfrm.c | 12 ++++++++
52 files changed, 609 insertions(+)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 588b1904e411..81adf294da25 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -123,6 +123,38 @@ struct nft_regs {
};
};
+struct nft_expr_track_ctx {
+ u32 reg_bitmap;
+ bool cancel;
+};
+
+static inline u32 nft_expr_track_bitmask(u8 reg, u8 len)
+{
+ return ((1 << DIV_ROUND_UP(len, 4)) - 1) << reg;
+}
+
+static inline void nft_expr_track_dreg(struct nft_expr_track_ctx *ctx, u8 dreg, u8 len)
+{
+ ctx->reg_bitmap |= nft_expr_track_bitmask(dreg, len);
+}
+
+static inline void nft_expr_track_sreg(struct nft_expr_track_ctx *ctx, u8 sreg, u8 len)
+{
+ if (!(ctx->reg_bitmap & nft_expr_track_bitmask(sreg, len)))
+ ctx->cancel = true;
+}
+
+static inline void nft_expr_track_reset_dreg(struct nft_expr_track_ctx *ctx, u8 dreg, u8 len)
+{
+ ctx->reg_bitmap &= ~nft_expr_track_bitmask(dreg, len);
+}
+
+#define __NFT_TRACK_GENERIC 1UL
+#define NFT_TRACK_GENERIC (void *)__NFT_TRACK_GENERIC
+
+struct nft_expr_track {
+};
+
/* 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 +966,9 @@ 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_ctx *ctx,
+ 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/nft_fib.h b/include/net/netfilter/nft_fib.h
index 2e434ba41b97..7045e7106611 100644
--- a/include/net/netfilter/nft_fib.h
+++ b/include/net/netfilter/nft_fib.h
@@ -7,6 +7,7 @@
struct nft_fib {
u8 dreg;
u8 result;
+ u8 len;
u32 flags;
};
@@ -38,4 +39,7 @@ 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);
+int nft_fib_track(struct nft_expr_track_ctx *ctx, struct nft_expr_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 690f6245026c..e03e008cbd51 100644
--- a/include/net/netfilter/nft_meta.h
+++ b/include/net/netfilter/nft_meta.h
@@ -44,6 +44,14 @@ int nft_meta_set_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data);
+int nft_meta_get_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr);
+
+int nft_meta_set_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_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 93e8a8dadd80..3964f0a0f328 100644
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -102,6 +102,7 @@ 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,
+ .track = nft_meta_get_track,
};
static void nft_meta_bridge_set_eval(const struct nft_expr *expr,
@@ -173,6 +174,7 @@ 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,
+ .track = nft_meta_set_track,
.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 fbf858ddec35..eb94369d24bf 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -184,6 +184,7 @@ static const struct nft_expr_ops nft_reject_bridge_ops = {
.eval = nft_reject_bridge_eval,
.init = nft_reject_init,
.dump = nft_reject_dump,
+ .track = NFT_TRACK_GENERIC,
.validate = nft_reject_bridge_validate,
};
diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c b/net/ipv4/netfilter/nft_dup_ipv4.c
index cae5b38335b3..b7b0cbe3115b 100644
--- a/net/ipv4/netfilter/nft_dup_ipv4.c
+++ b/net/ipv4/netfilter/nft_dup_ipv4.c
@@ -69,6 +69,19 @@ static int nft_dup_ipv4_dump(struct sk_buff *skb,
return -1;
}
+static int nft_dup_ipv4_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_dup_ipv4 *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg_addr, sizeof(struct in_addr));
+ if (priv->sreg_dev)
+ nft_expr_track_dreg(ctx, priv->sreg_dev, sizeof(int));
+
+ return 1;
+}
+
static struct nft_expr_type nft_dup_ipv4_type;
static const struct nft_expr_ops nft_dup_ipv4_ops = {
.type = &nft_dup_ipv4_type,
@@ -76,6 +89,7 @@ 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,
+ .track = nft_dup_ipv4_track,
};
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 55c4b73265ed..258a3ffd3294 100644
--- a/net/ipv4/netfilter/nft_fib_ipv4.c
+++ b/net/ipv4/netfilter/nft_fib_ipv4.c
@@ -158,6 +158,7 @@ static const struct nft_expr_ops nft_fib4_type_ops = {
.eval = nft_fib4_eval_type,
.init = nft_fib_init,
.dump = nft_fib_dump,
+ .track = nft_fib_track,
.validate = nft_fib_validate,
};
@@ -167,6 +168,7 @@ static const struct nft_expr_ops nft_fib4_ops = {
.eval = nft_fib4_eval,
.init = nft_fib_init,
.dump = nft_fib_dump,
+ .track = nft_fib_track,
.validate = nft_fib_validate,
};
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
index 55fc23a8f7a7..56e18609df8c 100644
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -44,6 +44,7 @@ static const struct nft_expr_ops nft_reject_ipv4_ops = {
.eval = nft_reject_ipv4_eval,
.init = nft_reject_init,
.dump = nft_reject_dump,
+ .track = NFT_TRACK_GENERIC,
.validate = nft_reject_validate,
};
diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c b/net/ipv6/netfilter/nft_dup_ipv6.c
index e859beb29bb1..0527a6f064b7 100644
--- a/net/ipv6/netfilter/nft_dup_ipv6.c
+++ b/net/ipv6/netfilter/nft_dup_ipv6.c
@@ -67,6 +67,19 @@ static int nft_dup_ipv6_dump(struct sk_buff *skb,
return -1;
}
+static int nft_dup_ipv6_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_dup_ipv6 *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg_addr, sizeof(struct in6_addr));
+ if (priv->sreg_dev)
+ nft_expr_track_dreg(ctx, priv->sreg_dev, sizeof(int));
+
+ return 1;
+}
+
static struct nft_expr_type nft_dup_ipv6_type;
static const struct nft_expr_ops nft_dup_ipv6_ops = {
.type = &nft_dup_ipv6_type,
@@ -74,6 +87,7 @@ 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,
+ .track = nft_dup_ipv6_track,
};
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 6ae17f530994..bf46d169cd15 100644
--- a/net/ipv6/netfilter/nft_fib_ipv6.c
+++ b/net/ipv6/netfilter/nft_fib_ipv6.c
@@ -219,6 +219,7 @@ static const struct nft_expr_ops nft_fib6_type_ops = {
.eval = nft_fib6_eval_type,
.init = nft_fib_init,
.dump = nft_fib_dump,
+ .track = nft_fib_track,
.validate = nft_fib_validate,
};
@@ -228,6 +229,7 @@ static const struct nft_expr_ops nft_fib6_ops = {
.eval = nft_fib6_eval,
.init = nft_fib_init,
.dump = nft_fib_dump,
+ .track = nft_fib_track,
.validate = nft_fib_validate,
};
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c
index ed69c768797e..0cb315f57c74 100644
--- a/net/ipv6/netfilter/nft_reject_ipv6.c
+++ b/net/ipv6/netfilter/nft_reject_ipv6.c
@@ -45,6 +45,7 @@ static const struct nft_expr_ops nft_reject_ipv6_ops = {
.eval = nft_reject_ipv6_eval,
.init = nft_reject_init,
.dump = nft_reject_dump,
+ .track = NFT_TRACK_GENERIC,
.validate = nft_reject_validate,
};
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index b358c03bdb04..0ab2d281f245 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -262,6 +262,18 @@ static int nft_bitwise_dump(struct sk_buff *skb,
static struct nft_data zero;
+static int nft_bitwise_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_bitwise *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
struct nft_flow_rule *flow,
const struct nft_expr *expr)
@@ -287,6 +299,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_byteorder.c b/net/netfilter/nft_byteorder.c
index a42d03741bb3..3d7ed9c8b611 100644
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -169,12 +169,25 @@ static int nft_byteorder_dump(struct sk_buff *skb,
return -1;
}
+static int nft_byteorder_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_byteorder *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
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,
+ .track = nft_byteorder_track,
};
struct nft_expr_type nft_byteorder_type __read_mostly = {
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 7f3f87446683..dc026cd4458d 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -184,12 +184,24 @@ 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_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_cmp_expr *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+
+ return 1;
+}
+
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,
};
@@ -275,12 +287,24 @@ static int nft_cmp_fast_dump(struct sk_buff *skb,
return -1;
}
+static int nft_cmp_fast_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, sizeof(u32));
+
+ 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,
+ .track = nft_cmp_fast_track,
.offload = nft_cmp_fast_offload,
};
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index e178b479dfaf..af88078caf99 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -864,6 +864,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
ops->destroy = nft_target_destroy;
ops->dump = nft_target_dump;
ops->validate = nft_target_validate;
+ ops->track = NFT_TRACK_GENERIC;
ops->data = target;
if (family == NFPROTO_BRIDGE)
diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c
index 53ef6854f8e6..029414111cdb 100644
--- a/net/netfilter/nft_connlimit.c
+++ b/net/netfilter/nft_connlimit.c
@@ -257,6 +257,7 @@ static const struct nft_expr_ops nft_connlimit_ops = {
.clone = nft_connlimit_clone,
.destroy_clone = nft_connlimit_destroy_clone,
.dump = nft_connlimit_dump,
+ .track = NFT_TRACK_GENERIC,
.gc = nft_connlimit_gc,
};
diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c
index 446406631c9a..04fdc9378087 100644
--- a/net/netfilter/nft_counter.c
+++ b/net/netfilter/nft_counter.c
@@ -293,6 +293,7 @@ static const struct nft_expr_ops nft_counter_ops = {
.destroy = nft_counter_destroy,
.destroy_clone = nft_counter_destroy,
.dump = nft_counter_dump,
+ .track = NFT_TRACK_GENERIC,
.clone = nft_counter_clone,
.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 fe25ce6fa0bd..0cd628cc2282 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -697,6 +697,28 @@ static int nft_ct_set_dump(struct sk_buff *skb,
return -1;
}
+static int nft_ct_get_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_ct *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
+static int nft_ct_set_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_ct *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+
+ return 1;
+}
+
static struct nft_expr_type nft_ct_type;
static const struct nft_expr_ops nft_ct_get_ops = {
.type = &nft_ct_type,
@@ -705,6 +727,7 @@ 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,
+ .track = nft_ct_get_track,
};
#ifdef CONFIG_RETPOLINE
@@ -715,6 +738,7 @@ 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,
+ .track = nft_ct_get_track,
};
#endif
@@ -725,6 +749,7 @@ 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,
+ .track = nft_ct_set_track,
};
#ifdef CONFIG_NF_CONNTRACK_ZONES
@@ -735,6 +760,7 @@ 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,
+ .track = nft_ct_set_track,
};
#endif
@@ -804,6 +830,7 @@ static const struct nft_expr_ops nft_notrack_ops = {
.type = &nft_notrack_type,
.size = NFT_EXPR_SIZE(0),
.eval = nft_notrack_eval,
+ .track = NFT_TRACK_GENERIC,
};
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 2007700bef8e..e2f1ac2a3bb7 100644
--- a/net/netfilter/nft_dup_netdev.c
+++ b/net/netfilter/nft_dup_netdev.c
@@ -58,6 +58,17 @@ static int nft_dup_netdev_dump(struct sk_buff *skb,
return -1;
}
+static int nft_dup_netdev_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_dup_netdev *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg_dev, IFNAMSIZ);
+
+ return 1;
+}
+
static int nft_dup_netdev_offload(struct nft_offload_ctx *ctx,
struct nft_flow_rule *flow,
const struct nft_expr *expr)
@@ -80,6 +91,7 @@ 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,
+ .track = nft_dup_netdev_track,
.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 c3bd57be2ee8..4b2ff0b25dfe 100644
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -405,6 +405,19 @@ static int nft_dynset_dump(struct sk_buff *skb,
return -1;
}
+static int nft_dynset_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_dynset *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg_key, priv->set->klen);
+ if (priv->set->flags & NFT_SET_MAP)
+ nft_expr_track_sreg(ctx, priv->sreg_data, priv->set->dlen);
+
+ return 1;
+}
+
static const struct nft_expr_ops nft_dynset_ops = {
.type = &nft_dynset_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_dynset)),
@@ -414,6 +427,7 @@ static const struct nft_expr_ops nft_dynset_ops = {
.activate = nft_dynset_activate,
.deactivate = nft_dynset_deactivate,
.dump = nft_dynset_dump,
+ .track = nft_dynset_track,
};
struct nft_expr_type nft_dynset_type __read_mostly = {
diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c
index 41e8ae77b823..83f783e8b7b7 100644
--- a/net/netfilter/nft_exthdr.c
+++ b/net/netfilter/nft_exthdr.c
@@ -698,12 +698,35 @@ static int nft_exthdr_dump_strip(struct sk_buff *skb,
return nft_exthdr_dump_common(skb, priv);
}
+static int nft_exthdr_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_exthdr *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
+static int nft_exthdr_set_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_exthdr *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+
+ return 1;
+}
+
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,
+ .track = nft_exthdr_track,
};
static const struct nft_expr_ops nft_exthdr_ipv4_ops = {
@@ -712,6 +735,7 @@ static const struct nft_expr_ops nft_exthdr_ipv4_ops = {
.eval = nft_exthdr_ipv4_eval,
.init = nft_exthdr_ipv4_init,
.dump = nft_exthdr_dump,
+ .track = nft_exthdr_track,
};
static const struct nft_expr_ops nft_exthdr_tcp_ops = {
@@ -720,6 +744,7 @@ static const struct nft_expr_ops nft_exthdr_tcp_ops = {
.eval = nft_exthdr_tcp_eval,
.init = nft_exthdr_init,
.dump = nft_exthdr_dump,
+ .track = nft_exthdr_track,
};
static const struct nft_expr_ops nft_exthdr_tcp_set_ops = {
@@ -728,6 +753,7 @@ 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,
+ .track = nft_exthdr_set_track,
};
static const struct nft_expr_ops nft_exthdr_tcp_strip_ops = {
@@ -736,6 +762,7 @@ 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,
+ .track = NFT_TRACK_GENERIC,
};
static const struct nft_expr_ops nft_exthdr_sctp_ops = {
@@ -744,6 +771,7 @@ static const struct nft_expr_ops nft_exthdr_sctp_ops = {
.eval = nft_exthdr_sctp_eval,
.init = nft_exthdr_init,
.dump = nft_exthdr_dump,
+ .track = nft_exthdr_track,
};
static const struct nft_expr_ops nft_exthdr_dccp_ops = {
@@ -752,6 +780,7 @@ static const struct nft_expr_ops nft_exthdr_dccp_ops = {
.eval = nft_exthdr_dccp_eval,
.init = nft_exthdr_dccp_init,
.dump = nft_exthdr_dump,
+ .track = nft_exthdr_track,
};
static const struct nft_expr_ops *
diff --git a/net/netfilter/nft_fib.c b/net/netfilter/nft_fib.c
index e7cb42c9c175..12eff4ba05bd 100644
--- a/net/netfilter/nft_fib.c
+++ b/net/netfilter/nft_fib.c
@@ -108,6 +108,7 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
default:
return -EINVAL;
}
+ priv->len = len;
err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
@@ -135,6 +136,17 @@ int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr, bool reset)
}
EXPORT_SYMBOL_GPL(nft_fib_dump);
+int nft_fib_track(struct nft_expr_track_ctx *ctx, struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(nft_fib_track);
+
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
const struct net_device *dev)
{
diff --git a/net/netfilter/nft_fib_inet.c b/net/netfilter/nft_fib_inet.c
index a88d44e163d1..9dc81538815f 100644
--- a/net/netfilter/nft_fib_inet.c
+++ b/net/netfilter/nft_fib_inet.c
@@ -48,6 +48,7 @@ static const struct nft_expr_ops nft_fib_inet_ops = {
.eval = nft_fib_inet_eval,
.init = nft_fib_init,
.dump = nft_fib_dump,
+ .track = nft_fib_track,
.validate = nft_fib_validate,
};
diff --git a/net/netfilter/nft_fib_netdev.c b/net/netfilter/nft_fib_netdev.c
index 3f3478abd845..69448f630fdb 100644
--- a/net/netfilter/nft_fib_netdev.c
+++ b/net/netfilter/nft_fib_netdev.c
@@ -57,6 +57,7 @@ static const struct nft_expr_ops nft_fib_netdev_ops = {
.eval = nft_fib_netdev_eval,
.init = nft_fib_init,
.dump = nft_fib_dump,
+ .track = nft_fib_track,
.validate = nft_fib_validate,
};
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index 59c468261134..84fbe808644a 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -462,6 +462,7 @@ 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,
+ .track = NFT_TRACK_GENERIC,
};
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 a534d060ce1b..e535b27d05ae 100644
--- a/net/netfilter/nft_fwd_netdev.c
+++ b/net/netfilter/nft_fwd_netdev.c
@@ -70,6 +70,17 @@ static int nft_fwd_netdev_dump(struct sk_buff *skb,
return -1;
}
+static int nft_fwd_netdev_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_fwd_netdev *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg_dev, IFNAMSIZ);
+
+ return 1;
+}
+
static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx,
struct nft_flow_rule *flow,
const struct nft_expr *expr)
@@ -203,6 +214,29 @@ static int nft_fwd_neigh_dump(struct sk_buff *skb,
return -1;
}
+static int nft_fwd_neigh_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_fwd_neigh *priv = nft_expr_priv(expr);
+ u8 addr_len;
+
+ switch (priv->nfproto) {
+ case NFPROTO_IPV4:
+ addr_len = sizeof(struct in_addr);
+ break;
+ case NFPROTO_IPV6:
+ addr_len = sizeof(struct in6_addr);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ nft_expr_track_sreg(ctx, priv->sreg_dev, IFNAMSIZ);
+ nft_expr_track_sreg(ctx, priv->sreg_addr, addr_len);
+
+ return 1;
+}
+
static int nft_fwd_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
@@ -219,6 +253,7 @@ 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,
+ .track = nft_fwd_neigh_track,
};
static const struct nft_expr_ops nft_fwd_netdev_ops = {
@@ -228,6 +263,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = {
.init = nft_fwd_netdev_init,
.dump = nft_fwd_netdev_dump,
.validate = nft_fwd_validate,
+ .track = nft_fwd_netdev_track,
.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 4fc99c80b28e..f64394e0327e 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -165,6 +165,18 @@ static int nft_jhash_dump(struct sk_buff *skb,
return -1;
}
+static int nft_jhash_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_jhash *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+ nft_expr_track_dreg(ctx, priv->dreg, sizeof(u32));
+
+ return 1;
+}
+
static int nft_symhash_dump(struct sk_buff *skb,
const struct nft_expr *expr, bool reset)
{
@@ -185,6 +197,17 @@ static int nft_symhash_dump(struct sk_buff *skb,
return -1;
}
+static int nft_symhash_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_symhash *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, sizeof(u32));
+
+ return 1;
+}
+
static struct nft_expr_type nft_hash_type;
static const struct nft_expr_ops nft_jhash_ops = {
.type = &nft_hash_type,
@@ -192,6 +215,7 @@ static const struct nft_expr_ops nft_jhash_ops = {
.eval = nft_jhash_eval,
.init = nft_jhash_init,
.dump = nft_jhash_dump,
+ .track = nft_jhash_track,
};
static const struct nft_expr_ops nft_symhash_ops = {
@@ -200,6 +224,7 @@ static const struct nft_expr_ops nft_symhash_ops = {
.eval = nft_symhash_eval,
.init = nft_symhash_init,
.dump = nft_symhash_dump,
+ .track = nft_symhash_track,
};
static const struct nft_expr_ops *
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index 0d744c3f73b3..4b977538ecdd 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -162,6 +162,17 @@ static int nft_immediate_dump(struct sk_buff *skb,
return -1;
}
+static int nft_immediate_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->dlen);
+
+ return 1;
+}
+
static int nft_immediate_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **d)
@@ -249,6 +260,7 @@ static const struct nft_expr_ops nft_imm_ops = {
.deactivate = nft_immediate_deactivate,
.destroy = nft_immediate_destroy,
.dump = nft_immediate_dump,
+ .track = nft_immediate_track,
.validate = nft_immediate_validate,
.offload = nft_immediate_offload,
.offload_action = nft_immediate_offload_action,
diff --git a/net/netfilter/nft_inner.c b/net/netfilter/nft_inner.c
index 28e2873ba24e..470ddf59b1ea 100644
--- a/net/netfilter/nft_inner.c
+++ b/net/netfilter/nft_inner.c
@@ -368,12 +368,22 @@ static int nft_inner_dump(struct sk_buff *skb,
return -1;
}
+static int nft_inner_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ struct nft_inner *priv = nft_expr_priv(expr);
+
+ return priv->expr.ops->track(ctx, track, (struct nft_expr *)&priv->expr);
+}
+
static const struct nft_expr_ops nft_inner_ops = {
.type = &nft_inner_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_inner)),
.eval = nft_inner_eval,
.init = nft_inner_init,
.dump = nft_inner_dump,
+ .track = nft_inner_track,
};
struct nft_expr_type nft_inner_type __read_mostly = {
diff --git a/net/netfilter/nft_last.c b/net/netfilter/nft_last.c
index 5d44d45ca4ef..ac6facafff94 100644
--- a/net/netfilter/nft_last.c
+++ b/net/netfilter/nft_last.c
@@ -125,6 +125,7 @@ static const struct nft_expr_ops nft_last_ops = {
.destroy = nft_last_destroy,
.clone = nft_last_clone,
.dump = nft_last_dump,
+ .track = NFT_TRACK_GENERIC,
};
struct nft_expr_type nft_last_type __read_mostly = {
diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c
index 10752da5bd16..074de96c4d13 100644
--- a/net/netfilter/nft_limit.c
+++ b/net/netfilter/nft_limit.c
@@ -228,6 +228,7 @@ 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,
+ .track = NFT_TRACK_GENERIC,
};
static void nft_limit_bytes_eval(const struct nft_expr *expr,
@@ -280,6 +281,7 @@ static const struct nft_expr_ops nft_limit_bytes_ops = {
.eval = nft_limit_bytes_eval,
.init = nft_limit_bytes_init,
.dump = nft_limit_bytes_dump,
+ .track = NFT_TRACK_GENERIC,
.clone = nft_limit_bytes_clone,
.destroy = nft_limit_bytes_destroy,
};
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 84e374411877..c72ce995cb55 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -291,6 +291,7 @@ static const struct nft_expr_ops nft_log_ops = {
.init = nft_log_init,
.destroy = nft_log_destroy,
.dump = nft_log_dump,
+ .track = NFT_TRACK_GENERIC,
};
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 5ba799a7722d..efb45b2ed405 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -206,6 +206,19 @@ static int nft_lookup_dump(struct sk_buff *skb,
return -1;
}
+static int nft_lookup_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_lookup *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->set->klen);
+ if (priv->dreg_set)
+ nft_expr_track_dreg(ctx, priv->dreg, priv->set->dlen);
+
+ return 1;
+}
+
static int nft_lookup_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **d)
@@ -243,6 +256,7 @@ static const struct nft_expr_ops nft_lookup_ops = {
.destroy = nft_lookup_destroy,
.dump = nft_lookup_dump,
.validate = nft_lookup_validate,
+ .track = nft_lookup_track,
};
struct nft_expr_type nft_lookup_type __read_mostly = {
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index b6cd11fd596b..b21e8634d1e0 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -96,6 +96,20 @@ static int nft_masq_dump(struct sk_buff *skb,
return -1;
}
+static int nft_masq_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_masq *priv = nft_expr_priv(expr);
+
+ if (priv->sreg_proto_min) {
+ nft_expr_track_sreg(ctx, priv->sreg_proto_min, sizeof(u16));
+ nft_expr_track_sreg(ctx, priv->sreg_proto_max, sizeof(u16));
+ }
+
+ return 1;
+}
+
static void nft_masq_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
@@ -145,6 +159,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = {
.init = nft_masq_init,
.destroy = nft_masq_ipv4_destroy,
.dump = nft_masq_dump,
+ .track = nft_masq_track,
.validate = nft_masq_validate,
};
@@ -172,6 +187,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = {
.init = nft_masq_init,
.destroy = nft_masq_ipv6_destroy,
.dump = nft_masq_dump,
+ .track = nft_masq_track,
.validate = nft_masq_validate,
};
@@ -213,6 +229,7 @@ static const struct nft_expr_ops nft_masq_inet_ops = {
.init = nft_masq_init,
.destroy = nft_masq_inet_destroy,
.dump = nft_masq_dump,
+ .track = nft_masq_track,
.validate = nft_masq_validate,
};
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 73128d73fc99..db445f8c9f9f 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -744,6 +744,30 @@ static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
return 0;
}
+int nft_meta_get_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_meta *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(nft_meta_get_track);
+
+int nft_meta_set_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_meta *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(nft_meta_set_track);
+
static const struct nft_expr_ops nft_meta_get_ops = {
.type = &nft_meta_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
@@ -761,6 +785,7 @@ 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,
+ .track = nft_meta_set_track,
.validate = nft_meta_set_validate,
};
@@ -845,6 +870,7 @@ static const struct nft_expr_ops nft_meta_inner_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
.init = nft_meta_inner_init,
.dump = nft_meta_get_dump,
+ .track = nft_meta_get_track,
/* direct call to nft_meta_inner_eval(). */
};
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index 296667e25420..e12f4e75f247 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -301,6 +301,36 @@ static int nft_nat_dump(struct sk_buff *skb,
return -1;
}
+static int nft_nat_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_nat *priv = nft_expr_priv(expr);
+ u8 alen;
+
+ if (priv->sreg_addr_min) {
+ switch (priv->family) {
+ case NFPROTO_IPV4:
+ alen = sizeof_field(struct nf_nat_range, min_addr.ip);
+ break;
+ case NFPROTO_IPV6:
+ alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
+ break;
+ default:
+ break;
+ }
+
+ nft_expr_track_sreg(ctx, priv->sreg_addr_min, alen);
+ nft_expr_track_sreg(ctx, priv->sreg_addr_max, alen);
+ }
+ if (priv->sreg_proto_min) {
+ nft_expr_track_sreg(ctx, priv->sreg_proto_min, sizeof(u16));
+ nft_expr_track_sreg(ctx, priv->sreg_proto_max, sizeof(u16));
+ }
+
+ return 1;
+}
+
static void
nft_nat_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
@@ -317,6 +347,7 @@ static const struct nft_expr_ops nft_nat_ops = {
.init = nft_nat_init,
.destroy = nft_nat_destroy,
.dump = nft_nat_dump,
+ .track = nft_nat_track,
.validate = nft_nat_validate,
};
@@ -347,6 +378,7 @@ static const struct nft_expr_ops nft_nat_inet_ops = {
.init = nft_nat_init,
.destroy = nft_nat_destroy,
.dump = nft_nat_dump,
+ .track = nft_nat_track,
.validate = nft_nat_validate,
};
diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c
index c46534347405..0cd44b561492 100644
--- a/net/netfilter/nft_numgen.c
+++ b/net/netfilter/nft_numgen.c
@@ -111,6 +111,17 @@ static int nft_ng_inc_dump(struct sk_buff *skb,
priv->offset);
}
+static int nft_ng_inc_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ struct nft_ng_inc *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, sizeof(u32));
+
+ return 1;
+}
+
static void nft_ng_inc_destroy(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
@@ -168,6 +179,17 @@ static int nft_ng_random_dump(struct sk_buff *skb,
priv->offset);
}
+static int nft_ng_random_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ struct nft_ng_random *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, sizeof(u32));
+
+ return 1;
+}
+
static struct nft_expr_type nft_ng_type;
static const struct nft_expr_ops nft_ng_inc_ops = {
.type = &nft_ng_type,
@@ -176,6 +198,7 @@ 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,
+ .track = nft_ng_inc_track,
};
static const struct nft_expr_ops nft_ng_random_ops = {
@@ -184,6 +207,7 @@ 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,
+ .track = nft_ng_random_track,
};
static const struct nft_expr_ops *
diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c
index 0db12fe25d16..e3c3154cbf6f 100644
--- a/net/netfilter/nft_objref.c
+++ b/net/netfilter/nft_objref.c
@@ -91,6 +91,7 @@ static const struct nft_expr_ops nft_objref_ops = {
.activate = nft_objref_activate,
.deactivate = nft_objref_deactivate,
.dump = nft_objref_dump,
+ .track = NFT_TRACK_GENERIC,
};
struct nft_objref_map {
@@ -170,6 +171,17 @@ static int nft_objref_map_dump(struct sk_buff *skb,
return -1;
}
+static int nft_objref_map_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_objref_map *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->set->klen);
+
+ return 1;
+}
+
static void nft_objref_map_deactivate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
enum nft_trans_phase phase)
@@ -204,6 +216,7 @@ 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,
+ .track = nft_objref_map_track,
};
static const struct nft_expr_ops *
diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c
index 093ec7f96a77..3717b041ed37 100644
--- a/net/netfilter/nft_osf.c
+++ b/net/netfilter/nft_osf.c
@@ -112,6 +112,17 @@ static int nft_osf_dump(struct sk_buff *skb,
return -1;
}
+static int nft_osf_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_osf *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, NFT_OSF_MAXGENRELEN);
+
+ return 1;
+}
+
static int nft_osf_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
@@ -139,6 +150,7 @@ static const struct nft_expr_ops nft_osf_op = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_osf)),
.init = nft_osf_init,
.dump = nft_osf_dump,
+ .track = nft_osf_track,
.type = &nft_osf_type,
.validate = nft_osf_validate,
};
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 2c06aca301cb..e5929aea685f 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -247,6 +247,17 @@ static int nft_payload_dump(struct sk_buff *skb,
return -1;
}
+static int nft_payload_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_payload *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
static bool nft_payload_offload_mask(struct nft_offload_reg *reg,
u32 priv_len, u32 field_len)
{
@@ -550,6 +561,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 +571,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,
};
@@ -645,6 +658,7 @@ static const struct nft_expr_ops nft_payload_inner_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_payload)),
.init = nft_payload_inner_init,
.dump = nft_payload_dump,
+ .track = nft_payload_track,
/* direct call to nft_payload_inner_eval(). */
};
@@ -913,12 +927,24 @@ static int nft_payload_set_dump(struct sk_buff *skb,
return -1;
}
+static int nft_payload_set_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_payload_set *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+
+ return 1;
+}
+
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,
+ .track = nft_payload_set_track,
};
static const struct nft_expr_ops *
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
index 160541791939..62fe8cfa322d 100644
--- a/net/netfilter/nft_queue.c
+++ b/net/netfilter/nft_queue.c
@@ -184,6 +184,18 @@ nft_queue_sreg_dump(struct sk_buff *skb,
return -1;
}
+static int nft_queue_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_queue *priv = nft_expr_priv(expr);
+
+ if (priv->sreg_qnum)
+ nft_expr_track_sreg(ctx, priv->sreg_qnum, sizeof(u32));
+
+ return 1;
+}
+
static struct nft_expr_type nft_queue_type;
static const struct nft_expr_ops nft_queue_ops = {
.type = &nft_queue_type,
@@ -191,6 +203,7 @@ static const struct nft_expr_ops nft_queue_ops = {
.eval = nft_queue_eval,
.init = nft_queue_init,
.dump = nft_queue_dump,
+ .track = nft_queue_track,
.validate = nft_queue_validate,
};
@@ -200,6 +213,7 @@ static const struct nft_expr_ops nft_queue_sreg_ops = {
.eval = nft_queue_sreg_eval,
.init = nft_queue_sreg_init,
.dump = nft_queue_sreg_dump,
+ .track = nft_queue_track,
.validate = nft_queue_validate,
};
diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c
index 5453056f07df..eb2ae8a7a6a5 100644
--- a/net/netfilter/nft_quota.c
+++ b/net/netfilter/nft_quota.c
@@ -259,6 +259,7 @@ static const struct nft_expr_ops nft_quota_ops = {
.destroy = nft_quota_destroy,
.clone = nft_quota_clone,
.dump = nft_quota_dump,
+ .track = NFT_TRACK_GENERIC,
};
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 f8258d520229..c75acc1995fc 100644
--- a/net/netfilter/nft_range.c
+++ b/net/netfilter/nft_range.c
@@ -132,12 +132,24 @@ static int nft_range_dump(struct sk_buff *skb,
return -1;
}
+static int nft_range_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_range_expr *priv = nft_expr_priv(expr);
+
+ nft_expr_track_sreg(ctx, priv->sreg, priv->len);
+
+ return 1;
+}
+
static const struct nft_expr_ops nft_range_ops = {
.type = &nft_range_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_range_expr)),
.eval = nft_range_eval,
.init = nft_range_init,
.dump = nft_range_dump,
+ .track = nft_range_track,
};
struct nft_expr_type nft_range_type __read_mostly = {
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index ab8dfaa34230..824aaf1abdf3 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -101,6 +101,20 @@ static int nft_redir_dump(struct sk_buff *skb,
return -1;
}
+static int nft_redir_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_redir *priv = nft_expr_priv(expr);
+
+ if (priv->sreg_proto_min) {
+ nft_expr_track_sreg(ctx, priv->sreg_proto_min, sizeof(u16));
+ nft_expr_track_sreg(ctx, priv->sreg_proto_max, sizeof(u16));
+ }
+
+ return 1;
+}
+
static void nft_redir_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
@@ -148,6 +162,7 @@ static const struct nft_expr_ops nft_redir_ipv4_ops = {
.init = nft_redir_init,
.destroy = nft_redir_ipv4_destroy,
.dump = nft_redir_dump,
+ .track = nft_redir_track,
.validate = nft_redir_validate,
};
@@ -175,6 +190,7 @@ static const struct nft_expr_ops nft_redir_ipv6_ops = {
.init = nft_redir_init,
.destroy = nft_redir_ipv6_destroy,
.dump = nft_redir_dump,
+ .track = nft_redir_track,
.validate = nft_redir_validate,
};
@@ -203,6 +219,7 @@ static const struct nft_expr_ops nft_redir_inet_ops = {
.init = nft_redir_init,
.destroy = nft_redir_inet_destroy,
.dump = nft_redir_dump,
+ .track = nft_redir_track,
.validate = nft_redir_validate,
};
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c
index 554caf967baa..8be0bda077f9 100644
--- a/net/netfilter/nft_reject_inet.c
+++ b/net/netfilter/nft_reject_inet.c
@@ -79,6 +79,7 @@ static const struct nft_expr_ops nft_reject_inet_ops = {
.eval = nft_reject_inet_eval,
.init = nft_reject_init,
.dump = nft_reject_dump,
+ .track = NFT_TRACK_GENERIC,
.validate = nft_reject_inet_validate,
};
diff --git a/net/netfilter/nft_reject_netdev.c b/net/netfilter/nft_reject_netdev.c
index 61cd8c4ac385..d4f6cfa5c34a 100644
--- a/net/netfilter/nft_reject_netdev.c
+++ b/net/netfilter/nft_reject_netdev.c
@@ -158,6 +158,7 @@ static const struct nft_expr_ops nft_reject_netdev_ops = {
.eval = nft_reject_netdev_eval,
.init = nft_reject_init,
.dump = nft_reject_dump,
+ .track = NFT_TRACK_GENERIC,
.validate = nft_reject_netdev_validate,
};
diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c
index 63a6069aa02b..478276db8868 100644
--- a/net/netfilter/nft_rt.c
+++ b/net/netfilter/nft_rt.c
@@ -16,6 +16,7 @@
struct nft_rt {
enum nft_rt_keys key:8;
u8 dreg;
+ u8 len;
};
static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbdst)
@@ -140,6 +141,7 @@ static int nft_rt_get_init(const struct nft_ctx *ctx,
default:
return -EOPNOTSUPP;
}
+ priv->len = len;
return nft_parse_register_store(ctx, tb[NFTA_RT_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
@@ -160,6 +162,17 @@ static int nft_rt_get_dump(struct sk_buff *skb,
return -1;
}
+static int nft_rt_get_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_rt *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data)
{
@@ -190,6 +203,7 @@ static const struct nft_expr_ops nft_rt_get_ops = {
.eval = nft_rt_get_eval,
.init = nft_rt_get_init,
.dump = nft_rt_get_dump,
+ .track = nft_rt_get_track,
.validate = nft_rt_validate,
};
diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
index 3bfcfe3ee5aa..bb714dc19247 100644
--- a/net/netfilter/nft_socket.c
+++ b/net/netfilter/nft_socket.c
@@ -213,6 +213,17 @@ static int nft_socket_dump(struct sk_buff *skb,
return 0;
}
+static int nft_socket_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_socket *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
static int nft_socket_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
@@ -230,6 +241,7 @@ static const struct nft_expr_ops nft_socket_ops = {
.eval = nft_socket_eval,
.init = nft_socket_init,
.dump = nft_socket_dump,
+ .track = nft_socket_track,
.validate = nft_socket_validate,
};
diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c
index bf7268908154..81707c8844d4 100644
--- a/net/netfilter/nft_synproxy.c
+++ b/net/netfilter/nft_synproxy.c
@@ -287,6 +287,7 @@ static const struct nft_expr_ops nft_synproxy_ops = {
.init = nft_synproxy_init,
.destroy = nft_synproxy_destroy,
.dump = nft_synproxy_dump,
+ .track = NFT_TRACK_GENERIC,
.type = &nft_synproxy_type,
.validate = nft_synproxy_validate,
};
diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c
index 089d608f6b32..d7b4ed7f5009 100644
--- a/net/netfilter/nft_tproxy.c
+++ b/net/netfilter/nft_tproxy.c
@@ -312,6 +312,32 @@ static int nft_tproxy_dump(struct sk_buff *skb,
return 0;
}
+static int nft_tproxy_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_tproxy *priv = nft_expr_priv(expr);
+ u8 alen = 0;
+
+ switch (priv->family) {
+ case NFPROTO_IPV4:
+ alen = sizeof_field(union nf_inet_addr, in);
+ break;
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+ case NFPROTO_IPV6:
+ alen = sizeof_field(union nf_inet_addr, in6);
+ break;
+#endif
+ }
+
+ if (priv->sreg_addr)
+ nft_expr_track_sreg(ctx, priv->sreg_addr, alen);
+ if (priv->sreg_port)
+ nft_expr_track_sreg(ctx, priv->sreg_port, sizeof(u16));
+
+ return 1;
+}
+
static int nft_tproxy_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
@@ -327,6 +353,7 @@ static const struct nft_expr_ops nft_tproxy_ops = {
.init = nft_tproxy_init,
.destroy = nft_tproxy_destroy,
.dump = nft_tproxy_dump,
+ .track = nft_tproxy_track,
.validate = nft_tproxy_validate,
};
diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c
index ddd698332730..9ed4e65899f3 100644
--- a/net/netfilter/nft_tunnel.c
+++ b/net/netfilter/nft_tunnel.c
@@ -124,6 +124,17 @@ static int nft_tunnel_get_dump(struct sk_buff *skb,
return -1;
}
+static int nft_tunnel_get_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_tunnel *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
static struct nft_expr_type nft_tunnel_type;
static const struct nft_expr_ops nft_tunnel_get_ops = {
.type = &nft_tunnel_type,
@@ -131,6 +142,7 @@ 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,
+ .track = nft_tunnel_get_track,
};
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 6252e1d9def8..f75fb1a2be80 100644
--- a/net/netfilter/nft_xfrm.c
+++ b/net/netfilter/nft_xfrm.c
@@ -229,6 +229,17 @@ static int nft_xfrm_get_dump(struct sk_buff *skb,
return 0;
}
+static int nft_xfrm_get_track(struct nft_expr_track_ctx *ctx,
+ struct nft_expr_track *track,
+ const struct nft_expr *expr)
+{
+ const struct nft_xfrm *priv = nft_expr_priv(expr);
+
+ nft_expr_track_dreg(ctx, priv->dreg, priv->len);
+
+ return 1;
+}
+
static int nft_xfrm_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data)
{
@@ -261,6 +272,7 @@ static const struct nft_expr_ops nft_xfrm_get_ops = {
.eval = nft_xfrm_get_eval,
.init = nft_xfrm_get_init,
.dump = nft_xfrm_get_dump,
+ .track = nft_xfrm_get_track,
.validate = nft_xfrm_validate,
};
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 4/7] netfilter: nf_tables: add payload + cmp combo match
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
` (2 preceding siblings ...)
2023-06-06 16:35 ` [PATCH nf-next,v2 3/7] netfilter: nf_tables: track register store and load operations Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 5/7] netfilter: nf_tables: add meta " Pablo Neira Ayuso
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
This patch uses the register 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.
If an expression accesses a register that has not been initialized via
previous load, then toggle the rule->skip_track flag and fall back to
use the normal expression representation. An attempt to recycle register
data that has been coalesced also triggers the skip_track fallback.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: use register tracking infrastructure and add skip_track fallback.
call nft_expr_track_reset_dreg() to reset combo'ed register in bitmap.
include/net/netfilter/nf_tables.h | 50 +++++++++-
include/net/netfilter/nf_tables_core.h | 4 +
net/netfilter/nf_tables_api.c | 123 +++++++++++++++++++++++--
net/netfilter/nf_tables_core.c | 44 ++++++++-
net/netfilter/nft_cmp.c | 22 ++++-
net/netfilter/nft_payload.c | 66 ++++++++++++-
6 files changed, 296 insertions(+), 13 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 81adf294da25..542b43f2be89 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -152,7 +152,54 @@ static inline void nft_expr_track_reset_dreg(struct nft_expr_track_ctx *ctx, u8
#define __NFT_TRACK_GENERIC 1UL
#define NFT_TRACK_GENERIC (void *)__NFT_TRACK_GENERIC
+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 base;
+ 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.
@@ -996,7 +1043,8 @@ struct nft_rule {
u64 handle:42,
genmask:2,
dlen:12,
- udata:1;
+ udata:1,
+ skip_track:1;
unsigned char data[]
__attribute__((aligned(__alignof__(struct nft_expr))));
};
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index 56b60dbe96d1..663a41605371 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -63,6 +63,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;
@@ -162,4 +163,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..119e92730553 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8901,13 +8901,70 @@ void nf_tables_trans_destroy_flush_work(void)
}
EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
+static int nft_expr_track(struct nft_expr_track_ctx *ctx,
+ struct nft_exprs_track *expr_track,
+ const struct nft_expr *expr)
+{
+ int ret, num_exprs = expr_track->num_exprs - 1;
+
+ if (WARN_ON_ONCE(!expr->ops->track)) {
+ pr_warn_once("%s has no track callback\n", expr->ops->type->name);
+ return 1;
+ }
+
+ if (expr->ops->track == NFT_TRACK_GENERIC)
+ return 1;
+
+ ret = expr->ops->track(ctx, &expr_track->expr[num_exprs], expr);
+ if (ret > 0)
+ return 1;
+
+ switch (num_exprs) {
+ case 0:
+ switch (expr_track->expr[0].type) {
+ case NFT_EXPR_PAYLOAD:
+ if (expr_track->expr[0].payload.base == NFT_PAYLOAD_NETWORK_HEADER)
+ return 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1:
+ switch (expr_track->expr[0].type) {
+ case NFT_EXPR_PAYLOAD:
+ if (expr_track->expr[1].type == NFT_EXPR_CMP &&
+ expr_track->expr[0].payload.dreg == expr_track->expr[1].cmp.sreg &&
+ expr_track->expr[0].payload.len == expr_track->expr[1].cmp.len) {
+ nft_expr_track_reset_dreg(ctx, expr_track->expr[0].payload.dreg, expr_track->expr[0].payload.len);
+ 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:
+ break;
+ }
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ 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;
+ struct nft_expr_track_ctx ctx;
unsigned int size, data_size;
void *data, *data_boundary;
struct nft_rule_dp *prule;
struct nft_rule *rule;
+ int i, ret;
/* already handled or inactive chain? */
if (chain->blob_next || !nft_is_active_next(net, chain))
@@ -8915,11 +8972,44 @@ 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;
+skip_track:
+ size = 0;
+ memset(&ctx, 0, sizeof(ctx));
+
+ nft_rule_for_each_expr(expr, last, rule) {
+ expr_track.saved_expr[expr_track.num_exprs] = expr;
+ expr_track.num_exprs++;
+
+ if (!rule->skip_track) {
+ ret = nft_expr_track(&ctx, &expr_track, expr);
+
+ if (ctx.cancel) {
+ if (WARN_ON_ONCE(rule->skip_track))
+ return -ENOMEM;
+
+ rule->skip_track = true;
+ pr_warn_once("skip tracking for %s\n", expr->ops->type->name);
+ goto skip_track;
+ }
+
+ if (ret == 0)
+ 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 +9019,8 @@ 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;
+ memset(&ctx, 0, sizeof(ctx));
list_for_each_entry(rule, &chain->rules, list) {
if (!nft_is_active_next(net, rule))
@@ -8941,12 +9033,27 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha
size = 0;
nft_rule_for_each_expr(expr, last, rule) {
+ expr_track.saved_expr[expr_track.num_exprs] = expr;
+ expr_track.num_exprs++;
- if (WARN_ON_ONCE(data + expr->ops->size > data_boundary))
- return -ENOMEM;
+ if (!rule->skip_track) {
+ ret = nft_expr_track(&ctx, &expr_track, expr);
- memcpy(data + size, expr, expr->ops->size);
- size += expr->ops->size;
+ WARN_ON_ONCE(ctx.cancel);
+
+ if (ret == 0)
+ continue;
+ }
+
+ for (i = 0; i < expr_track.num_exprs; i++) {
+ if (WARN_ON_ONCE(data + size + expr_track.saved_expr[i]->ops->size > data_boundary))
+ return -ENOMEM;
+
+ 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 0590f377a0fd..749bd81ca33c 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -152,6 +152,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 (unlikely(!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,
@@ -253,7 +293,9 @@ 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)
+ if (expr->ops == &nft_payload_combo_ops)
+ nft_payload_combo_eval(expr, ®s, pkt);
+ else if (expr->ops == &nft_cmp_fast_ops)
nft_cmp_fast_eval(expr, ®s);
else if (expr->ops != &nft_payload_fast_ops ||
!nft_payload_fast_eval(expr, ®s, pkt))
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index dc026cd4458d..c022e141db61 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -192,7 +192,18 @@ static int nft_cmp_track(struct nft_expr_track_ctx *ctx,
nft_expr_track_sreg(ctx, priv->sreg, priv->len);
- return 1;
+ 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 = {
@@ -295,7 +306,14 @@ static int nft_cmp_fast_track(struct nft_expr_track_ctx *ctx,
nft_expr_track_sreg(ctx, priv->sreg, sizeof(u32));
- return 1;
+ track->type = NFT_EXPR_CMP;
+ track->cmp.sreg = priv->sreg;
+ track->cmp.op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ;
+ track->cmp.len = sizeof(u32);
+ track->cmp.inv = priv->inv;
+ memcpy(&track->cmp.data, &priv->data, sizeof(priv->data));
+
+ return 0;
}
const struct nft_expr_ops nft_cmp_fast_ops = {
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index e5929aea685f..d6f59c82e14e 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -255,7 +255,16 @@ static int nft_payload_track(struct nft_expr_track_ctx *ctx,
nft_expr_track_dreg(ctx, priv->dreg, priv->len);
- return 1;
+ 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,
@@ -1003,3 +1012,58 @@ struct nft_expr_type nft_payload_type __read_mostly = {
.maxattr = NFTA_PAYLOAD_MAX,
.owner = THIS_MODULE,
};
+
+static u32 nft_cmp_mask(u32 bitlen)
+{
+ return ~0U >> (sizeof(u32) * BITS_PER_BYTE - bitlen);
+}
+
+/* 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_be_mask(u32 bitlen)
+{
+ return (__force u32)cpu_to_le32(nft_cmp_mask(bitlen));
+}
+
+static void nft_cmp16_mask(struct nft_data *data, unsigned int len, bool be)
+{
+ unsigned int bitlen = len * BITS_PER_BYTE;
+ int i, words = len / sizeof(u32);
+ u32 mask;
+
+ for (i = 0; i < words; i++) {
+ data->data[i] = 0xffffffff;
+ bitlen -= sizeof(u32) * BITS_PER_BYTE;
+ }
+
+ if (len % sizeof(u32)) {
+ if (be)
+ mask = nft_cmp_be_mask(bitlen);
+ else
+ mask = nft_cmp_mask(bitlen);
+
+ data->data[i++] = mask;
+ }
+
+ 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->base = track->expr[0].payload.base;
+ 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, true);
+}
+
+const struct nft_expr_ops nft_payload_combo_ops = {
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_combo)),
+};
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 5/7] netfilter: nf_tables: add meta + cmp combo match
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
` (3 preceding siblings ...)
2023-06-06 16:35 ` [PATCH nf-next,v2 4/7] netfilter: nf_tables: add payload + cmp combo match Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
2023-06-06 21:04 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 6/7] netfilter: nf_tables: add payload + bitwise " Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 7/7] netfilter: nf_tables: skip comment match when building blob Pablo Neira Ayuso
6 siblings, 1 reply; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
This patch allows to coalesce meta iifname,oifname + cmp into one combo
expression.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: fix nft_cmp16_mask() bitmask byteorder.
call nft_expr_track_reset_dreg() to reset combo'ed register.
include/net/netfilter/nf_tables.h | 17 +++++++++++
include/net/netfilter/nf_tables_core.h | 2 ++
net/netfilter/nf_tables_api.c | 19 ++++++++++++
net/netfilter/nf_tables_core.c | 40 ++++++++++++++++++++++++++
net/netfilter/nft_meta.c | 27 ++++++++++++++++-
net/netfilter/nft_payload.c | 2 +-
6 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 542b43f2be89..51bb7e295222 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -155,6 +155,7 @@ static inline void nft_expr_track_reset_dreg(struct nft_expr_track_ctx *ctx, u8
enum nft_expr_track_type {
NFT_EXPR_UNSET = 0,
NFT_EXPR_PAYLOAD,
+ NFT_EXPR_META,
NFT_EXPR_CMP
};
@@ -168,6 +169,12 @@ struct nft_expr_track {
u8 len;
u32 mask;
} payload;
+ struct {
+ u8 dreg;
+ u8 key;
+ u8 len;
+ bool inv;
+ } meta;
struct {
u8 sreg;
u8 op;
@@ -187,11 +194,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, bool be);
+
/* 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 663a41605371..1e101f66b26b 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -64,6 +64,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;
@@ -165,5 +166,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 119e92730553..007d184bd684 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8926,6 +8926,11 @@ static int nft_expr_track(struct nft_expr_track_ctx *ctx,
if (expr_track->expr[0].payload.base == NFT_PAYLOAD_NETWORK_HEADER)
return 0;
break;
+ case NFT_EXPR_META:
+ if (expr_track->expr[0].meta.key == NFT_META_IIFNAME ||
+ expr_track->expr[0].meta.key == NFT_META_OIFNAME)
+ return 0;
+ break;
default:
break;
}
@@ -8943,6 +8948,20 @@ static int nft_expr_track(struct nft_expr_track_ctx *ctx,
return 1;
}
break;
+ case NFT_EXPR_META:
+ if (expr_track->expr[1].type == NFT_EXPR_CMP &&
+ expr_track->expr[0].meta.dreg == expr_track->expr[1].cmp.sreg &&
+ expr_track->expr[0].meta.len >= expr_track->expr[1].cmp.len) {
+ if (expr_track->expr[0].meta.key == NFT_META_IIFNAME ||
+ expr_track->expr[0].meta.key == NFT_META_OIFNAME) {
+ nft_expr_track_reset_dreg(ctx, expr_track->expr[0].meta.dreg, expr_track->expr[0].meta.len);
+ 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:
break;
}
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 749bd81ca33c..cf3f96f0bf2f 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -192,6 +192,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 noinline 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,
@@ -295,6 +333,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_cmp_fast_ops)
nft_cmp_fast_eval(expr, ®s);
else if (expr->ops != &nft_payload_fast_ops ||
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index db445f8c9f9f..2467bab717b6 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -752,7 +752,16 @@ int nft_meta_get_track(struct nft_expr_track_ctx *ctx,
nft_expr_track_dreg(ctx, priv->dreg, priv->len);
- return 1;
+ 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;
+ track->meta.len = IFNAMSIZ;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(nft_meta_get_track);
@@ -774,6 +783,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,
};
@@ -990,3 +1000,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, false);
+}
+
+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 d6f59c82e14e..0169ced11704 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -1027,7 +1027,7 @@ static u32 nft_cmp_be_mask(u32 bitlen)
return (__force u32)cpu_to_le32(nft_cmp_mask(bitlen));
}
-static void nft_cmp16_mask(struct nft_data *data, unsigned int len, bool be)
+void nft_cmp16_mask(struct nft_data *data, unsigned int len, bool be)
{
unsigned int bitlen = len * BITS_PER_BYTE;
int i, words = len / sizeof(u32);
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 6/7] netfilter: nf_tables: add payload + bitwise + cmp combo match
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
` (4 preceding siblings ...)
2023-06-06 16:35 ` [PATCH nf-next,v2 5/7] netfilter: nf_tables: add meta " Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 7/7] netfilter: nf_tables: skip comment match when building blob Pablo Neira Ayuso
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
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 <pablo@netfilter.org>
---
v2: call nft_expr_track_reset_dreg() to reset register that has been combo'ed
in the register bitmap.
include/net/netfilter/nf_tables.h | 11 +++++++++--
include/net/netfilter/nf_tables_core.h | 3 ++-
net/netfilter/nf_tables_api.c | 26 +++++++++++++++++++++++++-
net/netfilter/nft_bitwise.c | 16 +++++++++++++++-
net/netfilter/nft_payload.c | 11 ++++++++---
5 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 51bb7e295222..28c12fb870d9 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -156,6 +156,7 @@ enum nft_expr_track_type {
NFT_EXPR_UNSET = 0,
NFT_EXPR_PAYLOAD,
NFT_EXPR_META,
+ NFT_EXPR_BITWISE,
NFT_EXPR_CMP
};
@@ -182,6 +183,12 @@ struct nft_expr_track {
bool inv;
struct nft_data data;
} cmp;
+ struct {
+ u8 sreg;
+ u8 dreg;
+ u8 len;
+ struct nft_data mask;
+ } bitwise;
};
};
@@ -214,8 +221,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 1e101f66b26b..419ae7a2d413 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -165,7 +165,8 @@ 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 bitmask);
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 007d184bd684..dc0b5e1ada16 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8942,7 +8942,7 @@ static int nft_expr_track(struct nft_expr_track_ctx *ctx,
expr_track->expr[0].payload.dreg == expr_track->expr[1].cmp.sreg &&
expr_track->expr[0].payload.len == expr_track->expr[1].cmp.len) {
nft_expr_track_reset_dreg(ctx, expr_track->expr[0].payload.dreg, expr_track->expr[0].payload.len);
- 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;
@@ -8962,6 +8962,30 @@ static int nft_expr_track(struct nft_expr_track_ctx *ctx,
}
}
break;
+ case NFT_EXPR_BITWISE:
+ if (expr_track->expr[0].type == NFT_EXPR_PAYLOAD &&
+ expr_track->expr[0].payload.dreg == expr_track->expr[1].bitwise.sreg &&
+ expr_track->expr[0].payload.len >= expr_track->expr[1].bitwise.len)
+ return 0;
+ break;
+ default:
+ return 1;
+ }
+ break;
+ case 2:
+ switch (expr_track->expr[0].type) {
+ case NFT_EXPR_PAYLOAD:
+ if (expr_track->expr[1].type == NFT_EXPR_BITWISE &&
+ expr_track->expr[2].type == NFT_EXPR_CMP &&
+ expr_track->expr[1].bitwise.dreg == expr_track->expr[2].cmp.sreg &&
+ expr_track->expr[1].bitwise.len >= expr_track->expr[2].cmp.len) {
+ nft_expr_track_reset_dreg(ctx, expr_track->expr[0].payload.dreg, expr_track->expr[0].payload.len);
+ 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;
+ return 1;
+ }
+ break;
default:
break;
}
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index 0ab2d281f245..a263f8ca59c5 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -271,7 +271,21 @@ static int nft_bitwise_track(struct nft_expr_track_ctx *ctx,
nft_expr_track_sreg(ctx, priv->sreg, priv->len);
nft_expr_track_dreg(ctx, priv->dreg, priv->len);
- return 1;
+ if (priv->op != NFT_BITWISE_BOOL)
+ return 1;
+
+ if (memcmp(&priv->xor, &zero, sizeof(priv->xor)))
+ return 1;
+
+ if (priv->sreg != priv->dreg)
+ 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,
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 0169ced11704..8d1d4df2f90a 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -1051,17 +1051,22 @@ void nft_cmp16_mask(struct nft_data *data, unsigned int len, bool be)
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->base = track->expr[0].payload.base;
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;
+ 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[1].cmp.len, true);
+
+ if (bitmask)
+ priv->mask.data[0] &= track->expr[1].bitwise.mask.data[0];
}
const struct nft_expr_ops nft_payload_combo_ops = {
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH nf-next,v2 7/7] netfilter: nf_tables: skip comment match when building blob
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
` (5 preceding siblings ...)
2023-06-06 16:35 ` [PATCH nf-next,v2 6/7] netfilter: nf_tables: add payload + bitwise " Pablo Neira Ayuso
@ 2023-06-06 16:35 ` Pablo Neira Ayuso
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 16:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
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 <pablo@netfilter.org>
---
v2: no changes
net/netfilter/nf_tables_api.c | 4 ++++
net/netfilter/nft_compat.c | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index dc0b5e1ada16..6b33fd0228e5 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8918,6 +8918,10 @@ static int nft_expr_track(struct nft_expr_track_ctx *ctx,
ret = expr->ops->track(ctx, &expr_track->expr[num_exprs], expr);
if (ret > 0)
return 1;
+ else if (ret < 0) {
+ expr_track->num_exprs--;
+ return 0;
+ }
switch (num_exprs) {
case 0:
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index af88078caf99..c72e2a39fe34 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -734,6 +734,18 @@ 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_ctx *ctx,
+ 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 +788,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) {
--
2.30.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH nf-next,v2 5/7] netfilter: nf_tables: add meta + cmp combo match
2023-06-06 16:35 ` [PATCH nf-next,v2 5/7] netfilter: nf_tables: add meta " Pablo Neira Ayuso
@ 2023-06-06 21:04 ` Pablo Neira Ayuso
0 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2023-06-06 21:04 UTC (permalink / raw)
To: netfilter-devel; +Cc: fw
On Tue, Jun 06, 2023 at 06:35:31PM +0200, Pablo Neira Ayuso wrote:
> This patch allows to coalesce meta iifname,oifname + cmp into one combo
> expression.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> v2: fix nft_cmp16_mask() bitmask byteorder.
nft_cmp16_mask() byteorder was correct in v1, and it is not fine in
this iteration, I will fix this in v3.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-06-06 21:04 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-06 16:35 [PATCH nf-next,v2 0/7] nf_tables combo match Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 1/7] netfilter: nf_tables: remove expression reduce infrastructure Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 2/7] netfilter: nf_tables: remove fast bitwise and fast cmp16 Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 3/7] netfilter: nf_tables: track register store and load operations Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 4/7] netfilter: nf_tables: add payload + cmp combo match Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 5/7] netfilter: nf_tables: add meta " Pablo Neira Ayuso
2023-06-06 21:04 ` Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 6/7] netfilter: nf_tables: add payload + bitwise " Pablo Neira Ayuso
2023-06-06 16:35 ` [PATCH nf-next,v2 7/7] netfilter: nf_tables: skip comment match when building blob Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).