FD.io VPP  v16.09
Vector Packet Processing
l2_rw.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 <vlib/vlib.h>
17 #include <vnet/l2/feat_bitmap.h>
18 #include <vnet/l2/l2_rw.h>
19 
21 
23 
24 typedef struct
25 {
30 
31 static u8 *
32 format_l2_rw_entry (u8 * s, va_list * args)
33 {
34  l2_rw_entry_t *e = va_arg (*args, l2_rw_entry_t *);
35  l2_rw_main_t *rw = &l2_rw_main;
36  s = format (s, "%d - mask:%U value:%U\n",
37  e - rw->entries,
38  format_hex_bytes, e->mask,
39  e->rewrite_n_vectors * sizeof (u32x4), format_hex_bytes,
40  e->value, e->rewrite_n_vectors * sizeof (u32x4));
41  s =
42  format (s, " hits:%d skip_bytes:%d", e->hit_count,
43  e->skip_n_vectors * sizeof (u32x4));
44  return s;
45 }
46 
47 static u8 *
48 format_l2_rw_config (u8 * s, va_list * args)
49 {
50  l2_rw_config_t *c = va_arg (*args, l2_rw_config_t *);
51  return format (s, "table-index:%d miss-index:%d",
52  c->table_index, c->miss_index);
53 }
54 
55 /* packet trace format function */
56 static u8 *
57 format_l2_rw_trace (u8 * s, va_list * args)
58 {
59  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
60  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
61  l2_rw_trace_t *t = va_arg (*args, l2_rw_trace_t *);
62  return format (s, "l2-rw: sw_if_index %d, table %d, entry %d",
65 }
66 
67 always_inline l2_rw_config_t *
68 l2_rw_get_config (u32 sw_if_index)
69 {
70  l2_rw_main_t *rw = &l2_rw_main;
71  if (PREDICT_FALSE (!clib_bitmap_get (rw->configs_bitmap, sw_if_index)))
72  {
73  vec_validate (rw->configs, sw_if_index);
74  rw->configs[sw_if_index].table_index = ~0;
75  rw->configs[sw_if_index].miss_index = ~0;
76  rw->configs_bitmap =
77  clib_bitmap_set (rw->configs_bitmap, sw_if_index, 1);
78  }
79  return &rw->configs[sw_if_index];
80 }
81 
83 l2_rw_rewrite (l2_rw_entry_t * rwe, u8 * h)
84 {
85  if (U32X4_ALIGNED (h))
86  {
87  u32x4 *d = ((u32x4 *) h) + rwe->skip_n_vectors;
88  switch (rwe->rewrite_n_vectors)
89  {
90  case 5:
91  d[4] = (d[4] & ~rwe->mask[4]) | rwe->value[4];
92  /* FALLTHROUGH */
93  case 4:
94  d[3] = (d[3] & ~rwe->mask[3]) | rwe->value[3];
95  /* FALLTHROUGH */
96  case 3:
97  d[2] = (d[2] & ~rwe->mask[2]) | rwe->value[2];
98  /* FALLTHROUGH */
99  case 2:
100  d[1] = (d[1] & ~rwe->mask[1]) | rwe->value[1];
101  /* FALLTHROUGH */
102  case 1:
103  d[0] = (d[0] & ~rwe->mask[0]) | rwe->value[0];
104  break;
105  default:
106  abort ();
107  }
108  }
109  else
110  {
111  u64 *d = ((u64 *) h) + rwe->skip_n_vectors * 2;
112  switch (rwe->rewrite_n_vectors)
113  {
114  case 5:
115  d[8] =
116  (d[8] & ~(((u64 *) rwe->mask)[8])) | (((u64 *) rwe->value)[8]);
117  d[9] =
118  (d[9] & ~(((u64 *) rwe->mask)[9])) | (((u64 *) rwe->value)[9]);
119  /* FALLTHROUGH */
120  case 4:
121  d[6] =
122  (d[6] & ~(((u64 *) rwe->mask)[6])) | (((u64 *) rwe->value)[6]);
123  d[7] =
124  (d[7] & ~(((u64 *) rwe->mask)[7])) | (((u64 *) rwe->value)[7]);
125  /* FALLTHROUGH */
126  case 3:
127  d[4] =
128  (d[4] & ~(((u64 *) rwe->mask)[4])) | (((u64 *) rwe->value)[4]);
129  d[5] =
130  (d[5] & ~(((u64 *) rwe->mask)[5])) | (((u64 *) rwe->value)[5]);
131  /* FALLTHROUGH */
132  case 2:
133  d[2] =
134  (d[2] & ~(((u64 *) rwe->mask)[2])) | (((u64 *) rwe->value)[2]);
135  d[3] =
136  (d[3] & ~(((u64 *) rwe->mask)[3])) | (((u64 *) rwe->value)[3]);
137  /* FALLTHROUGH */
138  case 1:
139  d[0] =
140  (d[0] & ~(((u64 *) rwe->mask)[0])) | (((u64 *) rwe->value)[0]);
141  d[1] =
142  (d[1] & ~(((u64 *) rwe->mask)[1])) | (((u64 *) rwe->value)[1]);
143  break;
144  default:
145  abort ();
146  }
147  }
148 }
149 
150 static uword
152  vlib_node_runtime_t * node, vlib_frame_t * frame)
153 {
154  l2_rw_main_t *rw = &l2_rw_main;
155  u32 n_left_from, *from, *to_next, next_index;
157  f64 now = vlib_time_now (vlib_get_main ());
158  u32 prefetch_size = 0;
159 
160  from = vlib_frame_vector_args (frame);
161  n_left_from = frame->n_vectors; /* number of packets to process */
162  next_index = node->cached_next_index;
163 
164  while (n_left_from > 0)
165  {
166  u32 n_left_to_next;
167 
168  /* get space to enqueue frame to graph node "next_index" */
169  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
170 
171  while (n_left_from >= 4 && n_left_to_next >= 2)
172  {
173  u32 bi0, next0, sw_if_index0, feature_bitmap0, rwe_index0;
174  u32 bi1, next1, sw_if_index1, feature_bitmap1, rwe_index1;
175  vlib_buffer_t *b0, *b1;
176  ethernet_header_t *h0, *h1;
177  l2_rw_config_t *config0, *config1;
178  u64 hash0, hash1;
179  vnet_classify_table_t *t0, *t1;
180  vnet_classify_entry_t *e0, *e1;
181  l2_rw_entry_t *rwe0, *rwe1;
182 
183  {
184  vlib_buffer_t *p2, *p3;
185  p2 = vlib_get_buffer (vm, from[2]);
186  p3 = vlib_get_buffer (vm, from[3]);
187 
188  vlib_prefetch_buffer_header (p2, LOAD);
189  vlib_prefetch_buffer_header (p3, LOAD);
190  CLIB_PREFETCH (vlib_buffer_get_current (p2), prefetch_size, LOAD);
191  CLIB_PREFETCH (vlib_buffer_get_current (p3), prefetch_size, LOAD);
192  }
193 
194  bi0 = from[0];
195  bi1 = from[1];
196  to_next[0] = bi0;
197  to_next[1] = bi1;
198  from += 2;
199  to_next += 2;
200  n_left_from -= 2;
201  n_left_to_next -= 2;
202 
203  b0 = vlib_get_buffer (vm, bi0);
204  b1 = vlib_get_buffer (vm, bi1);
205  h0 = vlib_buffer_get_current (b0);
206  h1 = vlib_buffer_get_current (b1);
207 
208  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
209  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
210  config0 = l2_rw_get_config (sw_if_index0); /*TODO: check sw_if_index0 value */
211  config1 = l2_rw_get_config (sw_if_index1); /*TODO: check sw_if_index0 value */
212  t0 = pool_elt_at_index (vcm->tables, config0->table_index);
213  t1 = pool_elt_at_index (vcm->tables, config1->table_index);
214  prefetch_size =
215  (t1->skip_n_vectors + t1->match_n_vectors) * sizeof (u32x4);
216 
217  hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
218  hash1 = vnet_classify_hash_packet (t1, (u8 *) h1);
219  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
220  e1 = vnet_classify_find_entry (t1, (u8 *) h1, hash1, now);
221 
222  while (!e0 && (t0->next_table_index != ~0))
223  {
224  t0 = pool_elt_at_index (vcm->tables, t0->next_table_index);
225  hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
226  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
227  }
228 
229  while (!e1 && (t1->next_table_index != ~0))
230  {
231  t1 = pool_elt_at_index (vcm->tables, t1->next_table_index);
232  hash1 = vnet_classify_hash_packet (t1, (u8 *) h1);
233  e1 = vnet_classify_find_entry (t1, (u8 *) h1, hash1, now);
234  }
235 
236  rwe_index0 = e0 ? e0->opaque_index : config0->miss_index;
237  rwe_index1 = e1 ? e1->opaque_index : config1->miss_index;
238 
239  if (rwe_index0 != ~0)
240  {
241  rwe0 = pool_elt_at_index (rw->entries, rwe_index0);
242  l2_rw_rewrite (rwe0, (u8 *) h0);
243  }
244  if (rwe_index1 != ~0)
245  {
246  rwe1 = pool_elt_at_index (rw->entries, rwe_index1);
247  l2_rw_rewrite (rwe1, (u8 *) h1);
248  }
249 
251  {
252  l2_rw_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
253  t->sw_if_index = sw_if_index0;
254  t->classify_table_index = config0->table_index;
255  t->rewrite_entry_index = rwe_index0;
256  }
257 
259  {
260  l2_rw_trace_t *t = vlib_add_trace (vm, node, b1, sizeof (*t));
261  t->sw_if_index = sw_if_index1;
262  t->classify_table_index = config1->table_index;
263  t->rewrite_entry_index = rwe_index1;
264  }
265 
266  /* Update feature bitmap and get next feature index */
267  feature_bitmap0 =
268  vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_RW;
269  feature_bitmap1 =
270  vnet_buffer (b1)->l2.feature_bitmap & ~L2INPUT_FEAT_RW;
271  vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0;
272  vnet_buffer (b1)->l2.feature_bitmap = feature_bitmap1;
274  feature_bitmap0);
276  feature_bitmap1);
277 
278  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
279  to_next, n_left_to_next,
280  bi0, bi1, next0, next1);
281  }
282 
283  while (n_left_from > 0 && n_left_to_next > 0)
284  {
285  u32 bi0, next0, sw_if_index0, feature_bitmap0, rwe_index0;
286  vlib_buffer_t *b0;
287  ethernet_header_t *h0;
288  l2_rw_config_t *config0;
289  u64 hash0;
291  vnet_classify_entry_t *e0;
292  l2_rw_entry_t *rwe0;
293 
294  bi0 = from[0];
295  to_next[0] = bi0;
296  from += 1;
297  to_next += 1;
298  n_left_from -= 1;
299  n_left_to_next -= 1;
300 
301  b0 = vlib_get_buffer (vm, bi0);
302  h0 = vlib_buffer_get_current (b0);
303 
304  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
305  config0 = l2_rw_get_config (sw_if_index0); /*TODO: check sw_if_index0 value */
306  t0 = pool_elt_at_index (vcm->tables, config0->table_index);
307 
308  hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
309  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
310 
311  while (!e0 && (t0->next_table_index != ~0))
312  {
313  t0 = pool_elt_at_index (vcm->tables, t0->next_table_index);
314  hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
315  e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
316  }
317 
318  rwe_index0 = e0 ? e0->opaque_index : config0->miss_index;
319 
320  if (rwe_index0 != ~0)
321  {
322  rwe0 = pool_elt_at_index (rw->entries, rwe_index0);
323  l2_rw_rewrite (rwe0, (u8 *) h0);
324  }
325 
327  {
328  l2_rw_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
329  t->sw_if_index = sw_if_index0;
330  t->classify_table_index = config0->table_index;
331  t->rewrite_entry_index = rwe_index0;
332  }
333 
334  /* Update feature bitmap and get next feature index */
335  feature_bitmap0 =
336  vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_RW;
337  vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0;
339  feature_bitmap0);
340 
341  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
342  to_next, n_left_to_next,
343  bi0, next0);
344  }
345  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
346  }
347 
348  return frame->n_vectors;
349 }
350 
351 int
353  u8 * mask, u8 * value, u32 len, u32 skip, u8 is_del)
354 {
355  l2_rw_main_t *rw = &l2_rw_main;
356  l2_rw_entry_t *e = 0;
357  if (*index != ~0)
358  {
359  if (pool_is_free_index (rw->entries, *index))
360  {
361  return -1;
362  }
363  e = pool_elt_at_index (rw->entries, *index);
364  }
365  else
366  {
367  pool_get (rw->entries, e);
368  *index = e - rw->entries;
369  }
370 
371  if (!e)
372  return -1;
373 
374  if (is_del)
375  {
376  pool_put (rw->entries, e);
377  return 0;
378  }
379 
380  e->skip_n_vectors = skip / sizeof (u32x4);
381  skip -= e->skip_n_vectors * sizeof (u32x4);
382  e->rewrite_n_vectors = (skip + len - 1) / sizeof (u32x4) + 1;
383  vec_alloc_aligned (e->mask, e->rewrite_n_vectors, sizeof (u32x4));
384  memset (e->mask, 0, e->rewrite_n_vectors * sizeof (u32x4));
385  vec_alloc_aligned (e->value, e->rewrite_n_vectors, sizeof (u32x4));
386  memset (e->value, 0, e->rewrite_n_vectors * sizeof (u32x4));
387 
388  clib_memcpy (((u8 *) e->value) + skip, value, len);
389  clib_memcpy (((u8 *) e->mask) + skip, mask, len);
390 
391  int i;
392  for (i = 0; i < e->rewrite_n_vectors; i++)
393  {
394  e->value[i] &= e->mask[i];
395  }
396 
397  return 0;
398 }
399 
400 static clib_error_t *
402  unformat_input_t * input, vlib_cli_command_t * cmd)
403 {
404  u32 index = ~0;
405  u8 *mask = 0;
406  u8 *value = 0;
407  u32 skip = 0;
408  u8 del = 0;
409 
411  {
412  if (unformat (input, "index %d", &index))
413  ;
414  else if (unformat (input, "mask %U", unformat_hex_string, &mask))
415  ;
416  else if (unformat (input, "value %U", unformat_hex_string, &value))
417  ;
418  else if (unformat (input, "skip %d", &skip))
419  ;
420  else if (unformat (input, "del"))
421  del = 1;
422  else
423  break;
424  }
425 
426  if (!mask || !value)
427  return clib_error_return (0, "Unspecified mask or value");
428 
429  if (vec_len (mask) != vec_len (value))
430  return clib_error_return (0, "Mask and value lengths must be identical");
431 
432  int ret;
433  if ((ret =
434  l2_rw_mod_entry (&index, mask, value, vec_len (mask), skip, del)))
435  return clib_error_return (0, "Could not add entry");
436 
437  return 0;
438 }
439 
440 /* *INDENT-OFF* */
441 VLIB_CLI_COMMAND (l2_rw_entry_cli, static) = {
442  .path = "l2 rewrite entry",
443  .short_help =
444  "l2 rewrite entry [index <index>] [mask <hex-mask>] [value <hex-value>] [skip <n_bytes>] [del]",
445  .function = l2_rw_entry_cli_fn,
446 };
447 /* *INDENT-ON* */
448 
449 int
450 l2_rw_interface_set_table (u32 sw_if_index, u32 table_index, u32 miss_index)
451 {
452  l2_rw_config_t *c = l2_rw_get_config (sw_if_index);
453  l2_rw_main_t *rw = &l2_rw_main;
454 
455  c->table_index = table_index;
456  c->miss_index = miss_index;
457  u32 feature_bitmap = (table_index == ~0) ? 0 : L2INPUT_FEAT_RW;
458 
459  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_RW, feature_bitmap);
460 
461  if (c->table_index == ~0)
462  clib_bitmap_set (rw->configs_bitmap, sw_if_index, 0);
463 
464  return 0;
465 }
466 
467 static clib_error_t *
469  unformat_input_t * input, vlib_cli_command_t * cmd)
470 {
471  vnet_main_t *vnm = vnet_get_main ();
472  u32 table_index = ~0;
473  u32 sw_if_index = ~0;
474  u32 miss_index = ~0;
475 
477  {
478  unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index);
479  }
480 
482  {
483  if (unformat (input, "table %d", &table_index))
484  ;
485  else if (unformat (input, "miss-index %d", &miss_index))
486  ;
487  else
488  break;
489  }
490 
491  if (sw_if_index == ~0)
492  return clib_error_return (0,
493  "You must specify an interface 'iface <interface>'",
494  format_unformat_error, input);
495  int ret;
496  if ((ret =
497  l2_rw_interface_set_table (sw_if_index, table_index, miss_index)))
498  return clib_error_return (0, "l2_rw_interface_set_table returned %d",
499  ret);
500 
501  return 0;
502 }
503 
504 /* *INDENT-OFF* */
505 VLIB_CLI_COMMAND (l2_rw_interface_cli, static) = {
506  .path = "set interface l2 rewrite",
507  .short_help =
508  "set interface l2 rewrite <interface> [table <table index>] [miss-index <entry-index>]",
509  .function = l2_rw_interface_cli_fn,
510 };
511 /* *INDENT-ON* */
512 
513 static clib_error_t *
515  unformat_input_t * input,
516  vlib_cli_command_t * cmd)
517 {
518  l2_rw_main_t *rw = &l2_rw_main;
520  vlib_cli_output (vm, "No interface is currently using l2 rewrite\n");
521 
522  uword i;
523  /* *INDENT-OFF* */
525  vlib_cli_output (vm, "sw_if_index:%d %U\n", i, format_l2_rw_config, &rw->configs[i]);
526  });
527  /* *INDENT-ON* */
528  return 0;
529 }
530 
531 /* *INDENT-OFF* */
532 VLIB_CLI_COMMAND (l2_rw_show_interfaces_cli, static) = {
533  .path = "show l2 rewrite interfaces",
534  .short_help =
535  "show l2 rewrite interfaces",
536  .function = l2_rw_show_interfaces_cli_fn,
537 };
538 /* *INDENT-ON* */
539 
540 static clib_error_t *
542  unformat_input_t * input, vlib_cli_command_t * cmd)
543 {
544  l2_rw_main_t *rw = &l2_rw_main;
545  l2_rw_entry_t *e;
546  if (pool_elts (rw->entries) == 0)
547  vlib_cli_output (vm, "No entries\n");
548 
549  /* *INDENT-OFF* */
550  pool_foreach(e, rw->entries, {
551  vlib_cli_output (vm, "%U\n", format_l2_rw_entry, e);
552  });
553  /* *INDENT-ON* */
554  return 0;
555 }
556 
557 /* *INDENT-OFF* */
558 VLIB_CLI_COMMAND (l2_rw_show_entries_cli, static) = {
559  .path = "show l2 rewrite entries",
560  .short_help =
561  "show l2 rewrite entries",
562  .function = l2_rw_show_entries_cli_fn,
563 };
564 /* *INDENT-ON* */
565 
566 int
567 l2_rw_enable_disable (u32 bridge_domain, u8 disable)
568 {
569  u32 mask = L2INPUT_FEAT_RW;
570  l2input_set_bridge_features (bridge_domain, mask, disable ? 0 : mask);
571  return 0;
572 }
573 
574 static clib_error_t *
576  unformat_input_t * input, vlib_cli_command_t * cmd)
577 {
578  u32 bridge_domain;
579  u8 disable = 0;
580 
582  !unformat (input, "%d", &bridge_domain))
583  {
584  return clib_error_return (0, "You must specify a bridge domain");
585  }
586 
588  unformat (input, "disable"))
589  {
590  disable = 1;
591  }
592 
593  if (l2_rw_enable_disable (bridge_domain, disable))
594  return clib_error_return (0, "Could not enable or disable rewrite");
595 
596  return 0;
597 }
598 
599 /* *INDENT-OFF* */
600 VLIB_CLI_COMMAND (l2_rw_set_cli, static) = {
601  .path = "set bridge-domain rewrite",
602  .short_help =
603  "set bridge-domain rewrite <bridge-domain> [disable]",
604  .function = l2_rw_set_cli_fn,
605 };
606 /* *INDENT-ON* */
607 
608 static clib_error_t *
610 {
611  l2_rw_main_t *rw = &l2_rw_main;
612  rw->configs = 0;
613  rw->entries = 0;
616  l2_rw_node.index,
620  return 0;
621 }
622 
624 
625 enum
626 {
629 };
630 
631 #define foreach_l2_rw_error \
632 _(UNKNOWN, "Unknown error")
633 
634 typedef enum
635 {
636 #define _(sym,str) L2_RW_ERROR_##sym,
638 #undef _
640 } l2_rw_error_t;
641 
642 static char *l2_rw_error_strings[] = {
643 #define _(sym,string) string,
645 #undef _
646 };
647 
648 /* *INDENT-OFF* */
650  .function = l2_rw_node_fn,
651  .name = "l2-rw",
652  .vector_size = sizeof (u32),
653  .format_trace = format_l2_rw_trace,
655  .n_errors = ARRAY_LEN(l2_rw_error_strings),
656  .error_strings = l2_rw_error_strings,
657  .runtime_data_bytes = 0,
658  .n_next_nodes = L2_RW_N_NEXT,
659  .next_nodes = { [L2_RW_NEXT_DROP] = "error-drop"},
660 };
661 /* *INDENT-ON* */
662 
664 /*
665  * fd.io coding-style-patch-verification: ON
666  *
667  * Local Variables:
668  * eval: (c-set-style "gnu")
669  * End:
670  */
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:396
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:457
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
static clib_error_t * l2_rw_show_interfaces_cli_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_rw.c:514
u32 l2input_set_bridge_features(u32 bd_index, u32 feat_mask, u32 feat_value)
Definition: l2_input.c:522
l2_rw_main_t l2_rw_main
Definition: l2_rw.c:20
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static l2_rw_config_t * l2_rw_get_config(u32 sw_if_index)
Definition: l2_rw.c:68
static u8 * format_l2_rw_entry(u8 *s, va_list *args)
Definition: l2_rw.c:32
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
static clib_error_t * l2_rw_show_entries_cli_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_rw.c:541
#define U32X4_ALIGNED(p)
Definition: vnet_classify.h:47
l2_rw_config_t * configs
Definition: l2_rw.h:57
struct _vlib_node_registration vlib_node_registration_t
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
unformat_function_t unformat_vnet_sw_interface
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
vlib_node_registration_t l2_rw_node
(constructor) VLIB_REGISTER_NODE (l2_rw_node)
Definition: l2_rw.c:22
static u8 * format_l2_rw_config(u8 *s, va_list *args)
Definition: l2_rw.c:48
#define foreach_l2_rw_error
Definition: l2_rw.c:631
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
u32 classify_table_index
Definition: l2_rw.c:27
#define static_always_inline
Definition: clib.h:85
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define always_inline
Definition: clib.h:84
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
unformat_function_t unformat_hex_string
Definition: format.h:287
unsigned long long u32x4
Definition: ixge.c:28
static char * l2_rw_error_strings[]
Definition: l2_rw.c:642
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
int l2_rw_enable_disable(u32 bridge_domain, u8 disable)
Definition: l2_rw.c:567
unsigned long u64
Definition: types.h:89
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
static clib_error_t * l2_rw_set_cli_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_rw.c:575
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
int l2_rw_mod_entry(u32 *index, u8 *mask, u8 *value, u32 len, u32 skip, u8 is_del)
Definition: l2_rw.c:352
static clib_error_t * l2_rw_entry_cli_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_rw.c:401
#define vec_alloc_aligned(V, N, A)
Allocate space for N more elements (no header, given alignment)
Definition: vec.h:248
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static_always_inline void l2_rw_rewrite(l2_rw_entry_t *rwe, u8 *h)
Definition: l2_rw.c:83
uword * configs_bitmap
Definition: l2_rw.h:58
#define PREDICT_FALSE(x)
Definition: clib.h:97
#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
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_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:130
#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:348
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
static u8 * format_l2_rw_trace(u8 *s, va_list *args)
Definition: l2_rw.c:57
static uword l2_rw_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l2_rw.c:151
#define clib_bitmap_alloc(v, n_bits)
Allocate a bitmap with the supplied number of bits.
Definition: bitmap.h:109
svmdb_client_t * c
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
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 clib_memcpy(a, b, c)
Definition: string.h:63
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
#define ARRAY_LEN(x)
Definition: clib.h:59
u32 rewrite_entry_index
Definition: l2_rw.c:28
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:46
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:50
u16 cached_next_index
Definition: node.h:462
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:335
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
u32 sw_if_index
Definition: l2_rw.c:26
static clib_error_t * l2_rw_init(vlib_main_t *vm)
Definition: l2_rw.c:609
static clib_error_t * l2_rw_interface_cli_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_rw.c:468
u32 feat_next_node_index[32]
Definition: l2_rw.h:51
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:21
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
u64 uword
Definition: types.h:112
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
u32 l2input_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_input.c:501
static uword clib_bitmap_count_set_bits(uword *ai)
Return the number of set bits in a bitmap.
Definition: bitmap.h:441
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
int l2_rw_interface_set_table(u32 sw_if_index, u32 table_index, u32 miss_index)
Definition: l2_rw.c:450
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:163
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:158
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
l2_rw_entry_t * entries
Definition: l2_rw.h:54
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
l2_rw_error_t
Definition: l2_rw.c:634
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
vnet_classify_entry_t * vnet_classify_find_entry(vnet_classify_table_t *t, u8 *h, u64 hash, f64 now)
Definition: defs.h:46
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109