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 465842 : vnet_classify_entry_is_free (vnet_classify_entry_t * e)
114 : {
115 465842 : return e->flags & VNET_CLASSIFY_ENTRY_FREE;
116 : }
117 :
118 : static inline int
119 256237 : vnet_classify_entry_is_busy (vnet_classify_entry_t * e)
120 : {
121 256237 : 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 163934 : vnet_classify_hash_packet_inline (const vnet_classify_table_t *t, const u8 *h)
260 : {
261 : u64 xor_sum;
262 163934 : ASSERT (t);
263 163934 : 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 163408 : u64x2 *mask = (u64x2 *) t->mask;
293 163408 : u64x2u *data = (u64x2u *) h;
294 : u64x2 xor_sum_x2;
295 :
296 163408 : xor_sum_x2 = data[0] & mask[0];
297 :
298 163408 : 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 125193 : case 3:
307 125193 : xor_sum_x2 ^= data[2] & mask[2];
308 : /* FALLTHROUGH */
309 163081 : case 2:
310 163081 : xor_sum_x2 ^= data[1] & mask[1];
311 : /* FALLTHROUGH */
312 163408 : case 1:
313 163408 : break;
314 0 : default:
315 0 : abort ();
316 : }
317 163408 : 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 163934 : 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 116906 : vnet_classify_get_entry (const vnet_classify_table_t *t, uword offset)
367 : {
368 116906 : u8 *hp = clib_mem_get_heap_base (t->mheap);
369 116906 : u8 *vp = hp + offset;
370 :
371 116906 : return (vnet_classify_entry_t *) vp;
372 : }
373 :
374 : static inline uword
375 127213 : vnet_classify_get_offset (vnet_classify_table_t * t,
376 : vnet_classify_entry_t * v)
377 : {
378 : u8 *hp, *vp;
379 :
380 127213 : hp = (u8 *) clib_mem_get_heap_base (t->mheap);
381 127213 : vp = (u8 *) v;
382 :
383 127213 : ASSERT ((vp - hp) < 0x100000000ULL);
384 127213 : return vp - hp;
385 : }
386 :
387 : static inline vnet_classify_entry_t *
388 849765 : 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 849765 : eu8 = (u8 *) e;
394 :
395 849765 : eu8 += index * (sizeof (vnet_classify_entry_t) +
396 849765 : (t->match_n_vectors * sizeof (u32x4)));
397 :
398 849765 : 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 722 : 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 324 : u64x4 r, *mask = (u64x4 *) m;
452 324 : u64x4u *data = (u64x4u *) d;
453 324 : u64x4 *key = (u64x4 *) v->key;
454 :
455 324 : r = (u64x4_mask_load_zero (data, load_mask) & mask[0]) ^
456 324 : u64x4_mask_load_zero (key, load_mask);
457 324 : load_mask >>= 4;
458 :
459 324 : r |= (u64x4_mask_load_zero (data + 1, load_mask) & mask[1]) ^
460 324 : u64x4_mask_load_zero (key + 1, load_mask);
461 324 : load_mask >>= 4;
462 :
463 324 : 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 324 : if (u64x4_is_all_zero (r))
468 242 : return 1;
469 :
470 : #elif defined(CLIB_HAVE_VEC128)
471 398 : u64x2u *data = (u64x2 *) d;
472 398 : u64x2 *key = (u64x2 *) v->key;
473 398 : u64x2 *mask = (u64x2 *) m;
474 : u64x2 r;
475 :
476 398 : r = (data[0] & mask[0]) ^ key[0];
477 398 : 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 76 : case 3:
486 76 : r |= (data[2] & mask[2]) ^ key[2];
487 : /* fall through */
488 311 : case 2:
489 311 : r |= (data[1] & mask[1]) ^ key[1];
490 : /* fall through */
491 398 : case 1:
492 398 : break;
493 0 : default:
494 0 : abort ();
495 : }
496 :
497 398 : if (u64x2_is_all_zero (r))
498 348 : 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 132 : return 0;
532 : }
533 :
534 : static inline vnet_classify_entry_t *
535 1688 : 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 1688 : u32 bucket_index, limit, pages, match_n_vectors = t->match_n_vectors;
541 1688 : u16 load_mask = t->load_mask;
542 1688 : u8 *mask = (u8 *) t->mask;
543 : int i;
544 :
545 1688 : bucket_index = hash & (t->nbuckets - 1);
546 1688 : b = &t->buckets[bucket_index];
547 :
548 1688 : if (b->offset == 0)
549 1044 : return 0;
550 :
551 644 : pages = 1 << b->log2_pages;
552 644 : v = vnet_classify_get_entry (t, b->offset);
553 644 : limit = t->entries_per_page;
554 644 : 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 644 : hash >>= t->log2_nbuckets;
562 644 : v = vnet_classify_entry_at_index (t, v, hash & (pages - 1));
563 : }
564 :
565 644 : h += t->skip_n_vectors * 16;
566 :
567 776 : for (i = 0; i < limit; i++)
568 : {
569 722 : if (vnet_classify_entry_is_equal (v, h, mask, match_n_vectors,
570 : load_mask))
571 : {
572 590 : if (PREDICT_TRUE (now))
573 : {
574 461 : v->hits++;
575 461 : v->last_heard = now;
576 : }
577 590 : return (v);
578 : }
579 132 : v = vnet_classify_entry_at_index (t, v, 1);
580 : }
581 54 : 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 : */
|