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

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

Florian Westphal says:

====================
netfilter: updates for net-next

1) prefer vmalloc_array in ebtables, from Qianfeng Rong.

2) Use csum_replace4 instead of open-coding it, from Christophe Leroy.

3+4) Get rid of GFP_ATOMIC in transaction object allocations, those
cause silly failures with large sets under memory pressure, from
myself.

5) Remove test for AVX cpu feature in nftables pipapo set type,
testing for AVX2 feature is sufficient.

6) Unexport a few function in nf_reject infra: no external callers.

7) Extend payload offset to u16, this was restricted to values <=255
so far, from Fernando Fernandez Mancera.

* tag 'nf-next-25-09-02' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
netfilter: nft_payload: extend offset to 65535 bytes
netfilter: nf_reject: remove unneeded exports
netfilter: nft_set_pipapo: remove redundant test for avx feature bit
netfilter: nf_tables: all transaction allocations can now sleep
netfilter: nf_tables: allow iter callbacks to sleep
netfilter: nft_payload: Use csum_replace4() instead of opencoding
netfilter: ebtables: Use vmalloc_array() to improve code
====================

Link: https://patch.msgid.link/20250902133549.15945-1-fw@strlen.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+209 -98
-8
include/net/netfilter/ipv4/nf_reject.h
··· 10 10 void nf_send_unreach(struct sk_buff *skb_in, int code, int hook); 11 11 void nf_send_reset(struct net *net, struct sock *, struct sk_buff *oldskb, 12 12 int hook); 13 - const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, 14 - struct tcphdr *_oth, int hook); 15 - struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb, 16 - const struct sk_buff *oldskb, 17 - __u8 protocol, int ttl); 18 - void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, 19 - const struct tcphdr *oth); 20 - 21 13 struct sk_buff *nf_reject_skb_v4_unreach(struct net *net, 22 14 struct sk_buff *oldskb, 23 15 const struct net_device *dev,
-10
include/net/netfilter/ipv6/nf_reject.h
··· 9 9 unsigned int hooknum); 10 10 void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb, 11 11 int hook); 12 - const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, 13 - struct tcphdr *otcph, 14 - unsigned int *otcplen, int hook); 15 - struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb, 16 - const struct sk_buff *oldskb, 17 - __u8 protocol, int hoplimit); 18 - void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, 19 - const struct sk_buff *oldskb, 20 - const struct tcphdr *oth, unsigned int otcplen); 21 - 22 12 struct sk_buff *nf_reject_skb_v6_tcp_reset(struct net *net, 23 13 struct sk_buff *oldskb, 24 14 const struct net_device *dev,
+2
include/net/netfilter/nf_tables.h
··· 556 556 * @size: maximum set size 557 557 * @field_len: length of each field in concatenation, bytes 558 558 * @field_count: number of concatenated fields in element 559 + * @in_update_walk: true during ->walk() in transaction phase 559 560 * @use: number of rules references to this set 560 561 * @nelems: number of elements 561 562 * @ndeact: number of deactivated elements queued for removal ··· 591 590 u32 size; 592 591 u8 field_len[NFT_REG32_COUNT]; 593 592 u8 field_count; 593 + bool in_update_walk; 594 594 u32 use; 595 595 atomic_t nelems; 596 596 u32 ndeact;
+1 -1
include/net/netfilter/nf_tables_core.h
··· 73 73 74 74 struct nft_payload { 75 75 enum nft_payload_bases base:8; 76 - u8 offset; 76 + u16 offset; 77 77 u8 len; 78 78 u8 dreg; 79 79 };
+7 -7
net/bridge/netfilter/ebtables.c
··· 920 920 * if an error occurs 921 921 */ 922 922 newinfo->chainstack = 923 - vmalloc(array_size(nr_cpu_ids, 924 - sizeof(*(newinfo->chainstack)))); 923 + vmalloc_array(nr_cpu_ids, 924 + sizeof(*(newinfo->chainstack))); 925 925 if (!newinfo->chainstack) 926 926 return -ENOMEM; 927 927 for_each_possible_cpu(i) { ··· 938 938 } 939 939 } 940 940 941 - cl_s = vmalloc(array_size(udc_cnt, sizeof(*cl_s))); 941 + cl_s = vmalloc_array(udc_cnt, sizeof(*cl_s)); 942 942 if (!cl_s) 943 943 return -ENOMEM; 944 944 i = 0; /* the i'th udc */ ··· 1018 1018 * the check on the size is done later, when we have the lock 1019 1019 */ 1020 1020 if (repl->num_counters) { 1021 - unsigned long size = repl->num_counters * sizeof(*counterstmp); 1022 - counterstmp = vmalloc(size); 1021 + counterstmp = vmalloc_array(repl->num_counters, 1022 + sizeof(*counterstmp)); 1023 1023 if (!counterstmp) 1024 1024 return -ENOMEM; 1025 1025 } ··· 1386 1386 if (num_counters == 0) 1387 1387 return -EINVAL; 1388 1388 1389 - tmp = vmalloc(array_size(num_counters, sizeof(*tmp))); 1389 + tmp = vmalloc_array(num_counters, sizeof(*tmp)); 1390 1390 if (!tmp) 1391 1391 return -ENOMEM; 1392 1392 ··· 1526 1526 if (num_counters != nentries) 1527 1527 return -EINVAL; 1528 1528 1529 - counterstmp = vmalloc(array_size(nentries, sizeof(*counterstmp))); 1529 + counterstmp = vmalloc_array(nentries, sizeof(*counterstmp)); 1530 1530 if (!counterstmp) 1531 1531 return -ENOMEM; 1532 1532
+17 -10
net/ipv4/netfilter/nf_reject_ipv4.c
··· 12 12 #include <linux/netfilter_ipv4.h> 13 13 #include <linux/netfilter_bridge.h> 14 14 15 + static struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb, 16 + const struct sk_buff *oldskb, 17 + __u8 protocol, int ttl); 18 + static void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, 19 + const struct tcphdr *oth); 20 + static const struct tcphdr * 21 + nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, 22 + struct tcphdr *_oth, int hook); 23 + 15 24 static int nf_reject_iphdr_validate(struct sk_buff *skb) 16 25 { 17 26 struct iphdr *iph; ··· 145 136 } 146 137 EXPORT_SYMBOL_GPL(nf_reject_skb_v4_unreach); 147 138 148 - const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, 149 - struct tcphdr *_oth, int hook) 139 + static const struct tcphdr * 140 + nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, 141 + struct tcphdr *_oth, int hook) 150 142 { 151 143 const struct tcphdr *oth; 152 144 ··· 173 163 174 164 return oth; 175 165 } 176 - EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_get); 177 166 178 - struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb, 179 - const struct sk_buff *oldskb, 180 - __u8 protocol, int ttl) 167 + static struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb, 168 + const struct sk_buff *oldskb, 169 + __u8 protocol, int ttl) 181 170 { 182 171 struct iphdr *niph, *oiph = ip_hdr(oldskb); 183 172 ··· 197 188 198 189 return niph; 199 190 } 200 - EXPORT_SYMBOL_GPL(nf_reject_iphdr_put); 201 191 202 - void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, 203 - const struct tcphdr *oth) 192 + static void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb, 193 + const struct tcphdr *oth) 204 194 { 205 195 struct iphdr *niph = ip_hdr(nskb); 206 196 struct tcphdr *tcph; ··· 226 218 nskb->csum_start = (unsigned char *)tcph - nskb->head; 227 219 nskb->csum_offset = offsetof(struct tcphdr, check); 228 220 } 229 - EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put); 230 221 231 222 static int nf_reject_fill_skb_dst(struct sk_buff *skb_in) 232 223 {
+25 -12
net/ipv6/netfilter/nf_reject_ipv6.c
··· 12 12 #include <linux/netfilter_ipv6.h> 13 13 #include <linux/netfilter_bridge.h> 14 14 15 + static struct ipv6hdr * 16 + nf_reject_ip6hdr_put(struct sk_buff *nskb, 17 + const struct sk_buff *oldskb, 18 + __u8 protocol, int hoplimit); 19 + static void 20 + nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, 21 + const struct sk_buff *oldskb, 22 + const struct tcphdr *oth, unsigned int otcplen); 23 + static const struct tcphdr * 24 + nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, 25 + struct tcphdr *otcph, 26 + unsigned int *otcplen, int hook); 27 + 15 28 static bool nf_reject_v6_csum_ok(struct sk_buff *skb, int hook) 16 29 { 17 30 const struct ipv6hdr *ip6h = ipv6_hdr(skb); ··· 159 146 } 160 147 EXPORT_SYMBOL_GPL(nf_reject_skb_v6_unreach); 161 148 162 - const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, 163 - struct tcphdr *otcph, 164 - unsigned int *otcplen, int hook) 149 + static const struct tcphdr * 150 + nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, 151 + struct tcphdr *otcph, 152 + unsigned int *otcplen, int hook) 165 153 { 166 154 const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); 167 155 u8 proto; ··· 206 192 207 193 return otcph; 208 194 } 209 - EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_get); 210 195 211 - struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb, 212 - const struct sk_buff *oldskb, 213 - __u8 protocol, int hoplimit) 196 + static struct ipv6hdr * 197 + nf_reject_ip6hdr_put(struct sk_buff *nskb, 198 + const struct sk_buff *oldskb, 199 + __u8 protocol, int hoplimit) 214 200 { 215 201 struct ipv6hdr *ip6h; 216 202 const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); ··· 230 216 231 217 return ip6h; 232 218 } 233 - EXPORT_SYMBOL_GPL(nf_reject_ip6hdr_put); 234 219 235 - void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, 236 - const struct sk_buff *oldskb, 237 - const struct tcphdr *oth, unsigned int otcplen) 220 + static void 221 + nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, 222 + const struct sk_buff *oldskb, 223 + const struct tcphdr *oth, unsigned int otcplen) 238 224 { 239 225 struct tcphdr *tcph; 240 226 ··· 262 248 csum_partial(tcph, 263 249 sizeof(struct tcphdr), 0)); 264 250 } 265 - EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put); 266 251 267 252 static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in) 268 253 {
+19 -28
net/netfilter/nf_tables_api.c
··· 151 151 bitmap_zero(ctx->reg_inited, NFT_REG32_NUM); 152 152 } 153 153 154 - static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx, 155 - int msg_type, u32 size, gfp_t gfp) 154 + static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx, 155 + int msg_type, u32 size) 156 156 { 157 157 struct nft_trans *trans; 158 158 159 - trans = kzalloc(size, gfp); 159 + trans = kzalloc(size, GFP_KERNEL); 160 160 if (trans == NULL) 161 161 return NULL; 162 162 ··· 170 170 trans->report = ctx->report; 171 171 172 172 return trans; 173 - } 174 - 175 - static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx, 176 - int msg_type, u32 size) 177 - { 178 - return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL); 179 173 } 180 174 181 175 static struct nft_trans_binding *nft_trans_get_binding(struct nft_trans *trans) ··· 436 442 437 443 static bool nft_trans_collapse_set_elem(struct nftables_pernet *nft_net, 438 444 struct nft_trans_elem *tail, 439 - struct nft_trans_elem *trans, 440 - gfp_t gfp) 445 + struct nft_trans_elem *trans) 441 446 { 442 447 unsigned int nelems, old_nelems = tail->nelems; 443 448 struct nft_trans_elem *new_trans; ··· 459 466 /* krealloc might free tail which invalidates list pointers */ 460 467 list_del_init(&tail->nft_trans.list); 461 468 462 - new_trans = krealloc(tail, struct_size(tail, elems, nelems), gfp); 469 + new_trans = krealloc(tail, struct_size(tail, elems, nelems), 470 + GFP_KERNEL); 463 471 if (!new_trans) { 464 - list_add_tail(&tail->nft_trans.list, &nft_net->commit_list); 472 + list_add_tail(&tail->nft_trans.list, 473 + &nft_net->commit_list); 465 474 return false; 466 475 } 467 476 ··· 479 484 } 480 485 481 486 static bool nft_trans_try_collapse(struct nftables_pernet *nft_net, 482 - struct nft_trans *trans, gfp_t gfp) 487 + struct nft_trans *trans) 483 488 { 484 489 struct nft_trans *tail; 485 490 ··· 496 501 case NFT_MSG_DELSETELEM: 497 502 return nft_trans_collapse_set_elem(nft_net, 498 503 nft_trans_container_elem(tail), 499 - nft_trans_container_elem(trans), gfp); 504 + nft_trans_container_elem(trans)); 500 505 } 501 506 502 507 return false; ··· 532 537 } 533 538 } 534 539 535 - static void nft_trans_commit_list_add_elem(struct net *net, struct nft_trans *trans, 536 - gfp_t gfp) 540 + static void nft_trans_commit_list_add_elem(struct net *net, struct nft_trans *trans) 537 541 { 538 542 struct nftables_pernet *nft_net = nft_pernet(net); 539 543 540 544 WARN_ON_ONCE(trans->msg_type != NFT_MSG_NEWSETELEM && 541 545 trans->msg_type != NFT_MSG_DELSETELEM); 542 546 543 - might_alloc(gfp); 544 - 545 - if (nft_trans_try_collapse(nft_net, trans, gfp)) { 547 + if (nft_trans_try_collapse(nft_net, trans)) { 546 548 kfree(trans); 547 549 return; 548 550 } ··· 7541 7549 } 7542 7550 7543 7551 ue->priv = elem_priv; 7544 - nft_trans_commit_list_add_elem(ctx->net, trans, GFP_KERNEL); 7552 + nft_trans_commit_list_add_elem(ctx->net, trans); 7545 7553 goto err_elem_free; 7546 7554 } 7547 7555 } ··· 7565 7573 } 7566 7574 7567 7575 nft_trans_container_elem(trans)->elems[0].priv = elem.priv; 7568 - nft_trans_commit_list_add_elem(ctx->net, trans, GFP_KERNEL); 7576 + nft_trans_commit_list_add_elem(ctx->net, trans); 7569 7577 return 0; 7570 7578 7571 7579 err_set_full: ··· 7831 7839 nft_setelem_data_deactivate(ctx->net, set, elem.priv); 7832 7840 7833 7841 nft_trans_container_elem(trans)->elems[0].priv = elem.priv; 7834 - nft_trans_commit_list_add_elem(ctx->net, trans, GFP_KERNEL); 7842 + nft_trans_commit_list_add_elem(ctx->net, trans); 7835 7843 return 0; 7836 7844 7837 7845 fail_ops: ··· 7856 7864 if (!nft_set_elem_active(ext, iter->genmask)) 7857 7865 return 0; 7858 7866 7859 - trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM, 7860 - struct_size_t(struct nft_trans_elem, elems, 1), 7861 - GFP_ATOMIC); 7867 + trans = nft_trans_alloc(ctx, NFT_MSG_DELSETELEM, 7868 + struct_size_t(struct nft_trans_elem, elems, 1)); 7862 7869 if (!trans) 7863 7870 return -ENOMEM; 7864 7871 ··· 7868 7877 nft_trans_elem_set(trans) = set; 7869 7878 nft_trans_container_elem(trans)->nelems = 1; 7870 7879 nft_trans_container_elem(trans)->elems[0].priv = elem_priv; 7871 - nft_trans_commit_list_add_elem(ctx->net, trans, GFP_ATOMIC); 7880 + nft_trans_commit_list_add_elem(ctx->net, trans); 7872 7881 7873 7882 return 0; 7874 7883 } ··· 7885 7894 7886 7895 nft_setelem_data_deactivate(ctx->net, set, elem_priv); 7887 7896 nft_trans_container_elem(trans)->elems[0].priv = elem_priv; 7888 - nft_trans_commit_list_add_elem(ctx->net, trans, GFP_KERNEL); 7897 + nft_trans_commit_list_add_elem(ctx->net, trans); 7889 7898 7890 7899 return 0; 7891 7900 }
+12 -8
net/netfilter/nft_payload.c
··· 40 40 41 41 /* add vlan header into the user buffer for if tag was removed by offloads */ 42 42 static bool 43 - nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len) 43 + nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u16 offset, u8 len) 44 44 { 45 45 int mac_off = skb_mac_header(skb) - skb->data; 46 46 u8 *vlanh, *dst_u8 = (u8 *) d; ··· 212 212 [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, 213 213 [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, 214 214 [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, 215 - [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), 215 + [NFTA_PAYLOAD_OFFSET] = { .type = NLA_BE32 }, 216 216 [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX(NLA_BE32, 255), 217 217 [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, 218 218 [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), ··· 684 684 685 685 static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum) 686 686 { 687 - *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum)); 687 + csum_replace4(sum, (__force __be32)fsum, (__force __be32)tsum); 688 688 if (*sum == 0) 689 689 *sum = CSUM_MANGLED_0; 690 690 } ··· 797 797 798 798 struct nft_payload_set { 799 799 enum nft_payload_bases base:8; 800 - u8 offset; 800 + u16 offset; 801 801 u8 len; 802 802 u8 sreg; 803 803 u8 csum_type; ··· 812 812 }; 813 813 814 814 static bool 815 - nft_payload_set_vlan(const u32 *src, struct sk_buff *skb, u8 offset, u8 len, 815 + nft_payload_set_vlan(const u32 *src, struct sk_buff *skb, u16 offset, u8 len, 816 816 int *vlan_hlen) 817 817 { 818 818 struct nft_payload_vlan_hdr *vlanh; ··· 940 940 const struct nft_expr *expr, 941 941 const struct nlattr * const tb[]) 942 942 { 943 + u32 csum_offset, offset, csum_type = NFT_PAYLOAD_CSUM_NONE; 943 944 struct nft_payload_set *priv = nft_expr_priv(expr); 944 - u32 csum_offset, csum_type = NFT_PAYLOAD_CSUM_NONE; 945 945 int err; 946 946 947 947 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 948 - priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 949 948 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 949 + 950 + err = nft_parse_u32_check(tb[NFTA_PAYLOAD_OFFSET], U16_MAX, &offset); 951 + if (err < 0) 952 + return err; 953 + priv->offset = offset; 950 954 951 955 if (tb[NFTA_PAYLOAD_CSUM_TYPE]) 952 956 csum_type = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE])); ··· 1073 1069 if (tb[NFTA_PAYLOAD_DREG] == NULL) 1074 1070 return ERR_PTR(-EINVAL); 1075 1071 1076 - err = nft_parse_u32_check(tb[NFTA_PAYLOAD_OFFSET], U8_MAX, &offset); 1072 + err = nft_parse_u32_check(tb[NFTA_PAYLOAD_OFFSET], U16_MAX, &offset); 1077 1073 if (err < 0) 1078 1074 return ERR_PTR(err); 1079 1075
+97 -3
net/netfilter/nft_set_hash.c
··· 30 30 struct nft_rhash_elem { 31 31 struct nft_elem_priv priv; 32 32 struct rhash_head node; 33 + struct llist_node walk_node; 33 34 u32 wq_gc_seq; 34 35 struct nft_set_ext ext; 35 36 }; ··· 145 144 goto err1; 146 145 147 146 he = nft_elem_priv_cast(elem_priv); 147 + init_llist_node(&he->walk_node); 148 148 prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node, 149 149 nft_rhash_params); 150 150 if (IS_ERR(prev)) ··· 182 180 }; 183 181 struct nft_rhash_elem *prev; 184 182 183 + init_llist_node(&he->walk_node); 185 184 prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node, 186 185 nft_rhash_params); 187 186 if (IS_ERR(prev)) ··· 264 261 return true; 265 262 } 266 263 267 - static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, 268 - struct nft_set_iter *iter) 264 + static void nft_rhash_walk_ro(const struct nft_ctx *ctx, struct nft_set *set, 265 + struct nft_set_iter *iter) 269 266 { 270 267 struct nft_rhash *priv = nft_set_priv(set); 271 - struct nft_rhash_elem *he; 272 268 struct rhashtable_iter hti; 269 + struct nft_rhash_elem *he; 273 270 274 271 rhashtable_walk_enter(&priv->ht, &hti); 275 272 rhashtable_walk_start(&hti); ··· 296 293 } 297 294 rhashtable_walk_stop(&hti); 298 295 rhashtable_walk_exit(&hti); 296 + } 297 + 298 + static void nft_rhash_walk_update(const struct nft_ctx *ctx, 299 + struct nft_set *set, 300 + struct nft_set_iter *iter) 301 + { 302 + struct nft_rhash *priv = nft_set_priv(set); 303 + struct nft_rhash_elem *he, *tmp; 304 + struct llist_node *first_node; 305 + struct rhashtable_iter hti; 306 + LLIST_HEAD(walk_list); 307 + 308 + lockdep_assert_held(&nft_pernet(ctx->net)->commit_mutex); 309 + 310 + if (set->in_update_walk) { 311 + /* This can happen with bogus rulesets during ruleset validation 312 + * when a verdict map causes a jump back to the same map. 313 + * 314 + * Without this extra check the walk_next loop below will see 315 + * elems on the callers walk_list and skip (not validate) them. 316 + */ 317 + iter->err = -EMLINK; 318 + return; 319 + } 320 + 321 + /* walk happens under RCU. 322 + * 323 + * We create a snapshot list so ->iter callback can sleep. 324 + * commit_mutex is held, elements can ... 325 + * .. be added in parallel from dataplane (dynset) 326 + * .. be marked as dead in parallel from dataplane (dynset). 327 + * .. be queued for removal in parallel (gc timeout). 328 + * .. not be freed: transaction mutex is held. 329 + */ 330 + rhashtable_walk_enter(&priv->ht, &hti); 331 + rhashtable_walk_start(&hti); 332 + 333 + while ((he = rhashtable_walk_next(&hti))) { 334 + if (IS_ERR(he)) { 335 + if (PTR_ERR(he) != -EAGAIN) { 336 + iter->err = PTR_ERR(he); 337 + break; 338 + } 339 + 340 + continue; 341 + } 342 + 343 + /* rhashtable resized during walk, skip */ 344 + if (llist_on_list(&he->walk_node)) 345 + continue; 346 + 347 + llist_add(&he->walk_node, &walk_list); 348 + } 349 + rhashtable_walk_stop(&hti); 350 + rhashtable_walk_exit(&hti); 351 + 352 + first_node = __llist_del_all(&walk_list); 353 + set->in_update_walk = true; 354 + llist_for_each_entry_safe(he, tmp, first_node, walk_node) { 355 + if (iter->err == 0) { 356 + iter->err = iter->fn(ctx, set, iter, &he->priv); 357 + if (iter->err == 0) 358 + iter->count++; 359 + } 360 + 361 + /* all entries must be cleared again, else next ->walk iteration 362 + * will skip entries. 363 + */ 364 + init_llist_node(&he->walk_node); 365 + } 366 + set->in_update_walk = false; 367 + } 368 + 369 + static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, 370 + struct nft_set_iter *iter) 371 + { 372 + switch (iter->type) { 373 + case NFT_ITER_UPDATE: 374 + /* only relevant for netlink dumps which use READ type */ 375 + WARN_ON_ONCE(iter->skip != 0); 376 + 377 + nft_rhash_walk_update(ctx, set, iter); 378 + break; 379 + case NFT_ITER_READ: 380 + nft_rhash_walk_ro(ctx, set, iter); 381 + break; 382 + default: 383 + iter->err = -EINVAL; 384 + WARN_ON_ONCE(1); 385 + break; 386 + } 299 387 } 300 388 301 389 static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set,
+1 -2
net/netfilter/nft_set_pipapo.c
··· 530 530 local_bh_disable(); 531 531 532 532 #if defined(CONFIG_X86_64) && !defined(CONFIG_UML) 533 - if (boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_AVX) && 534 - irq_fpu_usable()) { 533 + if (boot_cpu_has(X86_FEATURE_AVX2) && irq_fpu_usable()) { 535 534 e = pipapo_get_avx2(m, data, genmask, tstamp); 536 535 local_bh_enable(); 537 536 return e;
+1 -1
net/netfilter/nft_set_pipapo_avx2.c
··· 1099 1099 desc->field_count < NFT_PIPAPO_MIN_FIELDS) 1100 1100 return false; 1101 1101 1102 - if (!boot_cpu_has(X86_FEATURE_AVX2) || !boot_cpu_has(X86_FEATURE_AVX)) 1102 + if (!boot_cpu_has(X86_FEATURE_AVX2)) 1103 1103 return false; 1104 1104 1105 1105 est->size = pipapo_estimate_size(desc);
+27 -8
net/netfilter/nft_set_rbtree.c
··· 584 584 return NULL; 585 585 } 586 586 587 - static void nft_rbtree_walk(const struct nft_ctx *ctx, 588 - struct nft_set *set, 589 - struct nft_set_iter *iter) 587 + static void nft_rbtree_do_walk(const struct nft_ctx *ctx, 588 + struct nft_set *set, 589 + struct nft_set_iter *iter) 590 590 { 591 591 struct nft_rbtree *priv = nft_set_priv(set); 592 592 struct nft_rbtree_elem *rbe; 593 593 struct rb_node *node; 594 594 595 - read_lock_bh(&priv->lock); 596 595 for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { 597 596 rbe = rb_entry(node, struct nft_rbtree_elem, node); 598 597 ··· 599 600 goto cont; 600 601 601 602 iter->err = iter->fn(ctx, set, iter, &rbe->priv); 602 - if (iter->err < 0) { 603 - read_unlock_bh(&priv->lock); 603 + if (iter->err < 0) 604 604 return; 605 - } 606 605 cont: 607 606 iter->count++; 608 607 } 609 - read_unlock_bh(&priv->lock); 608 + } 609 + 610 + static void nft_rbtree_walk(const struct nft_ctx *ctx, 611 + struct nft_set *set, 612 + struct nft_set_iter *iter) 613 + { 614 + struct nft_rbtree *priv = nft_set_priv(set); 615 + 616 + switch (iter->type) { 617 + case NFT_ITER_UPDATE: 618 + lockdep_assert_held(&nft_pernet(ctx->net)->commit_mutex); 619 + nft_rbtree_do_walk(ctx, set, iter); 620 + break; 621 + case NFT_ITER_READ: 622 + read_lock_bh(&priv->lock); 623 + nft_rbtree_do_walk(ctx, set, iter); 624 + read_unlock_bh(&priv->lock); 625 + break; 626 + default: 627 + iter->err = -EINVAL; 628 + WARN_ON_ONCE(1); 629 + break; 630 + } 610 631 } 611 632 612 633 static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set,