Skip to content

Commit 416e53e

Browse files
author
Florian Westphal
committed
netfilter: nft_set_pipapo_avx2: split lookup function in two parts
Split the main avx2 lookup function into a helper. This is a preparation patch: followup change will use the new helper from the insertion path if possible. This greatly improves insertion performance when avx2 is supported. Reviewed-by: Stefano Brivio <[email protected]> Signed-off-by: Florian Westphal <[email protected]>
1 parent d11b264 commit 416e53e

File tree

1 file changed

+77
-49
lines changed

1 file changed

+77
-49
lines changed

net/netfilter/nft_set_pipapo_avx2.c

Lines changed: 77 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,56 +1133,35 @@ static inline void pipapo_resmap_init_avx2(const struct nft_pipapo_match *m, uns
11331133
}
11341134

11351135
/**
1136-
* nft_pipapo_avx2_lookup() - Lookup function for AVX2 implementation
1137-
* @net: Network namespace
1138-
* @set: nftables API set representation
1139-
* @key: nftables API element representation containing key data
1136+
* pipapo_get_avx2() - Lookup function for AVX2 implementation
1137+
* @m: Storage containing the set elements
1138+
* @data: Key data to be matched against existing elements
1139+
* @genmask: If set, check that element is active in given genmask
1140+
* @tstamp: Timestamp to check for expired elements
11401141
*
11411142
* For more details, see DOC: Theory of Operation in nft_set_pipapo.c.
11421143
*
11431144
* This implementation exploits the repetitive characteristic of the algorithm
11441145
* to provide a fast, vectorised version using the AVX2 SIMD instruction set.
11451146
*
1146-
* Return: true on match, false otherwise.
1147+
* The caller must check that the FPU is usable.
1148+
* This function must be called with BH disabled.
1149+
*
1150+
* Return: pointer to &struct nft_pipapo_elem on match, NULL otherwise.
11471151
*/
1148-
const struct nft_set_ext *
1149-
nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
1150-
const u32 *key)
1152+
static struct nft_pipapo_elem *pipapo_get_avx2(const struct nft_pipapo_match *m,
1153+
const u8 *data, u8 genmask,
1154+
u64 tstamp)
11511155
{
1152-
struct nft_pipapo *priv = nft_set_priv(set);
1153-
const struct nft_set_ext *ext = NULL;
11541156
struct nft_pipapo_scratch *scratch;
1155-
u8 genmask = nft_genmask_cur(net);
1156-
const struct nft_pipapo_match *m;
11571157
const struct nft_pipapo_field *f;
1158-
const u8 *rp = (const u8 *)key;
11591158
unsigned long *res, *fill;
11601159
bool map_index;
11611160
int i;
11621161

1163-
local_bh_disable();
1164-
1165-
if (unlikely(!irq_fpu_usable())) {
1166-
ext = nft_pipapo_lookup(net, set, key);
1167-
1168-
local_bh_enable();
1169-
return ext;
1170-
}
1171-
1172-
m = rcu_dereference(priv->match);
1173-
1174-
/* Note that we don't need a valid MXCSR state for any of the
1175-
* operations we use here, so pass 0 as mask and spare a LDMXCSR
1176-
* instruction.
1177-
*/
1178-
kernel_fpu_begin_mask(0);
1179-
11801162
scratch = *raw_cpu_ptr(m->scratch);
1181-
if (unlikely(!scratch)) {
1182-
kernel_fpu_end();
1183-
local_bh_enable();
1163+
if (unlikely(!scratch))
11841164
return NULL;
1185-
}
11861165

11871166
map_index = scratch->map_index;
11881167

@@ -1191,6 +1170,12 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
11911170

11921171
pipapo_resmap_init_avx2(m, res);
11931172

1173+
/* Note that we don't need a valid MXCSR state for any of the
1174+
* operations we use here, so pass 0 as mask and spare a LDMXCSR
1175+
* instruction.
1176+
*/
1177+
kernel_fpu_begin_mask(0);
1178+
11941179
nft_pipapo_avx2_prepare();
11951180

11961181
next_match:
@@ -1200,7 +1185,7 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
12001185

12011186
#define NFT_SET_PIPAPO_AVX2_LOOKUP(b, n) \
12021187
(ret = nft_pipapo_avx2_lookup_##b##b_##n(res, fill, f, \
1203-
ret, rp, \
1188+
ret, data, \
12041189
first, last))
12051190

