FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
node_funcs.c
Go to the documentation of this file.
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 
16 #include <stdint.h>
17 
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 #include <vnet/policer/policer.h>
22 #include <vnet/ip/ip.h>
25 #include <vnet/l2/feat_bitmap.h>
26 #include <vnet/l2/l2_input.h>
27 
28 
29 /* Dispatch functions meant to be instantiated elsewhere */
30 
31 typedef struct
32 {
37 
38 /* packet trace format function */
39 static u8 *
40 format_policer_trace (u8 * s, va_list * args)
41 {
42  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
43  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
44  vnet_policer_trace_t *t = va_arg (*args, vnet_policer_trace_t *);
45 
46  s = format (s, "VNET_POLICER: sw_if_index %d policer_index %d next %d",
48  return s;
49 }
50 
51 #define foreach_vnet_policer_error \
52 _(TRANSMIT, "Packets Transmitted") \
53 _(DROP, "Packets Dropped")
54 
55 typedef enum
56 {
57 #define _(sym,str) VNET_POLICER_ERROR_##sym,
59 #undef _
62 
63 static char *vnet_policer_error_strings[] = {
64 #define _(sym,string) string,
66 #undef _
67 };
68 
69 static inline uword
73 {
74  u32 n_left_from, *from, *to_next;
75  vnet_policer_next_t next_index;
77  u64 time_in_policer_periods;
78  u32 transmitted = 0;
79 
80  time_in_policer_periods =
82 
83  from = vlib_frame_vector_args (frame);
84  n_left_from = frame->n_vectors;
85  next_index = node->cached_next_index;
86 
87  while (n_left_from > 0)
88  {
89  u32 n_left_to_next;
90 
91  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
92 
93  while (n_left_from >= 4 && n_left_to_next >= 2)
94  {
95  u32 bi0, bi1;
96  vlib_buffer_t *b0, *b1;
97  u32 next0, next1;
98  u32 sw_if_index0, sw_if_index1;
99  u32 pi0 = 0, pi1 = 0;
100  u8 act0, act1;
101 
102  /* Prefetch next iteration. */
103  {
104  vlib_buffer_t *b2, *b3;
105 
106  b2 = vlib_get_buffer (vm, from[2]);
107  b3 = vlib_get_buffer (vm, from[3]);
108 
109  vlib_prefetch_buffer_header (b2, LOAD);
110  vlib_prefetch_buffer_header (b3, LOAD);
111  }
112 
113  /* speculatively enqueue b0 and b1 to the current next frame */
114  to_next[0] = bi0 = from[0];
115  to_next[1] = bi1 = from[1];
116  from += 2;
117  to_next += 2;
118  n_left_from -= 2;
119  n_left_to_next -= 2;
120 
121  b0 = vlib_get_buffer (vm, bi0);
122  b1 = vlib_get_buffer (vm, bi1);
123 
124  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
126 
127  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
129 
130 
132  {
133  pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
134  pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
135  }
136 
137  if (which == VNET_POLICER_INDEX_BY_OPAQUE)
138  {
139  pi0 = vnet_buffer (b0)->policer.index;
140  pi1 = vnet_buffer (b1)->policer.index;
141  }
142 
143  if (which == VNET_POLICER_INDEX_BY_EITHER)
144  {
145  pi0 = vnet_buffer (b0)->policer.index;
146  pi0 = (pi0 != ~0) ? pi0 :
147  pm->policer_index_by_sw_if_index[sw_if_index0];
148  pi1 = vnet_buffer (b1)->policer.index;
149  pi1 = (pi1 != ~0) ? pi1 :
150  pm->policer_index_by_sw_if_index[sw_if_index1];
151  }
152 
153  act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
154  POLICE_CONFORM /* no chaining */ );
155 
156  act1 = vnet_policer_police (vm, b1, pi1, time_in_policer_periods,
157  POLICE_CONFORM /* no chaining */ );
158 
159  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
160  {
161  next0 = VNET_POLICER_NEXT_DROP;
162  b0->error = node->errors[VNET_POLICER_ERROR_DROP];
163  }
164  else /* transmit or mark-and-transmit action */
165  {
166  transmitted++;
167  }
168 
169  if (PREDICT_FALSE (act1 == SSE2_QOS_ACTION_DROP)) /* drop action */
170  {
171  next1 = VNET_POLICER_NEXT_DROP;
172  b1->error = node->errors[VNET_POLICER_ERROR_DROP];
173  }
174  else /* transmit or mark-and-transmit action */
175  {
176  transmitted++;
177  }
178 
179 
180  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
181  {
182  if (b0->flags & VLIB_BUFFER_IS_TRACED)
183  {
185  vlib_add_trace (vm, node, b0, sizeof (*t));
186  t->sw_if_index = sw_if_index0;
187  t->next_index = next0;
188  }
189  if (b1->flags & VLIB_BUFFER_IS_TRACED)
190  {
192  vlib_add_trace (vm, node, b1, sizeof (*t));
193  t->sw_if_index = sw_if_index1;
194  t->next_index = next1;
195  }
196  }
197 
198  /* verify speculative enqueues, maybe switch current next frame */
199  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
200  to_next, n_left_to_next,
201  bi0, bi1, next0, next1);
202  }
203 
204  while (n_left_from > 0 && n_left_to_next > 0)
205  {
206  u32 bi0;
207  vlib_buffer_t *b0;
208  u32 next0;
209  u32 sw_if_index0;
210  u32 pi0 = 0;
211  u8 act0;
212 
213  bi0 = from[0];
214  to_next[0] = bi0;
215  from += 1;
216  to_next += 1;
217  n_left_from -= 1;
218  n_left_to_next -= 1;
219 
220  b0 = vlib_get_buffer (vm, bi0);
221 
222  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
224 
226  pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
227 
228  if (which == VNET_POLICER_INDEX_BY_OPAQUE)
229  pi0 = vnet_buffer (b0)->policer.index;
230 
231  if (which == VNET_POLICER_INDEX_BY_EITHER)
232  {
233  pi0 = vnet_buffer (b0)->policer.index;
234  pi0 = (pi0 != ~0) ? pi0 :
235  pm->policer_index_by_sw_if_index[sw_if_index0];
236  }
237 
238  act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
239  POLICE_CONFORM /* no chaining */ );
240 
241  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
242  {
243  next0 = VNET_POLICER_NEXT_DROP;
244  b0->error = node->errors[VNET_POLICER_ERROR_DROP];
245  }
246  else /* transmit or mark-and-transmit action */
247  {
248  transmitted++;
249  }
250 
252  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
253  {
255  vlib_add_trace (vm, node, b0, sizeof (*t));
256  t->sw_if_index = sw_if_index0;
257  t->next_index = next0;
258  t->policer_index = pi0;
259  }
260 
261  /* verify speculative enqueue, maybe switch current next frame */
262  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
263  to_next, n_left_to_next,
264  bi0, next0);
265  }
266 
267  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
268  }
269 
271  VNET_POLICER_ERROR_TRANSMIT, transmitted);
272  return frame->n_vectors;
273 }
274 
278 {
279  return vnet_policer_inline (vm, node, frame,
281 }
282 
283 #ifndef CLIB_MARCH_VARIANT
284 uword
287 {
288  return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_OPAQUE);
289 }
290 
291 uword
294 {
295  return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_EITHER);
296 }
297 
298 void
300 {
301 }
302 #endif /* CLIB_MARCH_VARIANT */
303 
304 
305 #define TEST_CODE 1
306 
307 #ifdef TEST_CODE
308 
309 /* *INDENT-OFF* */
311  .name = "policer-by-sw-if-index",
312  .vector_size = sizeof (u32),
313  .format_trace = format_policer_trace,
315 
317  .error_strings = vnet_policer_error_strings,
318 
319  .n_next_nodes = VNET_POLICER_N_NEXT,
320 
321  /* edit / add dispositions here */
322  .next_nodes = {
323  [VNET_POLICER_NEXT_TRANSMIT] = "ethernet-input",
324  [VNET_POLICER_NEXT_DROP] = "error-drop",
325  },
326 };
327 /* *INDENT-ON* */
328 
329 
330 #ifndef CLIB_MARCH_VARIANT
331 int
332 test_policer_add_del (u32 rx_sw_if_index, u8 * config_name, int is_add)
333 {
337  vnet_hw_interface_t *rxhi;
338  uword *p;
339 
340  rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
341 
342  /* Make sure caller didn't pass a vlan subif, etc. */
343  if (rxhi->sw_if_index != rx_sw_if_index)
344  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
345 
346  if (is_add)
347  {
348 
349  p = hash_get_mem (pm->policer_config_by_name, config_name);
350 
351  if (p == 0)
352  return -2;
353 
354  template = pool_elt_at_index (pm->policer_templates, p[0]);
355 
358 
360 
361  policer[0] = template[0];
362 
363  vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
364  pm->policer_index_by_sw_if_index[rx_sw_if_index]
365  = policer - pm->policers;
366  }
367  else
368  {
369  u32 pi;
371  rxhi->hw_if_index,
372  ~0 /* disable */ );
373 
374  pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
375  pm->policer_index_by_sw_if_index[rx_sw_if_index] = ~0;
376  pool_put_index (pm->policers, pi);
377  }
378 
379  return 0;
380 }
381 
382 static clib_error_t *
384  unformat_input_t * input, vlib_cli_command_t * cmd)
385 {
387  unformat_input_t _line_input, *line_input = &_line_input;
388  u32 rx_sw_if_index;
389  int rv;
390  u8 *config_name = 0;
391  int rx_set = 0;
392  int is_add = 1;
393  int is_show = 0;
394  clib_error_t *error = NULL;
395 
396  /* Get a line of input. */
397  if (!unformat_user (input, unformat_line_input, line_input))
398  return 0;
399 
400  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
401  {
402  if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
403  pm->vnet_main, &rx_sw_if_index))
404  rx_set = 1;
405  else if (unformat (line_input, "show"))
406  is_show = 1;
407  else if (unformat (line_input, "policer %s", &config_name))
408  ;
409  else if (unformat (line_input, "del"))
410  is_add = 0;
411  else
412  break;
413  }
414 
415  if (rx_set == 0)
416  {
417  error = clib_error_return (0, "interface not set");
418  goto done;
419  }
420 
421  if (is_show)
422  {
423  u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
425  policer = pool_elt_at_index (pm->policers, pi);
426 
427  vlib_cli_output (vm, "%U", format_policer_instance, policer);
428  goto done;
429  }
430 
431  if (is_add && config_name == 0)
432  {
433  error = clib_error_return (0, "policer config name required");
434  goto done;
435  }
436 
437  rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
438 
439  switch (rv)
440  {
441  case 0:
442  break;
443 
444  default:
445  error = clib_error_return
446  (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
447  goto done;
448  }
449 
450 done:
451  unformat_free (line_input);
452 
453  return error;
454 }
455 
456 /* *INDENT-OFF* */
457 VLIB_CLI_COMMAND (test_patch_command, static) = {
458  .path = "test policer",
459  .short_help =
460  "intfc <intfc> policer <policer-config-name> [del]",
461  .function = test_policer_command_fn,
462 };
463 /* *INDENT-ON* */
464 #endif /* CLIB_MARCH_VARIANT */
465 
466 #endif /* TEST_CODE */
467 
468 
469 typedef struct
470 {
477 
478 static u8 *
479 format_policer_classify_trace (u8 * s, va_list * args)
480 {
481  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
482  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
483  policer_classify_trace_t *t = va_arg (*args, policer_classify_trace_t *);
484 
485  s = format (s, "POLICER_CLASSIFY: sw_if_index %d next %d table %d offset %d"
486  " policer_index %d",
487  t->sw_if_index, t->next_index, t->table_index, t->offset,
488  t->policer_index);
489  return s;
490 }
491 
492 #define foreach_policer_classify_error \
493 _(MISS, "Policer classify misses") \
494 _(HIT, "Policer classify hits") \
495 _(CHAIN_HIT, "Policer classify hits after chain walk") \
496 _(DROP, "Policer classify action drop")
497 
498 typedef enum
499 {
500 #define _(sym,str) POLICER_CLASSIFY_ERROR_##sym,
502 #undef _
505 
507 #define _(sym,string) string,
509 #undef _
510 };
511 
512 static inline uword
517 {
518  u32 n_left_from, *from, *to_next;
522  f64 now = vlib_time_now (vm);
523  u32 hits = 0;
524  u32 misses = 0;
525  u32 chain_hits = 0;
526  u32 n_next_nodes;
527  u64 time_in_policer_periods;
528 
529  time_in_policer_periods =
531 
532  n_next_nodes = node->n_next_nodes;
533 
534  from = vlib_frame_vector_args (frame);
535  n_left_from = frame->n_vectors;
536 
537  /* First pass: compute hashes */
538  while (n_left_from > 2)
539  {
540  vlib_buffer_t *b0, *b1;
541  u32 bi0, bi1;
542  u8 *h0, *h1;
543  u32 sw_if_index0, sw_if_index1;
544  u32 table_index0, table_index1;
545  vnet_classify_table_t *t0, *t1;
546 
547  /* Prefetch next iteration */
548  {
549  vlib_buffer_t *p1, *p2;
550 
551  p1 = vlib_get_buffer (vm, from[1]);
552  p2 = vlib_get_buffer (vm, from[2]);
553 
554  vlib_prefetch_buffer_header (p1, STORE);
556  vlib_prefetch_buffer_header (p2, STORE);
558  }
559 
560  bi0 = from[0];
561  b0 = vlib_get_buffer (vm, bi0);
562  h0 = b0->data;
563 
564  bi1 = from[1];
565  b1 = vlib_get_buffer (vm, bi1);
566  h1 = b1->data;
567 
568  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
569  table_index0 =
570  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
571 
572  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
573  table_index1 =
574  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
575 
576  t0 = pool_elt_at_index (vcm->tables, table_index0);
577 
578  t1 = pool_elt_at_index (vcm->tables, table_index1);
579 
580  vnet_buffer (b0)->l2_classify.hash =
581  vnet_classify_hash_packet (t0, (u8 *) h0);
582 
583  vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
584 
585  vnet_buffer (b1)->l2_classify.hash =
586  vnet_classify_hash_packet (t1, (u8 *) h1);
587 
588  vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash);
589 
590  vnet_buffer (b0)->l2_classify.table_index = table_index0;
591 
592  vnet_buffer (b1)->l2_classify.table_index = table_index1;
593 
594  from += 2;
595  n_left_from -= 2;
596  }
597 
598  while (n_left_from > 0)
599  {
600  vlib_buffer_t *b0;
601  u32 bi0;
602  u8 *h0;
603  u32 sw_if_index0;
604  u32 table_index0;
606 
607  bi0 = from[0];
608  b0 = vlib_get_buffer (vm, bi0);
609  h0 = b0->data;
610 
611  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
612  table_index0 =
613  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
614 
615  t0 = pool_elt_at_index (vcm->tables, table_index0);
616  vnet_buffer (b0)->l2_classify.hash =
617  vnet_classify_hash_packet (t0, (u8 *) h0);
618 
619  vnet_buffer (b0)->l2_classify.table_index = table_index0;
620  vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
621 
622  from++;
623  n_left_from--;
624  }
625 
626  next_index = node->cached_next_index;
627  from = vlib_frame_vector_args (frame);
628  n_left_from = frame->n_vectors;
629 
630  while (n_left_from > 0)
631  {
632  u32 n_left_to_next;
633 
634  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
635 
636  /* Not enough load/store slots to dual loop... */
637  while (n_left_from > 0 && n_left_to_next > 0)
638  {
639  u32 bi0;
640  vlib_buffer_t *b0;
642  u32 table_index0;
644  vnet_classify_entry_t *e0;
645  u64 hash0;
646  u8 *h0;
647  u8 act0;
648 
649  /* Stride 3 seems to work best */
650  if (PREDICT_TRUE (n_left_from > 3))
651  {
652  vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
654  u32 table_index1;
655  u64 phash1;
656 
657  table_index1 = vnet_buffer (p1)->l2_classify.table_index;
658 
659  if (PREDICT_TRUE (table_index1 != ~0))
660  {
661  tp1 = pool_elt_at_index (vcm->tables, table_index1);
662  phash1 = vnet_buffer (p1)->l2_classify.hash;
663  vnet_classify_prefetch_entry (tp1, phash1);
664  }
665  }
666 
667  /* Speculatively enqueue b0 to the current next frame */
668  bi0 = from[0];
669  to_next[0] = bi0;
670  from += 1;
671  to_next += 1;
672  n_left_from -= 1;
673  n_left_to_next -= 1;
674 
675  b0 = vlib_get_buffer (vm, bi0);
676  h0 = b0->data;
677  table_index0 = vnet_buffer (b0)->l2_classify.table_index;
678  e0 = 0;
679  t0 = 0;
680 
681  if (tid == POLICER_CLASSIFY_TABLE_L2)
682  {
683  /* Feature bitmap update and determine the next node */
684  next0 = vnet_l2_feature_next (b0, pcm->feat_next_node_index,
685  L2INPUT_FEAT_POLICER_CLAS);
686  }
687  else
689  &b0->current_config_index, &next0,
690  /* # bytes of config data */ 0);
691 
692  vnet_buffer (b0)->l2_classify.opaque_index = ~0;
693 
694  if (PREDICT_TRUE (table_index0 != ~0))
695  {
696  hash0 = vnet_buffer (b0)->l2_classify.hash;
697  t0 = pool_elt_at_index (vcm->tables, table_index0);
698  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
699 
700  if (e0)
701  {
702  act0 = vnet_policer_police (vm,
703  b0,
704  e0->next_index,
705  time_in_policer_periods,
706  e0->opaque_index);
707  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
708  {
710  b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
711  }
712  hits++;
713  }
714  else
715  {
716  while (1)
717  {
718  if (PREDICT_TRUE (t0->next_table_index != ~0))
719  {
720  t0 = pool_elt_at_index (vcm->tables,
721  t0->next_table_index);
722  }
723  else
724  {
725  next0 = (t0->miss_next_index < n_next_nodes) ?
726  t0->miss_next_index : next0;
727  misses++;
728  break;
729  }
730 
731  hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
732  e0 =
733  vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
734  if (e0)
735  {
736  act0 = vnet_policer_police (vm,
737  b0,
738  e0->next_index,
739  time_in_policer_periods,
740  e0->opaque_index);
741  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
742  {
744  b0->error =
745  node->errors[POLICER_CLASSIFY_ERROR_DROP];
746  }
747  hits++;
748  chain_hits++;
749  break;
750  }
751  }
752  }
753  }
755  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
756  {
758  vlib_add_trace (vm, node, b0, sizeof (*t));
759  t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
760  t->next_index = next0;
761  t->table_index = t0 ? t0 - vcm->tables : ~0;
762  t->offset = (e0 && t0) ? vnet_classify_get_offset (t0, e0) : ~0;
763  t->policer_index = e0 ? e0->next_index : ~0;
764  }
765 
766  /* Verify speculative enqueue, maybe switch current next frame */
767  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
768  n_left_to_next, bi0, next0);
769  }
770 
771  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
772  }
773 
775  POLICER_CLASSIFY_ERROR_MISS, misses);
777  POLICER_CLASSIFY_ERROR_HIT, hits);
779  POLICER_CLASSIFY_ERROR_CHAIN_HIT, chain_hits);
780 
781  return frame->n_vectors;
782 }
783 
787 {
788  return policer_classify_inline (vm, node, frame,
790 }
791 
792 /* *INDENT-OFF* */
794  .name = "ip4-policer-classify",
795  .vector_size = sizeof (u32),
796  .format_trace = format_policer_classify_trace,
798  .error_strings = policer_classify_error_strings,
799  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
800  .next_nodes = {
801  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
802  },
803 };
804 /* *INDENT-ON* */
805 
809 {
810  return policer_classify_inline (vm, node, frame,
812 }
813 
814 /* *INDENT-OFF* */
816  .name = "ip6-policer-classify",
817  .vector_size = sizeof (u32),
818  .format_trace = format_policer_classify_trace,
820  .error_strings = policer_classify_error_strings,
821  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
822  .next_nodes = {
823  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
824  },
825 };
826 /* *INDENT-ON* */
827 
831 {
833 }
834 
835 /* *INDENT-OFF* */
837  .name = "l2-policer-classify",
838  .vector_size = sizeof (u32),
839  .format_trace = format_policer_classify_trace,
841  .error_strings = policer_classify_error_strings,
842  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
843  .next_nodes = {
844  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
845  },
846 };
847 /* *INDENT-ON* */
848 
849 #ifndef CLIB_MARCH_VARIANT
850 static clib_error_t *
852 {
854 
855  pcm->vlib_main = vm;
856  pcm->vnet_main = vnet_get_main ();
858 
859  /* Initialize L2 feature next-node indexes */
864  pcm->feat_next_node_index);
865 
866  return 0;
867 }
868 
870 #endif /* CLIB_MARCH_VARIANT */
871 
872 /*
873  * fd.io coding-style-patch-verification: ON
874  *
875  * Local Variables:
876  * eval: (c-set-style "gnu")
877  * End:
878  */
u64 vnet_classify_hash_packet(vnet_classify_table_t *t, u8 *h)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
policer_classify_main_t policer_classify_main
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
#define foreach_vnet_policer_error
Definition: node_funcs.c:51
#define CLIB_UNUSED(x)
Definition: clib.h:87
#define POLICER_TICKS_PER_PERIOD_SHIFT
Definition: police.h:57
vnet_policer_error_t
Definition: node_funcs.c:55
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_node_registration_t ip6_policer_classify_node
(constructor) VLIB_REGISTER_NODE (ip6_policer_classify_node)
Definition: node_funcs.c:815
uword * policer_config_by_name
Definition: policer.h:34
#define PREDICT_TRUE(x)
Definition: clib.h:121
unsigned long u64
Definition: types.h:89
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:1209
vnet_policer_next_t
Definition: policer.h:56
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:333
static uword vnet_policer_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_policer_index_t which)
Definition: node_funcs.c:70
int test_policer_add_del(u32 rx_sw_if_index, u8 *config_name, int is_add)
Definition: node_funcs.c:332
static u64 clib_cpu_time_now(void)
Definition: time.h:81
policer_classify_error_t
Definition: node_funcs.c:498
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
vlib_main_t * vm
Definition: in2out_ed.c:1582
vnet_main_t * vnet_main
Definition: policer.h:44
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
#define VLIB_NODE_FN(node)
Definition: node.h:202
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:469
u8 * format_policer_instance(u8 *s, va_list *va)
Definition: policer.c:101
unsigned char u8
Definition: types.h:56
static u32 vnet_l2_feature_next(vlib_buffer_t *b, u32 *next_nodes, u32 feat_bit)
Return the graph node index for the feature corresponding to the next set bit after clearing the curr...
Definition: feat_bitmap.h:94
double f64
Definition: types.h:142
policer_classify_table_id_t
vnet_policer_main_t vnet_policer_main
Definition: policer.c:19
vlib_node_registration_t policer_by_sw_if_index_node
(constructor) VLIB_REGISTER_NODE (policer_by_sw_if_index_node)
Definition: node_funcs.c:310
uword vnet_policer_by_opaque(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:285
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static char * vnet_policer_error_strings[]
Definition: node_funcs.c:63
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
static void vnet_classify_prefetch_bucket(vnet_classify_table_t *t, u64 hash)
u32 * classify_table_index_by_sw_if_index[POLICER_CLASSIFY_N_TABLES]
static clib_error_t * policer_classify_init(vlib_main_t *vm)
Definition: node_funcs.c:851
static void vnet_classify_prefetch_entry(vnet_classify_table_t *t, u64 hash)
unformat_function_t unformat_line_input
Definition: format.h:283
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
struct _unformat_input_t unformat_input_t
vnet_config_main_t * vnet_config_main[POLICER_CLASSIFY_N_TABLES]
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:123
#define PREDICT_FALSE(x)
Definition: clib.h:120
static uword policer_classify_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, policer_classify_table_id_t tid)
Definition: node_funcs.c:513
u32 node_index
Node index.
Definition: node.h:487
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
policer_read_response_type_st * policers
Definition: policer.h:27
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:391
void vnet_policer_node_funcs_reference(void)
Definition: node_funcs.c:299
uword vnet_policer_by_either(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:292
u32 * policer_index_by_sw_if_index
Definition: policer.h:40
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1231
static char * policer_classify_error_strings[]
Definition: node_funcs.c:506
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:246
static uword vnet_classify_get_offset(vnet_classify_table_t *t, vnet_classify_entry_t *v)
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u16 n_vectors
Definition: node.h:396
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
static void feat_bitmap_init_next_nodes(vlib_main_t *vm, u32 node_index, u32 num_features, char **feat_names, u32 *next_nodes)
Initialize the feature next-node indexes of a graph node.
Definition: feat_bitmap.h:43
u8 data[]
Packet data.
Definition: buffer.h:181
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:147
#define ARRAY_LEN(x)
Definition: clib.h:67
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:62
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:55
#define foreach_policer_classify_error
Definition: node_funcs.c:492
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:510
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:331
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static_always_inline u8 vnet_policer_police(vlib_main_t *vm, vlib_buffer_t *b, u32 policer_index, u64 time_in_policer_periods, policer_result_e packet_color)
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:29
policer_classify_next_index_t
vnet_classify_main_t * vnet_classify_main
vlib_node_registration_t ip4_policer_classify_node
(constructor) VLIB_REGISTER_NODE (ip4_policer_classify_node)
Definition: node_funcs.c:793
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
static clib_error_t * test_policer_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: node_funcs.c:383
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define hash_get_mem(h, key)
Definition: hash.h:269
policer_read_response_type_st * policer_templates
Definition: policer.h:31
#define vnet_buffer(b)
Definition: buffer.h:417
vlib_node_registration_t l2_policer_classify_node
(constructor) VLIB_REGISTER_NODE (l2_policer_classify_node)
Definition: node_funcs.c:836
u16 flags
Copy of main node flags.
Definition: node.h:500
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:577
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
vnet_classify_entry_t * vnet_classify_find_entry(vnet_classify_table_t *t, u8 *h, u64 hash, f64 now)
static u8 * format_policer_trace(u8 *s, va_list *args)
Definition: node_funcs.c:40
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vnet_policer_index_t
Definition: policer.h:49
Definition: defs.h:46
static u8 * format_policer_classify_trace(u8 *s, va_list *args)
Definition: node_funcs.c:479
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171