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

nft_set_pipapo: Prepare for single ranged field usage

A few adjustments in nft_pipapo_init() are needed to allow usage of
this set back-end for a single, ranged field.

Provide a convenient NFT_PIPAPO_MIN_FIELDS definition that currently
makes sure that the rbtree back-end is selected instead, for sets
with a single field.

This finally allows a fair comparison with rbtree sets, by defining
NFT_PIPAPO_MIN_FIELDS as 0 and skipping rbtree back-end initialisation:

---------------.--------------------------.-------------------------.
AMD Epyc 7402 | baselines, Mpps | Mpps, % over rbtree |
1 thread |__________________________|_________________________|
3.35GHz | | | | | |
768KiB L1D$ | netdev | hash | rbtree | | pipapo |
---------------| hook | no | single | pipapo |single field|
type entries | drop | ranges | field |single field| AVX2 |
---------------|--------|--------|--------|------------|------------|
net,port | | | | | |
1000 | 19.0 | 10.4 | 3.8 | 6.0 +58% | 9.6 +153% |
---------------|--------|--------|--------|------------|------------|
port,net | | | | | |
100 | 18.8 | 10.3 | 5.8 | 9.1 +57% |11.6 +100% |
---------------|--------|--------|--------|------------|------------|
net6,port | | | | | |
1000 | 16.4 | 7.6 | 1.8 | 2.8 +55% | 6.5 +261% |
---------------|--------|--------|--------|------------|------------|
port,proto | | | | [1] | [1] |
30000 | 19.6 | 11.6 | 3.9 | 0.9 -77% | 2.7 -31% |
---------------|--------|--------|--------|------------|------------|
port,proto | | | | | |
10000 | 19.6 | 11.6 | 4.4 | 2.1 -52% | 5.6 +27% |
---------------|--------|--------|--------|------------|------------|
port,proto | | | | | |
4 threads 10000| 77.9 | 45.1 | 17.4 | 8.3 -52% |22.4 +29% |
---------------|--------|--------|--------|------------|------------|
net6,port,mac | | | | | |
10 | 16.5 | 5.4 | 4.3 | 4.5 +5% | 8.2 +91% |
---------------|--------|--------|--------|------------|------------|
net6,port,mac, | | | | | |
proto 1000 | 16.5 | 5.7 | 1.9 | 2.8 +47% | 6.6 +247% |
---------------|--------|--------|--------|------------|------------|
net,mac | | | | | |
1000 | 19.0 | 8.4 | 3.9 | 6.0 +54% | 9.9 +154% |
---------------'--------'--------'--------'------------'------------'
[1] Causes switch of lookup table buckets for 'port' to 4-bit groups

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Stefano Brivio and committed by
Pablo Neira Ayuso
eb16933a 7400b063

+18 -9
+13 -8
net/netfilter/nft_set_pipapo.c
··· 1983 1983 static bool nft_pipapo_estimate(const struct nft_set_desc *desc, u32 features, 1984 1984 struct nft_set_estimate *est) 1985 1985 { 1986 - if (!(features & NFT_SET_INTERVAL) || desc->field_count <= 1) 1986 + if (!(features & NFT_SET_INTERVAL) || 1987 + desc->field_count < NFT_PIPAPO_MIN_FIELDS) 1987 1988 return false; 1988 1989 1989 1990 est->size = pipapo_estimate_size(desc); ··· 2017 2016 struct nft_pipapo *priv = nft_set_priv(set); 2018 2017 struct nft_pipapo_match *m; 2019 2018 struct nft_pipapo_field *f; 2020 - int err, i; 2019 + int err, i, field_count; 2021 2020 2022 - if (desc->field_count > NFT_PIPAPO_MAX_FIELDS) 2021 + field_count = desc->field_count ? : 1; 2022 + 2023 + if (field_count > NFT_PIPAPO_MAX_FIELDS) 2023 2024 return -EINVAL; 2024 2025 2025 - m = kmalloc(sizeof(*priv->match) + sizeof(*f) * desc->field_count, 2026 + m = kmalloc(sizeof(*priv->match) + sizeof(*f) * field_count, 2026 2027 GFP_KERNEL); 2027 2028 if (!m) 2028 2029 return -ENOMEM; 2029 2030 2030 - m->field_count = desc->field_count; 2031 + m->field_count = field_count; 2031 2032 m->bsize_max = 0; 2032 2033 2033 2034 m->scratch = alloc_percpu(unsigned long *); ··· 2053 2050 rcu_head_init(&m->rcu); 2054 2051 2055 2052 nft_pipapo_for_each_field(f, i, m) { 2056 - f->bb = NFT_PIPAPO_GROUP_BITS_INIT; 2057 - f->groups = desc->field_len[i] * NFT_PIPAPO_GROUPS_PER_BYTE(f); 2053 + int len = desc->field_len[i] ? : set->klen; 2058 2054 2059 - priv->width += round_up(desc->field_len[i], sizeof(u32)); 2055 + f->bb = NFT_PIPAPO_GROUP_BITS_INIT; 2056 + f->groups = len * NFT_PIPAPO_GROUPS_PER_BYTE(f); 2057 + 2058 + priv->width += round_up(len, sizeof(u32)); 2060 2059 2061 2060 f->bsize = 0; 2062 2061 f->rules = 0;
+3
net/netfilter/nft_set_pipapo.h
··· 8 8 /* Count of concatenated fields depends on count of 32-bit nftables registers */ 9 9 #define NFT_PIPAPO_MAX_FIELDS NFT_REG32_COUNT 10 10 11 + /* Restrict usage to multiple fields, make sure rbtree is used otherwise */ 12 + #define NFT_PIPAPO_MIN_FIELDS 2 13 + 11 14 /* Largest supported field size */ 12 15 #define NFT_PIPAPO_MAX_BYTES (sizeof(struct in6_addr)) 13 16 #define NFT_PIPAPO_MAX_BITS (NFT_PIPAPO_MAX_BYTES * BITS_PER_BYTE)
+2 -1
net/netfilter/nft_set_pipapo_avx2.c
··· 1087 1087 bool nft_pipapo_avx2_estimate(const struct nft_set_desc *desc, u32 features, 1088 1088 struct nft_set_estimate *est) 1089 1089 { 1090 - if (!(features & NFT_SET_INTERVAL) || desc->field_count <= 1) 1090 + if (!(features & NFT_SET_INTERVAL) || 1091 + desc->field_count < NFT_PIPAPO_MIN_FIELDS) 1091 1092 return false; 1092 1093 1093 1094 if (!boot_cpu_has(X86_FEATURE_AVX2) || !boot_cpu_has(X86_FEATURE_AVX))