@@ -397,35 +397,36 @@ int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules,
397397}
398398
399399/**
400- * nft_pipapo_lookup () - Lookup function
401- * @net: Network namespace
402- * @set: nftables API set representation
403- * @key: nftables API element representation containing key data
404- * @ext: nftables API extension pointer, filled with matching reference
400+ * pipapo_get () - Get matching element reference given key data
401+ * @m: storage containing the set elements
402+ * @data: Key data to be matched against existing elements
403+ * @genmask: If set, check that element is active in given genmask
404+ * @tstamp: timestamp to check for expired elements
405405 *
406406 * For more details, see DOC: Theory of Operation.
407407 *
408- * Return: true on match, false otherwise.
408+ * This is the main lookup function. It matches key data against either
409+ * the working match set or the uncommitted copy, depending on what the
410+ * caller passed to us.
411+ * nft_pipapo_get (lookup from userspace/control plane) and nft_pipapo_lookup
412+ * (datapath lookup) pass the active copy.
413+ * The insertion path will pass the uncommitted working copy.
414+ *
415+ * Return: pointer to &struct nft_pipapo_elem on match, NULL otherwise.
409416 */
410- const struct nft_set_ext *
411- nft_pipapo_lookup ( const struct net * net , const struct nft_set * set ,
412- const u32 * key )
417+ static struct nft_pipapo_elem * pipapo_get ( const struct nft_pipapo_match * m ,
418+ const u8 * data , u8 genmask ,
419+ u64 tstamp )
413420{
414- struct nft_pipapo * priv = nft_set_priv (set );
415421 struct nft_pipapo_scratch * scratch ;
416422 unsigned long * res_map , * fill_map ;
417- u8 genmask = nft_genmask_cur (net );
418- const struct nft_pipapo_match * m ;
419423 const struct nft_pipapo_field * f ;
420- const u8 * rp = (const u8 * )key ;
421424 bool map_index ;
422425 int i ;
423426
424427 local_bh_disable ();
425428
426- m = rcu_dereference (priv -> match );
427-
428- if (unlikely (!m || !* raw_cpu_ptr (m -> scratch )))
429+ if (unlikely (!raw_cpu_ptr (m -> scratch )))
429430 goto out ;
430431
431432 scratch = * raw_cpu_ptr (m -> scratch );
@@ -445,12 +446,12 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
445446 * packet bytes value, then AND bucket value
446447 */
447448 if (likely (f -> bb == 8 ))
448- pipapo_and_field_buckets_8bit (f , res_map , rp );
449+ pipapo_and_field_buckets_8bit (f , res_map , data );
449450 else
450- pipapo_and_field_buckets_4bit (f , res_map , rp );
451+ pipapo_and_field_buckets_4bit (f , res_map , data );
451452 NFT_PIPAPO_GROUP_BITS_ARE_8_OR_4 ;
452453
453- rp += f -> groups / NFT_PIPAPO_GROUPS_PER_BYTE (f );
454+ data += f -> groups / NFT_PIPAPO_GROUPS_PER_BYTE (f );
454455
455456 /* Now populate the bitmap for the next field, unless this is
456457 * the last field, in which case return the matched 'ext'
@@ -470,11 +471,11 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
470471 }
471472
472473 if (last ) {
473- const struct nft_set_ext * ext ;
474+ struct nft_pipapo_elem * e ;
474475
475- ext = & f -> mt [b ].e -> ext ;
476- if (unlikely (nft_set_elem_expired ( ext ) ||
477- !nft_set_elem_active (ext , genmask )))
476+ e = f -> mt [b ].e ;
477+ if (unlikely (__nft_set_elem_expired ( & e -> ext , tstamp ) ||
478+ !nft_set_elem_active (& e -> ext , genmask )))
478479 goto next_match ;
479480
480481 /* Last field: we're just returning the key without
@@ -484,8 +485,7 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
484485 */
485486 scratch -> map_index = map_index ;
486487 local_bh_enable ();
487-
488- return ext ;
488+ return e ;
489489 }
490490
491491 /* Swap bitmap indices: res_map is the initial bitmap for the
@@ -495,7 +495,7 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
495495 map_index = !map_index ;
496496 swap (res_map , fill_map );
497497
498- rp += NFT_PIPAPO_GROUPS_PADDING (f );
498+ data += NFT_PIPAPO_GROUPS_PADDING (f );
499499 }
500500
501501out :
@@ -504,99 +504,29 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
504504}
505505
506506/**
507- * pipapo_get() - Get matching element reference given key data
508- * @m: storage containing active/existing elements
509- * @data: Key data to be matched against existing elements
510- * @genmask: If set, check that element is active in given genmask
511- * @tstamp: timestamp to check for expired elements
512- * @gfp: the type of memory to allocate (see kmalloc).
507+ * nft_pipapo_lookup() - Dataplane fronted for main lookup function
508+ * @net: Network namespace
509+ * @set: nftables API set representation
510+ * @key: pointer to nft registers containing key data
513511 *
514- * This is essentially the same as the lookup function, except that it matches
515- * key data against the uncommitted copy and doesn't use preallocated maps for
516- * bitmap results.
512+ * This function is called from the data path. It will search for
513+ * an element matching the given key in the current active copy.
517514 *
518- * Return: pointer to &struct nft_pipapo_elem on match, error pointer otherwise .
515+ * Return: ntables API extension pointer or NULL if no match .
519516 */
520- static struct nft_pipapo_elem * pipapo_get ( const struct nft_pipapo_match * m ,
521- const u8 * data , u8 genmask ,
522- u64 tstamp , gfp_t gfp )
517+ const struct nft_set_ext *
518+ nft_pipapo_lookup ( const struct net * net , const struct nft_set * set ,
519+ const u32 * key )
523520{
524- struct nft_pipapo_elem * ret = ERR_PTR (- ENOENT );
525- unsigned long * res_map , * fill_map = NULL ;
526- const struct nft_pipapo_field * f ;
527- int i ;
528-
529- if (m -> bsize_max == 0 )
530- return ret ;
531-
532- res_map = kmalloc_array (m -> bsize_max , sizeof (* res_map ), gfp );
533- if (!res_map ) {
534- ret = ERR_PTR (- ENOMEM );
535- goto out ;
536- }
537-
538- fill_map = kcalloc (m -> bsize_max , sizeof (* res_map ), gfp );
539- if (!fill_map ) {
540- ret = ERR_PTR (- ENOMEM );
541- goto out ;
542- }
543-
544- pipapo_resmap_init (m , res_map );
545-
546- nft_pipapo_for_each_field (f , i , m ) {
547- bool last = i == m -> field_count - 1 ;
548- int b ;
549-
550- /* For each bit group: select lookup table bucket depending on
551- * packet bytes value, then AND bucket value
552- */
553- if (f -> bb == 8 )
554- pipapo_and_field_buckets_8bit (f , res_map , data );
555- else if (f -> bb == 4 )
556- pipapo_and_field_buckets_4bit (f , res_map , data );
557- else
558- BUG ();
559-
560- data += f -> groups / NFT_PIPAPO_GROUPS_PER_BYTE (f );
561-
562- /* Now populate the bitmap for the next field, unless this is
563- * the last field, in which case return the matched 'ext'
564- * pointer if any.
565- *
566- * Now res_map contains the matching bitmap, and fill_map is the
567- * bitmap for the next field.
568- */
569- next_match :
570- b = pipapo_refill (res_map , f -> bsize , f -> rules , fill_map , f -> mt ,
571- last );
572- if (b < 0 )
573- goto out ;
574-
575- if (last ) {
576- if (__nft_set_elem_expired (& f -> mt [b ].e -> ext , tstamp ))
577- goto next_match ;
578- if ((genmask &&
579- !nft_set_elem_active (& f -> mt [b ].e -> ext , genmask )))
580- goto next_match ;
581-
582- ret = f -> mt [b ].e ;
583- goto out ;
584- }
585-
586- data += NFT_PIPAPO_GROUPS_PADDING (f );
521+ struct nft_pipapo * priv = nft_set_priv (set );
522+ u8 genmask = nft_genmask_cur (net );
523+ const struct nft_pipapo_match * m ;
524+ const struct nft_pipapo_elem * e ;
587525
588- /* Swap bitmap indices: fill_map will be the initial bitmap for
589- * the next field (i.e. the new res_map), and res_map is
590- * guaranteed to be all-zeroes at this point, ready to be filled
591- * according to the next mapping table.
592- */
593- swap (res_map , fill_map );
594- }
526+ m = rcu_dereference (priv -> match );
527+ e = pipapo_get (m , (const u8 * )key , genmask , get_jiffies_64 ());
595528
596- out :
597- kfree (fill_map );
598- kfree (res_map );
599- return ret ;
529+ return e ? & e -> ext : NULL ;
600530}
601531
602532/**
@@ -605,6 +535,11 @@ static struct nft_pipapo_elem *pipapo_get(const struct nft_pipapo_match *m,
605535 * @set: nftables API set representation
606536 * @elem: nftables API element representation containing key data
607537 * @flags: Unused
538+ *
539+ * This function is called from the control plane path under
540+ * RCU read lock.
541+ *
542+ * Return: set element private pointer or ERR_PTR(-ENOENT).
608543 */
609544static struct nft_elem_priv *
610545nft_pipapo_get (const struct net * net , const struct nft_set * set ,
@@ -615,10 +550,9 @@ nft_pipapo_get(const struct net *net, const struct nft_set *set,
615550 struct nft_pipapo_elem * e ;
616551
617552 e = pipapo_get (m , (const u8 * )elem -> key .val .data ,
618- nft_genmask_cur (net ), get_jiffies_64 (),
619- GFP_ATOMIC );
620- if (IS_ERR (e ))
621- return ERR_CAST (e );
553+ nft_genmask_cur (net ), get_jiffies_64 ());
554+ if (!e )
555+ return ERR_PTR (- ENOENT );
622556
623557 return & e -> priv ;
624558}
@@ -1344,8 +1278,8 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
13441278 else
13451279 end = start ;
13461280
1347- dup = pipapo_get (m , start , genmask , tstamp , GFP_KERNEL );
1348- if (! IS_ERR ( dup ) ) {
1281+ dup = pipapo_get (m , start , genmask , tstamp );
1282+ if (dup ) {
13491283 /* Check if we already have the same exact entry */
13501284 const struct nft_data * dup_key , * dup_end ;
13511285
@@ -1364,15 +1298,9 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
13641298 return - ENOTEMPTY ;
13651299 }
13661300
1367- if (PTR_ERR (dup ) == - ENOENT ) {
1368- /* Look for partially overlapping entries */
1369- dup = pipapo_get (m , end , nft_genmask_next (net ), tstamp ,
1370- GFP_KERNEL );
1371- }
1372-
1373- if (PTR_ERR (dup ) != - ENOENT ) {
1374- if (IS_ERR (dup ))
1375- return PTR_ERR (dup );
1301+ /* Look for partially overlapping entries */
1302+ dup = pipapo_get (m , end , nft_genmask_next (net ), tstamp );
1303+ if (dup ) {
13761304 * elem_priv = & dup -> priv ;
13771305 return - ENOTEMPTY ;
13781306 }
@@ -1914,8 +1842,8 @@ nft_pipapo_deactivate(const struct net *net, const struct nft_set *set,
19141842 return NULL ;
19151843
19161844 e = pipapo_get (m , (const u8 * )elem -> key .val .data ,
1917- nft_genmask_next (net ), nft_net_tstamp (net ), GFP_KERNEL );
1918- if (IS_ERR ( e ) )
1845+ nft_genmask_next (net ), nft_net_tstamp (net ));
1846+ if (! e )
19191847 return NULL ;
19201848
19211849 nft_set_elem_change_active (net , set , & e -> ext );
0 commit comments