FD.io VPP  v16.09
Vector Packet Processing
l2_flood.c
Go to the documentation of this file.
1 /*
2  * l2_flood.c : layer 2 flooding
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 #include <vnet/l2/l2_input.h>
24 #include <vnet/l2/feat_bitmap.h>
25 #include <vnet/l2/l2_bvi.h>
26 #include <vnet/replication.h>
27 #include <vnet/l2/l2_fib.h>
28 
29 #include <vppinfra/error.h>
30 #include <vppinfra/hash.h>
31 
32 
33 /*
34  * Flooding uses the packet replication infrastructure to send a copy of the
35  * packet to each member interface. Logically the replication infrastructure
36  * expects two graph nodes: a prep node that initiates replication and sends the
37  * packet to the first destination, and a recycle node that is passed the packet
38  * after it has been transmitted.
39  *
40  * To decrease the amount of code, l2 flooding implements both functions in
41  * the same graph node. This node can tell if is it being called as the "prep"
42  * or "recycle" using replication_is_recycled().
43  */
44 
45 
46 typedef struct
47 {
48 
49  /* Next nodes for each feature */
50  u32 feat_next_node_index[32];
51 
52  /* next node index for the L3 input node of each ethertype */
54 
55  /* convenience variables */
59 
60 typedef struct
61 {
62  u8 src[6];
63  u8 dst[6];
67 
68 
69 /* packet trace format function */
70 static u8 *
71 format_l2flood_trace (u8 * s, va_list * args)
72 {
73  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
74  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
75  l2flood_trace_t *t = va_arg (*args, l2flood_trace_t *);
76 
77  s = format (s, "l2-flood: sw_if_index %d dst %U src %U bd_index %d",
78  t->sw_if_index,
81  return s;
82 }
83 
85 
87 
88 #define foreach_l2flood_error \
89 _(L2FLOOD, "L2 flood packets") \
90 _(REPL_FAIL, "L2 replication failures") \
91 _(NO_MEMBERS, "L2 replication complete") \
92 _(BVI_BAD_MAC, "BVI L3 mac mismatch") \
93 _(BVI_ETHERTYPE, "BVI packet with unhandled ethertype")
94 
95 typedef enum
96 {
97 #define _(sym,str) L2FLOOD_ERROR_##sym,
99 #undef _
102 
103 static char *l2flood_error_strings[] = {
104 #define _(sym,string) string,
106 #undef _
107 };
108 
109 typedef enum
110 {
115 
116 /*
117  * Perform flooding on one packet
118  *
119  * Due to the way BVI processing can modify the packet, the BVI interface
120  * (if present) must be processed last in the replication. The member vector
121  * is arranged so that the BVI interface is always the first element.
122  * Flooding walks the vector in reverse.
123  *
124  * BVI processing causes the packet to go to L3 processing. This strips the
125  * L2 header, which is fine because the replication infrastructure restores
126  * it. However L3 processing can trigger larger changes to the packet. For
127  * example, an ARP request could be turned into an ARP reply, an ICMP request
128  * could be turned into an ICMP reply. If BVI processing is not performed
129  * last, the modified packet would be replicated to the remaining members.
130  */
131 
134  vlib_node_runtime_t * node,
135  l2flood_main_t * msm,
136  u64 * counter_base,
137  vlib_buffer_t * b0,
138  u32 * sw_if_index0,
139  l2fib_entry_key_t * key0,
140  u32 * bucket0, l2fib_entry_result_t * result0, u32 * next0)
141 {
142  u16 bd_index0;
143  l2_bridge_domain_t *bd_config;
144  l2_flood_member_t *members;
145  i32 current_member; /* signed */
147  u8 in_shg = vnet_buffer (b0)->l2.shg;
148 
149  if (!replication_is_recycled (b0))
150  {
151 
152  /* Do flood "prep node" processing */
153 
154  /* Get config for the bridge domain interface */
155  bd_index0 = vnet_buffer (b0)->l2.bd_index;
156  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index0);
157  members = bd_config->members;
158 
159  /* Find first member that passes the reflection and SHG checks */
160  current_member = vec_len (members) - 1;
161  while ((current_member >= 0) &&
162  ((members[current_member].sw_if_index == *sw_if_index0) ||
163  (in_shg && members[current_member].shg == in_shg)))
164  {
165  current_member--;
166  }
167 
168  if (current_member < 0)
169  {
170  /* No members to flood to */
171  *next0 = L2FLOOD_NEXT_DROP;
172  b0->error = node->errors[L2FLOOD_ERROR_NO_MEMBERS];
173  return;
174  }
175 
176  if ((current_member > 0) &&
177  ((current_member > 1) ||
178  ((members[0].sw_if_index != *sw_if_index0) &&
179  (!in_shg || members[0].shg != in_shg))))
180  {
181  /* If more than one member then initiate replication */
182  ctx =
183  replication_prep (vm, b0, l2flood_node.index, 1 /* l2_packet */ );
184  ctx->feature_replicas = (uword) members;
185  ctx->feature_counter = current_member;
186  }
187 
188  }
189  else
190  {
191  vnet_buffer_opaque_t *vnet_buff_op;
192 
193  /* Do flood "recycle node" processing */
194 
196  {
197  (void) replication_recycle (vm, b0, 1 /* is_last */ );
198  *next0 = L2FLOOD_NEXT_DROP;
199  b0->error = node->errors[L2FLOOD_ERROR_REPL_FAIL];
200  return;
201  }
202 
203  ctx = replication_get_ctx (b0);
205 
206  members = (l2_flood_member_t *) (intptr_t) ctx->feature_replicas;
207  current_member = (i32) ctx->feature_counter - 1;
208 
209  /* Need to update input index from saved packet context */
210  vnet_buff_op = (vnet_buffer_opaque_t *) ctx->vnet_buffer;
211  *sw_if_index0 = vnet_buff_op->sw_if_index[VLIB_RX];
212 
213  /* Find next member that passes the reflection and SHG check */
214  while ((current_member >= 0) &&
215  ((members[current_member].sw_if_index == *sw_if_index0) ||
216  (in_shg && members[current_member].shg == in_shg)))
217  {
218  current_member--;
219  }
220 
221  if (current_member < 0)
222  {
223  /*
224  * No more members to flood to.
225  * Terminate replication and drop packet.
226  */
227 
228  replication_recycle (vm, b0, 1 /* is_last */ );
229 
230  *next0 = L2FLOOD_NEXT_DROP;
231  /* Ideally we woudn't bump a counter here, just silently complete */
232  b0->error = node->errors[L2FLOOD_ERROR_NO_MEMBERS];
233  return;
234  }
235 
236  /* Restore packet and context and continue replication */
237  ctx->feature_counter = current_member;
238  replication_recycle (vm, b0, ((current_member == 0) || /*is_last */
239  ((current_member == 1) &&
240  ((members[0].sw_if_index ==
241  *sw_if_index0) || (in_shg
242  && members[0].shg ==
243  in_shg)))));
244  }
245 
246  /* Forward packet to the current member */
247 
248  if (PREDICT_TRUE (members[current_member].flags == L2_FLOOD_MEMBER_NORMAL))
249  {
250  /* Do normal L2 forwarding */
251  vnet_buffer (b0)->sw_if_index[VLIB_TX] =
252  members[current_member].sw_if_index;
253  *next0 = L2FLOOD_NEXT_L2_OUTPUT;
254 
255  }
256  else
257  {
258  /* Do BVI processing */
259  u32 rc;
260  rc = l2_to_bvi (vm,
261  msm->vnet_main,
262  b0,
263  members[current_member].sw_if_index,
264  &msm->l3_next, next0);
265 
266  if (PREDICT_FALSE (rc))
267  {
268  if (rc == TO_BVI_ERR_BAD_MAC)
269  {
270  b0->error = node->errors[L2FLOOD_ERROR_BVI_BAD_MAC];
271  *next0 = L2FLOOD_NEXT_DROP;
272  }
273  else if (rc == TO_BVI_ERR_ETHERTYPE)
274  {
275  b0->error = node->errors[L2FLOOD_ERROR_BVI_ETHERTYPE];
276  *next0 = L2FLOOD_NEXT_DROP;
277  }
278  }
279  }
280 
281 }
282 
283 
284 static uword
286  vlib_node_runtime_t * node, vlib_frame_t * frame)
287 {
288  u32 n_left_from, *from, *to_next;
289  l2flood_next_t next_index;
291  vlib_node_t *n = vlib_get_node (vm, l2flood_node.index);
292  u32 node_counter_base_index = n->error_heap_index;
293  vlib_error_main_t *em = &vm->error_main;
294 
295  from = vlib_frame_vector_args (frame);
296  n_left_from = frame->n_vectors; /* number of packets to process */
297  next_index = node->cached_next_index;
298 
299  while (n_left_from > 0)
300  {
301  u32 n_left_to_next;
302 
303  /* get space to enqueue frame to graph node "next_index" */
304  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
305 
306  while (n_left_from >= 6 && n_left_to_next >= 2)
307  {
308  u32 bi0, bi1;
309  vlib_buffer_t *b0, *b1;
310  u32 next0, next1;
311  u32 sw_if_index0, sw_if_index1;
312  l2fib_entry_key_t key0, key1;
313  l2fib_entry_result_t result0, result1;
314  u32 bucket0, bucket1;
315 
316  /* Prefetch next iteration. */
317  {
318  vlib_buffer_t *p2, *p3, *p4, *p5;
319 
320  p2 = vlib_get_buffer (vm, from[2]);
321  p3 = vlib_get_buffer (vm, from[3]);
322  p4 = vlib_get_buffer (vm, from[4]);
323  p5 = vlib_get_buffer (vm, from[5]);
324 
325  /* Prefetch the buffer header for the N+2 loop iteration */
326  vlib_prefetch_buffer_header (p4, LOAD);
327  vlib_prefetch_buffer_header (p5, LOAD);
328 
329  /* Prefetch the replication context for the N+1 loop iteration */
330  /* This depends on the buffer header above */
333 
334  /* Prefetch the packet for the N+1 loop iteration */
337  }
338 
339  /* speculatively enqueue b0 and b1 to the current next frame */
340  /* bi is "buffer index", b is pointer to the buffer */
341  to_next[0] = bi0 = from[0];
342  to_next[1] = bi1 = from[1];
343  from += 2;
344  to_next += 2;
345  n_left_from -= 2;
346  n_left_to_next -= 2;
347 
348  b0 = vlib_get_buffer (vm, bi0);
349  b1 = vlib_get_buffer (vm, bi1);
350 
351  /* RX interface handles */
352  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
353  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
354 
355  /* process 2 pkts */
356  em->counters[node_counter_base_index + L2FLOOD_ERROR_L2FLOOD] += 2;
357 
358  l2flood_process (vm, node, msm,
359  &em->counters[node_counter_base_index], b0,
360  &sw_if_index0, &key0, &bucket0, &result0, &next0);
361 
362  l2flood_process (vm, node, msm,
363  &em->counters[node_counter_base_index], b1,
364  &sw_if_index1, &key1, &bucket1, &result1, &next1);
365 
366  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
367  {
369  {
370  l2flood_trace_t *t =
371  vlib_add_trace (vm, node, b0, sizeof (*t));
373  t->sw_if_index = sw_if_index0;
374  t->bd_index = vnet_buffer (b0)->l2.bd_index;
375  clib_memcpy (t->src, h0->src_address, 6);
376  clib_memcpy (t->dst, h0->dst_address, 6);
377  }
379  {
380  l2flood_trace_t *t =
381  vlib_add_trace (vm, node, b1, sizeof (*t));
383  t->sw_if_index = sw_if_index1;
384  t->bd_index = vnet_buffer (b1)->l2.bd_index;
385  clib_memcpy (t->src, h1->src_address, 6);
386  clib_memcpy (t->dst, h1->dst_address, 6);
387  }
388  }
389 
390  /* verify speculative enqueues, maybe switch current next frame */
391  /* if next0==next1==next_index then nothing special needs to be done */
392  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
393  to_next, n_left_to_next,
394  bi0, bi1, next0, next1);
395  }
396 
397  while (n_left_from > 0 && n_left_to_next > 0)
398  {
399  u32 bi0;
400  vlib_buffer_t *b0;
401  u32 next0;
402  u32 sw_if_index0;
403  l2fib_entry_key_t key0;
404  l2fib_entry_result_t result0;
405  u32 bucket0;
406 
407  /* speculatively enqueue b0 to the current next frame */
408  bi0 = from[0];
409  to_next[0] = bi0;
410  from += 1;
411  to_next += 1;
412  n_left_from -= 1;
413  n_left_to_next -= 1;
414 
415  b0 = vlib_get_buffer (vm, bi0);
416 
417  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
418 
419  /* process 1 pkt */
420  em->counters[node_counter_base_index + L2FLOOD_ERROR_L2FLOOD] += 1;
421 
422  l2flood_process (vm, node, msm,
423  &em->counters[node_counter_base_index], b0,
424  &sw_if_index0, &key0, &bucket0, &result0, &next0);
425 
426  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
427  (b0->flags & VLIB_BUFFER_IS_TRACED)))
428  {
429  l2flood_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
431  t->sw_if_index = sw_if_index0;
432  t->bd_index = vnet_buffer (b0)->l2.bd_index;
433  clib_memcpy (t->src, h0->src_address, 6);
434  clib_memcpy (t->dst, h0->dst_address, 6);
435  }
436 
437  /* verify speculative enqueue, maybe switch current next frame */
438  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
439  to_next, n_left_to_next,
440  bi0, next0);
441  }
442 
443  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
444  }
445 
446  return frame->n_vectors;
447 }
448 
449 
450 /* *INDENT-OFF* */
451 VLIB_REGISTER_NODE (l2flood_node,static) = {
452  .function = l2flood_node_fn,
453  .name = "l2-flood",
454  .vector_size = sizeof (u32),
455  .format_trace = format_l2flood_trace,
457 
458  .n_errors = ARRAY_LEN(l2flood_error_strings),
459  .error_strings = l2flood_error_strings,
460 
461  .n_next_nodes = L2FLOOD_N_NEXT,
462 
463  /* edit / add dispositions here */
464  .next_nodes = {
465  [L2FLOOD_NEXT_L2_OUTPUT] = "l2-output",
466  [L2FLOOD_NEXT_DROP] = "error-drop",
467  },
468 };
469 /* *INDENT-ON* */
470 
473 {
475 
476  mp->vlib_main = vm;
477  mp->vnet_main = vnet_get_main ();
478 
479  /* Initialize the feature next-node indexes */
481  l2flood_node.index,
485 
486  return 0;
487 }
488 
490 
491 
492 
493 /** Add the L3 input node for this ethertype to the next nodes structure. */
494 void
496  ethernet_type_t type, u32 node_index)
497 {
499  u32 next_index;
500 
501  next_index = vlib_node_add_next (vm, l2flood_node.index, node_index);
502 
503  next_by_ethertype_register (&mp->l3_next, type, next_index);
504 }
505 
506 
507 /**
508  * Set subinterface flood enable/disable.
509  * The CLI format is:
510  * set interface l2 flood <interface> [disable]
511  */
512 static clib_error_t *
514  unformat_input_t * input, vlib_cli_command_t * cmd)
515 {
516  vnet_main_t *vnm = vnet_get_main ();
517  clib_error_t *error = 0;
518  u32 sw_if_index;
519  u32 enable;
520 
521  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
522  {
523  error = clib_error_return (0, "unknown interface `%U'",
524  format_unformat_error, input);
525  goto done;
526  }
527 
528  enable = 1;
529  if (unformat (input, "disable"))
530  {
531  enable = 0;
532  }
533 
534  /* set the interface flag */
535  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_FLOOD, enable);
536 
537 done:
538  return error;
539 }
540 
541 /* *INDENT-OFF* */
542 VLIB_CLI_COMMAND (int_flood_cli, static) = {
543  .path = "set interface l2 flood",
544  .short_help = "set interface l2 flood <interface> [disable]",
545  .function = int_flood,
546 };
547 /* *INDENT-ON* */
548 
549 /*
550  * fd.io coding-style-patch-verification: ON
551  *
552  * Local Variables:
553  * eval: (c-set-style "gnu")
554  * End:
555  */
u32 feat_next_node_index[32]
Definition: l2_flood.c:50
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
vnet_main_t * vnet_main
Definition: l2_flood.c:57
l2flood_next_t
Definition: l2_flood.c:109
u32 error_heap_index
Definition: node.h:278
#define L2_FLOOD_MEMBER_NORMAL
Definition: l2_bd.h:41
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
#define TO_BVI_ERR_BAD_MAC
Definition: l2_bvi.h:28
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define PREDICT_TRUE(x)
Definition: clib.h:98
ethernet_type_t
Definition: packet.h:43
#define TO_BVI_ERR_ETHERTYPE
Definition: l2_bvi.h:29
static_always_inline u32 l2_to_bvi(vlib_main_t *vlib_main, vnet_main_t *vnet_main, vlib_buffer_t *b0, u32 bvi_sw_if_index, next_by_ethertype_t *l3_next, u32 *next0)
Send a packet from L2 processing to L3 via the BVI interface.
Definition: l2_bvi.h:38
u8 src_address[6]
Definition: packet.h:54
vlib_main_t * vlib_main
Definition: l2_flood.c:56
l2flood_main_t l2flood_main
Definition: l2_flood.c:84
static void replication_clear_recycled(vlib_buffer_t *b0)
Definition: replication.h:86
static uword l2flood_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l2_flood.c:285
void l2flood_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Add the L3 input node for this ethertype to the next nodes structure.
Definition: l2_flood.c:495
struct _vlib_node_registration vlib_node_registration_t
l2_flood_member_t * members
Definition: l2_bd.h:71
static char * l2flood_error_strings[]
Definition: l2_flood.c:103
unformat_function_t unformat_vnet_sw_interface
Definition: l2_fib.h:54
vlib_error_t * errors
Definition: node.h:418
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1061
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define static_always_inline
Definition: clib.h:85
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
u8 dst_address[6]
Definition: packet.h:53
static u8 * format_l2flood_trace(u8 *s, va_list *args)
Definition: l2_flood.c:71
int i32
Definition: types.h:81
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned long u64
Definition: types.h:89
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
static void replication_prefetch_ctx(vlib_buffer_t *b0)
Definition: replication.h:109
vlib_error_main_t error_main
Definition: main.h:124
#define PREDICT_FALSE(x)
Definition: clib.h:97
static vlib_node_registration_t l2flood_node
(constructor) VLIB_REGISTER_NODE (l2flood_node)
Definition: l2_flood.c:86
replication_context_t * replication_prep(vlib_main_t *vm, vlib_buffer_t *b0, u32 recycle_node_index, u32 l2_packet)
Definition: replication.c:29
#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
#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
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:118
u64 * counters
Definition: error.h:78
clib_error_t * next_by_ethertype_register(next_by_ethertype_t *l3_next, u32 ethertype, u32 next_index)
Definition: node.c:1107
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
u32 sw_if_index[VLIB_N_RX_TX]
Definition: buffer.h:99
#define clib_memcpy(a, b, c)
Definition: string.h:63
#define ARRAY_LEN(x)
Definition: clib.h:59
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:46
static replication_context_t * replication_get_ctx(vlib_buffer_t *b0)
Definition: replication.h:98
u16 cached_next_index
Definition: node.h:462
static u32 replication_is_recycled(vlib_buffer_t *b0)
Definition: replication.h:76
#define VLIB_BUFFER_REPL_FAIL
Definition: buffer.h:98
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
Definition: l2_fib.h:33
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
#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
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
l2input_main_t l2input_main
Definition: l2_input.c:76
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)
unsigned char u8
Definition: types.h:56
#define foreach_l2flood_error
Definition: l2_flood.c:88
l2flood_error_t
Definition: l2_flood.c:95
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:69
replication_context_t * replication_recycle(vlib_main_t *vm, vlib_buffer_t *b0, u32 is_last)
Definition: replication.c:93
static_always_inline void l2flood_process(vlib_main_t *vm, vlib_node_runtime_t *node, l2flood_main_t *msm, u64 *counter_base, vlib_buffer_t *b0, u32 *sw_if_index0, l2fib_entry_key_t *key0, u32 *bucket0, l2fib_entry_result_t *result0, u32 *next0)
Definition: l2_flood.c:133
#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
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 data[0]
Packet data.
Definition: buffer.h:151
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:58
u32 sw_if_index
Definition: l2_bd.h:46
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
next_by_ethertype_t l3_next
Definition: l2_flood.c:53
u32 flags
Definition: vhost-user.h:76
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static clib_error_t * int_flood(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set subinterface flood enable/disable.
Definition: l2_flood.c:513
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
Definition: defs.h:46
clib_error_t * l2flood_init(vlib_main_t *vm)
Definition: l2_flood.c:472