FD.io VPP  v18.10-32-g1161dda
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 drop = 0;
527  u32 n_next_nodes;
528  u64 time_in_policer_periods;
529 
530  time_in_policer_periods =
532 
533  n_next_nodes = node->n_next_nodes;
534 
535  from = vlib_frame_vector_args (frame);
536  n_left_from = frame->n_vectors;
537 
538  /* First pass: compute hashes */
539  while (n_left_from > 2)
540  {
541  vlib_buffer_t *b0, *b1;
542  u32 bi0, bi1;
543  u8 *h0, *h1;
544  u32 sw_if_index0, sw_if_index1;
545  u32 table_index0, table_index1;
546  vnet_classify_table_t *t0, *t1;
547 
548  /* Prefetch next iteration */
549  {
550  vlib_buffer_t *p1, *p2;
551 
552  p1 = vlib_get_buffer (vm, from[1]);
553  p2 = vlib_get_buffer (vm, from[2]);
554 
555  vlib_prefetch_buffer_header (p1, STORE);
557  vlib_prefetch_buffer_header (p2, STORE);
559  }
560 
561  bi0 = from[0];
562  b0 = vlib_get_buffer (vm, bi0);
563  h0 = b0->data;
564 
565  bi1 = from[1];
566  b1 = vlib_get_buffer (vm, bi1);
567  h1 = b1->data;
568 
569  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
570  table_index0 =
571  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
572 
573  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
574  table_index1 =
575  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
576 
577  t0 = pool_elt_at_index (vcm->tables, table_index0);
578 
579  t1 = pool_elt_at_index (vcm->tables, table_index1);
580 
581  vnet_buffer (b0)->l2_classify.hash =
582  vnet_classify_hash_packet (t0, (u8 *) h0);
583 
584  vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
585 
586  vnet_buffer (b1)->l2_classify.hash =
587  vnet_classify_hash_packet (t1, (u8 *) h1);
588 
589  vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash);
590 
591  vnet_buffer (b0)->l2_classify.table_index = table_index0;
592 
593  vnet_buffer (b1)->l2_classify.table_index = table_index1;
594 
595  from += 2;
596  n_left_from -= 2;
597  }
598 
599  while (n_left_from > 0)
600  {
601  vlib_buffer_t *b0;
602  u32 bi0;
603  u8 *h0;
604  u32 sw_if_index0;
605  u32 table_index0;
607 
608  bi0 = from[0];
609  b0 = vlib_get_buffer (vm, bi0);
610  h0 = b0->data;
611 
612  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
613  table_index0 =
614  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
615 
616  t0 = pool_elt_at_index (vcm->tables, table_index0);
617  vnet_buffer (b0)->l2_classify.hash =
618  vnet_classify_hash_packet (t0, (u8 *) h0);
619 
620  vnet_buffer (b0)->l2_classify.table_index = table_index0;
621  vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
622 
623  from++;
624  n_left_from--;
625  }
626 
627  next_index = node->cached_next_index;
628  from = vlib_frame_vector_args (frame);
629  n_left_from = frame->n_vectors;
630 
631  while (n_left_from > 0)
632  {
633  u32 n_left_to_next;
634 
635  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
636 
637  /* Not enough load/store slots to dual loop... */
638  while (n_left_from > 0 && n_left_to_next > 0)
639  {
640  u32 bi0;
641  vlib_buffer_t *b0;
643  u32 table_index0;
645  vnet_classify_entry_t *e0;
646  u64 hash0;
647  u8 *h0;
648  u8 act0;
649 
650  /* Stride 3 seems to work best */
651  if (PREDICT_TRUE (n_left_from > 3))
652  {
653  vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
655  u32 table_index1;
656  u64 phash1;
657 
658  table_index1 = vnet_buffer (p1)->l2_classify.table_index;
659 
660  if (PREDICT_TRUE (table_index1 != ~0))
661  {
662  tp1 = pool_elt_at_index (vcm->tables, table_index1);
663  phash1 = vnet_buffer (p1)->l2_classify.hash;
664  vnet_classify_prefetch_entry (tp1, phash1);
665  }
666  }
667 
668  /* Speculatively enqueue b0 to the current next frame */
669  bi0 = from[0];
670  to_next[0] = bi0;
671  from += 1;
672  to_next += 1;
673  n_left_from -= 1;
674  n_left_to_next -= 1;
675 
676  b0 = vlib_get_buffer (vm, bi0);
677  h0 = b0->data;
678  table_index0 = vnet_buffer (b0)->l2_classify.table_index;
679  e0 = 0;
680  t0 = 0;
681 
682  if (tid == POLICER_CLASSIFY_TABLE_L2)
683  {
684  /* Feature bitmap update and determine the next node */
685  next0 = vnet_l2_feature_next (b0, pcm->feat_next_node_index,
686  L2INPUT_FEAT_POLICER_CLAS);
687  }
688  else
690  &b0->current_config_index, &next0,
691  /* # bytes of config data */ 0);
692 
693  vnet_buffer (b0)->l2_classify.opaque_index = ~0;
694 
695  if (PREDICT_TRUE (table_index0 != ~0))
696  {
697  hash0 = vnet_buffer (b0)->l2_classify.hash;
698  t0 = pool_elt_at_index (vcm->tables, table_index0);
699  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
700 
701  if (e0)
702  {
703  act0 = vnet_policer_police (vm,
704  b0,
705  e0->next_index,
706  time_in_policer_periods,
707  e0->opaque_index);
708  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
709  {
711  b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
712  drop++;
713  }
714  hits++;
715  }
716  else
717  {
718  while (1)
719  {
720  if (PREDICT_TRUE (t0->next_table_index != ~0))
721  {
722  t0 = pool_elt_at_index (vcm->tables,
723  t0->next_table_index);
724  }
725  else
726  {
727  next0 = (t0->miss_next_index < n_next_nodes) ?
728  t0->miss_next_index : next0;
729  misses++;
730  break;
731  }
732 
733  hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
734  e0 =
735  vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
736  if (e0)
737  {
738  act0 = vnet_policer_police (vm,
739  b0,
740  e0->next_index,
741  time_in_policer_periods,
742  e0->opaque_index);
743  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
744  {
746  b0->error =
747  node->errors[POLICER_CLASSIFY_ERROR_DROP];
748  drop++;
749  }
750  hits++;
751  chain_hits++;
752  break;
753  }
754  }
755  }
756  }
758  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
759  {
761  vlib_add_trace (vm, node, b0, sizeof (*t));
762  t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
763  t->next_index = next0;
764  t->table_index = t0 ? t0 - vcm->tables : ~0;
765  t->offset = (e0 && t0) ? vnet_classify_get_offset (t0, e0) : ~0;
766  t->policer_index = e0 ? e0->next_index : ~0;
767  }
768 
769  /* Verify speculative enqueue, maybe switch current next frame */
770  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
771  n_left_to_next, bi0, next0);
772  }
773 
774  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
775  }
776 
778  POLICER_CLASSIFY_ERROR_MISS, misses);
780  POLICER_CLASSIFY_ERROR_HIT, hits);
782  POLICER_CLASSIFY_ERROR_CHAIN_HIT, chain_hits);
784  POLICER_CLASSIFY_ERROR_DROP, drop);
785 
786  return frame->n_vectors;
787 }
788 
789 static uword
791  vlib_node_runtime_t * node, vlib_frame_t * frame)
792 {
793  return policer_classify_inline (vm, node, frame,
795 }
796 
797 /* *INDENT-OFF* */
799  .function = ip4_policer_classify,
800  .name = "ip4-policer-classify",
801  .vector_size = sizeof (u32),
802  .format_trace = format_policer_classify_trace,
804  .error_strings = policer_classify_error_strings,
805  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
806  .next_nodes = {
807  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
808  },
809 };
810 
812 /* *INDENT-ON* */
813 
814 static uword
816  vlib_node_runtime_t * node, vlib_frame_t * frame)
817 {
818  return policer_classify_inline (vm, node, frame,
820 }
821 
822 /* *INDENT-OFF* */
824  .function = ip6_policer_classify,
825  .name = "ip6-policer-classify",
826  .vector_size = sizeof (u32),
827  .format_trace = format_policer_classify_trace,
829  .error_strings = policer_classify_error_strings,
830  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
831  .next_nodes = {
832  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
833  },
834 };
835 
837 /* *INDENT-ON* */
838 
839 static uword
841  vlib_node_runtime_t * node, vlib_frame_t * frame)
842 {
843  return policer_classify_inline (vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
844 }
845 
846 /* *INDENT-OFF* */
848  .function = l2_policer_classify,
849  .name = "l2-policer-classify",
850  .vector_size = sizeof (u32),
851  .format_trace = format_policer_classify_trace,
853  .error_strings = policer_classify_error_strings,
854  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
855  .next_nodes = {
856  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
857  },
858 };
859 
861 /* *INDENT-ON* */
862 
863 static clib_error_t *
865 {
867 
868  pcm->vlib_main = vm;
869  pcm->vnet_main = vnet_get_main ();
871 
872  /* Initialize L2 feature next-node indexes */
877  pcm->feat_next_node_index);
878 
879  return 0;
880 }
881 
883 
884 /*
885  * fd.io coding-style-patch-verification: ON
886  *
887  * Local Variables:
888  * eval: (c-set-style "gnu")
889  * End:
890  */
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:437
policer_classify_main_t policer_classify_main
#define foreach_vnet_policer_error
Definition: node_funcs.c:51
#define CLIB_UNUSED(x)
Definition: clib.h:81
#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:135
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:823
uword * policer_config_by_name
Definition: policer.h:34
#define PREDICT_TRUE(x)
Definition: clib.h:108
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:1138
#define NULL
Definition: clib.h:57
vnet_policer_next_t
Definition: policer.h:56
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
static uword l2_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:840
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:73
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:472
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:187
#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:864
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:464
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:107
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:494
#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:364
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:138
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:1176
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 (general version).
Definition: pool.h:188
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:790
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:401
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:294
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:61
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:455
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:513
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:299
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:798
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:267
#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:815
policer_read_response_type_st * policer_templates
Definition: policer.h:31
#define vnet_buffer(b)
Definition: buffer.h:344
u8 data[0]
Packet data.
Definition: buffer.h:175
vlib_node_registration_t l2_policer_classify_node
(constructor) VLIB_REGISTER_NODE (l2_policer_classify_node)
Definition: node_funcs.c:847
u16 flags
Copy of main node flags.
Definition: node.h:507
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:310
#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:116
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
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