FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
l2_output.c
Go to the documentation of this file.
1 /*
2  * l2_output.c : layer 2 output packet processing
3  *
4  * Copyright (c) 2013 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 #include <vnet/pg/pg.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vlib/cli.h>
23 
24 #include <vppinfra/error.h>
25 #include <vppinfra/hash.h>
26 #include <vnet/l2/feat_bitmap.h>
27 #include <vnet/l2/l2_output.h>
28 
29 
30 #ifndef CLIB_MARCH_VARIANT
31 /* Feature graph node names */
32 static char *l2output_feat_names[] = {
33 #define _(sym,name) name,
35 #undef _
36 };
37 
38 char **
40 {
41  return l2output_feat_names;
42 }
43 
44 u8 *
45 format_l2_output_features (u8 * s, va_list * args)
46 {
47  static char *display_names[] = {
48 #define _(sym,name) #sym,
50 #undef _
51  };
52  u32 feature_bitmap = va_arg (*args, u32);
53 
54  if (feature_bitmap == 0)
55  {
56  s = format (s, " none configured");
57  return s;
58  }
59 
60  int i;
61  for (i = L2OUTPUT_N_FEAT - 1; i >= 0; i--)
62  if (feature_bitmap & (1 << i))
63  s = format (s, "%10s (%s)\n", display_names[i], l2output_feat_names[i]);
64  return s;
65 }
66 
68 #endif
69 
70 typedef struct
71 {
72  /* per-pkt trace data */
73  u8 src[6];
74  u8 dst[6];
76  u8 raw[12]; /* raw data */
78 
79 #ifndef CLIB_MARCH_VARIANT
80 /* packet trace format function */
81 static u8 *
82 format_l2output_trace (u8 * s, va_list * args)
83 {
84  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
85  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
86  l2output_trace_t *t = va_arg (*args, l2output_trace_t *);
87 
88  s = format (s, "l2-output: sw_if_index %d dst %U src %U data "
89  "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
90  t->sw_if_index,
93  t->raw[0], t->raw[1], t->raw[2], t->raw[3], t->raw[4],
94  t->raw[5], t->raw[6], t->raw[7], t->raw[8], t->raw[9],
95  t->raw[10], t->raw[11]);
96 
97  return s;
98 }
99 
100 
101 static char *l2output_error_strings[] = {
102 #define _(sym,string) string,
104 #undef _
105 };
106 #endif
107 
108 /**
109  * Check for split horizon violations.
110  * Return 0 if split horizon check passes, otherwise return non-zero.
111  * Packets should not be transmitted out an interface with the same
112  * split-horizon group as the input interface, except if the @c shg is 0
113  * in which case the check always passes.
114  */
117  vlib_buffer_t * b, u16 * next)
118 {
119  if (shg != vnet_buffer (b)->l2.shg)
120  return;
121  next[0] = L2OUTPUT_NEXT_DROP;
122  b->error = node->errors[L2OUTPUT_ERROR_SHG_DROP];
123 }
124 
127  l2_output_config_t * config,
128  vlib_buffer_t ** b, i16 * cdo, u16 * next,
129  u32 n_left, int l2_efp, int l2_vtr, int l2_pbb,
130  int shg_set, int update_feature_bitmap)
131 {
132  while (n_left >= 8)
133  {
134  vlib_prefetch_buffer_header (b[4], LOAD);
135  vlib_prefetch_buffer_header (b[5], LOAD);
136  vlib_prefetch_buffer_header (b[6], LOAD);
137  vlib_prefetch_buffer_header (b[7], LOAD);
138 
139  /* prefetch eth headers only if we need to touch them */
140  if (l2_vtr || l2_pbb || shg_set)
141  {
142  CLIB_PREFETCH (b[4]->data + cdo[4], CLIB_CACHE_LINE_BYTES, LOAD);
143  CLIB_PREFETCH (b[5]->data + cdo[5], CLIB_CACHE_LINE_BYTES, LOAD);
144  CLIB_PREFETCH (b[6]->data + cdo[6], CLIB_CACHE_LINE_BYTES, LOAD);
145  CLIB_PREFETCH (b[7]->data + cdo[7], CLIB_CACHE_LINE_BYTES, LOAD);
146  }
147 
148  if (update_feature_bitmap)
149  {
150  vnet_buffer (b[0])->l2.feature_bitmap = config->feature_bitmap;
151  vnet_buffer (b[1])->l2.feature_bitmap = config->feature_bitmap;
152  vnet_buffer (b[2])->l2.feature_bitmap = config->feature_bitmap;
153  vnet_buffer (b[3])->l2.feature_bitmap = config->feature_bitmap;
154  }
155 
156  if (l2_vtr)
157  {
158  int i;
159  for (i = 0; i < 4; i++)
160  {
161  u32 failed1 = l2_efp &&
162  l2_efp_filter_process (b[i], &(config->input_vtr));
163  u32 failed2 = l2_vtr_process (b[i], &(config->output_vtr));
164  if (PREDICT_FALSE (failed1 | failed2))
165  {
166  next[i] = L2OUTPUT_NEXT_DROP;
167  if (failed2)
168  b[i]->error = node->errors[L2OUTPUT_ERROR_VTR_DROP];
169  if (failed1)
170  b[i]->error = node->errors[L2OUTPUT_ERROR_EFP_DROP];
171  }
172  }
173  }
174 
175  if (l2_pbb)
176  {
177  int i;
178  for (i = 0; i < 4; i++)
179  if (l2_pbb_process (b[i], &(config->output_pbb_vtr)))
180  {
181  next[i] = L2OUTPUT_NEXT_DROP;
182  b[i]->error = node->errors[L2OUTPUT_ERROR_VTR_DROP];
183  }
184  }
185 
186  if (shg_set)
187  {
188  split_horizon_violation (node, config->shg, b[0], next);
189  split_horizon_violation (node, config->shg, b[1], next + 1);
190  split_horizon_violation (node, config->shg, b[2], next + 2);
191  split_horizon_violation (node, config->shg, b[3], next + 3);
192  }
193  /* next */
194  n_left -= 4;
195  b += 4;
196  next += 4;
197  cdo += 4;
198  }
199 
200  while (n_left)
201  {
202  if (update_feature_bitmap)
203  vnet_buffer (b[0])->l2.feature_bitmap = config->feature_bitmap;
204 
205  if (l2_vtr)
206  {
207  u32 failed1 = l2_efp &&
208  l2_efp_filter_process (b[0], &(config->input_vtr));
209  u32 failed2 = l2_vtr_process (b[0], &(config->output_vtr));
210  if (PREDICT_FALSE (failed1 | failed2))
211  {
212  *next = L2OUTPUT_NEXT_DROP;
213  if (failed2)
214  b[0]->error = node->errors[L2OUTPUT_ERROR_VTR_DROP];
215  if (failed1)
216  b[0]->error = node->errors[L2OUTPUT_ERROR_EFP_DROP];
217  }
218  }
219 
220  if (l2_pbb && l2_pbb_process (b[0], &(config->output_pbb_vtr)))
221  {
222  next[0] = L2OUTPUT_NEXT_DROP;
223  b[0]->error = node->errors[L2OUTPUT_ERROR_VTR_DROP];
224  }
225 
226  if (shg_set)
227  split_horizon_violation (node, config->shg, b[0], next);
228 
229  /* next */
230  n_left -= 1;
231  b += 1;
232  next += 1;
233  }
234 }
235 
238 {
239  while (n_left >= 8)
240  {
241  vlib_prefetch_buffer_header (b[4], LOAD);
242  vlib_prefetch_buffer_header (b[5], LOAD);
243  vlib_prefetch_buffer_header (b[6], LOAD);
244  vlib_prefetch_buffer_header (b[7], LOAD);
245  b[0]->error = b[1]->error = b[2]->error = b[3]->error = error;
246  b += 4;
247  n_left -= 4;
248  }
249  while (n_left)
250  {
251  b[0]->error = error;
252  b += 1;
253  n_left -= 1;
254  }
255 }
256 
259  l2_output_config_t * config, vlib_buffer_t ** b,
260  i16 * cdo, u16 * next, u32 n_left, int l2_efp,
261  int l2_vtr, int l2_pbb)
262 {
263  u32 feature_bitmap = config->feature_bitmap & ~L2OUTPUT_FEAT_OUTPUT;
264  if (config->shg == 0 && feature_bitmap == 0)
265  l2output_process_batch_inline (vm, node, config, b, cdo, next, n_left,
266  l2_efp, l2_vtr, l2_pbb, 0, 0);
267  else if (config->shg == 0)
268  l2output_process_batch_inline (vm, node, config, b, cdo, next, n_left,
269  l2_efp, l2_vtr, l2_pbb, 0, 1);
270  else if (feature_bitmap == 0)
271  l2output_process_batch_inline (vm, node, config, b, cdo, next, n_left,
272  l2_efp, l2_vtr, l2_pbb, 1, 0);
273  else
274  l2output_process_batch_inline (vm, node, config, b, cdo, next, n_left,
275  l2_efp, l2_vtr, l2_pbb, 1, 1);
276 }
277 
279  vlib_node_runtime_t * node,
280  vlib_frame_t * frame)
281 {
282  u32 n_left, *from;
284  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
285  u16 nexts[VLIB_FRAME_SIZE];
286  u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index;
287  i16 cur_data_offsets[VLIB_FRAME_SIZE], *cdo;
288  l2_output_config_t *config;
289  u32 feature_bitmap;
290 
291  from = vlib_frame_vector_args (frame);
292  n_left = frame->n_vectors; /* number of packets to process */
293 
294  vlib_get_buffers (vm, from, bufs, n_left);
295  b = bufs;
296  sw_if_index = sw_if_indices;
297  cdo = cur_data_offsets;
298 
299  /* extract data from buffer metadata */
300  while (n_left >= 8)
301  {
302  /* Prefetch the buffer header for the N+2 loop iteration */
303  vlib_prefetch_buffer_header (b[4], LOAD);
304  vlib_prefetch_buffer_header (b[5], LOAD);
305  vlib_prefetch_buffer_header (b[6], LOAD);
306  vlib_prefetch_buffer_header (b[7], LOAD);
307 
308  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
309  cdo[0] = b[0]->current_data;
310  sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
311  cdo[1] = b[1]->current_data;
312  sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
313  cdo[2] = b[2]->current_data;
314  sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
315  cdo[3] = b[3]->current_data;
316 
317  /* next */
318  sw_if_index += 4;
319  n_left -= 4;
320  b += 4;
321  cdo += 4;
322  }
323  while (n_left)
324  {
325  sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
326  cdo[0] = b[0]->current_data;
327 
328  /* next */
329  sw_if_index += 1;
330  n_left -= 1;
331  b += 1;
332  cdo += 1;
333  }
334 
335  n_left = frame->n_vectors;
336  while (n_left)
337  {
338  u16 count, new_next, *next;
339  u16 off = frame->n_vectors - n_left;
340  b = bufs + off;
341 
342  if (n_left >= 4)
343  {
344  vlib_prefetch_buffer_header (b[0], LOAD);
345  vlib_prefetch_buffer_header (b[1], LOAD);
346  vlib_prefetch_buffer_header (b[2], LOAD);
347  vlib_prefetch_buffer_header (b[3], LOAD);
348  }
349 
350  sw_if_index = sw_if_indices + off;
351  cdo = cur_data_offsets + off;
352  next = nexts + off;
353 
354  count = clib_count_equal_u32 (sw_if_index, n_left);
355  n_left -= count;
356 
357  config = vec_elt_at_index (msm->configs, sw_if_index[0]);
358  feature_bitmap = config->feature_bitmap;
359  if (PREDICT_FALSE ((feature_bitmap & ~L2OUTPUT_FEAT_OUTPUT) != 0))
361  (l2output_main.l2_out_feat_next, feature_bitmap);
362  else
363  new_next = vec_elt (l2output_main.output_node_index_vec,
364  sw_if_index[0]);
365  clib_memset_u16 (nexts + off, new_next, count);
366 
367  if (new_next == L2OUTPUT_NEXT_DROP)
368  {
370  (b, count, node->errors[L2OUTPUT_ERROR_MAPPING_DROP]);
371  continue;
372  }
373 
374  /* VTR */
375  if (config->out_vtr_flag && config->output_vtr.push_and_pop_bytes)
376  {
377  if (feature_bitmap & L2OUTPUT_FEAT_EFP_FILTER)
378  l2output_process_batch (vm, node, config, b, cdo, next, count,
379  /* l2_efp */ 1,
380  /* l2_vtr */ 1,
381  /* l2_pbb */ 0);
382  else
383  l2output_process_batch (vm, node, config, b, cdo, next, count,
384  /* l2_efp */ 0,
385  /* l2_vtr */ 1,
386  /* l2_pbb */ 0);
387  }
388  else if (config->out_vtr_flag &&
390  l2output_process_batch (vm, node, config, b, cdo, next, count,
391  /* l2_efp */ 0,
392  /* l2_vtr */ 0,
393  /* l2_pbb */ 1);
394  else
395  l2output_process_batch (vm, node, config, b, cdo, next, count,
396  /* l2_efp */ 0,
397  /* l2_vtr */ 0,
398  /* l2_pbb */ 0);
399  }
400 
401 
402  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
403  {
404  n_left = frame->n_vectors; /* number of packets to process */
405  b = bufs;
406 
407  while (n_left)
408  {
409  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
410  {
412  l2output_trace_t *t =
413  vlib_add_trace (vm, node, b[0], sizeof (*t));
414  t->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
415  h = vlib_buffer_get_current (b[0]);
416  clib_memcpy (t->src, h->src_address, 6);
417  clib_memcpy (t->dst, h->dst_address, 6);
418  clib_memcpy (t->raw, &h->type, sizeof (t->raw));
419  }
420  /* next */
421  n_left--;
422  b++;
423  }
424  }
425 
426  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
428  L2OUTPUT_ERROR_L2OUTPUT, frame->n_vectors);
429 
430  return frame->n_vectors;
431 }
432 
433 #ifndef CLIB_MARCH_VARIANT
434 /* *INDENT-OFF* */
436  .name = "l2-output",
437  .vector_size = sizeof (u32),
438  .format_trace = format_l2output_trace,
439  .type = VLIB_NODE_TYPE_INTERNAL,
440 
441  .n_errors = ARRAY_LEN(l2output_error_strings),
442  .error_strings = l2output_error_strings,
443 
444  .n_next_nodes = L2OUTPUT_N_NEXT,
445 
446  /* edit / add dispositions here */
447  .next_nodes = {
448  [L2OUTPUT_NEXT_DROP] = "error-drop",
449  [L2OUTPUT_NEXT_BAD_INTF] = "l2-output-bad-intf",
450  },
451 };
452 /* *INDENT-ON* */
453 
454 
455 #define foreach_l2output_bad_intf_error \
456 _(DROP, "L2 output to interface not in L2 mode or deleted")
457 
459 #define _(sym,string) string,
461 #undef _
462 };
463 
464 typedef enum
465 {
466 #define _(sym,str) L2OUTPUT_BAD_INTF_ERROR_##sym,
468 #undef _
471 
472 
473 /**
474  * Output node for interfaces/tunnels which was in L2 mode but were changed
475  * to L3 mode or possibly deleted thereafter. On changing forwarding mode
476  * of any tunnel/interface from L2 to L3, its entry in l2_output_main table
477  * next_nodes.output_node_index_vec[sw_if_index] MUST be set to the value of
478  * L2OUTPUT_NEXT_BAD_INTF. Thus, if there are stale entries in the L2FIB for
479  * this sw_if_index, l2-output will send packets for this sw_if_index to the
480  * l2-output-bad-intf node which just setup the proper drop reason before
481  * sending packets to the error-drop node to drop the packet. Then, stale L2FIB
482  * entries for delted tunnels won't cause possible packet or memory corrpution.
483  */
485 
486 static uword
488  vlib_node_runtime_t * node, vlib_frame_t * frame)
489 {
490  u32 n_left_from, *from, *to_next;
491  l2output_next_t next_index = 0;
492 
493  from = vlib_frame_vector_args (frame);
494  n_left_from = frame->n_vectors; /* number of packets to process */
495 
496  while (n_left_from > 0)
497  {
498  u32 n_left_to_next;
499 
500  /* get space to enqueue frame to graph node "next_index" */
501  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
502 
503  while (n_left_from >= 4 && n_left_to_next >= 2)
504  {
505  u32 bi0, bi1;
506  vlib_buffer_t *b0, *b1;
507 
508  to_next[0] = bi0 = from[0];
509  to_next[1] = bi1 = from[1];
510  from += 2;
511  to_next += 2;
512  n_left_from -= 2;
513  n_left_to_next -= 2;
514  b0 = vlib_get_buffer (vm, bi0);
515  b1 = vlib_get_buffer (vm, bi1);
516  b0->error = node->errors[L2OUTPUT_BAD_INTF_ERROR_DROP];
517  b1->error = node->errors[L2OUTPUT_BAD_INTF_ERROR_DROP];
518  }
519 
520  while (n_left_from > 0 && n_left_to_next > 0)
521  {
522  u32 bi0;
523  vlib_buffer_t *b0;
524 
525  bi0 = from[0];
526  to_next[0] = bi0;
527  from += 1;
528  to_next += 1;
529  n_left_from -= 1;
530  n_left_to_next -= 1;
531  b0 = vlib_get_buffer (vm, bi0);
532  b0->error = node->errors[L2OUTPUT_BAD_INTF_ERROR_DROP];
533  }
534 
535  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
536  }
537 
538  return frame->n_vectors;
539 }
540 
541 /* *INDENT-OFF* */
543  .function = l2output_bad_intf_node_fn,
544  .name = "l2-output-bad-intf",
545  .vector_size = sizeof (u32),
546  .type = VLIB_NODE_TYPE_INTERNAL,
547 
549  .error_strings = l2output_bad_intf_error_strings,
550 
551  .n_next_nodes = 1,
552 
553  /* edit / add dispositions here */
554  .next_nodes = {
555  [0] = "error-drop",
556  },
557 };
558 
560 /* *INDENT-ON* */
561 
562 static clib_error_t *
564 {
566 
567  mp->vlib_main = vm;
568  mp->vnet_main = vnet_get_main ();
569 
570  /* Create the config vector */
571  vec_validate (mp->configs, 100);
572  /* Until we hook up the CLI config, just create 100 sw interface entries and zero them */
573 
574  /* Initialize the feature next-node indexes */
576  l2output_node.index,
579  mp->l2_out_feat_next);
580 
581  /* Initialize the output node mapping table */
584 
585  return 0;
586 }
587 
589 
590 
591 /** Create a mapping in the next node mapping table for the given sw_if_index. */
592 void
594  vnet_main_t * vnet_main, u32 sw_if_index)
595 {
596  vnet_hw_interface_t *hw0 =
597  vnet_get_sup_hw_interface (vnet_main, sw_if_index);
598 
599  /* dynamically create graph node arc */
600  u32 next = vlib_node_add_next (vlib_main, l2output_node.index,
601  hw0->output_node_index);
602  l2output_main.output_node_index_vec[sw_if_index] = next;
603 }
604 
605 /* Get a pointer to the config for the given interface */
608 {
610 
611  vec_validate (mp->configs, sw_if_index);
612  return vec_elt_at_index (mp->configs, sw_if_index);
613 }
614 
615 /** Enable (or disable) the feature in the bitmap for the given interface. */
616 void
617 l2output_intf_bitmap_enable (u32 sw_if_index, u32 feature_bitmap, u32 enable)
618 {
620  l2_output_config_t *config;
621 
622  vec_validate (mp->configs, sw_if_index);
623  config = vec_elt_at_index (mp->configs, sw_if_index);
624 
625  if (enable)
626  {
627  config->feature_bitmap |= feature_bitmap;
628  }
629  else
630  {
631  config->feature_bitmap &= ~feature_bitmap;
632  }
633 }
634 #endif
635 
636 /*
637  * fd.io coding-style-patch-verification: ON
638  *
639  * Local Variables:
640  * eval: (c-set-style "gnu")
641  * End:
642  */
l2output_bad_intf_error_t
Definition: l2_output.c:464
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
#define foreach_l2output_error
Definition: l2_output.h:119
#define CLIB_UNUSED(x)
Definition: clib.h:79
char ** l2output_get_feat_names(void)
Definition: l2_output.c:39
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)
u8 * format_l2_output_features(u8 *s, va_list *args)
Definition: l2_output.c:45
vlib_node_registration_t l2output_node
(constructor) VLIB_REGISTER_NODE (l2output_node)
Definition: l2_output.c:435
l2output_next_t
Definition: l2_output.h:127
VLIB_NODE_FUNCTION_MULTIARCH(l2output_bad_intf_node, l2output_bad_intf_node_fn)
u8 src_address[6]
Definition: packet.h:56
static_always_inline void split_horizon_violation(vlib_node_runtime_t *node, u8 shg, vlib_buffer_t *b, u16 *next)
Check for split horizon violations.
Definition: l2_output.c:116
u16 vlib_error_t
Definition: error.h:44
int i
static_always_inline void l2output_set_buffer_error(vlib_buffer_t **b, u32 n_left, vlib_error_t error)
Definition: l2_output.c:237
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define VLIB_NODE_FN(node)
Definition: node.h:173
static u32 l2_pbb_process(vlib_buffer_t *b0, ptr_config_t *config)
Definition: l2_vtr.h:201
u32 * output_node_index_vec
Definition: l2_output.h:62
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:451
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1110
unsigned char u8
Definition: types.h:56
static clib_error_t * l2output_init(vlib_main_t *vm)
Definition: l2_output.c:563
u16 push_and_pop_bytes
Definition: l2_vtr.h:64
void l2output_create_output_node_mapping(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index)
Create a mapping in the next node mapping table for the given sw_if_index.
Definition: l2_output.c:593
u16 push_and_pop_bytes
Definition: l2_vtr.h:196
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:104
#define static_always_inline
Definition: clib.h:93
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
ptr_config_t output_pbb_vtr
Definition: l2_output.h:41
u8 dst_address[6]
Definition: packet.h:55
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:184
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned int u32
Definition: types.h:88
#define VLIB_FRAME_SIZE
Definition: node.h:364
void l2output_intf_bitmap_enable(u32 sw_if_index, u32 feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_output.c:617
static u32 l2_vtr_process(vlib_buffer_t *b0, vtr_config_t *config)
Perform the configured tag rewrite on the packet.
Definition: l2_vtr.h:75
l2_output_config_t * l2output_intf_config(u32 sw_if_index)
Get a pointer to the config for the given interface.
Definition: l2_output.c:607
static_always_inline void l2output_process_batch(vlib_main_t *vm, vlib_node_runtime_t *node, l2_output_config_t *config, vlib_buffer_t **b, i16 *cdo, u16 *next, u32 n_left, int l2_efp, int l2_vtr, int l2_pbb)
Definition: l2_output.c:258
static uword l2output_bad_intf_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l2_output.c:487
vtr_config_t input_vtr
Definition: l2_output.h:38
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
#define PREDICT_FALSE(x)
Definition: clib.h:105
vnet_main_t vnet_main
Definition: misc.c:43
#define foreach_l2output_bad_intf_error
Definition: l2_output.c:455
l2output_main_t l2output_main
Definition: l2_output.c:67
static u32 feat_bitmap_get_next_node_index(u32 *next_nodes, u32 bitmap)
Return the graph node index for the feature corresponding to the first set bit in the bitmap...
Definition: feat_bitmap.h:79
#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
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:135
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1168
vlib_main_t * vlib_main
Definition: l2_output.h:74
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
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_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:332
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
static u8 l2_efp_filter_process(vlib_buffer_t *b0, vtr_config_t *in_config)
Definition: l2_vtr.h:141
#define clib_memcpy(a, b, c)
Definition: string.h:75
static char * l2output_feat_names[]
Definition: l2_output.c:32
#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
vtr_config_t output_vtr
Definition: l2_output.h:39
static_always_inline void l2output_process_batch_inline(vlib_main_t *vm, vlib_node_runtime_t *node, l2_output_config_t *config, vlib_buffer_t **b, i16 *cdo, u16 *next, u32 n_left, int l2_efp, int l2_vtr, int l2_pbb, int shg_set, int update_feature_bitmap)
Definition: l2_output.c:126
size_t count
Definition: vapi.c:42
static char * l2output_error_strings[]
Definition: l2_output.c:101
static vlib_node_registration_t l2output_bad_intf_node
Output node for interfaces/tunnels which was in L2 mode but were changed to L3 mode or possibly delet...
Definition: l2_output.c:484
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
static_always_inline void clib_memset_u16(void *p, u16 val, uword count)
Definition: string.h:233
#define vec_elt(v, i)
Get vector value at index i.
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
Definition: main.c:1695
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
static char * l2output_bad_intf_error_strings[]
Definition: l2_output.c:458
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
l2_output_config_t * configs
Definition: l2_output.h:71
#define vnet_buffer(b)
Definition: buffer.h:360
static_always_inline uword clib_count_equal_u32(u32 *data, uword max_count)
Definition: string.h:366
static u8 * format_l2output_trace(u8 *s, va_list *args)
Definition: l2_output.c:82
u32 l2_out_feat_next[32]
Definition: l2_output.h:68
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:128
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:295
u32 flags
Definition: vhost-user.h:77
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
vnet_main_t * vnet_main
Definition: l2_output.h:75
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
signed short i16
Definition: types.h:46