LCOV - code coverage report
Current view: top level - vnet/classify - vnet_classify.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 116 146 79.5 %
Date: 2023-10-26 01:39:38 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : #ifndef __included_vnet_classify_h__
      16             : #define __included_vnet_classify_h__
      17             : 
      18             : #include <vnet/vnet.h>
      19             : #include <vnet/api_errno.h>       /* for API error numbers */
      20             : 
      21             : #include <vppinfra/error.h>
      22             : #include <vppinfra/hash.h>
      23             : #include <vppinfra/cache.h>
      24             : #include <vppinfra/crc32.h>
      25             : #include <vppinfra/xxhash.h>
      26             : 
      27             : extern vlib_node_registration_t ip4_classify_node;
      28             : extern vlib_node_registration_t ip6_classify_node;
      29             : 
      30             : #define CLASSIFY_TRACE 0
      31             : 
      32             : /*
      33             :  * Classify table option to process packets
      34             :  *  CLASSIFY_FLAG_USE_CURR_DATA:
      35             :  *   - classify packets starting from VPP node’s current data pointer
      36             :  */
      37             : typedef enum vnet_classify_flags_t_
      38             : {
      39             :   CLASSIFY_FLAG_NONE = 0,
      40             :   CLASSIFY_FLAG_USE_CURR_DATA = (1 << 0),
      41             : } __clib_packed vnet_classify_flags_t;
      42             : 
      43             : /*
      44             :  * Classify session action
      45             :  *  CLASSIFY_ACTION_SET_IP4_FIB_INDEX:
      46             :  *   - Classified IP packets will be looked up
      47             :  *     from the specified ipv4 fib table
      48             :  *  CLASSIFY_ACTION_SET_IP6_FIB_INDEX:
      49             :  *   - Classified IP packets will be looked up
      50             :  *     from the specified ipv6 fib table
      51             :  */
      52             : typedef enum vnet_classify_action_t_
      53             : {
      54             :   CLASSIFY_ACTION_NONE = 0,
      55             :   CLASSIFY_ACTION_SET_IP4_FIB_INDEX = 1,
      56             :   CLASSIFY_ACTION_SET_IP6_FIB_INDEX = 2,
      57             :   CLASSIFY_ACTION_SET_METADATA = 3,
      58             : } __clib_packed vnet_classify_action_t;
      59             : 
      60             : struct _vnet_classify_main;
      61             : typedef struct _vnet_classify_main vnet_classify_main_t;
      62             : 
      63             : #define foreach_size_in_u32x4                   \
      64             : _(1)                                            \
      65             : _(2)                                            \
      66             : _(3)                                            \
      67             : _(4)                                            \
      68             : _(5)
      69             : 
      70             : typedef struct _vnet_classify_entry
      71             : {
      72             :   /* put into vnet_buffer(b)->l2_classfy.opaque_index */
      73             :   union
      74             :   {
      75             :     struct
      76             :     {
      77             :       u32 opaque_index;
      78             :       /* advance on hit, note it's a signed quantity... */
      79             :       i32 advance;
      80             :     };
      81             :     u64 opaque_count;
      82             :   };
      83             :   /* Hit counter */
      84             :   union
      85             :   {
      86             :     u64 hits;
      87             :     struct _vnet_classify_entry *next_free;
      88             :   };
      89             :   /* last heard time */
      90             :   f64 last_heard;
      91             : 
      92             :   u32 metadata;
      93             : 
      94             :   /* Graph node next index */
      95             :   u16 next_index;
      96             : 
      97             :   vnet_classify_action_t action;
      98             : 
      99             :   /* Really only need 1 bit */
     100             :   u8 flags;
     101             : #define VNET_CLASSIFY_ENTRY_FREE        (1<<0)
     102             : 
     103             :   /* Must be aligned to a 16-octet boundary */
     104             :   u32x4 key[0];
     105             : } vnet_classify_entry_t;
     106             : 
     107             : /**
     108             :  * Check there's no padding in the entry. the key lies on a 16 byte boundary.
     109             :  */
     110             : STATIC_ASSERT_OFFSET_OF (vnet_classify_entry_t, key, 32);
     111             : 
     112             : static inline int
     113      464764 : vnet_classify_entry_is_free (vnet_classify_entry_t * e)
     114             : {
     115      464764 :   return e->flags & VNET_CLASSIFY_ENTRY_FREE;
     116             : }
     117             : 
     118             : static inline int
     119      253139 : vnet_classify_entry_is_busy (vnet_classify_entry_t * e)
     120             : {
     121      253139 :   return ((e->flags & VNET_CLASSIFY_ENTRY_FREE) == 0);
     122             : }
     123             : 
     124             : /* Need these to con the vector allocator */
     125             : #define _(size)                                                               \
     126             :   typedef struct                                                              \
     127             :   {                                                                           \
     128             :     vnet_classify_entry_t e;                                                  \
     129             :     u32x4 key[size];                                                          \
     130             :   } __clib_packed vnet_classify_entry_##size##_t;
     131             : foreach_size_in_u32x4;
     132             : #undef _
     133             : 
     134             : typedef struct
     135             : {
     136             :   union
     137             :   {
     138             :     struct
     139             :     {
     140             :       u32 offset;
     141             :       u8 linear_search;
     142             :       u8 pad[2];
     143             :       u8 log2_pages;
     144             :     };
     145             :     u64 as_u64;
     146             :   };
     147             : } vnet_classify_bucket_t;
     148             : 
     149             : typedef struct
     150             : {
     151             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
     152             :   /* hash Buckets */
     153             :   vnet_classify_bucket_t *buckets;
     154             : 
     155             :   /* Private allocation arena, protected by the writer lock,
     156             :    * where the entries are stored. */
     157             :   void *mheap;
     158             : 
     159             :   /* User/client data associated with the table */
     160             :   uword user_ctx;
     161             : 
     162             :   u32 nbuckets;
     163             :   u32 log2_nbuckets;
     164             :   u32 entries_per_page;
     165             :   u32 skip_n_vectors;
     166             :   u32 match_n_vectors;
     167             :   u16 load_mask;
     168             : 
     169             :   /* Index of next table to try */
     170             :   u32 next_table_index;
     171             : 
     172             :   /* packet offsets */
     173             :   i16 current_data_offset;
     174             :   vnet_classify_flags_t current_data_flag;
     175             :   /* Miss next index, return if next_table_index = 0 */
     176             :   u32 miss_next_index;
     177             : 
     178             :   /**
     179             :    * All members accessed in the DP above here
     180             :    */
     181             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
     182             : 
     183             :   /* Config parameters */
     184             :   u32 linear_buckets;
     185             :   u32 active_elements;
     186             :   u32 data_offset;
     187             : 
     188             :   /* Per-bucket working copies, one per thread */
     189             :   vnet_classify_entry_t **working_copies;
     190             :   int *working_copy_lengths;
     191             :   vnet_classify_bucket_t saved_bucket;
     192             : 
     193             :   /* Free entry freelists */
     194             :   vnet_classify_entry_t **freelists;
     195             : 
     196             :   /* Writer (only) lock for this table */
     197             :   clib_spinlock_t writer_lock;
     198             : 
     199             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
     200             :   /* Mask to apply after skipping N vectors */
     201             :   union
     202             :   {
     203             :     u32x4 mask[8];
     204             :     u32 mask_u32[32];
     205             :   };
     206             : 
     207             : } vnet_classify_table_t;
     208             : 
     209             : /**
     210             :  * Ensure DP fields don't spill over to cache-line 2
     211             :  */
     212             : STATIC_ASSERT_OFFSET_OF (vnet_classify_table_t, cacheline1,
     213             :                          CLIB_CACHE_LINE_BYTES);
     214             : 
     215             : /**
     216             :  * The vector size for the classifier
     217             :  *  in the add/del table 'match' is the number of vectors of this size
     218             :  */
     219             : #define VNET_CLASSIFY_VECTOR_SIZE                                             \
     220             :   sizeof (((vnet_classify_table_t *) 0)->mask[0])
     221             : 
     222             : struct _vnet_classify_main
     223             : {
     224             :   /* Table pool */
     225             :   vnet_classify_table_t *tables;
     226             : 
     227             :   /* Registered next-index, opaque unformat fcns */
     228             :   unformat_function_t **unformat_l2_next_index_fns;
     229             :   unformat_function_t **unformat_ip_next_index_fns;
     230             :   unformat_function_t **unformat_acl_next_index_fns;
     231             :   unformat_function_t **unformat_policer_next_index_fns;
     232             :   unformat_function_t **unformat_opaque_index_fns;
     233             : 
     234             :   /* Per-interface filter table.  [0] is used for pcap */
     235             :   u32 *classify_table_index_by_sw_if_index;
     236             : 
     237             :   /* convenience variables */
     238             :   vlib_main_t *vlib_main;
     239             :   vnet_main_t *vnet_main;
     240             : };
     241             : 
     242             : extern vnet_classify_main_t vnet_classify_main;
     243             : 
     244             : u8 *format_classify_entry (u8 *s, va_list *args);
     245             : u8 *format_classify_table (u8 * s, va_list * args);
     246             : u8 *format_vnet_classify_table (u8 *s, va_list *args);
     247             : 
     248             : u32 vnet_classify_hash_packet (const vnet_classify_table_t *t, u8 *h);
     249             : 
     250             : static_always_inline vnet_classify_table_t *
     251         234 : vnet_classify_table_get (u32 table_index)
     252             : {
     253         234 :   vnet_classify_main_t *vcm = &vnet_classify_main;
     254             : 
     255         234 :   return (pool_elt_at_index (vcm->tables, table_index));
     256             : }
     257             : 
     258             : static inline u32
     259      164729 : vnet_classify_hash_packet_inline (const vnet_classify_table_t *t, const u8 *h)
     260             : {
     261             :   u64 xor_sum;
     262      164729 :   ASSERT (t);
     263      164729 :   h += t->skip_n_vectors * 16;
     264             : 
     265             : #if defined(CLIB_HAVE_VEC512) && defined(CLIB_HAVE_VEC512_MASK_LOAD_STORE)
     266           0 :   u64x8 xor_sum_x8, *mask = (u64x8 *) t->mask;
     267           0 :   u16 load_mask = t->load_mask;
     268           0 :   u64x8u *data = (u64x8u *) h;
     269             : 
     270           0 :   xor_sum_x8 = u64x8_mask_load_zero (data, load_mask) & mask[0];
     271             : 
     272           0 :   if (PREDICT_FALSE (load_mask >> 8))
     273           0 :     xor_sum_x8 ^= u64x8_mask_load_zero (data + 1, load_mask >> 8) & mask[1];
     274             : 
     275           0 :   xor_sum_x8 ^= u64x8_align_right (xor_sum_x8, xor_sum_x8, 4);
     276           0 :   xor_sum_x8 ^= u64x8_align_right (xor_sum_x8, xor_sum_x8, 2);
     277           0 :   xor_sum = xor_sum_x8[0] ^ xor_sum_x8[1];
     278             : #elif defined(CLIB_HAVE_VEC256) && defined(CLIB_HAVE_VEC256_MASK_LOAD_STORE)
     279         526 :   u64x4 xor_sum_x4, *mask = (u64x4 *) t->mask;
     280         526 :   u16 load_mask = t->load_mask;
     281         526 :   u64x4u *data = (u64x4u *) h;
     282             : 
     283         526 :   xor_sum_x4 = u64x4_mask_load_zero (data, load_mask) & mask[0];
     284         526 :   xor_sum_x4 ^= u64x4_mask_load_zero (data + 1, load_mask >> 4) & mask[1];
     285             : 
     286         526 :   if (PREDICT_FALSE (load_mask >> 8))
     287           4 :     xor_sum_x4 ^= u64x4_mask_load_zero (data + 2, load_mask >> 8) & mask[2];
     288             : 
     289         526 :   xor_sum_x4 ^= u64x4_align_right (xor_sum_x4, xor_sum_x4, 2);
     290         526 :   xor_sum = xor_sum_x4[0] ^ xor_sum_x4[1];
     291             : #elif defined(CLIB_HAVE_VEC128)
     292      164203 :   u64x2 *mask = (u64x2 *) t->mask;
     293      164203 :   u64x2u *data = (u64x2u *) h;
     294             :   u64x2 xor_sum_x2;
     295             : 
     296      164203 :   xor_sum_x2 = data[0] & mask[0];
     297             : 
     298      164203 :   switch (t->match_n_vectors)
     299             :     {
     300           2 :     case 5:
     301           2 :       xor_sum_x2 ^= data[4] & mask[4];
     302             :       /* FALLTHROUGH */
     303          12 :     case 4:
     304          12 :       xor_sum_x2 ^= data[3] & mask[3];
     305             :       /* FALLTHROUGH */
     306      125749 :     case 3:
     307      125749 :       xor_sum_x2 ^= data[2] & mask[2];
     308             :       /* FALLTHROUGH */
     309      163875 :     case 2:
     310      163875 :       xor_sum_x2 ^= data[1] & mask[1];
     311             :       /* FALLTHROUGH */
     312      164203 :     case 1:
     313      164203 :       break;
     314           0 :     default:
     315           0 :       abort ();
     316             :     }
     317      164203 :   xor_sum = xor_sum_x2[0] ^ xor_sum_x2[1];
     318             : #else
     319             :   u64 *data = (u64 *) h;
     320             :   u64 *mask = (u64 *) t->mask;
     321             : 
     322             :   xor_sum = (data[0] & mask[0]) ^ (data[1] & mask[1]);
     323             : 
     324             :   switch (t->match_n_vectors)
     325             :     {
     326             :     case 5:
     327             :       xor_sum ^= (data[8] & mask[8]) ^ (data[9] & mask[9]);
     328             :       /* FALLTHROUGH */
     329             :     case 4:
     330             :       xor_sum ^= (data[6] & mask[6]) ^ (data[7] & mask[7]);
     331             :       /* FALLTHROUGH */
     332             :     case 3:
     333             :       xor_sum ^= (data[4] & mask[4]) ^ (data[5] & mask[5]);
     334             :       /* FALLTHROUGH */
     335             :     case 2:
     336             :       xor_sum ^= (data[2] & mask[2]) ^ (data[3] & mask[3]);
     337             :       /* FALLTHROUGH */
     338             :     case 1:
     339             :       break;
     340             : 
     341             :     default:
     342             :       abort ();
     343             :     }
     344             : #endif /* CLIB_HAVE_VEC128 */
     345             : 
     346             : #ifdef clib_crc32c_uses_intrinsics
     347      164729 :   return clib_crc32c ((u8 *) & xor_sum, sizeof (xor_sum));
     348             : #else
     349             :   return clib_xxhash (xor_sum);
     350             : #endif
     351             : }
     352             : 
     353             : static inline void
     354         453 : vnet_classify_prefetch_bucket (vnet_classify_table_t * t, u64 hash)
     355             : {
     356             :   u32 bucket_index;
     357             : 
     358         453 :   ASSERT (is_pow2 (t->nbuckets));
     359             : 
     360         453 :   bucket_index = hash & (t->nbuckets - 1);
     361             : 
     362         453 :   clib_prefetch_load (&t->buckets[bucket_index]);
     363         453 : }
     364             : 
     365             : static inline vnet_classify_entry_t *
     366      117010 : vnet_classify_get_entry (const vnet_classify_table_t *t, uword offset)
     367             : {
     368      117010 :   u8 *hp = clib_mem_get_heap_base (t->mheap);
     369      117010 :   u8 *vp = hp + offset;
     370             : 
     371      117010 :   return (vnet_classify_entry_t *) vp;
     372             : }
     373             : 
     374             : static inline uword
     375      127152 : vnet_classify_get_offset (vnet_classify_table_t * t,
     376             :                           vnet_classify_entry_t * v)
     377             : {
     378             :   u8 *hp, *vp;
     379             : 
     380      127152 :   hp = (u8 *) clib_mem_get_heap_base (t->mheap);
     381      127152 :   vp = (u8 *) v;
     382             : 
     383      127152 :   ASSERT ((vp - hp) < 0x100000000ULL);
     384      127152 :   return vp - hp;
     385             : }
     386             : 
     387             : static inline vnet_classify_entry_t *
     388      837103 : vnet_classify_entry_at_index (const vnet_classify_table_t *t,
     389             :                               vnet_classify_entry_t *e, u32 index)
     390             : {
     391             :   u8 *eu8;
     392             : 
     393      837103 :   eu8 = (u8 *) e;
     394             : 
     395      837103 :   eu8 += index * (sizeof (vnet_classify_entry_t) +
     396      837103 :                   (t->match_n_vectors * sizeof (u32x4)));
     397             : 
     398      837103 :   return (vnet_classify_entry_t *) eu8;
     399             : }
     400             : 
     401             : static inline void
     402         138 : vnet_classify_prefetch_entry (vnet_classify_table_t * t, u64 hash)
     403             : {
     404             :   u32 bucket_index;
     405             :   u32 value_index;
     406             :   vnet_classify_bucket_t *b;
     407             :   vnet_classify_entry_t *e;
     408             : 
     409         138 :   bucket_index = hash & (t->nbuckets - 1);
     410             : 
     411         138 :   b = &t->buckets[bucket_index];
     412             : 
     413         138 :   if (b->offset == 0)
     414          83 :     return;
     415             : 
     416          55 :   hash >>= t->log2_nbuckets;
     417             : 
     418          55 :   e = vnet_classify_get_entry (t, b->offset);
     419          55 :   value_index = hash & ((1 << b->log2_pages) - 1);
     420             : 
     421          55 :   e = vnet_classify_entry_at_index (t, e, value_index);
     422             : 
     423          55 :   clib_prefetch_load (e);
     424             : }
     425             : 
     426             : vnet_classify_entry_t *
     427             : vnet_classify_find_entry (const vnet_classify_table_t *t, u8 *h, u32 hash,
     428             :                           f64 now);
     429             : 
     430             : static_always_inline int
     431         921 : vnet_classify_entry_is_equal (vnet_classify_entry_t *v, const u8 *d, u8 *m,
     432             :                               u32 match_n_vectors, u16 load_mask)
     433             : {
     434             : #if defined(CLIB_HAVE_VEC512) && defined(CLIB_HAVE_VEC512_MASK_LOAD_STORE)
     435           0 :   u64x8 r, *mask = (u64x8 *) m;
     436           0 :   u64x8u *data = (u64x8u *) d;
     437           0 :   u64x8 *key = (u64x8 *) v->key;
     438             : 
     439           0 :   r = (u64x8_mask_load_zero (data, load_mask) & mask[0]) ^
     440           0 :       u64x8_mask_load_zero (key, load_mask);
     441           0 :   load_mask >>= 8;
     442             : 
     443           0 :   if (PREDICT_FALSE (load_mask))
     444           0 :     r |= (u64x8_mask_load_zero (data + 1, load_mask) & mask[1]) ^
     445           0 :          u64x8_mask_load_zero (key + 1, load_mask);
     446             : 
     447           0 :   if (u64x8_is_all_zero (r))
     448           0 :     return 1;
     449             : 
     450             : #elif defined(CLIB_HAVE_VEC256) && defined(CLIB_HAVE_VEC256_MASK_LOAD_STORE)
     451         318 :   u64x4 r, *mask = (u64x4 *) m;
     452         318 :   u64x4u *data = (u64x4u *) d;
     453         318 :   u64x4 *key = (u64x4 *) v->key;
     454             : 
     455         318 :   r = (u64x4_mask_load_zero (data, load_mask) & mask[0]) ^
     456         318 :       u64x4_mask_load_zero (key, load_mask);
     457         318 :   load_mask >>= 4;
     458             : 
     459         318 :   r |= (u64x4_mask_load_zero (data + 1, load_mask) & mask[1]) ^
     460         318 :        u64x4_mask_load_zero (key + 1, load_mask);
     461         318 :   load_mask >>= 4;
     462             : 
     463         318 :   if (PREDICT_FALSE (load_mask))
     464           8 :     r |= (u64x4_mask_load_zero (data + 2, load_mask) & mask[2]) ^
     465           4 :          u64x4_mask_load_zero (key + 2, load_mask);
     466             : 
     467         318 :   if (u64x4_is_all_zero (r))
     468         242 :     return 1;
     469             : 
     470             : #elif defined(CLIB_HAVE_VEC128)
     471         603 :   u64x2u *data = (u64x2 *) d;
     472         603 :   u64x2 *key = (u64x2 *) v->key;
     473         603 :   u64x2 *mask = (u64x2 *) m;
     474             :   u64x2 r;
     475             : 
     476         603 :   r = (data[0] & mask[0]) ^ key[0];
     477         603 :   switch (match_n_vectors)
     478             :     {
     479           0 :     case 5:
     480           0 :       r |= (data[4] & mask[4]) ^ key[4];
     481             :       /* fall through */
     482           0 :     case 4:
     483           0 :       r |= (data[3] & mask[3]) ^ key[3];
     484             :       /* fall through */
     485          80 :     case 3:
     486          80 :       r |= (data[2] & mask[2]) ^ key[2];
     487             :       /* fall through */
     488         516 :     case 2:
     489         516 :       r |= (data[1] & mask[1]) ^ key[1];
     490             :       /* fall through */
     491         603 :     case 1:
     492         603 :       break;
     493           0 :     default:
     494           0 :       abort ();
     495             :     }
     496             : 
     497         603 :   if (u64x2_is_all_zero (r))
     498         415 :     return 1;
     499             : 
     500             : #else
     501             :   u64 *data = (u64 *) d;
     502             :   u64 *key = (u64 *) v->key;
     503             :   u64 *mask = (u64 *) m;
     504             :   u64 r;
     505             : 
     506             :   r = ((data[0] & mask[0]) ^ key[0]) | ((data[1] & mask[1]) ^ key[1]);
     507             :   switch (match_n_vectors)
     508             :     {
     509             :     case 5:
     510             :       r |= ((data[8] & mask[8]) ^ key[8]) | ((data[9] & mask[9]) ^ key[9]);
     511             :       /* fall through */
     512             :     case 4:
     513             :       r |= ((data[6] & mask[6]) ^ key[6]) | ((data[7] & mask[7]) ^ key[7]);
     514             :       /* fall through */
     515             :     case 3:
     516             :       r |= ((data[4] & mask[4]) ^ key[4]) | ((data[5] & mask[5]) ^ key[5]);
     517             :       /* fall through */
     518             :     case 2:
     519             :       r |= ((data[2] & mask[2]) ^ key[2]) | ((data[3] & mask[3]) ^ key[3]);
     520             :       /* fall through */
     521             :     case 1:
     522             :       break;
     523             :     default:
     524             :       abort ();
     525             :     }
     526             : 
     527             :   if (r == 0)
     528             :     return 1;
     529             : 
     530             : #endif /* CLIB_HAVE_VEC128 */
     531         264 :   return 0;
     532             : }
     533             : 
     534             : static inline vnet_classify_entry_t *
     535        1889 : vnet_classify_find_entry_inline (const vnet_classify_table_t *t, const u8 *h,
     536             :                                  u32 hash, f64 now)
     537             : {
     538             :   vnet_classify_entry_t *v;
     539             :   vnet_classify_bucket_t *b;
     540        1889 :   u32 bucket_index, limit, pages, match_n_vectors = t->match_n_vectors;
     541        1889 :   u16 load_mask = t->load_mask;
     542        1889 :   u8 *mask = (u8 *) t->mask;
     543             :   int i;
     544             : 
     545        1889 :   bucket_index = hash & (t->nbuckets - 1);
     546        1889 :   b = &t->buckets[bucket_index];
     547             : 
     548        1889 :   if (b->offset == 0)
     549        1112 :     return 0;
     550             : 
     551         777 :   pages = 1 << b->log2_pages;
     552         777 :   v = vnet_classify_get_entry (t, b->offset);
     553         777 :   limit = t->entries_per_page;
     554         777 :   if (PREDICT_FALSE (b->linear_search))
     555             :     {
     556           0 :       limit *= pages;
     557           0 :       v = vnet_classify_entry_at_index (t, v, 0);
     558             :     }
     559             :   else
     560             :     {
     561         777 :       hash >>= t->log2_nbuckets;
     562         777 :       v = vnet_classify_entry_at_index (t, v, hash & (pages - 1));
     563             :     }
     564             : 
     565         777 :   h += t->skip_n_vectors * 16;
     566             : 
     567        1041 :   for (i = 0; i < limit; i++)
     568             :     {
     569         921 :       if (vnet_classify_entry_is_equal (v, h, mask, match_n_vectors,
     570             :                                         load_mask))
     571             :         {
     572         657 :           if (PREDICT_TRUE (now))
     573             :             {
     574         461 :               v->hits++;
     575         461 :               v->last_heard = now;
     576             :             }
     577         657 :           return (v);
     578             :         }
     579         264 :       v = vnet_classify_entry_at_index (t, v, 1);
     580             :     }
     581         120 :   return 0;
     582             : }
     583             : 
     584             : vnet_classify_table_t *vnet_classify_new_table (vnet_classify_main_t *cm,
     585             :                                                 const u8 *mask, u32 nbuckets,
     586             :                                                 u32 memory_size,
     587             :                                                 u32 skip_n_vectors,
     588             :                                                 u32 match_n_vectors);
     589             : 
     590             : int vnet_classify_add_del_session (vnet_classify_main_t *cm, u32 table_index,
     591             :                                    const u8 *match, u16 hit_next_index,
     592             :                                    u32 opaque_index, i32 advance, u8 action,
     593             :                                    u32 metadata, int is_add);
     594             : 
     595             : int vnet_classify_add_del_table (vnet_classify_main_t *cm, const u8 *mask,
     596             :                                  u32 nbuckets, u32 memory_size, u32 skip,
     597             :                                  u32 match, u32 next_table_index,
     598             :                                  u32 miss_next_index, u32 *table_index,
     599             :                                  u8 current_data_flag, i16 current_data_offset,
     600             :                                  int is_add, int del_chain);
     601             : void vnet_classify_delete_table_index (vnet_classify_main_t *cm,
     602             :                                        u32 table_index, int del_chain);
     603             : 
     604             : unformat_function_t unformat_ip4_mask;
     605             : unformat_function_t unformat_ip6_mask;
     606             : unformat_function_t unformat_l3_mask;
     607             : unformat_function_t unformat_l2_mask;
     608             : unformat_function_t unformat_classify_mask;
     609             : unformat_function_t unformat_l2_next_index;
     610             : unformat_function_t unformat_ip_next_index;
     611             : unformat_function_t unformat_ip4_match;
     612             : unformat_function_t unformat_ip6_match;
     613             : unformat_function_t unformat_l3_match;
     614             : unformat_function_t unformat_l4_match;
     615             : unformat_function_t unformat_vlan_tag;
     616             : unformat_function_t unformat_l2_match;
     617             : unformat_function_t unformat_classify_match;
     618             : 
     619             : void vnet_classify_register_unformat_ip_next_index_fn
     620             :   (unformat_function_t * fn);
     621             : 
     622             : void vnet_classify_register_unformat_l2_next_index_fn
     623             :   (unformat_function_t * fn);
     624             : 
     625             : void vnet_classify_register_unformat_acl_next_index_fn
     626             :   (unformat_function_t * fn);
     627             : 
     628             : void vnet_classify_register_unformat_policer_next_index_fn
     629             :   (unformat_function_t * fn);
     630             : 
     631             : void vnet_classify_register_unformat_opaque_index_fn (unformat_function_t *
     632             :                                                       fn);
     633             : 
     634             : u32 classify_get_pcap_chain (vnet_classify_main_t * cm, u32 sw_if_index);
     635             : void classify_set_pcap_chain (vnet_classify_main_t * cm,
     636             :                               u32 sw_if_index, u32 table_index);
     637             : 
     638             : u32 classify_get_trace_chain (void);
     639             : void classify_set_trace_chain (vnet_classify_main_t * cm, u32 table_index);
     640             : 
     641             : u32 classify_sort_table_chain (vnet_classify_main_t * cm, u32 table_index);
     642             : u32 classify_lookup_chain (u32 table_index,
     643             :                            u8 * mask, u32 n_skip, u32 n_match);
     644             : 
     645             : #endif /* __included_vnet_classify_h__ */
     646             : 
     647             : /*
     648             :  * fd.io coding-style-patch-verification: ON
     649             :  *
     650             :  * Local Variables:
     651             :  * eval: (c-set-style "gnu")
     652             :  * End:
     653             :  */

Generated by: LCOV version 1.14