FD.io VPP  v18.07-rc0-415-g6c78436
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 
26 
27 /* Dispatch functions meant to be instantiated elsewhere */
28 
29 typedef struct
30 {
35 
36 /* packet trace format function */
37 static u8 *
38 format_policer_trace (u8 * s, va_list * args)
39 {
40  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
41  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
42  vnet_policer_trace_t *t = va_arg (*args, vnet_policer_trace_t *);
43 
44  s = format (s, "VNET_POLICER: sw_if_index %d policer_index %d next %d",
46  return s;
47 }
48 
49 #define foreach_vnet_policer_error \
50 _(TRANSMIT, "Packets Transmitted") \
51 _(DROP, "Packets Dropped")
52 
53 typedef enum
54 {
55 #define _(sym,str) VNET_POLICER_ERROR_##sym,
57 #undef _
60 
61 static char *vnet_policer_error_strings[] = {
62 #define _(sym,string) string,
64 #undef _
65 };
66 
67 static inline uword
69  vlib_node_runtime_t * node,
70  vlib_frame_t * frame, vnet_policer_index_t which)
71 {
72  u32 n_left_from, *from, *to_next;
73  vnet_policer_next_t next_index;
75  u64 time_in_policer_periods;
76  u32 transmitted = 0;
77 
78  time_in_policer_periods =
80 
81  from = vlib_frame_vector_args (frame);
82  n_left_from = frame->n_vectors;
83  next_index = node->cached_next_index;
84 
85  while (n_left_from > 0)
86  {
87  u32 n_left_to_next;
88 
89  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
90 
91  while (n_left_from >= 4 && n_left_to_next >= 2)
92  {
93  u32 bi0, bi1;
94  vlib_buffer_t *b0, *b1;
95  u32 next0, next1;
96  u32 sw_if_index0, sw_if_index1;
97  u32 pi0 = 0, pi1 = 0;
98  u8 act0, act1;
99 
100  /* Prefetch next iteration. */
101  {
102  vlib_buffer_t *b2, *b3;
103 
104  b2 = vlib_get_buffer (vm, from[2]);
105  b3 = vlib_get_buffer (vm, from[3]);
106 
107  vlib_prefetch_buffer_header (b2, LOAD);
108  vlib_prefetch_buffer_header (b3, LOAD);
109  }
110 
111  /* speculatively enqueue b0 and b1 to the current next frame */
112  to_next[0] = bi0 = from[0];
113  to_next[1] = bi1 = from[1];
114  from += 2;
115  to_next += 2;
116  n_left_from -= 2;
117  n_left_to_next -= 2;
118 
119  b0 = vlib_get_buffer (vm, bi0);
120  b1 = vlib_get_buffer (vm, bi1);
121 
122  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
124 
125  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
127 
128 
130  {
131  pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
132  pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
133  }
134 
135  if (which == VNET_POLICER_INDEX_BY_OPAQUE)
136  {
137  pi0 = vnet_buffer (b0)->policer.index;
138  pi1 = vnet_buffer (b1)->policer.index;
139  }
140 
141  if (which == VNET_POLICER_INDEX_BY_EITHER)
142  {
143  pi0 = vnet_buffer (b0)->policer.index;
144  pi0 = (pi0 != ~0) ? pi0 :
145  pm->policer_index_by_sw_if_index[sw_if_index0];
146  pi1 = vnet_buffer (b1)->policer.index;
147  pi1 = (pi1 != ~0) ? pi1 :
148  pm->policer_index_by_sw_if_index[sw_if_index1];
149  }
150 
151  act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
152  POLICE_CONFORM /* no chaining */ );
153 
154  act1 = vnet_policer_police (vm, b1, pi1, time_in_policer_periods,
155  POLICE_CONFORM /* no chaining */ );
156 
157  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
158  {
159  next0 = VNET_POLICER_NEXT_DROP;
160  b0->error = node->errors[VNET_POLICER_ERROR_DROP];
161  }
162  else /* transmit or mark-and-transmit action */
163  {
164  transmitted++;
165  }
166 
167  if (PREDICT_FALSE (act1 == SSE2_QOS_ACTION_DROP)) /* drop action */
168  {
169  next1 = VNET_POLICER_NEXT_DROP;
170  b1->error = node->errors[VNET_POLICER_ERROR_DROP];
171  }
172  else /* transmit or mark-and-transmit action */
173  {
174  transmitted++;
175  }
176 
177 
178  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
179  {
180  if (b0->flags & VLIB_BUFFER_IS_TRACED)
181  {
183  vlib_add_trace (vm, node, b0, sizeof (*t));
184  t->sw_if_index = sw_if_index0;
185  t->next_index = next0;
186  }
187  if (b1->flags & VLIB_BUFFER_IS_TRACED)
188  {
190  vlib_add_trace (vm, node, b1, sizeof (*t));
191  t->sw_if_index = sw_if_index1;
192  t->next_index = next1;
193  }
194  }
195 
196  /* verify speculative enqueues, maybe switch current next frame */
197  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
198  to_next, n_left_to_next,
199  bi0, bi1, next0, next1);
200  }
201 
202  while (n_left_from > 0 && n_left_to_next > 0)
203  {
204  u32 bi0;
205  vlib_buffer_t *b0;
206  u32 next0;
207  u32 sw_if_index0;
208  u32 pi0 = 0;
209  u8 act0;
210 
211  bi0 = from[0];
212  to_next[0] = bi0;
213  from += 1;
214  to_next += 1;
215  n_left_from -= 1;
216  n_left_to_next -= 1;
217 
218  b0 = vlib_get_buffer (vm, bi0);
219 
220  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
222 
224  pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
225 
226  if (which == VNET_POLICER_INDEX_BY_OPAQUE)
227  pi0 = vnet_buffer (b0)->policer.index;
228 
229  if (which == VNET_POLICER_INDEX_BY_EITHER)
230  {
231  pi0 = vnet_buffer (b0)->policer.index;
232  pi0 = (pi0 != ~0) ? pi0 :
233  pm->policer_index_by_sw_if_index[sw_if_index0];
234  }
235 
236  act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
237  POLICE_CONFORM /* no chaining */ );
238 
239  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
240  {
241  next0 = VNET_POLICER_NEXT_DROP;
242  b0->error = node->errors[VNET_POLICER_ERROR_DROP];
243  }
244  else /* transmit or mark-and-transmit action */
245  {
246  transmitted++;
247  }
248 
250  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
251  {
253  vlib_add_trace (vm, node, b0, sizeof (*t));
254  t->sw_if_index = sw_if_index0;
255  t->next_index = next0;
256  t->policer_index = pi0;
257  }
258 
259  /* verify speculative enqueue, maybe switch current next frame */
260  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
261  to_next, n_left_to_next,
262  bi0, next0);
263  }
264 
265  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
266  }
267 
269  VNET_POLICER_ERROR_TRANSMIT, transmitted);
270  return frame->n_vectors;
271 }
272 
273 uword
275  vlib_node_runtime_t * node, vlib_frame_t * frame)
276 {
277  return vnet_policer_inline (vm, node, frame,
279 }
280 
281 uword
283  vlib_node_runtime_t * node, vlib_frame_t * frame)
284 {
285  return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_OPAQUE);
286 }
287 
288 uword
290  vlib_node_runtime_t * node, vlib_frame_t * frame)
291 {
292  return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_EITHER);
293 }
294 
295 void
297 {
298 }
299 
300 
301 #define TEST_CODE 1
302 
303 #ifdef TEST_CODE
304 
305 /* *INDENT-OFF* */
307  .function = vnet_policer_by_sw_if_index,
308  .name = "policer-by-sw-if-index",
309  .vector_size = sizeof (u32),
310  .format_trace = format_policer_trace,
311  .type = VLIB_NODE_TYPE_INTERNAL,
312 
314  .error_strings = vnet_policer_error_strings,
315 
316  .n_next_nodes = VNET_POLICER_N_NEXT,
317 
318  /* edit / add dispositions here */
319  .next_nodes = {
320  [VNET_POLICER_NEXT_TRANSMIT] = "ethernet-input",
321  [VNET_POLICER_NEXT_DROP] = "error-drop",
322  },
323 };
324 
327 /* *INDENT-ON* */
328 
329 
330 int
331 test_policer_add_del (u32 rx_sw_if_index, u8 * config_name, int is_add)
332 {
336  vnet_hw_interface_t *rxhi;
337  uword *p;
338 
339  rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
340 
341  /* Make sure caller didn't pass a vlan subif, etc. */
342  if (rxhi->sw_if_index != rx_sw_if_index)
343  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
344 
345  if (is_add)
346  {
347 
348  p = hash_get_mem (pm->policer_config_by_name, config_name);
349 
350  if (p == 0)
351  return -2;
352 
353  template = pool_elt_at_index (pm->policer_templates, p[0]);
354 
357 
359 
360  policer[0] = template[0];
361 
362  vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
363  pm->policer_index_by_sw_if_index[rx_sw_if_index]
364  = policer - pm->policers;
365  }
366  else
367  {
368  u32 pi;
370  rxhi->hw_if_index,
371  ~0 /* disable */ );
372 
373  pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
374  pm->policer_index_by_sw_if_index[rx_sw_if_index] = ~0;
375  pool_put_index (pm->policers, pi);
376  }
377 
378  return 0;
379 }
380 
381 static clib_error_t *
383  unformat_input_t * input, vlib_cli_command_t * cmd)
384 {
386  unformat_input_t _line_input, *line_input = &_line_input;
387  u32 rx_sw_if_index;
388  int rv;
389  u8 *config_name = 0;
390  int rx_set = 0;
391  int is_add = 1;
392  int is_show = 0;
393  clib_error_t *error = NULL;
394 
395  /* Get a line of input. */
396  if (!unformat_user (input, unformat_line_input, line_input))
397  return 0;
398 
399  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
400  {
401  if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
402  pm->vnet_main, &rx_sw_if_index))
403  rx_set = 1;
404  else if (unformat (line_input, "show"))
405  is_show = 1;
406  else if (unformat (line_input, "policer %s", &config_name))
407  ;
408  else if (unformat (line_input, "del"))
409  is_add = 0;
410  else
411  break;
412  }
413 
414  if (rx_set == 0)
415  {
416  error = clib_error_return (0, "interface not set");
417  goto done;
418  }
419 
420  if (is_show)
421  {
422  u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
424  policer = pool_elt_at_index (pm->policers, pi);
425 
426  vlib_cli_output (vm, "%U", format_policer_instance, policer);
427  goto done;
428  }
429 
430  if (is_add && config_name == 0)
431  {
432  error = clib_error_return (0, "policer config name required");
433  goto done;
434  }
435 
436  rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
437 
438  switch (rv)
439  {
440  case 0:
441  break;
442 
443  default:
444  error = clib_error_return
445  (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
446  goto done;
447  }
448 
449 done:
450  unformat_free (line_input);
451 
452  return error;
453 }
454 
455 /* *INDENT-OFF* */
456 VLIB_CLI_COMMAND (test_patch_command, static) = {
457  .path = "test policer",
458  .short_help =
459  "intfc <intfc> policer <policer-config-name> [del]",
460  .function = test_policer_command_fn,
461 };
462 /* *INDENT-ON* */
463 
464 #endif /* TEST_CODE */
465 
466 
467 typedef struct
468 {
475 
476 static u8 *
477 format_policer_classify_trace (u8 * s, va_list * args)
478 {
479  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
480  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
481  policer_classify_trace_t *t = va_arg (*args, policer_classify_trace_t *);
482 
483  s = format (s, "POLICER_CLASSIFY: sw_if_index %d next %d table %d offset %d"
484  " policer_index %d",
485  t->sw_if_index, t->next_index, t->table_index, t->offset,
486  t->policer_index);
487  return s;
488 }
489 
490 #define foreach_policer_classify_error \
491 _(MISS, "Policer classify misses") \
492 _(HIT, "Policer classify hits") \
493 _(CHAIN_HIT, "Polcier classify hits after chain walk") \
494 _(DROP, "Policer classify action drop")
495 
496 typedef enum
497 {
498 #define _(sym,str) POLICER_CLASSIFY_ERROR_##sym,
500 #undef _
503 
505 #define _(sym,string) string,
507 #undef _
508 };
509 
510 static inline uword
512  vlib_node_runtime_t * node,
513  vlib_frame_t * frame,
515 {
516  u32 n_left_from, *from, *to_next;
520  f64 now = vlib_time_now (vm);
521  u32 hits = 0;
522  u32 misses = 0;
523  u32 chain_hits = 0;
524  u32 drop = 0;
525  u32 n_next_nodes;
526  u64 time_in_policer_periods;
527 
528  time_in_policer_periods =
530 
531  n_next_nodes = node->n_next_nodes;
532 
533  from = vlib_frame_vector_args (frame);
534  n_left_from = frame->n_vectors;
535 
536  /* First pass: compute hashes */
537  while (n_left_from > 2)
538  {
539  vlib_buffer_t *b0, *b1;
540  u32 bi0, bi1;
541  u8 *h0, *h1;
542  u32 sw_if_index0, sw_if_index1;
543  u32 table_index0, table_index1;
544  vnet_classify_table_t *t0, *t1;
545 
546  /* Prefetch next iteration */
547  {
548  vlib_buffer_t *p1, *p2;
549 
550  p1 = vlib_get_buffer (vm, from[1]);
551  p2 = vlib_get_buffer (vm, from[2]);
552 
553  vlib_prefetch_buffer_header (p1, STORE);
555  vlib_prefetch_buffer_header (p2, STORE);
557  }
558 
559  bi0 = from[0];
560  b0 = vlib_get_buffer (vm, bi0);
561  h0 = b0->data;
562 
563  bi1 = from[1];
564  b1 = vlib_get_buffer (vm, bi1);
565  h1 = b1->data;
566 
567  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
568  table_index0 =
569  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
570 
571  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
572  table_index1 =
573  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
574 
575  t0 = pool_elt_at_index (vcm->tables, table_index0);
576 
577  t1 = pool_elt_at_index (vcm->tables, table_index1);
578 
579  vnet_buffer (b0)->l2_classify.hash =
580  vnet_classify_hash_packet (t0, (u8 *) h0);
581 
582  vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
583 
584  vnet_buffer (b1)->l2_classify.hash =
585  vnet_classify_hash_packet (t1, (u8 *) h1);
586 
587  vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash);
588 
589  vnet_buffer (b0)->l2_classify.table_index = table_index0;
590 
591  vnet_buffer (b1)->l2_classify.table_index = table_index1;
592 
593  from += 2;
594  n_left_from -= 2;
595  }
596 
597  while (n_left_from > 0)
598  {
599  vlib_buffer_t *b0;
600  u32 bi0;
601  u8 *h0;
602  u32 sw_if_index0;
603  u32 table_index0;
605 
606  bi0 = from[0];
607  b0 = vlib_get_buffer (vm, bi0);
608  h0 = b0->data;
609 
610  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
611  table_index0 =
612  pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
613 
614  t0 = pool_elt_at_index (vcm->tables, table_index0);
615  vnet_buffer (b0)->l2_classify.hash =
616  vnet_classify_hash_packet (t0, (u8 *) h0);
617 
618  vnet_buffer (b0)->l2_classify.table_index = table_index0;
619  vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
620 
621  from++;
622  n_left_from--;
623  }
624 
625  next_index = node->cached_next_index;
626  from = vlib_frame_vector_args (frame);
627  n_left_from = frame->n_vectors;
628 
629  while (n_left_from > 0)
630  {
631  u32 n_left_to_next;
632 
633  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
634 
635  /* Not enough load/store slots to dual loop... */
636  while (n_left_from > 0 && n_left_to_next > 0)
637  {
638  u32 bi0;
639  vlib_buffer_t *b0;
641  u32 table_index0;
643  vnet_classify_entry_t *e0;
644  u64 hash0;
645  u8 *h0;
646  u8 act0;
647 
648  /* Stride 3 seems to work best */
649  if (PREDICT_TRUE (n_left_from > 3))
650  {
651  vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
653  u32 table_index1;
654  u64 phash1;
655 
656  table_index1 = vnet_buffer (p1)->l2_classify.table_index;
657 
658  if (PREDICT_TRUE (table_index1 != ~0))
659  {
660  tp1 = pool_elt_at_index (vcm->tables, table_index1);
661  phash1 = vnet_buffer (p1)->l2_classify.hash;
662  vnet_classify_prefetch_entry (tp1, phash1);
663  }
664  }
665 
666  /* Speculatively enqueue b0 to the current next frame */
667  bi0 = from[0];
668  to_next[0] = bi0;
669  from += 1;
670  to_next += 1;
671  n_left_from -= 1;
672  n_left_to_next -= 1;
673 
674  b0 = vlib_get_buffer (vm, bi0);
675  h0 = b0->data;
676  table_index0 = vnet_buffer (b0)->l2_classify.table_index;
677  e0 = 0;
678  t0 = 0;
679 
680  if (tid == POLICER_CLASSIFY_TABLE_L2)
681  {
682  /* Feature bitmap update and determine the next node */
683  next0 = vnet_l2_feature_next (b0, pcm->feat_next_node_index,
684  L2INPUT_FEAT_POLICER_CLAS);
685  }
686  else
688  &b0->current_config_index, &next0,
689  /* # bytes of config data */ 0);
690 
691  vnet_buffer (b0)->l2_classify.opaque_index = ~0;
692 
693  if (PREDICT_TRUE (table_index0 != ~0))
694  {
695  hash0 = vnet_buffer (b0)->l2_classify.hash;
696  t0 = pool_elt_at_index (vcm->tables, table_index0);
697  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
698 
699  if (e0)
700  {
701  act0 = vnet_policer_police (vm,
702  b0,
703  e0->next_index,
704  time_in_policer_periods,
705  e0->opaque_index);
706  if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
707  {
709  b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
710  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  drop++;
747  }
748  hits++;
749  chain_hits++;
750  break;
751  }
752  }
753  }
754  }
756  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
757  {
759  vlib_add_trace (vm, node, b0, sizeof (*t));
760  t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
761  t->next_index = next0;
762  t->table_index = t0 ? t0 - vcm->tables : ~0;
763  t->offset = (e0 && t0) ? vnet_classify_get_offset (t0, e0) : ~0;
764  t->policer_index = e0 ? e0->next_index : ~0;
765  }
766 
767  /* Verify speculative enqueue, maybe switch current next frame */
768  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
769  n_left_to_next, bi0, next0);
770  }
771 
772  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
773  }
774 
776  POLICER_CLASSIFY_ERROR_MISS, misses);
778  POLICER_CLASSIFY_ERROR_HIT, hits);
780  POLICER_CLASSIFY_ERROR_CHAIN_HIT, chain_hits);
782  POLICER_CLASSIFY_ERROR_DROP, drop);
783 
784  return frame->n_vectors;
785 }
786 
787 static uword
789  vlib_node_runtime_t * node, vlib_frame_t * frame)
790 {
791  return policer_classify_inline (vm, node, frame,
793 }
794 
795 /* *INDENT-OFF* */
797  .function = ip4_policer_classify,
798  .name = "ip4-policer-classify",
799  .vector_size = sizeof (u32),
800  .format_trace = format_policer_classify_trace,
802  .error_strings = policer_classify_error_strings,
803  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
804  .next_nodes = {
805  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
806  },
807 };
808 
810 /* *INDENT-ON* */
811 
812 static uword
814  vlib_node_runtime_t * node, vlib_frame_t * frame)
815 {
816  return policer_classify_inline (vm, node, frame,
818 }
819 
820 /* *INDENT-OFF* */
822  .function = ip6_policer_classify,
823  .name = "ip6-policer-classify",
824  .vector_size = sizeof (u32),
825  .format_trace = format_policer_classify_trace,
827  .error_strings = policer_classify_error_strings,
828  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
829  .next_nodes = {
830  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
831  },
832 };
833 
835 /* *INDENT-ON* */
836 
837 static uword
839  vlib_node_runtime_t * node, vlib_frame_t * frame)
840 {
841  return policer_classify_inline (vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
842 }
843 
844 /* *INDENT-OFF* */
846  .function = l2_policer_classify,
847  .name = "l2-policer-classify",
848  .vector_size = sizeof (u32),
849  .format_trace = format_policer_classify_trace,
851  .error_strings = policer_classify_error_strings,
852  .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
853  .next_nodes = {
854  [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
855  },
856 };
857 
859 /* *INDENT-ON* */
860 
861 static clib_error_t *
863 {
865 
866  pcm->vlib_main = vm;
867  pcm->vnet_main = vnet_get_main ();
869 
870  /* Initialize L2 feature next-node indexes */
875  pcm->feat_next_node_index);
876 
877  return 0;
878 }
879 
881 
882 /*
883  * fd.io coding-style-patch-verification: ON
884  *
885  * Local Variables:
886  * eval: (c-set-style "gnu")
887  * End:
888  */
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:49
#define CLIB_UNUSED(x)
Definition: clib.h:79
#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:132
vnet_policer_error_t
Definition: node_funcs.c:53
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:821
uword * policer_config_by_name
Definition: policer.h:34
#define PREDICT_TRUE(x)
Definition: clib.h:106
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:1222
#define NULL
Definition: clib.h:55
vnet_policer_next_t
Definition: policer.h:56
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:225
static uword l2_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:838
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:68
int test_policer_add_del(u32 rx_sw_if_index, u8 *config_name, int is_add)
Definition: node_funcs.c:331
static u64 clib_cpu_time_now(void)
Definition: time.h:73
policer_classify_error_t
Definition: node_funcs.c:496
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:451
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:306
uword vnet_policer_by_opaque(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:282
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
static char * vnet_policer_error_strings[]
Definition: node_funcs.c:61
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:184
#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:862
static void vnet_classify_prefetch_entry(vnet_classify_table_t *t, u64 hash)
unformat_function_t unformat_line_input
Definition: format.h:281
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
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:105
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:511
u32 node_index
Node index.
Definition: node.h:473
#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:296
uword vnet_policer_by_sw_if_index(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:274
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:135
uword vnet_policer_by_either(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:289
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:1168
static char * policer_classify_error_strings[]
Definition: node_funcs.c:504
#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:788
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u16 n_vectors
Definition: node.h:380
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:77
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:59
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:454
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:154
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:70
#define foreach_policer_classify_error
Definition: node_funcs.c:490
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:492
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:296
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:55
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:796
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:382
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
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:813
policer_read_response_type_st * policer_templates
Definition: policer.h:31
#define vnet_buffer(b)
Definition: buffer.h:360
u8 data[0]
Packet data.
Definition: buffer.h:172
vlib_node_registration_t l2_policer_classify_node
(constructor) VLIB_REGISTER_NODE (l2_policer_classify_node)
Definition: node_funcs.c:845
u16 flags
Copy of main node flags.
Definition: node.h:486
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:295
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
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:111
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
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:38
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:477
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169