@@ -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
11961181next_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