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

netfilter: nft_set_pipapo: use 0 genmask for packetpath lookups

In commit c4eaca2e1052 ("netfilter: nft_set_pipapo: don't check genbit from
packetpath lookups") I replaced genmask_cur() with NFT_GENMASK_ANY, but
this change has no effect in the pipapo set type.

New entries are unreachable from the active copy, so NFT_GENMASK_ANY has
same result as genmask_cur():

current-gen elements are disabled and the new-generation
elements cannot be found.

Tests did not catch this incomplete fix because the change also dropped
the genmask test from the AVX2 version of the algorithm, so test only
fails if host cpu lacks AVX2 support.

Use genmask test only from the control plane (inserts, deletions, ..).

Packet path has to skip the check, use of 0 is enough for this because
ext->genmask has a the relevant bit set when the element is INACTIVE
in that generation: using a 0 genmask thus makes nft_set_elem_active()
always return true.

Fix the comment and replace NFT_GENMASK_ANY with 0.

Fixes: c4eaca2e1052 ("netfilter: nft_set_pipapo: don't check genbit from packetpath lookups")
Signed-off-by: Florian Westphal <fw@strlen.de>

+5 -6
+4 -5
net/netfilter/nft_set_pipapo.c
··· 549 549 * 550 550 * This function is called from the data path. It will search for 551 551 * an element matching the given key in the current active copy. 552 - * Unlike other set types, this uses NFT_GENMASK_ANY instead of 553 - * nft_genmask_cur(). 552 + * Unlike other set types, this uses 0 instead of nft_genmask_cur(). 554 553 * 555 554 * This is because new (future) elements are not reachable from 556 555 * priv->match, they get added to priv->clone instead. ··· 559 560 * inconsistent state: matching old entries get skipped but thew 560 561 * newly matching entries are unreachable. 561 562 * 562 - * GENMASK will still find the 'now old' entries which ensures consistent 563 - * priv->match view. 563 + * GENMASK_ANY doesn't work for the same reason: old-gen entries get 564 + * skipped, new-gen entries are only reachable from priv->clone. 564 565 * 565 566 * nft_pipapo_commit swaps ->clone and ->match shortly after the 566 567 * genbit flip. As ->clone doesn't contain the old entries in the first ··· 577 578 const struct nft_pipapo_elem *e; 578 579 579 580 m = rcu_dereference(priv->match); 580 - e = pipapo_get_slow(m, (const u8 *)key, NFT_GENMASK_ANY, get_jiffies_64()); 581 + e = pipapo_get_slow(m, (const u8 *)key, 0, get_jiffies_64()); 581 582 582 583 return e ? &e->ext : NULL; 583 584 }
+1 -1
net/netfilter/nft_set_pipapo_avx2.c
··· 1292 1292 1293 1293 m = rcu_dereference(priv->match); 1294 1294 1295 - e = pipapo_get_avx2(m, rp, NFT_GENMASK_ANY, get_jiffies_64()); 1295 + e = pipapo_get_avx2(m, rp, 0, get_jiffies_64()); 1296 1296 local_bh_enable(); 1297 1297 1298 1298 return e ? &e->ext : NULL;