Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nf-next-25-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following series contains Netfilter/IPVS updates for net-next:

1) Display netns inode in conntrack table full log, from lvxiafei.

2) Autoload nf_log_syslog in case no logging backend is available,
from Lance Yang.

3) Three patches to remove unused functions in x_tables, nf_tables and
conntrack. From Yue Haibing.

4) Exclude LEGACY TABLES on PREEMPT_RT: Add NETFILTER_XTABLES_LEGACY
to exclude xtables legacy infrastructure.

5) Restore selftests by toggling NETFILTER_XTABLES_LEGACY where needed.
From Florian Westphal.

6) Use CONFIG_INET_SCTP_DIAG in tools/testing/selftests/net/netfilter/config,
from Sebastian Andrzej Siewior.

7) Use timer_delete in comment in IPVS codebase, from WangYuli.

8) Dump flowtable information in nfnetlink_hook, this includes an initial
patch to consolidate common code in helper function, from Phil Sutter.

9) Remove unused arguments in nft_pipapo set backend, from Florian Westphal.

10) Return nft_set_ext instead of boolean in set lookup function,
from Florian Westphal.

11) Remove indirection in dynamic set infrastructure, also from Florian.

12) Consolidate pipapo_get/lookup, from Florian.

13) Use kvmalloc in nft_pipapop, from Florian Westphal.

14) syzbot reports slab-out-of-bounds in xt_nfacct log message,
fix from Florian Westphal.

15) Ignored tainted kernels in selftest nft_interface_stress.sh,
from Phil Sutter.

16) Fix IPVS selftest by disabling rp_filter with ipip tunnel device,
from Yi Chen.

* tag 'nf-next-25-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
selftests: netfilter: ipvs.sh: Explicity disable rp_filter on interface tunl0
selftests: netfilter: Ignore tainted kernels in interface stress test
netfilter: xt_nfacct: don't assume acct name is null-terminated
netfilter: nft_set_pipapo: prefer kvmalloc for scratch maps
netfilter: nft_set_pipapo: merge pipapo_get/lookup
netfilter: nft_set: remove indirection from update API call
netfilter: nft_set: remove one argument from lookup and update functions
netfilter: nft_set_pipapo: remove unused arguments
netfilter: nfnetlink_hook: Dump flowtable info
netfilter: nfnetlink: New NFNLA_HOOK_INFO_DESC helper
ipvs: Rename del_timer in comment in ip_vs_conn_expire_now()
selftests: netfilter: Enable CONFIG_INET_SCTP_DIAG
selftests: net: Enable legacy netfilter legacy options.
netfilter: Exclude LEGACY TABLES on PREEMPT_RT.
netfilter: conntrack: Remove unused net in nf_conntrack_double_lock()
netfilter: nf_tables: Remove unused nft_reduce_is_readonly()
netfilter: x_tables: Remove unused functions xt_{in|out}name()
netfilter: load nf_log_syslog on enabling nf_conntrack_log_invalid
netfilter: conntrack: table full detailed log
====================

