FD.io VPP  v19.01.3-6-g70449b9b9
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
71  vlib_node_runtime_t * node,
72  vlib_frame_t * frame, vnet_policer_index_t which)
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 
275 uword
277  vlib_node_runtime_t * node, vlib_frame_t * frame)
278 {
279  return vnet_policer_inline (vm, node, frame,
281 }
282 
283 uword
285  vlib_node_runtime_t * node, vlib_frame_t * frame)
286 {
287  return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_OPAQUE);
288 }
289 
290 uword
292  vlib_node_runtime_t * node, vlib_frame_t * frame)
293 {
294  return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_EITHER);
295 }
296 
297 void
299 {
300 }
301 
302 
303 #define TEST_CODE 1
304 
305 #ifdef TEST_CODE
306 
307 /* *INDENT-OFF* */
309  .function = vnet_policer_by_sw_if_index,
310  .name = "policer-by-sw-if-index",
311  .vector_size = sizeof (u32),
312  .format_trace = format_policer_trace,
313  .type = VLIB_NODE_TYPE_INTERNAL,
314 
316  .error_strings = vnet_policer_error_strings,
317 
318  .n_next_nodes = VNET_POLICER_N_NEXT,
319 
320  /* edit / add dispositions here */
321  .next_nodes = {
322  [VNET_POLICER_NEXT_TRANSMIT] = "ethernet-input",
323  [VNET_POLICER_NEXT_DROP] = "error-drop",
324  },
325 };
326 
329 /* *INDENT-ON* */
330 
331 
332 int
333 test_policer_add_del (u32 rx_sw_if_index, u8 * config_name, int is_add)
334 {
338  vnet_hw_interface_t *rxhi;
339  uword *p;
340 
341  rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
342 
343  /* Make sure caller didn't pass a vlan subif, etc. */
344  if (rxhi->sw_if_index != rx_sw_if_index)
345  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
346 
347  if (is_add)
348  {
349 
350  p = hash_get_mem (pm->policer_config_by_name, config_name);
351 
352  if (p == 0)
353  return -2;
354 
355  template = pool_elt_at_index (pm->policer_templates, p[0]);
356 
359 
361 
362  policer[0] = template[0];
363 
364  vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
365  pm->policer_index_by_sw_if_index[rx_sw_if_index]
366  = policer - pm->policers;
367  }
368  else
369  {
370  u32 pi;
372  rxhi->hw_if_index,
373  ~0 /* disable */ );
374 
375  pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
376  pm->policer_index_by_sw_if_index[rx_sw_if_index] = ~0;
377  pool_put_index (pm->policers, pi);
378  }
379 
380  return 0;
381 }
382 
383 static clib_error_t *
385  unformat_input_t * input, vlib_cli_command_t * cmd)
386 {
388  unformat_input_t _line_input, *line_input = &_line_input;
389  u32 rx_sw_if_index;
390  int rv;
391  u8 *config_name = 0;
392  int rx_set = 0;
393  int is_add = 1;
394  int is_show = 0;
395  clib_error_t *error = NULL;
396 
397  /* Get a line of input. */
398  if (!unformat_user (input, unformat_line_input, line_input))
399  return 0;
400 
401  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
402  {
403  if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
404  pm->vnet_main, &rx_sw_if_index))
405  rx_set = 1;
406  else if (unformat (line_input, "show"))
407  is_show = 1;
408  else if (unformat (line_input, "policer %s", &config_name))
409  ;
410  else if (unformat (line_input, "del"))
411  is_add = 0;
412  else
413  break;
414  }
415 
416  if (rx_set == 0)
417  {
418  error = clib_error_return (0, "interface not set");
419  goto done;
420  }
421 
422  if (is_show)
423  {
424  u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
426  policer = pool_elt_at_index (pm->policers, pi);
427 
428  vlib_cli_output (vm, "%U", format_policer_instance, policer);
429  goto done;
430  }
431 
432  if (is_add && config_name == 0)
433  {
434  error = clib_error_return (0, "policer config name required");
435  goto done;
436  }
437 
438  rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
439 
440  switch (rv)
441  {
442  case 0:
443  break;
444 
445  default:
446  error = clib_error_return
447  (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
448  goto done;
449  }
450 
451 done:
452  unformat_free (line_input);
453 
454  return error;
455 }
456 
457 /* *INDENT-OFF* */
458 VLIB_CLI_COMMAND (test_patch_command, static) = {
459  .path = "test policer",
460  .short_help =
461  "intfc <intfc> policer <policer-config-name> [del]",
462  .function = test_policer_command_fn,
463 };
464 /* *INDENT-ON* */
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
514  vlib_node_runtime_t * node,
515  vlib_frame_t * frame,
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 
784 static uword
786  vlib_node_runtime_t * node, vlib_frame_t * frame)
787 {
788  return policer_classify_inline (vm, node, frame,
790 }
791 
792 /* *INDENT-OFF* */
794  .function = ip4_policer_classify,
795  .name = "ip4-policer-classify",
796  .vector_size = sizeof (u32),
797  .format_trace = format_policer_classify_trace,
799  .error_strings = policer_classify_error_strings,
800  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
801  .next_nodes = {
802  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
803  },
804 };
805 
807 /* *INDENT-ON* */
808 
809 static uword
811  vlib_node_runtime_t * node, vlib_frame_t * frame)
812 {
813  return policer_classify_inline (vm, node, frame,
815 }
816 
817 /* *INDENT-OFF* */
819  .function = ip6_policer_classify,
820  .name = "ip6-policer-classify",
821  .vector_size = sizeof (u32),
822  .format_trace = format_policer_classify_trace,
824  .error_strings = policer_classify_error_strings,
825  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
826  .next_nodes = {
827  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
828  },
829 };
830 
832 /* *INDENT-ON* */
833 
834 static uword
836  vlib_node_runtime_t * node, vlib_frame_t * frame)
837 {
838  return policer_classify_inline (vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
839 }
840 
841 /* *INDENT-OFF* */
843  .function = l2_policer_classify,
844  .name = "l2-policer-classify",
845  .vector_size = sizeof (u32),
846  .format_trace = format_policer_classify_trace,
848  .error_strings = policer_classify_error_strings,
849  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
850  .next_nodes = {
851  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
852  },
853 };
854 
856 /* *INDENT-ON* */
857 
858 static clib_error_t *
860 {
862 
863  pcm->vlib_main = vm;
864  pcm->vnet_main = vnet_get_main ();
866 
867  /* Initialize L2 feature next-node indexes */
872  pcm->feat_next_node_index);
873 
874  return 0;
875 }
876 
878 
879 /*
880  * fd.io coding-style-patch-verification: ON
881  *
882  * Local Variables:
883  * eval: (c-set-style "gnu")
884  * End:
885  */
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:439
policer_classify_main_t policer_classify_main
#define foreach_vnet_policer_error
Definition: node_funcs.c:51
#define CLIB_UNUSED(x)
Definition: clib.h:82
#define POLICER_TICKS_PER_PERIOD_SHIFT
Definition: police.h:57
VLIB_NODE_FUNCTION_MULTIARCH(policer_by_sw_if_index_node, vnet_policer_by_sw_if_index)
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:136
vnet_policer_error_t
Definition: node_funcs.c:55
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
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:818
uword * policer_config_by_name
Definition: policer.h:34
#define PREDICT_TRUE(x)
Definition: clib.h:112
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:1176
#define NULL
Definition: clib.h:58
vnet_policer_next_t
Definition: policer.h:56
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:232
static uword l2_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:835
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:333
static u64 clib_cpu_time_now(void)
Definition: time.h:75
policer_classify_error_t
Definition: node_funcs.c:498
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
vnet_main_t * vnet_main
Definition: policer.h:44
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:493
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
static vlib_node_registration_t policer_by_sw_if_index_node
(constructor) VLIB_REGISTER_NODE (policer_by_sw_if_index_node)
Definition: node_funcs.c:308
uword vnet_policer_by_opaque(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:284
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
static char * vnet_policer_error_strings[]
Definition: node_funcs.c:63
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
#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:859
static void vnet_classify_prefetch_entry(vnet_classify_table_t *t, u64 hash)
unformat_function_t unformat_line_input
Definition: format.h:282
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
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:122
#define PREDICT_FALSE(x)
Definition: clib.h:111
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:518
#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:218
#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:338
void vnet_policer_node_funcs_reference(void)
Definition: node_funcs.c:298
uword vnet_policer_by_sw_if_index(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:276
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
uword vnet_policer_by_either(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:291
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:1150
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:230
static uword vnet_classify_get_offset(vnet_classify_table_t *t, vnet_classify_entry_t *v)
static uword ip4_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:785
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:420
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:301
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
#define ARRAY_LEN(x)
Definition: clib.h:62
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:452
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:60
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:67
#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:537
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:311
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:22
policer_classify_next_index_t
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
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
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:384
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define hash_get_mem(h, key)
Definition: hash.h:269
static uword ip6_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:810
policer_read_response_type_st * policer_templates
Definition: policer.h:31
#define vnet_buffer(b)
Definition: buffer.h:368
u8 data[0]
Packet data.
Definition: buffer.h:176
vlib_node_registration_t l2_policer_classify_node
(constructor) VLIB_REGISTER_NODE (l2_policer_classify_node)
Definition: node_funcs.c:842
u16 flags
Copy of main node flags.
Definition: node.h:531
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
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:117
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
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:972
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:170