12061191
if (likely(f->bb == 8)) {
@@ -1216,7 +1201,7 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
12161201
NFT_SET_PIPAPO_AVX2_LOOKUP(8, 16);
12171202
} else {
12181203
ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
1219-
ret, rp,
1204+
ret, data,
12201205
first, last);
12211206
}
12221207
} else {
@@ -1232,37 +1217,80 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
12321217
NFT_SET_PIPAPO_AVX2_LOOKUP(4, 32);
12331218
} else {
12341219
ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
1235-
ret, rp,
1220+
ret, data,
12361221
first, last);
12371222
}
12381223
}
12391224
NFT_PIPAPO_GROUP_BITS_ARE_8_OR_4;
12401225

12411226
#undef NFT_SET_PIPAPO_AVX2_LOOKUP
12421227

1243-
if (ret < 0)
1244-
goto out;
1228+
if (ret < 0) {
1229+
scratch->map_index = map_index;
1230+
kernel_fpu_end();
1231+
return NULL;
1232+
}
12451233

12461234
if (last) {
1247-
const struct nft_set_ext *e = &f->mt[ret].e->ext;
1235+
struct nft_pipapo_elem *e;
12481236

1249-
if (unlikely(nft_set_elem_expired(e) ||
1250-
!nft_set_elem_active(e, genmask)))
1237+
e = f->mt[ret].e;
1238+
if (unlikely(__nft_set_elem_expired(&e->ext, tstamp) ||
1239+
!nft_set_elem_active(&e->ext, genmask)))
12511240
goto next_match;
12521241

1253-
ext = e;
1254-
goto out;
1242+
scratch->map_index = map_index;
1243+
kernel_fpu_end();
1244+
return e;
12551245
}
12561246

1247+
map_index = !map_index;
12571248
swap(res, fill);
1258-
rp += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
1249+
data += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
12591250
}
12601251

1261-
out:
1262-
if (i % 2)
1263-
scratch->map_index = !map_index;
12641252
kernel_fpu_end();
1253+
return NULL;
1254+
}
1255+
1256+
/**
1257+
* nft_pipapo_avx2_lookup() - Dataplane frontend for AVX2 implementation
1258+
* @net: Network namespace
1259+
* @set: nftables API set representation
1260+
* @key: nftables API element representation containing key data
1261+
*
1262+
* This function is called from the data path. It will search for
1263+
* an element matching the given key in the current active copy using
1264+
* the AVX2 routines if the fpu is usable or fall back to the generic
1265+
* implementation of the algorithm otherwise.
1266+
*
1267+
* Return: nftables API extension pointer or NULL if no match.
1268+
*/
1269+
const struct nft_set_ext *
1270+
nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
1271+
const u32 *key)
1272+
{
1273+
struct nft_pipapo *priv = nft_set_priv(set);
1274+
u8 genmask = nft_genmask_cur(net);
1275+
const struct nft_pipapo_match *m;
1276+
const u8 *rp = (const u8 *)key;
1277+
const struct nft_pipapo_elem *e;
1278+
1279+
local_bh_disable();
1280+
1281+
if (unlikely(!irq_fpu_usable())) {
1282+
const struct nft_set_ext *ext;
1283+
1284+
ext = nft_pipapo_lookup(net, set, key);
1285+
1286+
local_bh_enable();
1287+
return ext;
1288+
}
1289+
1290+
m = rcu_dereference(priv->match);
1291+
1292+
e = pipapo_get_avx2(m, rp, genmask, get_jiffies_64());
12651293
local_bh_enable();
12661294

1267-
return ext;
1295+
return e ? &e->ext : NULL;
12681296
}

0 commit comments

Comments
 (0)