Link: https://patch.msgid.link/20250725170340.21327-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+405 -351
+1
include/linux/netfilter.h
··· 92 92 NF_HOOK_OP_UNDEFINED, 93 93 NF_HOOK_OP_NF_TABLES, 94 94 NF_HOOK_OP_BPF, 95 + NF_HOOK_OP_NFT_FT, 95 96 }; 96 97 97 98 struct nf_hook_ops {
-10
include/linux/netfilter/x_tables.h
··· 51 51 return par->state->in; 52 52 } 53 53 54 - static inline const char *xt_inname(const struct xt_action_param *par) 55 - { 56 - return par->state->in->name; 57 - } 58 - 59 54 static inline struct net_device *xt_out(const struct xt_action_param *par) 60 55 { 61 56 return par->state->out; 62 - } 63 - 64 - static inline const char *xt_outname(const struct xt_action_param *par) 65 - { 66 - return par->state->out->name; 67 57 } 68 58 69 59 static inline unsigned int xt_hooknum(const struct xt_action_param *par)
+3
include/net/netfilter/nf_log.h
··· 59 59 int nf_log_register(u_int8_t pf, struct nf_logger *logger); 60 60 void nf_log_unregister(struct nf_logger *logger); 61 61 62 + /* Check if any logger is registered for a given protocol family. */ 63 + bool nf_log_is_registered(u_int8_t pf); 64 + 62 65 int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger); 63 66 void nf_log_unset(struct net *net, const struct nf_logger *logger); 64 67
+4 -15
include/net/netfilter/nf_tables.h
··· 459 459 * control plane functions. 460 460 */ 461 461 struct nft_set_ops { 462 - bool (*lookup)(const struct net *net, 462 + const struct nft_set_ext * (*lookup)(const struct net *net, 463 463 const struct nft_set *set, 464 + const u32 *key); 465 + const struct nft_set_ext * (*update)(struct nft_set *set, 464 466 const u32 *key, 465 - const struct nft_set_ext **ext); 466 - bool (*update)(struct nft_set *set, 467 - const u32 *key, 468 - struct nft_elem_priv * 469 - (*new)(struct nft_set *, 470 - const struct nft_expr *, 471 - struct nft_regs *), 472 467 const struct nft_expr *expr, 473 - struct nft_regs *regs, 474 - const struct nft_set_ext **ext); 468 + struct nft_regs *regs); 475 469 bool (*delete)(const struct nft_set *set, 476 470 const u32 *key); 477 471 ··· 1932 1938 1933 1939 #define __NFT_REDUCE_READONLY 1UL 1934 1940 #define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY 1935 - 1936 - static inline bool nft_reduce_is_readonly(const struct nft_expr *expr) 1937 - { 1938 - return expr->ops->reduce == NFT_REDUCE_READONLY; 1939 - } 1940 1941 1941 1942 void nft_reg_track_update(struct nft_regs_track *track, 1942 1943 const struct nft_expr *expr, u8 dreg, u8 len);
+31 -21
include/net/netfilter/nf_tables_core.h
··· 94 94 extern const struct nft_set_type nft_set_pipapo_avx2_type; 95 95 96 96 #ifdef CONFIG_MITIGATION_RETPOLINE 97 - bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, 98 - const u32 *key, const struct nft_set_ext **ext); 99 - bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, 100 - const u32 *key, const struct nft_set_ext **ext); 101 - bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, 102 - const u32 *key, const struct nft_set_ext **ext); 103 - bool nft_hash_lookup_fast(const struct net *net, 104 - const struct nft_set *set, 105 - const u32 *key, const struct nft_set_ext **ext); 106 - bool nft_hash_lookup(const struct net *net, const struct nft_set *set, 107 - const u32 *key, const struct nft_set_ext **ext); 108 - bool nft_set_do_lookup(const struct net *net, const struct nft_set *set, 109 - const u32 *key, const struct nft_set_ext **ext); 110 - #else 111 - static inline bool 97 + const struct nft_set_ext * 98 + nft_rhash_lookup(const struct net *net, const struct nft_set *set, 99 + const u32 *key); 100 + const struct nft_set_ext * 101 + nft_rbtree_lookup(const struct net *net, const struct nft_set *set, 102 + const u32 *key); 103 + const struct nft_set_ext * 104 + nft_bitmap_lookup(const struct net *net, const struct nft_set *set, 105 + const u32 *key); 106 + const struct nft_set_ext * 107 + nft_hash_lookup_fast(const struct net *net, const struct nft_set *set, 108 + const u32 *key); 109 + const struct nft_set_ext * 110 + nft_hash_lookup(const struct net *net, const struct nft_set *set, 111 + const u32 *key); 112 + const struct nft_set_ext * 112 113 nft_set_do_lookup(const struct net *net, const struct nft_set *set, 113 - const u32 *key, const struct nft_set_ext **ext) 114 + const u32 *key); 115 + #else 116 + static inline const struct nft_set_ext * 117 + nft_set_do_lookup(const struct net *net, const struct nft_set *set, 118 + const u32 *key) 114 119 { 115 - return set->ops->lookup(net, set, key, ext); 120 + return set->ops->lookup(net, set, key); 116 121 } 117 122 #endif 118 123 119 124 /* called from nft_pipapo_avx2.c */ 120 - bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, 121 - const u32 *key, const struct nft_set_ext **ext); 125 + const struct nft_set_ext * 126 + nft_pipapo_lookup(const struct net *net, const struct nft_set *set, 127 + const u32 *key); 122 128 /* called from nft_set_pipapo.c */ 123 - bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, 124 - const u32 *key, const struct nft_set_ext **ext); 129 + const struct nft_set_ext * 130 + nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, 131 + const u32 *key); 125 132 126 133 void nft_counter_init_seqcount(void); 127 134 ··· 188 181 const struct nft_pktinfo *pkt); 189 182 void nft_objref_map_eval(const struct nft_expr *expr, struct nft_regs *regs, 190 183 const struct nft_pktinfo *pkt); 184 + struct nft_elem_priv *nft_dynset_new(struct nft_set *set, 185 + const struct nft_expr *expr, 186 + struct nft_regs *regs); 191 187 #endif /* _NET_NF_TABLES_CORE_H */
+5 -5
net/bridge/netfilter/Kconfig
··· 42 42 # old sockopt interface and eval loop 43 43 config BRIDGE_NF_EBTABLES_LEGACY 44 44 tristate "Legacy EBTABLES support" 45 - depends on BRIDGE && NETFILTER_XTABLES 46 - default n 45 + depends on BRIDGE && NETFILTER_XTABLES_LEGACY 46 + default n 47 47 help 48 48 Legacy ebtables packet/frame classifier. 49 49 This is not needed if you are using ebtables over nftables ··· 65 65 # 66 66 config BRIDGE_EBT_BROUTE 67 67 tristate "ebt: broute table support" 68 - select BRIDGE_NF_EBTABLES_LEGACY 68 + depends on BRIDGE_NF_EBTABLES_LEGACY 69 69 help 70 70 The ebtables broute table is used to define rules that decide between 71 71 bridging and routing frames, giving Linux the functionality of a ··· 76 76 77 77 config BRIDGE_EBT_T_FILTER 78 78 tristate "ebt: filter table support" 79 - select BRIDGE_NF_EBTABLES_LEGACY 79 + depends on BRIDGE_NF_EBTABLES_LEGACY 80 80 help 81 81 The ebtables filter table is used to define frame filtering rules at 82 82 local input, forwarding and local output. See the man page for ··· 86 86 87 87 config BRIDGE_EBT_T_NAT 88 88 tristate "ebt: nat table support" 89 - select BRIDGE_NF_EBTABLES_LEGACY 89 + depends on BRIDGE_NF_EBTABLES_LEGACY 90 90 help 91 91 The ebtables nat table is used to define rules that alter the MAC 92 92 source address (MAC SNAT) or the MAC destination address (MAC DNAT).
+12 -12
net/ipv4/netfilter/Kconfig
··· 13 13 # old sockopt interface and eval loop 14 14 config IP_NF_IPTABLES_LEGACY 15 15 tristate "Legacy IP tables support" 16 - default n 17 - select NETFILTER_XTABLES 16 + depends on NETFILTER_XTABLES_LEGACY 17 + default m if NETFILTER_XTABLES_LEGACY 18 18 help 19 19 iptables is a legacy packet classifier. 20 20 This is not needed if you are using iptables over nftables ··· 182 182 # `filter', generic and specific targets 183 183 config IP_NF_FILTER 184 184 tristate "Packet filtering" 185 - default m if NETFILTER_ADVANCED=n 186 - select IP_NF_IPTABLES_LEGACY 185 + default m if NETFILTER_ADVANCED=n || IP_NF_IPTABLES_LEGACY 186 + depends on IP_NF_IPTABLES_LEGACY 187 187 help 188 188 Packet filtering defines a table `filter', which has a series of 189 189 rules for simple packet filtering at local input, forwarding and ··· 220 220 config IP_NF_NAT 221 221 tristate "iptables NAT support" 222 222 depends on NF_CONNTRACK 223 + depends on IP_NF_IPTABLES_LEGACY 223 224 default m if NETFILTER_ADVANCED=n 224 225 select NF_NAT 225 226 select NETFILTER_XT_NAT 226 - select IP_NF_IPTABLES_LEGACY 227 227 help 228 228 This enables the `nat' table in iptables. This allows masquerading, 229 229 port forwarding and other forms of full Network Address Port ··· 263 263 # mangle + specific targets 264 264 config IP_NF_MANGLE 265 265 tristate "Packet mangling" 266 - default m if NETFILTER_ADVANCED=n 267 - select IP_NF_IPTABLES_LEGACY 266 + default m if NETFILTER_ADVANCED=n || IP_NF_IPTABLES_LEGACY 267 + depends on IP_NF_IPTABLES_LEGACY 268 268 help 269 269 This option adds a `mangle' table to iptables: see the man page for 270 270 iptables(8). This table is used for various packet alterations ··· 299 299 # raw + specific targets 300 300 config IP_NF_RAW 301 301 tristate 'raw table support (required for NOTRACK/TRACE)' 302 - select IP_NF_IPTABLES_LEGACY 302 + depends on IP_NF_IPTABLES_LEGACY 303 303 help 304 304 This option adds a `raw' table to iptables. This table is the very 305 305 first in the netfilter framework and hooks in at the PREROUTING ··· 313 313 tristate "Security table" 314 314 depends on SECURITY 315 315 depends on NETFILTER_ADVANCED 316 - select IP_NF_IPTABLES_LEGACY 316 + depends on IP_NF_IPTABLES_LEGACY 317 317 help 318 318 This option adds a `security' table to iptables, for use 319 319 with Mandatory Access Control (MAC) policy. ··· 325 325 # ARP tables 326 326 config IP_NF_ARPTABLES 327 327 tristate "Legacy ARPTABLES support" 328 - depends on NETFILTER_XTABLES 329 - default n 328 + depends on NETFILTER_XTABLES_LEGACY 329 + default n 330 330 help 331 331 arptables is a legacy packet classifier. 332 332 This is not needed if you are using arptables over nftables ··· 342 342 tristate "arptables-legacy packet filtering support" 343 343 select IP_NF_ARPTABLES 344 344 select NETFILTER_FAMILY_ARP 345 - depends on NETFILTER_XTABLES 345 + depends on NETFILTER_XTABLES_LEGACY 346 346 help 347 347 ARP packet filtering defines a table `filter', which has a series of 348 348 rules for simple ARP packet filtering at local input and
+9 -10
net/ipv6/netfilter/Kconfig
··· 9 9 # old sockopt interface and eval loop 10 10 config IP6_NF_IPTABLES_LEGACY 11 11 tristate "Legacy IP6 tables support" 12 - depends on INET && IPV6 13 - select NETFILTER_XTABLES 14 - default n 12 + depends on INET && IPV6 && NETFILTER_XTABLES_LEGACY 13 + default m if NETFILTER_XTABLES_LEGACY 15 14 help 16 15 ip6tables is a legacy packet classifier. 17 16 This is not needed if you are using iptables over nftables ··· 195 196 196 197 config IP6_NF_FILTER 197 198 tristate "Packet filtering" 198 - default m if NETFILTER_ADVANCED=n 199 - select IP6_NF_IPTABLES_LEGACY 199 + default m if NETFILTER_ADVANCED=n || IP6_NF_IPTABLES_LEGACY 200 + depends on IP6_NF_IPTABLES_LEGACY 200 201 tristate 201 202 help 202 203 Packet filtering defines a table `filter', which has a series of ··· 232 233 233 234 config IP6_NF_MANGLE 234 235 tristate "Packet mangling" 235 - default m if NETFILTER_ADVANCED=n 236 - select IP6_NF_IPTABLES_LEGACY 236 + default m if NETFILTER_ADVANCED=n || IP6_NF_IPTABLES_LEGACY 237 + depends on IP6_NF_IPTABLES_LEGACY 237 238 help 238 239 This option adds a `mangle' table to iptables: see the man page for 239 240 iptables(8). This table is used for various packet alterations ··· 243 244 244 245 config IP6_NF_RAW 245 246 tristate 'raw table support (required for TRACE)' 246 - select IP6_NF_IPTABLES_LEGACY 247 + depends on IP6_NF_IPTABLES_LEGACY 247 248 help 248 249 This option adds a `raw' table to ip6tables. This table is the very 249 250 first in the netfilter framework and hooks in at the PREROUTING ··· 257 258 tristate "Security table" 258 259 depends on SECURITY 259 260 depends on NETFILTER_ADVANCED 260 - select IP6_NF_IPTABLES_LEGACY 261 + depends on IP6_NF_IPTABLES_LEGACY 261 262 help 262 263 This option adds a `security' table to iptables, for use 263 264 with Mandatory Access Control (MAC) policy. ··· 268 269 tristate "ip6tables NAT support" 269 270 depends on NF_CONNTRACK 270 271 depends on NETFILTER_ADVANCED 272 + depends on IP6_NF_IPTABLES_LEGACY 271 273 select NF_NAT 272 - select IP6_NF_IPTABLES_LEGACY 273 274 select NETFILTER_XT_NAT 274 275 help 275 276 This enables the `nat' table in ip6tables. This allows masquerading,
+10
net/netfilter/Kconfig
··· 758 758 759 759 If unsure, say N. 760 760 761 + config NETFILTER_XTABLES_LEGACY 762 + bool "Netfilter legacy tables support" 763 + depends on !PREEMPT_RT 764 + help 765 + Say Y here if you still require support for legacy tables. This is 766 + required by the legacy tools (iptables-legacy) and is not needed if 767 + you use iptables over nftables (iptables-nft). 768 + Legacy support is not limited to IP, it also includes EBTABLES and 769 + ARPTABLES. 770 + 761 771 comment "Xtables combined modules" 762 772 763 773 config NETFILTER_XT_MARK
+1 -1
net/netfilter/ipvs/ip_vs_conn.c
··· 926 926 void ip_vs_conn_expire_now(struct ip_vs_conn *cp) 927 927 { 928 928 /* Using mod_timer_pending will ensure the timer is not 929 - * modified after the final del_timer in ip_vs_conn_expire. 929 + * modified after the final timer_delete in ip_vs_conn_expire. 930 930 */ 931 931 if (timer_pending(&cp->timer) && 932 932 time_after(cp->timer.expires, jiffies))
+10 -6
net/netfilter/nf_conntrack_core.c
··· 136 136 } 137 137 138 138 /* return true if we need to recompute hashes (in case hash table was resized) */ 139 - static bool nf_conntrack_double_lock(struct net *net, unsigned int h1, 140 - unsigned int h2, unsigned int sequence) 139 + static bool nf_conntrack_double_lock(unsigned int h1, unsigned int h2, 140 + unsigned int sequence) 141 141 { 142 142 h1 %= CONNTRACK_LOCKS; 143 143 h2 %= CONNTRACK_LOCKS; ··· 613 613 reply_hash = hash_conntrack(net, 614 614 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, 615 615 nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_REPLY)); 616 - } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); 616 + } while (nf_conntrack_double_lock(hash, reply_hash, sequence)); 617 617 618 618 clean_from_lists(ct); 619 619 nf_conntrack_double_unlock(hash, reply_hash); ··· 890 890 reply_hash = hash_conntrack(net, 891 891 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, 892 892 nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_REPLY)); 893 - } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); 893 + } while (nf_conntrack_double_lock(hash, reply_hash, sequence)); 894 894 895 895 max_chainlen = MIN_CHAINLEN + get_random_u32_below(MAX_CHAINLEN); 896 896 ··· 1234 1234 reply_hash = hash_conntrack(net, 1235 1235 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, 1236 1236 nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_REPLY)); 1237 - } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); 1237 + } while (nf_conntrack_double_lock(hash, reply_hash, sequence)); 1238 1238 1239 1239 /* We're not in hash table, and we refuse to set up related 1240 1240 * connections for unconfirmed conns. But packet copies and ··· 1673 1673 if (!conntrack_gc_work.early_drop) 1674 1674 conntrack_gc_work.early_drop = true; 1675 1675 atomic_dec(&cnet->count); 1676 - net_warn_ratelimited("nf_conntrack: table full, dropping packet\n"); 1676 + if (net == &init_net) 1677 + net_warn_ratelimited("nf_conntrack: table full, dropping packet\n"); 1678 + else 1679 + net_warn_ratelimited("nf_conntrack: table full in netns %u, dropping packet\n", 1680 + net->ns.inum); 1677 1681 return ERR_PTR(-ENOMEM); 1678 1682 } 1679 1683 }
+25 -1
net/netfilter/nf_conntrack_standalone.c
··· 14 14 #include <linux/sysctl.h> 15 15 #endif 16 16 17 + #include <net/netfilter/nf_log.h> 17 18 #include <net/netfilter/nf_conntrack.h> 18 19 #include <net/netfilter/nf_conntrack_core.h> 19 20 #include <net/netfilter/nf_conntrack_l4proto.h> ··· 556 555 return ret; 557 556 } 558 557 558 + static int 559 + nf_conntrack_log_invalid_sysctl(const struct ctl_table *table, int write, 560 + void *buffer, size_t *lenp, loff_t *ppos) 561 + { 562 + int ret, i; 563 + 564 + ret = proc_dou8vec_minmax(table, write, buffer, lenp, ppos); 565 + if (ret < 0 || !write) 566 + return ret; 567 + 568 + if (*(u8 *)table->data == 0) 569 + return ret; 570 + 571 + /* Load nf_log_syslog only if no logger is currently registered */ 572 + for (i = 0; i < NFPROTO_NUMPROTO; i++) { 573 + if (nf_log_is_registered(i)) 574 + return ret; 575 + } 576 + request_module("%s", "nf_log_syslog"); 577 + 578 + return ret; 579 + } 580 + 559 581 static struct ctl_table_header *nf_ct_netfilter_header; 560 582 561 583 enum nf_ct_sysctl_index { ··· 675 651 .data = &init_net.ct.sysctl_log_invalid, 676 652 .maxlen = sizeof(u8), 677 653 .mode = 0644, 678 - .proc_handler = proc_dou8vec_minmax, 654 + .proc_handler = nf_conntrack_log_invalid_sysctl, 679 655 }, 680 656 [NF_SYSCTL_CT_EXPECT_MAX] = { 681 657 .procname = "nf_conntrack_expect_max",
+26
net/netfilter/nf_log.c
··· 125 125 } 126 126 EXPORT_SYMBOL(nf_log_unregister); 127 127 128 + /** 129 + * nf_log_is_registered - Check if any logger is registered for a given 130 + * protocol family. 131 + * 132 + * @pf: Protocol family 133 + * 134 + * Returns: true if at least one logger is active for @pf, false otherwise. 135 + */ 136 + bool nf_log_is_registered(u_int8_t pf) 137 + { 138 + int i; 139 + 140 + if (pf >= NFPROTO_NUMPROTO) { 141 + WARN_ON_ONCE(1); 142 + return false; 143 + } 144 + 145 + for (i = 0; i < NF_LOG_TYPE_MAX; i++) { 146 + if (rcu_access_pointer(loggers[pf][i])) 147 + return true; 148 + } 149 + 150 + return false; 151 + } 152 + EXPORT_SYMBOL(nf_log_is_registered); 153 + 128 154 int nf_log_bind_pf(struct net *net, u_int8_t pf, 129 155 const struct nf_logger *logger) 130 156 {
+13 -11
net/netfilter/nf_tables_api.c
··· 8895 8895 8896 8896 list_for_each_entry(hook, &flowtable_hook->list, list) { 8897 8897 list_for_each_entry(ops, &hook->ops_list, list) { 8898 - ops->pf = NFPROTO_NETDEV; 8899 - ops->hooknum = flowtable_hook->num; 8900 - ops->priority = flowtable_hook->priority; 8901 - ops->priv = &flowtable->data; 8902 - ops->hook = flowtable->data.type->hook; 8898 + ops->pf = NFPROTO_NETDEV; 8899 + ops->hooknum = flowtable_hook->num; 8900 + ops->priority = flowtable_hook->priority; 8901 + ops->priv = &flowtable->data; 8902 + ops->hook = flowtable->data.type->hook; 8903 + ops->hook_ops_type = NF_HOOK_OP_NFT_FT; 8903 8904 } 8904 8905 } 8905 8906 ··· 9728 9727 if (!ops) 9729 9728 return 1; 9730 9729 9731 - ops->pf = NFPROTO_NETDEV; 9732 - ops->hooknum = flowtable->hooknum; 9733 - ops->priority = flowtable->data.priority; 9734 - ops->priv = &flowtable->data; 9735 - ops->hook = flowtable->data.type->hook; 9736 - ops->dev = dev; 9730 + ops->pf = NFPROTO_NETDEV; 9731 + ops->hooknum = flowtable->hooknum; 9732 + ops->priority = flowtable->data.priority; 9733 + ops->priv = &flowtable->data; 9734 + ops->hook = flowtable->data.type->hook; 9735 + ops->hook_ops_type = NF_HOOK_OP_NFT_FT; 9736 + ops->dev = dev; 9737 9737 if (nft_register_flowtable_ops(dev_net(dev), 9738 9738 flowtable, ops)) { 9739 9739 kfree(ops);
+5 -5
net/netfilter/nft_dynset.c
··· 44 44 return 0; 45 45 } 46 46 47 - static struct nft_elem_priv *nft_dynset_new(struct nft_set *set, 48 - const struct nft_expr *expr, 49 - struct nft_regs *regs) 47 + struct nft_elem_priv *nft_dynset_new(struct nft_set *set, 48 + const struct nft_expr *expr, 49 + struct nft_regs *regs) 50 50 { 51 51 const struct nft_dynset *priv = nft_expr_priv(expr); 52 52 struct nft_set_ext *ext; ··· 91 91 return; 92 92 } 93 93 94 - if (set->ops->update(set, &regs->data[priv->sreg_key], nft_dynset_new, 95 - expr, regs, &ext)) { 94 + ext = set->ops->update(set, &regs->data[priv->sreg_key], expr, regs); 95 + if (ext) { 96 96 if (priv->op == NFT_DYNSET_OP_UPDATE && 97 97 nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) && 98 98 READ_ONCE(nft_set_ext_timeout(ext)->timeout) != 0) {
+14 -13
net/netfilter/nft_lookup.c
··· 25 25 }; 26 26 27 27 #ifdef CONFIG_MITIGATION_RETPOLINE 28 - bool nft_set_do_lookup(const struct net *net, const struct nft_set *set, 29 - const u32 *key, const struct nft_set_ext **ext) 28 + const struct nft_set_ext * 29 + nft_set_do_lookup(const struct net *net, const struct nft_set *set, 30 + const u32 *key) 30 31 { 31 32 if (set->ops == &nft_set_hash_fast_type.ops) 32 - return nft_hash_lookup_fast(net, set, key, ext); 33 + return nft_hash_lookup_fast(net, set, key); 33 34 if (set->ops == &nft_set_hash_type.ops) 34 - return nft_hash_lookup(net, set, key, ext); 35 + return nft_hash_lookup(net, set, key); 35 36 36 37 if (set->ops == &nft_set_rhash_type.ops) 37 - return nft_rhash_lookup(net, set, key, ext); 38 + return nft_rhash_lookup(net, set, key); 38 39 39 40 if (set->ops == &nft_set_bitmap_type.ops) 40 - return nft_bitmap_lookup(net, set, key, ext); 41 + return nft_bitmap_lookup(net, set, key); 41 42 42 43 if (set->ops == &nft_set_pipapo_type.ops) 43 - return nft_pipapo_lookup(net, set, key, ext); 44 + return nft_pipapo_lookup(net, set, key); 44 45 #if defined(CONFIG_X86_64) && !defined(CONFIG_UML) 45 46 if (set->ops == &nft_set_pipapo_avx2_type.ops) 46 - return nft_pipapo_avx2_lookup(net, set, key, ext); 47 + return nft_pipapo_avx2_lookup(net, set, key); 47 48 #endif 48 49 49 50 if (set->ops == &nft_set_rbtree_type.ops) 50 - return nft_rbtree_lookup(net, set, key, ext); 51 + return nft_rbtree_lookup(net, set, key); 51 52 52 53 WARN_ON_ONCE(1); 53 - return set->ops->lookup(net, set, key, ext); 54 + return set->ops->lookup(net, set, key); 54 55 } 55 56 EXPORT_SYMBOL_GPL(nft_set_do_lookup); 56 57 #endif ··· 62 61 { 63 62 const struct nft_lookup *priv = nft_expr_priv(expr); 64 63 const struct nft_set *set = priv->set; 65 - const struct nft_set_ext *ext = NULL; 66 64 const struct net *net = nft_net(pkt); 65 + const struct nft_set_ext *ext; 67 66 bool found; 68 67 69 - found = nft_set_do_lookup(net, set, &regs->data[priv->sreg], &ext) ^ 70 - priv->invert; 68 + ext = nft_set_do_lookup(net, set, &regs->data[priv->sreg]); 69 + found = !!ext ^ priv->invert; 71 70 if (!found) { 72 71 ext = nft_set_catchall_lookup(net, set); 73 72 if (!ext) {
+2 -3
net/netfilter/nft_objref.c
··· 111 111 struct net *net = nft_net(pkt); 112 112 const struct nft_set_ext *ext; 113 113 struct nft_object *obj; 114 - bool found; 115 114 116 - found = nft_set_do_lookup(net, set, &regs->data[priv->sreg], &ext); 117 - if (!found) { 115 + ext = nft_set_do_lookup(net, set, &regs->data[priv->sreg]); 116 + if (!ext) { 118 117 ext = nft_set_catchall_lookup(net, set); 119 118 if (!ext) { 120 119 regs->verdict.code = NFT_BREAK;
+8 -3
net/netfilter/nft_set_bitmap.c
··· 75 75 } 76 76 77 77 INDIRECT_CALLABLE_SCOPE 78 - bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, 79 - const u32 *key, const struct nft_set_ext **ext) 78 + const struct nft_set_ext * 79 + nft_bitmap_lookup(const struct net *net, const struct nft_set *set, 80 + const u32 *key) 80 81 { 81 82 const struct nft_bitmap *priv = nft_set_priv(set); 83 + static const struct nft_set_ext found; 82 84 u8 genmask = nft_genmask_cur(net); 83 85 u32 idx, off; 84 86 85 87 nft_bitmap_location(set, key, &idx, &off); 86 88 87 - return nft_bitmap_active(priv->bitmap, idx, off, genmask); 89 + if (nft_bitmap_active(priv->bitmap, idx, off, genmask)) 90 + return &found; 91 + 92 + return NULL; 88 93 } 89 94 90 95 static struct nft_bitmap_elem *
+23 -31
net/netfilter/nft_set_hash.c
··· 81 81 }; 82 82 83 83 INDIRECT_CALLABLE_SCOPE 84 - bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, 85 - const u32 *key, const struct nft_set_ext **ext) 84 + const struct nft_set_ext * 85 + nft_rhash_lookup(const struct net *net, const struct nft_set *set, 86 + const u32 *key) 86 87 { 87 88 struct nft_rhash *priv = nft_set_priv(set); 88 89 const struct nft_rhash_elem *he; ··· 96 95 97 96 he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); 98 97 if (he != NULL) 99 - *ext = &he->ext; 98 + return &he->ext; 100 99 101 - return !!he; 100 + return NULL; 102 101 } 103 102 104 103 static struct nft_elem_priv * ··· 121 120 return ERR_PTR(-ENOENT); 122 121 } 123 122 124 - static bool nft_rhash_update(struct nft_set *set, const u32 *key, 125 - struct nft_elem_priv * 126 - (*new)(struct nft_set *, 127 - const struct nft_expr *, 128 - struct nft_regs *regs), 129 - const struct nft_expr *expr, 130 - struct nft_regs *regs, 131 - const struct nft_set_ext **ext) 123 + static const struct nft_set_ext * 124 + nft_rhash_update(struct nft_set *set, const u32 *key, 125 + const struct nft_expr *expr, struct nft_regs *regs) 132 126 { 133 127 struct nft_rhash *priv = nft_set_priv(set); 134 128 struct nft_rhash_elem *he, *prev; ··· 139 143 if (he != NULL) 140 144 goto out; 141 145 142 - elem_priv = new(set, expr, regs); 146 + elem_priv = nft_dynset_new(set, expr, regs); 143 147 if (!elem_priv) 144 148 goto err1; 145 149 ··· 157 161 } 158 162 159 163 out: 160 - *ext = &he->ext; 161 - return true; 164 + return &he->ext; 162 165 163 166 err2: 164 167 nft_set_elem_destroy(set, &he->priv, true); 165 168 atomic_dec(&set->nelems); 166 169 err1: 167 - return false; 170 + return NULL; 168 171 } 169 172 170 173 static int nft_rhash_insert(const struct net *net, const struct nft_set *set, ··· 502 507 }; 503 508 504 509 INDIRECT_CALLABLE_SCOPE 505 - bool nft_hash_lookup(const struct net *net, const struct nft_set *set, 506 - const u32 *key, const struct nft_set_ext **ext) 510 + const struct nft_set_ext * 511 + nft_hash_lookup(const struct net *net, const struct nft_set *set, 512 + const u32 *key) 507 513 { 508 514 struct nft_hash *priv = nft_set_priv(set); 509 515 u8 genmask = nft_genmask_cur(net); ··· 515 519 hash = reciprocal_scale(hash, priv->buckets); 516 520 hlist_for_each_entry_rcu(he, &priv->table[hash], node) { 517 521 if (!memcmp(nft_set_ext_key(&he->ext), key, set->klen) && 518 - nft_set_elem_active(&he->ext, genmask)) { 519 - *ext = &he->ext; 520 - return true; 521 - } 522 + nft_set_elem_active(&he->ext, genmask)) 523 + return &he->ext; 522 524 } 523 - return false; 525 + return NULL; 524 526 } 525 527 526 528 static struct nft_elem_priv * ··· 541 547 } 542 548 543 549 INDIRECT_CALLABLE_SCOPE 544 - bool nft_hash_lookup_fast(const struct net *net, 545 - const struct nft_set *set, 546 - const u32 *key, const struct nft_set_ext **ext) 550 + const struct nft_set_ext * 551 + nft_hash_lookup_fast(const struct net *net, const struct nft_set *set, 552 + const u32 *key) 547 553 { 548 554 struct nft_hash *priv = nft_set_priv(set); 549 555 u8 genmask = nft_genmask_cur(net); ··· 556 562 hlist_for_each_entry_rcu(he, &priv->table[hash], node) { 557 563 k2 = *(u32 *)nft_set_ext_key(&he->ext)->data; 558 564 if (k1 == k2 && 559 - nft_set_elem_active(&he->ext, genmask)) { 560 - *ext = &he->ext; 561 - return true; 562 - } 565 + nft_set_elem_active(&he->ext, genmask)) 566 + return &he->ext; 563 567 } 564 - return false; 568 + return NULL; 565 569 } 566 570 567 571 static u32 nft_jhash(const struct nft_set *set, const struct nft_hash *priv,
+65 -139
net/netfilter/nft_set_pipapo.c
··· 397 397 } 398 398 399 399 /** 400 - * nft_pipapo_lookup() - Lookup function 401 - * @net: Network namespace 402 - * @set: nftables API set representation 403 - * @key: nftables API element representation containing key data 404 - * @ext: nftables API extension pointer, filled with matching reference 400 + * pipapo_get() - Get matching element reference given key data 401 + * @m: storage containing the set elements 402 + * @data: Key data to be matched against existing elements 403 + * @genmask: If set, check that element is active in given genmask 404 + * @tstamp: timestamp to check for expired elements 405 405 * 406 406 * For more details, see DOC: Theory of Operation. 407 407 * 408 - * Return: true on match, false otherwise. 408 + * This is the main lookup function. It matches key data against either 409 + * the working match set or the uncommitted copy, depending on what the 410 + * caller passed to us. 411 + * nft_pipapo_get (lookup from userspace/control plane) and nft_pipapo_lookup 412 + * (datapath lookup) pass the active copy. 413 + * The insertion path will pass the uncommitted working copy. 414 + * 415 + * Return: pointer to &struct nft_pipapo_elem on match, NULL otherwise. 409 416 */ 410 - bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, 411 - const u32 *key, const struct nft_set_ext **ext) 417 + static struct nft_pipapo_elem *pipapo_get(const struct nft_pipapo_match *m, 418 + const u8 *data, u8 genmask, 419 + u64 tstamp) 412 420 { 413 - struct nft_pipapo *priv = nft_set_priv(set); 414 421 struct nft_pipapo_scratch *scratch; 415 422 unsigned long *res_map, *fill_map; 416 - u8 genmask = nft_genmask_cur(net); 417 - const struct nft_pipapo_match *m; 418 423 const struct nft_pipapo_field *f; 419 - const u8 *rp = (const u8 *)key; 420 424 bool map_index; 421 425 int i; 422 426 423 427 local_bh_disable(); 424 428 425 - m = rcu_dereference(priv->match); 426 - 427 - if (unlikely(!m || !*raw_cpu_ptr(m->scratch))) 429 + if (unlikely(!raw_cpu_ptr(m->scratch))) 428 430 goto out; 429 431 430 432 scratch = *raw_cpu_ptr(m->scratch); ··· 446 444 * packet bytes value, then AND bucket value 447 445 */ 448 446 if (likely(f->bb == 8)) 449 - pipapo_and_field_buckets_8bit(f, res_map, rp); 447 + pipapo_and_field_buckets_8bit(f, res_map, data); 450 448 else 451 - pipapo_and_field_buckets_4bit(f, res_map, rp); 449 + pipapo_and_field_buckets_4bit(f, res_map, data); 452 450 NFT_PIPAPO_GROUP_BITS_ARE_8_OR_4; 453 451 454 - rp += f->groups / NFT_PIPAPO_GROUPS_PER_BYTE(f); 452 + data += f->groups / NFT_PIPAPO_GROUPS_PER_BYTE(f); 455 453 456 454 /* Now populate the bitmap for the next field, unless this is 457 455 * the last field, in which case return the matched 'ext' ··· 467 465 scratch->map_index = map_index; 468 466 local_bh_enable(); 469 467 470 - return false; 468 + return NULL; 471 469 } 472 470 473 471 if (last) { 474 - *ext = &f->mt[b].e->ext; 475 - if (unlikely(nft_set_elem_expired(*ext) || 476 - !nft_set_elem_active(*ext, genmask))) 472 + struct nft_pipapo_elem *e; 473 + 474 + e = f->mt[b].e; 475 + if (unlikely(__nft_set_elem_expired(&e->ext, tstamp) || 476 + !nft_set_elem_active(&e->ext, genmask))) 477 477 goto next_match; 478 478 479 479 /* Last field: we're just returning the key without ··· 485 481 */ 486 482 scratch->map_index = map_index; 487 483 local_bh_enable(); 488 - 489 - return true; 484 + return e; 490 485 } 491 486 492 487 /* Swap bitmap indices: res_map is the initial bitmap for the ··· 495 492 map_index = !map_index; 496 493 swap(res_map, fill_map); 497 494 498 - rp += NFT_PIPAPO_GROUPS_PADDING(f); 495 + data += NFT_PIPAPO_GROUPS_PADDING(f); 499 496 } 500 497 501 498 out: 502 499 local_bh_enable(); 503 - return false; 500 + return NULL; 504 501 } 505 502 506 503 /** 507 - * pipapo_get() - Get matching element reference given key data 504 + * nft_pipapo_lookup() - Dataplane fronted for main lookup function 508 505 * @net: Network namespace 509 506 * @set: nftables API set representation 510 - * @m: storage containing active/existing elements 511 - * @data: Key data to be matched against existing elements 512 - * @genmask: If set, check that element is active in given genmask 513 - * @tstamp: timestamp to check for expired elements 514 - * @gfp: the type of memory to allocate (see kmalloc). 507 + * @key: pointer to nft registers containing key data 515 508 * 516 - * This is essentially the same as the lookup function, except that it matches 517 - * key data against the uncommitted copy and doesn't use preallocated maps for 518 - * bitmap results. 509 + * This function is called from the data path. It will search for 510 + * an element matching the given key in the current active copy. 519 511 * 520 - * Return: pointer to &struct nft_pipapo_elem on match, error pointer otherwise. 512 + * Return: ntables API extension pointer or NULL if no match. 521 513 */ 522 - static struct nft_pipapo_elem *pipapo_get(const struct net *net, 523 - const struct nft_set *set, 524 - const struct nft_pipapo_match *m, 525 - const u8 *data, u8 genmask, 526 - u64 tstamp, gfp_t gfp) 514 + const struct nft_set_ext * 515 + nft_pipapo_lookup(const struct net *net, const struct nft_set *set, 516 + const u32 *key) 527 517 { 528 - struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT); 529 - unsigned long *res_map, *fill_map = NULL; 530 - const struct nft_pipapo_field *f; 531 - int i; 518 + struct nft_pipapo *priv = nft_set_priv(set); 519 + u8 genmask = nft_genmask_cur(net); 520 + const struct nft_pipapo_match *m; 521 + const struct nft_pipapo_elem *e; 532 522 533 - if (m->bsize_max == 0) 534 - return ret; 523 + m = rcu_dereference(priv->match); 524 + e = pipapo_get(m, (const u8 *)key, genmask, get_jiffies_64()); 535 525 536 - res_map = kmalloc_array(m->bsize_max, sizeof(*res_map), gfp); 537 - if (!res_map) { 538 - ret = ERR_PTR(-ENOMEM); 539 - goto out; 540 - } 541 - 542 - fill_map = kcalloc(m->bsize_max, sizeof(*res_map), gfp); 543 - if (!fill_map) { 544 - ret = ERR_PTR(-ENOMEM); 545 - goto out; 546 - } 547 - 548 - pipapo_resmap_init(m, res_map); 549 - 550 - nft_pipapo_for_each_field(f, i, m) { 551 - bool last = i == m->field_count - 1; 552 - int b; 553 - 554 - /* For each bit group: select lookup table bucket depending on 555 - * packet bytes value, then AND bucket value 556 - */ 557 - if (f->bb == 8) 558 - pipapo_and_field_buckets_8bit(f, res_map, data); 559 - else if (f->bb == 4) 560 - pipapo_and_field_buckets_4bit(f, res_map, data); 561 - else 562 - BUG(); 563 - 564 - data += f->groups / NFT_PIPAPO_GROUPS_PER_BYTE(f); 565 - 566 - /* Now populate the bitmap for the next field, unless this is 567 - * the last field, in which case return the matched 'ext' 568 - * pointer if any. 569 - * 570 - * Now res_map contains the matching bitmap, and fill_map is the 571 - * bitmap for the next field. 572 - */ 573 - next_match: 574 - b = pipapo_refill(res_map, f->bsize, f->rules, fill_map, f->mt, 575 - last); 576 - if (b < 0) 577 - goto out; 578 - 579 - if (last) { 580 - if (__nft_set_elem_expired(&f->mt[b].e->ext, tstamp)) 581 - goto next_match; 582 - if ((genmask && 583 - !nft_set_elem_active(&f->mt[b].e->ext, genmask))) 584 - goto next_match; 585 - 586 - ret = f->mt[b].e; 587 - goto out; 588 - } 589 - 590 - data += NFT_PIPAPO_GROUPS_PADDING(f); 591 - 592 - /* Swap bitmap indices: fill_map will be the initial bitmap for 593 - * the next field (i.e. the new res_map), and res_map is 594 - * guaranteed to be all-zeroes at this point, ready to be filled 595 - * according to the next mapping table. 596 - */ 597 - swap(res_map, fill_map); 598 - } 599 - 600 - out: 601 - kfree(fill_map); 602 - kfree(res_map); 603 - return ret; 526 + return e ? &e->ext : NULL; 604 527 } 605 528 606 529 /** ··· 535 606 * @set: nftables API set representation 536 607 * @elem: nftables API element representation containing key data 537 608 * @flags: Unused 609 + * 610 + * This function is called from the control plane path under 611 + * RCU read lock. 612 + * 613 + * Return: set element private pointer or ERR_PTR(-ENOENT). 538 614 */ 539 615 static struct nft_elem_priv * 540 616 nft_pipapo_get(const struct net *net, const struct nft_set *set, ··· 549 615 struct nft_pipapo_match *m = rcu_dereference(priv->match); 550 616 struct nft_pipapo_elem *e; 551 617 552 - e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data, 553 - nft_genmask_cur(net), get_jiffies_64(), 554 - GFP_ATOMIC); 555 - if (IS_ERR(e)) 556 - return ERR_CAST(e); 618 + e = pipapo_get(m, (const u8 *)elem->key.val.data, 619 + nft_genmask_cur(net), get_jiffies_64()); 620 + if (!e) 621 + return ERR_PTR(-ENOENT); 557 622 558 623 return &e->priv; 559 624 } ··· 1152 1219 1153 1220 mem = s; 1154 1221 mem -= s->align_off; 1155 - kfree(mem); 1222 + kvfree(mem); 1156 1223 } 1157 1224 1158 1225 /** ··· 1173 1240 void *scratch_aligned; 1174 1241 u32 align_off; 1175 1242 #endif 1176 - scratch = kzalloc_node(struct_size(scratch, map, 1177 - bsize_max * 2) + 1178 - NFT_PIPAPO_ALIGN_HEADROOM, 1179 - GFP_KERNEL_ACCOUNT, cpu_to_node(i)); 1243 + scratch = kvzalloc_node(struct_size(scratch, map, bsize_max * 2) + 1244 + NFT_PIPAPO_ALIGN_HEADROOM, 1245 + GFP_KERNEL_ACCOUNT, cpu_to_node(i)); 1180 1246 if (!scratch) { 1181 1247 /* On failure, there's no need to undo previous 1182 1248 * allocations: this means that some scratch maps have ··· 1277 1345 else 1278 1346 end = start; 1279 1347 1280 - dup = pipapo_get(net, set, m, start, genmask, tstamp, GFP_KERNEL); 1281 - if (!IS_ERR(dup)) { 1348 + dup = pipapo_get(m, start, genmask, tstamp); 1349 + if (dup) { 1282 1350 /* Check if we already have the same exact entry */ 1283 1351 const struct nft_data *dup_key, *dup_end; 1284 1352 ··· 1297 1365 return -ENOTEMPTY; 1298 1366 } 1299 1367 1300 - if (PTR_ERR(dup) == -ENOENT) { 1301 - /* Look for partially overlapping entries */ 1302 - dup = pipapo_get(net, set, m, end, nft_genmask_next(net), tstamp, 1303 - GFP_KERNEL); 1304 - } 1305 - 1306 - if (PTR_ERR(dup) != -ENOENT) { 1307 - if (IS_ERR(dup)) 1308 - return PTR_ERR(dup); 1368 + /* Look for partially overlapping entries */ 1369 + dup = pipapo_get(m, end, nft_genmask_next(net), tstamp); 1370 + if (dup) { 1309 1371 *elem_priv = &dup->priv; 1310 1372 return -ENOTEMPTY; 1311 1373 } ··· 1840 1914 if (!m) 1841 1915 return NULL; 1842 1916 1843 - e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data, 1844 - nft_genmask_next(net), nft_net_tstamp(net), GFP_KERNEL); 1845 - if (IS_ERR(e)) 1917 + e = pipapo_get(m, (const u8 *)elem->key.val.data, 1918 + nft_genmask_next(net), nft_net_tstamp(net)); 1919 + if (!e) 1846 1920 return NULL; 1847 1921 1848 1922 nft_set_elem_change_active(net, set, &e->ext);
+14 -12
net/netfilter/nft_set_pipapo_avx2.c
··· 1137 1137 * @net: Network namespace 1138 1138 * @set: nftables API set representation 1139 1139 * @key: nftables API element representation containing key data 1140 - * @ext: nftables API extension pointer, filled with matching reference 1141 1140 * 1142 1141 * For more details, see DOC: Theory of Operation in nft_set_pipapo.c. 1143 1142 * ··· 1145 1146 * 1146 1147 * Return: true on match, false otherwise. 1147 1148 */ 1148 - bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, 1149 - const u32 *key, const struct nft_set_ext **ext) 1149 + const struct nft_set_ext * 1150 + nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, 1151 + const u32 *key) 1150 1152 { 1151 1153 struct nft_pipapo *priv = nft_set_priv(set); 1152 1154 struct nft_pipapo_scratch *scratch; ··· 1155 1155 const struct nft_pipapo_match *m; 1156 1156 const struct nft_pipapo_field *f; 1157 1157 const u8 *rp = (const u8 *)key; 1158 + const struct nft_set_ext *ext; 1158 1159 unsigned long *res, *fill; 1159 1160 bool map_index; 1160 - int i, ret = 0; 1161 + int i; 1161 1162 1162 1163 local_bh_disable(); 1163 1164 1164 1165 if (unlikely(!irq_fpu_usable())) { 1165 - bool fallback_res = nft_pipapo_lookup(net, set, key, ext); 1166 + ext = nft_pipapo_lookup(net, set, key); 1166 1167 1167 1168 local_bh_enable(); 1168 - return fallback_res; 1169 + return ext; 1169 1170 } 1170 1171 1171 1172 m = rcu_dereference(priv->match); ··· 1183 1182 if (unlikely(!scratch)) { 1184 1183 kernel_fpu_end(); 1185 1184 local_bh_enable(); 1186 - return false; 1185 + return NULL; 1187 1186 } 1188 1187 1189 1188 map_index = scratch->map_index; ··· 1198 1197 next_match: 1199 1198 nft_pipapo_for_each_field(f, i, m) { 1200 1199 bool last = i == m->field_count - 1, first = !i; 1200 + int ret = 0; 1201 1201 1202 1202 #define NFT_SET_PIPAPO_AVX2_LOOKUP(b, n) \ 1203 1203 (ret = nft_pipapo_avx2_lookup_##b##b_##n(res, fill, f, \ ··· 1246 1244 goto out; 1247 1245 1248 1246 if (last) { 1249 - *ext = &f->mt[ret].e->ext; 1250 - if (unlikely(nft_set_elem_expired(*ext) || 1251 - !nft_set_elem_active(*ext, genmask))) { 1252 - ret = 0; 1247 + ext = &f->mt[ret].e->ext; 1248 + if (unlikely(nft_set_elem_expired(ext) || 1249 + !nft_set_elem_active(ext, genmask))) { 1250 + ext = NULL; 1253 1251 goto next_match; 1254 1252 } 1255 1253 ··· 1266 1264 kernel_fpu_end(); 1267 1265 local_bh_enable(); 1268 1266 1269 - return ret >= 0; 1267 + return ext; 1270 1268 }
+19 -21
net/netfilter/nft_set_rbtree.c
··· 52 52 return nft_set_elem_expired(&rbe->ext); 53 53 } 54 54 55 - static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, 56 - const u32 *key, const struct nft_set_ext **ext, 57 - unsigned int seq) 55 + static const struct nft_set_ext * 56 + __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, 57 + const u32 *key, unsigned int seq) 58 58 { 59 59 struct nft_rbtree *priv = nft_set_priv(set); 60 60 const struct nft_rbtree_elem *rbe, *interval = NULL; ··· 65 65 parent = rcu_dereference_raw(priv->root.rb_node); 66 66 while (parent != NULL) { 67 67 if (read_seqcount_retry(&priv->count, seq)) 68 - return false; 68 + return NULL; 69 69 70 70 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 71 71 ··· 87 87 } 88 88 89 89 if (nft_rbtree_elem_expired(rbe)) 90 - return false; 90 + return NULL; 91 91 92 92 if (nft_rbtree_interval_end(rbe)) { 93 93 if (nft_set_is_anonymous(set)) 94 - return false; 94 + return NULL; 95 95 parent = rcu_dereference_raw(parent->rb_left); 96 96 interval = NULL; 97 97 continue; 98 98 } 99 99 100 - *ext = &rbe->ext; 101 - return true; 100 + return &rbe->ext; 102 101 } 103 102 } 104 103 105 104 if (set->flags & NFT_SET_INTERVAL && interval != NULL && 106 105 nft_set_elem_active(&interval->ext, genmask) && 107 106 !nft_rbtree_elem_expired(interval) && 108 - nft_rbtree_interval_start(interval)) { 109 - *ext = &interval->ext; 110 - return true; 111 - } 107 + nft_rbtree_interval_start(interval)) 108 + return &interval->ext; 112 109 113 - return false; 110 + return NULL; 114 111 } 115 112 116 113 INDIRECT_CALLABLE_SCOPE 117 - bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, 118 - const u32 *key, const struct nft_set_ext **ext) 114 + const struct nft_set_ext * 115 + nft_rbtree_lookup(const struct net *net, const struct nft_set *set, 116 + const u32 *key) 119 117 { 120 118 struct nft_rbtree *priv = nft_set_priv(set); 121 119 unsigned int seq = read_seqcount_begin(&priv->count); 122 - bool ret; 120 + const struct nft_set_ext *ext; 123 121 124 - ret = __nft_rbtree_lookup(net, set, key, ext, seq); 125 - if (ret || !read_seqcount_retry(&priv->count, seq)) 126 - return ret; 122 + ext = __nft_rbtree_lookup(net, set, key, seq); 123 + if (ext || !read_seqcount_retry(&priv->count, seq)) 124 + return ext; 127 125 128 126 read_lock_bh(&priv->lock); 129 127 seq = read_seqcount_begin(&priv->count); 130 - ret = __nft_rbtree_lookup(net, set, key, ext, seq); 128 + ext = __nft_rbtree_lookup(net, set, key, seq); 131 129 read_unlock_bh(&priv->lock); 132 130 133 - return ret; 131 + return ext; 134 132 } 135 133 136 134 static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
+11 -5
net/netfilter/x_tables.c
··· 1317 1317 EXPORT_SYMBOL_GPL(xt_compat_unlock); 1318 1318 #endif 1319 1319 1320 - DEFINE_PER_CPU(seqcount_t, xt_recseq); 1321 - EXPORT_PER_CPU_SYMBOL_GPL(xt_recseq); 1322 - 1323 1320 struct static_key xt_tee_enabled __read_mostly; 1324 1321 EXPORT_SYMBOL_GPL(xt_tee_enabled); 1322 + 1323 + #ifdef CONFIG_NETFILTER_XTABLES_LEGACY 1324 + DEFINE_PER_CPU(seqcount_t, xt_recseq); 1325 + EXPORT_PER_CPU_SYMBOL_GPL(xt_recseq); 1325 1326 1326 1327 static int xt_jumpstack_alloc(struct xt_table_info *i) 1327 1328 { ··· 1515 1514 return private; 1516 1515 } 1517 1516 EXPORT_SYMBOL_GPL(xt_unregister_table); 1517 + #endif 1518 1518 1519 1519 #ifdef CONFIG_PROC_FS 1520 1520 static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos) ··· 1899 1897 } 1900 1898 EXPORT_SYMBOL_GPL(xt_proto_fini); 1901 1899 1900 + #ifdef CONFIG_NETFILTER_XTABLES_LEGACY 1902 1901 /** 1903 1902 * xt_percpu_counter_alloc - allocate x_tables rule counter 1904 1903 * ··· 1954 1951 free_percpu((void __percpu *)pcnt); 1955 1952 } 1956 1953 EXPORT_SYMBOL_GPL(xt_percpu_counter_free); 1954 + #endif 1957 1955 1958 1956 static int __net_init xt_net_init(struct net *net) 1959 1957 { ··· 1987 1983 unsigned int i; 1988 1984 int rv; 1989 1985 1990 - for_each_possible_cpu(i) { 1991 - seqcount_init(&per_cpu(xt_recseq, i)); 1986 + if (IS_ENABLED(CONFIG_NETFILTER_XTABLES_LEGACY)) { 1987 + for_each_possible_cpu(i) { 1988 + seqcount_init(&per_cpu(xt_recseq, i)); 1989 + } 1992 1990 } 1993 1991 1994 1992 xt = kcalloc(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
+2 -2
net/netfilter/xt_nfacct.c
··· 38 38 39 39 nfacct = nfnl_acct_find_get(par->net, info->name); 40 40 if (nfacct == NULL) { 41 - pr_info_ratelimited("accounting object `%s' does not exists\n", 42 - info->name); 41 + pr_info_ratelimited("accounting object `%.*s' does not exist\n", 42 + NFACCT_NAME_MAX, info->name); 43 43 return -ENOENT; 44 44 } 45 45 info->nfacct = nfacct;
+1
tools/testing/selftests/bpf/config
··· 97 97 CONFIG_NF_TABLES_IPV4=y 98 98 CONFIG_NF_TABLES_IPV6=y 99 99 CONFIG_NETFILTER_INGRESS=y 100 + CONFIG_NETFILTER_XTABLES_LEGACY=y 100 101 CONFIG_NF_FLOW_TABLE=y 101 102 CONFIG_NF_FLOW_TABLE_INET=y 102 103 CONFIG_NETFILTER_NETLINK=y
+1
tools/testing/selftests/hid/config.common
··· 135 135 CONFIG_NETFILTER_NETLINK_LOG=y 136 136 CONFIG_NETFILTER_NETLINK_QUEUE=y 137 137 CONFIG_NETFILTER_XTABLES=y 138 + CONFIG_NETFILTER_XTABLES_LEGACY=y 138 139 CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y 139 140 CONFIG_NETFILTER_XT_MATCH_BPF=y 140 141 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+11
tools/testing/selftests/net/config
··· 30 30 CONFIG_NET_FOU_IP_TUNNELS=y 31 31 CONFIG_NETFILTER=y 32 32 CONFIG_NETFILTER_ADVANCED=y 33 + CONFIG_NETFILTER_XTABLES_LEGACY=y 33 34 CONFIG_NF_CONNTRACK=m 34 35 CONFIG_IPV6_MROUTE=y 35 36 CONFIG_IPV6_SIT=y 36 37 CONFIG_NF_NAT=m 37 38 CONFIG_IP6_NF_IPTABLES=m 39 + CONFIG_IP6_NF_IPTABLES_LEGACY=m 38 40 CONFIG_IP_NF_IPTABLES=m 41 + CONFIG_IP_NF_IPTABLES_LEGACY=m 42 + CONFIG_IP6_NF_MANGLE=m 43 + CONFIG_IP6_NF_FILTER=m 39 44 CONFIG_IP6_NF_NAT=m 40 45 CONFIG_IP6_NF_RAW=m 46 + CONFIG_IP_NF_MANGLE=m 47 + CONFIG_IP_NF_FILTER=m 41 48 CONFIG_IP_NF_NAT=m 42 49 CONFIG_IP_NF_RAW=m 50 + CONFIG_IP_NF_TARGET_REJECT=m 51 + CONFIG_IP6_NF_TARGET_REJECT=m 43 52 CONFIG_IP_NF_TARGET_TTL=m 44 53 CONFIG_IPV6_GRE=m 45 54 CONFIG_IPV6_SEG6_LWTUNNEL=y ··· 66 57 CONFIG_NF_TABLES_IPV4=y 67 58 CONFIG_NFT_NAT=m 68 59 CONFIG_NETFILTER_XT_MATCH_LENGTH=m 60 + CONFIG_NETFILTER_XT_TARGET_HL=m 61 + CONFIG_NETFILTER_XT_NAT=m 69 62 CONFIG_NET_ACT_CSUM=m 70 63 CONFIG_NET_ACT_CT=m 71 64 CONFIG_NET_ACT_GACT=m
+2
tools/testing/selftests/net/mptcp/config
··· 13 13 CONFIG_NF_TABLES=m 14 14 CONFIG_NFT_COMPAT=m 15 15 CONFIG_NETFILTER_XTABLES=m 16 + CONFIG_NETFILTER_XTABLES_LEGACY=y 16 17 CONFIG_NETFILTER_XT_MATCH_BPF=m 17 18 CONFIG_NETFILTER_XT_MATCH_LENGTH=m 18 19 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ··· 26 25 CONFIG_IP_NF_FILTER=m 27 26 CONFIG_IP_NF_MANGLE=m 28 27 CONFIG_IP_NF_TARGET_REJECT=m 28 + CONFIG_IP6_NF_TARGET_REJECT=m 29 29 CONFIG_IPV6_MULTIPLE_TABLES=y 30 30 CONFIG_IP6_NF_FILTER=m 31 31 CONFIG_NET_ACT_CSUM=m
+6 -1
tools/testing/selftests/net/netfilter/config
··· 1 1 CONFIG_AUDIT=y 2 2 CONFIG_BPF_SYSCALL=y 3 3 CONFIG_BRIDGE=m 4 + CONFIG_NETFILTER_XTABLES_LEGACY=y 5 + CONFIG_BRIDGE_NF_EBTABLES_LEGACY=m 4 6 CONFIG_BRIDGE_EBT_BROUTE=m 5 7 CONFIG_BRIDGE_EBT_IP=m 6 8 CONFIG_BRIDGE_EBT_REDIRECT=m ··· 16 14 CONFIG_IP_NF_MATCH_RPFILTER=m 17 15 CONFIG_IP6_NF_MATCH_RPFILTER=m 18 16 CONFIG_IP_NF_IPTABLES=m 17 + CONFIG_IP_NF_IPTABLES_LEGACY=m 19 18 CONFIG_IP6_NF_IPTABLES=m 19 + CONFIG_IP6_NF_IPTABLES_LEGACY=m 20 + CONFIG_IP_NF_NAT=m 20 21 CONFIG_IP_NF_FILTER=m 21 22 CONFIG_IP6_NF_FILTER=m 22 23 CONFIG_IP_NF_RAW=m ··· 97 92 CONFIG_NET_PKTGEN=m 98 93 CONFIG_TUN=m 99 94 CONFIG_INET_DIAG=m 100 - CONFIG_SCTP_DIAG=m 95 + CONFIG_INET_SCTP_DIAG=m
+2 -2
tools/testing/selftests/net/netfilter/ipvs.sh
··· 151 151 test_tun() { 152 152 ip netns exec "${ns0}" ip route add "${vip_v4}" via "${gip_v4}" dev br0 153 153 154 - ip netns exec "${ns1}" modprobe -q ipip 154 + modprobe -q ipip 155 155 ip netns exec "${ns1}" ip link set tunl0 up 156 156 ip netns exec "${ns1}" sysctl -qw net.ipv4.ip_forward=0 157 157 ip netns exec "${ns1}" sysctl -qw net.ipv4.conf.all.send_redirects=0 ··· 160 160 ip netns exec "${ns1}" ipvsadm -a -i -t "${vip_v4}:${port}" -r ${rip_v4}:${port} 161 161 ip netns exec "${ns1}" ip addr add ${vip_v4}/32 dev lo:1 162 162 163 - ip netns exec "${ns2}" modprobe -q ipip 164 163 ip netns exec "${ns2}" ip link set tunl0 up 165 164 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_ignore=1 166 165 ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_announce=2 166 + ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.tunl0.rp_filter=0 167 167 ip netns exec "${ns2}" ip addr add "${vip_v4}/32" dev lo:1 168 168 169 169 test_service
+4 -1
tools/testing/selftests/net/netfilter/nft_interface_stress.sh
··· 10 10 checktool "nft --version" "run test without nft tool" 11 11 checktool "iperf3 --version" "run test without iperf3 tool" 12 12 13 + read kernel_tainted < /proc/sys/kernel/tainted 14 + 13 15 # how many seconds to torture the kernel? 14 16 # default to 80% of max run time but don't exceed 48s 15 17 TEST_RUNTIME=$((${kselftest_timeout:-60} * 8 / 10)) ··· 137 135 wait 138 136 fi 139 137 140 - [[ $(</proc/sys/kernel/tainted) -eq 0 ]] || { 138 + 139 + [[ $kernel_tainted -eq 0 && $(</proc/sys/kernel/tainted) -ne 0 ]] && { 141 140 echo "FAIL: Kernel is tainted!" 142 141 exit $ksft_fail 143 142 }
+4
tools/testing/selftests/wireguard/qemu/kernel.config
··· 16 16 CONFIG_NF_CONNTRACK=y 17 17 CONFIG_NF_NAT=y 18 18 CONFIG_NETFILTER_XTABLES=y 19 + CONFIG_NETFILTER_XTABLES_LEGACY=y 19 20 CONFIG_NETFILTER_XT_NAT=y 20 21 CONFIG_NETFILTER_XT_MATCH_LENGTH=y 21 22 CONFIG_NETFILTER_XT_MARK=y 23 + CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m 24 + CONFIG_IP_NF_TARGET_REJECT=m 25 + CONFIG_IP6_NF_TARGET_REJECT=m 22 26 CONFIG_IP_NF_IPTABLES=y 23 27 CONFIG_IP_NF_FILTER=y 24 28 CONFIG_IP_NF_MANGLE=y