FD.io VPP  v16.09
Vector Packet Processing
l2_input.c
Go to the documentation of this file.
1 /*
2  * l2_input.c : layer 2 input 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 <vnet/ethernet/packet.h>
23 #include <vnet/ip/ip_packet.h>
24 #include <vnet/ip/ip4_packet.h>
25 #include <vnet/ip/ip6_packet.h>
26 #include <vlib/cli.h>
27 #include <vnet/l2/l2_input.h>
28 #include <vnet/l2/l2_output.h>
29 #include <vnet/l2/feat_bitmap.h>
30 #include <vnet/l2/l2_bvi.h>
31 #include <vnet/l2/l2_fib.h>
32 
33 #include <vppinfra/error.h>
34 #include <vppinfra/hash.h>
35 #include <vppinfra/cache.h>
36 
37 
38 /* Feature graph node names */
39 static char *l2input_feat_names[] = {
40 #define _(sym,name) name,
42 #undef _
43 };
44 
45 char **
47 {
48  return l2input_feat_names;
49 }
50 
51 
52 typedef struct
53 {
54  /* per-pkt trace data */
55  u8 src[6];
56  u8 dst[6];
60 
61 /* packet trace format function */
62 static u8 *
63 format_l2input_trace (u8 * s, va_list * args)
64 {
65  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
66  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
67  l2input_trace_t *t = va_arg (*args, l2input_trace_t *);
68 
69  s = format (s, "l2-input: sw_if_index %d dst %U src %U",
70  t->sw_if_index,
73  return s;
74 }
75 
77 
78 #define foreach_l2input_error \
79 _(L2INPUT, "L2 input packets") \
80 _(DROP, "L2 input drops")
81 
82 typedef enum
83 {
84 #define _(sym,str) L2INPUT_ERROR_##sym,
86 #undef _
89 
90 static char *l2input_error_strings[] = {
91 #define _(sym,string) string,
93 #undef _
94 };
95 
96 typedef enum
97 { /* */
103 
104 
107  vlib_node_runtime_t * node,
108  u32 cpu_index,
109  l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0)
110 {
111  /*
112  * Load L2 input feature struct
113  * Load bridge domain struct
114  * Parse ethernet header to determine unicast/mcast/broadcast
115  * take L2 input stat
116  * classify packet as IP/UDP/TCP, control, other
117  * mask feature bitmap
118  * go to first node in bitmap
119  * Later: optimize VTM
120  *
121  * For L2XC,
122  * set tx sw-if-handle
123  */
124 
125  u8 mcast_dmac;
126  __attribute__ ((unused)) u8 l2bcast;
127  __attribute__ ((unused)) u8 l2mcast;
128  __attribute__ ((unused)) u8 l2_stat_kind;
129  u16 ethertype;
130  u8 protocol;
131  l2_input_config_t *config;
132  l2_bridge_domain_t *bd_config;
133  u16 bd_index0;
134  u32 feature_bitmap;
135  u32 feat_mask;
136  ethernet_header_t *h0;
137  u8 *l3h0;
138  u32 sw_if_index0;
139 
140 #define get_u32(addr) ( *((u32 *)(addr)) )
141 #define get_u16(addr) ( *((u16 *)(addr)) )
142 #define STATS_IF_LAYER2_UCAST_INPUT_CNT 0
143 #define STATS_IF_LAYER2_MCAST_INPUT_CNT 1
144 #define STATS_IF_LAYER2_BCAST_INPUT_CNT 2
145 
146  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
147 
148  h0 = vlib_buffer_get_current (b0);
149  l3h0 = (u8 *) h0 + vnet_buffer (b0)->l2.l2_len;
150 
151  /*
152  * Determine L3 packet type. Only need to check the common types.
153  * Used to filter out features that don't apply to common packets.
154  */
155  ethertype = clib_net_to_host_u16 (get_u16 (l3h0 - 2));
156  if (ethertype == ETHERNET_TYPE_IP4)
157  {
158  protocol = ((ip4_header_t *) l3h0)->protocol;
159  if ((protocol == IP_PROTOCOL_UDP) || (protocol == IP_PROTOCOL_TCP))
160  {
161  feat_mask = IP_UDP_TCP_FEAT_MASK;
162  }
163  else
164  {
165  feat_mask = IP4_FEAT_MASK;
166  }
167  }
168  else if (ethertype == ETHERNET_TYPE_IP6)
169  {
170  protocol = ((ip6_header_t *) l3h0)->protocol;
171  /* Don't bother checking for extension headers for now */
172  if ((protocol == IP_PROTOCOL_UDP) || (protocol == IP_PROTOCOL_TCP))
173  {
174  feat_mask = IP_UDP_TCP_FEAT_MASK;
175  }
176  else
177  {
178  feat_mask = IP6_FEAT_MASK;
179  }
180  }
181  else if (ethertype == ETHERNET_TYPE_MPLS_UNICAST)
182  {
183  feat_mask = IP6_FEAT_MASK;
184  }
185  else
186  {
187  /* allow all features */
188  feat_mask = ~0;
189  }
190 
191  /* determine layer2 kind for stat and mask */
192  mcast_dmac = ethernet_address_cast (h0->dst_address);
193  l2bcast = 0;
194  l2mcast = 0;
195  l2_stat_kind = STATS_IF_LAYER2_UCAST_INPUT_CNT;
196  if (PREDICT_FALSE (mcast_dmac))
197  {
198  u32 *dsthi = (u32 *) & h0->dst_address[0];
199  u32 *dstlo = (u32 *) & h0->dst_address[2];
200 
201  /* Disable bridge forwarding (flooding will execute instead if not xconnect) */
202  feat_mask &= ~(L2INPUT_FEAT_FWD | L2INPUT_FEAT_UU_FLOOD);
203  if (ethertype != ETHERNET_TYPE_ARP) /* Disable ARP-term for non-ARP packet */
204  feat_mask &= ~(L2INPUT_FEAT_ARP_TERM);
205 
206  /* dest mac is multicast or broadcast */
207  if ((*dstlo == 0xFFFFFFFF) && (*dsthi == 0xFFFFFFFF))
208  {
209  /* dest mac == FF:FF:FF:FF:FF:FF */
210  l2_stat_kind = STATS_IF_LAYER2_BCAST_INPUT_CNT;
211  l2bcast = 1;
212  }
213  else
214  {
215  l2_stat_kind = STATS_IF_LAYER2_MCAST_INPUT_CNT;
216  l2mcast = 1;
217  }
218  }
219  /* TODO: take l2 stat */
220 
221  /* Get config for the input interface */
222  config = vec_elt_at_index (msm->configs, sw_if_index0);
223 
224  /* Save split horizon group */
225  vnet_buffer (b0)->l2.shg = config->shg;
226 
227  if (config->xconnect)
228  {
229  /* Set the output interface */
230  vnet_buffer (b0)->sw_if_index[VLIB_TX] = config->output_sw_if_index;
231 
232  }
233  else
234  {
235 
236  /*
237  * Check for from-BVI processing, TX is non-~0 if from BVI loopback
238  * Set SHG for BVI packets to 0 so it is not dropped for VXLAN tunnels
239  */
240  if (PREDICT_FALSE (vnet_buffer (b0)->sw_if_index[VLIB_TX] != ~0))
241  {
242  vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
243  vnet_buffer (b0)->l2.shg = 0;
244  }
245 
246  /* Do bridge-domain processing */
247  bd_index0 = config->bd_index;
248  /* save BD ID for next feature graph nodes */
249  vnet_buffer (b0)->l2.bd_index = bd_index0;
250 
251  /* Get config for the bridge domain interface */
252  bd_config = vec_elt_at_index (msm->bd_configs, bd_index0);
253 
254  /*
255  * Process bridge domain feature enables.
256  * To perform learning/flooding/forwarding, the corresponding bit
257  * must be enabled in both the input interface config and in the
258  * bridge domain config. In the bd_bitmap, bits for features other
259  * than learning/flooding/forwarding should always be set.
260  */
261  feat_mask = feat_mask & bd_config->feature_bitmap;
262  }
263 
264  /* mask out features from bitmap using packet type and bd config */
265  feature_bitmap = config->feature_bitmap & feat_mask;
266 
267  /* save for next feature graph nodes */
268  vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap;
269 
270  /* Determine the next node */
272  feature_bitmap);
273 }
274 
275 
276 static uword
278  vlib_node_runtime_t * node, vlib_frame_t * frame)
279 {
280  u32 n_left_from, *from, *to_next;
281  l2input_next_t next_index;
283  vlib_node_t *n = vlib_get_node (vm, l2input_node.index);
284  u32 node_counter_base_index = n->error_heap_index;
285  vlib_error_main_t *em = &vm->error_main;
286  u32 cpu_index = os_get_cpu_number ();
287 
288  from = vlib_frame_vector_args (frame);
289  n_left_from = frame->n_vectors; /* number of packets to process */
290  next_index = node->cached_next_index;
291 
292  while (n_left_from > 0)
293  {
294  u32 n_left_to_next;
295 
296  /* get space to enqueue frame to graph node "next_index" */
297  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
298 
299  while (n_left_from >= 6 && n_left_to_next >= 2)
300  {
301  u32 bi0, bi1;
302  vlib_buffer_t *b0, *b1;
303  u32 next0, next1;
304  u32 sw_if_index0, sw_if_index1;
305 
306  /* Prefetch next iteration. */
307  {
308  vlib_buffer_t *p2, *p3, *p4, *p5;
309  u32 sw_if_index2, sw_if_index3;
310 
311  p2 = vlib_get_buffer (vm, from[2]);
312  p3 = vlib_get_buffer (vm, from[3]);
313  p4 = vlib_get_buffer (vm, from[4]);
314  p5 = vlib_get_buffer (vm, from[5]);
315 
316  /* Prefetch the buffer header and packet for the N+2 loop iteration */
317  vlib_prefetch_buffer_header (p4, LOAD);
318  vlib_prefetch_buffer_header (p5, LOAD);
319 
322 
323  /*
324  * Prefetch the input config for the N+1 loop iteration
325  * This depends on the buffer header above
326  */
327  sw_if_index2 = vnet_buffer (p2)->sw_if_index[VLIB_RX];
328  sw_if_index3 = vnet_buffer (p3)->sw_if_index[VLIB_RX];
329  CLIB_PREFETCH (&msm->configs[sw_if_index2], CLIB_CACHE_LINE_BYTES,
330  LOAD);
331  CLIB_PREFETCH (&msm->configs[sw_if_index3], CLIB_CACHE_LINE_BYTES,
332  LOAD);
333 
334  /*
335  * Don't bother prefetching the bridge-domain config (which
336  * depends on the input config above). Only a small number of
337  * bridge domains are expected. Plus the structure is small
338  * and several fit in a cache line.
339  */
340  }
341 
342  /* speculatively enqueue b0 and b1 to the current next frame */
343  /* bi is "buffer index", b is pointer to the buffer */
344  to_next[0] = bi0 = from[0];
345  to_next[1] = bi1 = from[1];
346  from += 2;
347  to_next += 2;
348  n_left_from -= 2;
349  n_left_to_next -= 2;
350 
351  b0 = vlib_get_buffer (vm, bi0);
352  b1 = vlib_get_buffer (vm, bi1);
353 
354  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
355  {
356  /* RX interface handles */
357  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
358  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
359 
360  if (b0->flags & VLIB_BUFFER_IS_TRACED)
361  {
363  l2input_trace_t *t =
364  vlib_add_trace (vm, node, b0, sizeof (*t));
365  t->sw_if_index = sw_if_index0;
366  clib_memcpy (t->src, h0->src_address, 6);
367  clib_memcpy (t->dst, h0->dst_address, 6);
368  }
369  if (b1->flags & VLIB_BUFFER_IS_TRACED)
370  {
372  l2input_trace_t *t =
373  vlib_add_trace (vm, node, b1, sizeof (*t));
374  t->sw_if_index = sw_if_index1;
375  clib_memcpy (t->src, h1->src_address, 6);
376  clib_memcpy (t->dst, h1->dst_address, 6);
377  }
378  }
379 
380  em->counters[node_counter_base_index + L2INPUT_ERROR_L2INPUT] += 2;
381 
382  classify_and_dispatch (vm, node, cpu_index, msm, b0, &next0);
383 
384  classify_and_dispatch (vm, node, cpu_index, msm, b1, &next1);
385 
386  /* verify speculative enqueues, maybe switch current next frame */
387  /* if next0==next1==next_index then nothing special needs to be done */
388  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
389  to_next, n_left_to_next,
390  bi0, bi1, next0, next1);
391  }
392 
393  while (n_left_from > 0 && n_left_to_next > 0)
394  {
395  u32 bi0;
396  vlib_buffer_t *b0;
397  u32 next0;
398  u32 sw_if_index0;
399 
400  /* speculatively enqueue b0 to the current next frame */
401  bi0 = from[0];
402  to_next[0] = bi0;
403  from += 1;
404  to_next += 1;
405  n_left_from -= 1;
406  n_left_to_next -= 1;
407 
408  b0 = vlib_get_buffer (vm, bi0);
409 
411  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
412  {
414  l2input_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
415  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
416  t->sw_if_index = sw_if_index0;
417  clib_memcpy (t->src, h0->src_address, 6);
418  clib_memcpy (t->dst, h0->dst_address, 6);
419  }
420 
421  em->counters[node_counter_base_index + L2INPUT_ERROR_L2INPUT] += 1;
422 
423  classify_and_dispatch (vm, node, cpu_index, msm, b0, &next0);
424 
425  /* verify speculative enqueue, maybe switch current next frame */
426  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
427  to_next, n_left_to_next,
428  bi0, next0);
429  }
430 
431  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
432  }
433 
434  return frame->n_vectors;
435 }
436 
437 
438 /* *INDENT-OFF* */
440  .function = l2input_node_fn,
441  .name = "l2-input",
442  .vector_size = sizeof (u32),
443  .format_trace = format_l2input_trace,
444  .format_buffer = format_ethernet_header_with_length,
446 
447  .n_errors = ARRAY_LEN(l2input_error_strings),
448  .error_strings = l2input_error_strings,
449 
450  .n_next_nodes = L2INPUT_N_NEXT,
451 
452  /* edit / add dispositions here */
453  .next_nodes = {
454  [L2INPUT_NEXT_LEARN] = "l2-learn",
455  [L2INPUT_NEXT_FWD] = "l2-fwd",
456  [L2INPUT_NEXT_DROP] = "error-drop",
457  },
458 };
459 /* *INDENT-ON* */
460 
463 {
465 
466  mp->vlib_main = vm;
467  mp->vnet_main = vnet_get_main ();
468 
469  /* Get packets RX'd from L2 interfaces */
471 
472  /* Create the config vector */
473  vec_validate (mp->configs, 100);
474  /* create 100 sw interface entries and zero them */
475 
476  /* Initialize the feature next-node indexes */
478  l2input_node.index,
482 
483  return 0;
484 }
485 
487 
488 
489 /** Get a pointer to the config for the given interface. */
492 {
494 
495  vec_validate (mp->configs, sw_if_index);
496  return vec_elt_at_index (mp->configs, sw_if_index);
497 }
498 
499 /** Enable (or disable) the feature in the bitmap for the given interface. */
500 u32
501 l2input_intf_bitmap_enable (u32 sw_if_index, u32 feature_bitmap, u32 enable)
502 {
504  l2_input_config_t *config;
505 
506  vec_validate (mp->configs, sw_if_index);
507  config = vec_elt_at_index (mp->configs, sw_if_index);
508 
509  if (enable)
510  {
511  config->feature_bitmap |= feature_bitmap;
512  }
513  else
514  {
515  config->feature_bitmap &= ~feature_bitmap;
516  }
517 
518  return config->feature_bitmap;
519 }
520 
521 u32
522 l2input_set_bridge_features (u32 bd_index, u32 feat_mask, u32 feat_value)
523 {
524  l2_bridge_domain_t *bd_config;
525  vec_validate (l2input_main.bd_configs, bd_index);
526  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
527  bd_validate (bd_config);
528  bd_config->feature_bitmap =
529  (bd_config->feature_bitmap & ~feat_mask) | feat_value;
530  return bd_config->feature_bitmap;
531 }
532 
533 /**
534  * Set the subinterface to run in l2 or l3 mode.
535  * For L3 mode, just the sw_if_index is specified.
536  * For bridged mode, the bd id and bvi flag are also specified.
537  * For xconnect mode, the peer sw_if_index is also specified.
538  * Return 0 if ok, or non-0 if there was an error.
539  */
540 
541 u32
542 set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, /* for bridged interface */
543  u32 bvi, /* the bridged interface is the BVI */
544  u32 shg, /* the bridged interface's split horizon group */
545  u32 xc_sw_if_index) /* peer interface for xconnect */
546 {
549  vnet_main_t *vnm = vnet_get_main ();
551  l2_output_config_t *out_config;
552  l2_input_config_t *config;
553  l2_bridge_domain_t *bd_config;
554  l2_flood_member_t member;
555  u64 mac;
556  i32 l2_if_adjust = 0;
557  u32 slot;
558 
559  hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);
560 
561  vec_validate (mp->configs, sw_if_index);
562  config = vec_elt_at_index (mp->configs, sw_if_index);
563 
564  if (config->bridge)
565  {
566  /* Interface is already in bridge mode. Undo the existing config. */
567  bd_config = vec_elt_at_index (mp->bd_configs, config->bd_index);
568 
569  /* remove interface from flood vector */
570  bd_remove_member (bd_config, sw_if_index);
571 
572  /* undo any BVI-related config */
573  if (bd_config->bvi_sw_if_index == sw_if_index)
574  {
575  bd_config->bvi_sw_if_index = ~0;
576  config->bvi = 0;
577 
578  /* delete the l2fib entry for the bvi interface */
579  mac = *((u64 *) hi->hw_address);
580  l2fib_del_entry (mac, config->bd_index);
581 
582  /* Make loop output node send packet back to ethernet-input node */
583  slot =
585  "ethernet-input",
588  }
589  l2_if_adjust--;
590  }
591  else if (config->xconnect)
592  {
593  l2_if_adjust--;
594  }
595 
596  /* Initialize the l2-input configuration for the interface */
597  if (mode == MODE_L3)
598  {
599  config->xconnect = 0;
600  config->bridge = 0;
601  config->shg = 0;
602  config->bd_index = 0;
603  config->feature_bitmap = L2INPUT_FEAT_DROP;
604  /*
605  * Directs the l2 output path to work out the interface
606  * output next-arc itself. Needed when recycling a sw_if_index.
607  */
609  sw_if_index, ~0);
610  l2om->next_nodes.output_node_index_vec[sw_if_index] = ~0;
611 
612  }
613  else if (mode == MODE_L2_CLASSIFY)
614  {
615  config->xconnect = 1;
616  config->bridge = 0;
617  config->output_sw_if_index = xc_sw_if_index;
618 
619  /* Make sure last-chance drop is configured */
620  config->feature_bitmap |= L2INPUT_FEAT_DROP | L2INPUT_FEAT_CLASSIFY;
621 
622  /* Make sure bridging features are disabled */
623  config->feature_bitmap &=
624  ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD);
625  shg = 0; /* not used in xconnect */
626 
627  /* Insure all packets go to ethernet-input */
628  ethernet_set_rx_redirect (vnet_main, hi, 1);
629  }
630  else
631  {
632 
633  if (mode == MODE_L2_BRIDGE)
634  {
635  /*
636  * Remove a check that the interface must be an Ethernet.
637  * Specifically so we can bridge to L3 tunnel interfaces.
638  * Here's the check:
639  * if (hi->hw_class_index != ethernet_hw_interface_class.index)
640  *
641  */
642  if (!hi)
643  return MODE_ERROR_ETH; /* non-ethernet */
644 
645  config->xconnect = 0;
646  config->bridge = 1;
647  config->bd_index = bd_index;
648 
649  /*
650  * Enable forwarding, flooding, learning and ARP termination by default
651  * (note that ARP term is disabled on BD feature bitmap by default)
652  */
653  config->feature_bitmap |= L2INPUT_FEAT_FWD | L2INPUT_FEAT_UU_FLOOD |
654  L2INPUT_FEAT_FLOOD | L2INPUT_FEAT_LEARN | L2INPUT_FEAT_ARP_TERM;
655 
656  /* Make sure last-chance drop is configured */
657  config->feature_bitmap |= L2INPUT_FEAT_DROP;
658 
659  /* Make sure xconnect is disabled */
660  config->feature_bitmap &= ~L2INPUT_FEAT_XCONNECT;
661 
662  /* Set up bridge domain */
663  vec_validate (mp->bd_configs, bd_index);
664  bd_config = vec_elt_at_index (mp->bd_configs, bd_index);
665  bd_validate (bd_config);
666 
667  /* TODO: think: add l2fib entry even for non-bvi interface? */
668 
669  /* Do BVI interface initializations */
670  if (bvi)
671  {
672  /* ensure BD has no bvi interface (or replace that one with this??) */
673  if (bd_config->bvi_sw_if_index != ~0)
674  {
675  return MODE_ERROR_BVI_DEF; /* bd already has a bvi interface */
676  }
677  bd_config->bvi_sw_if_index = sw_if_index;
678  config->bvi = 1;
679 
680  /* create the l2fib entry for the bvi interface */
681  mac = *((u64 *) hi->hw_address);
682  l2fib_add_entry (mac, bd_index, sw_if_index, 1, 0, 1); /* static + bvi */
683 
684  /* Disable learning by default. no use since l2fib entry is static. */
685  config->feature_bitmap &= ~L2INPUT_FEAT_LEARN;
686 
687  /* Make loop output node send packet to l2-input node */
688  slot =
690  "l2-input",
693  }
694 
695  /* Add interface to bridge-domain flood vector */
696  member.sw_if_index = sw_if_index;
698  member.shg = shg;
699  bd_add_member (bd_config, &member);
700 
701  }
702  else
703  {
704  config->xconnect = 1;
705  config->bridge = 0;
706  config->output_sw_if_index = xc_sw_if_index;
707 
708  /* Make sure last-chance drop is configured */
709  config->feature_bitmap |= L2INPUT_FEAT_DROP;
710 
711  /* Make sure bridging features are disabled */
712  config->feature_bitmap &=
713  ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD);
714 
715  config->feature_bitmap |= L2INPUT_FEAT_XCONNECT;
716  shg = 0; /* not used in xconnect */
717  }
718 
719  /* set up split-horizon group */
720  config->shg = shg;
721  out_config = l2output_intf_config (sw_if_index);
722  out_config->shg = shg;
723 
724  /*
725  * Test: remove this when non-IP features can be configured.
726  * Enable a non-IP feature to test IP feature masking
727  * config->feature_bitmap |= L2INPUT_FEAT_CTRL_PKT;
728  */
729 
730  l2_if_adjust++;
731  }
732 
733  /* Adjust count of L2 interfaces */
734  hi->l2_if_count += l2_if_adjust;
735 
737  {
738  if ((hi->l2_if_count == 1) && (l2_if_adjust == 1))
739  {
740  /* Just added first L2 interface on this port */
741 
742  /* Set promiscuous mode on the l2 interface */
743  ethernet_set_flags (vnet_main, hi->hw_if_index,
745 
746  /* ensure all packets go to ethernet-input */
747  ethernet_set_rx_redirect (vnet_main, hi, 1);
748 
749  }
750  else if ((hi->l2_if_count == 0) && (l2_if_adjust == -1))
751  {
752  /* Just removed only L2 subinterface on this port */
753 
754  /* Disable promiscuous mode on the l2 interface */
755  ethernet_set_flags (vnet_main, hi->hw_if_index, 0);
756 
757  /* Allow ip packets to go directly to ip4-input etc */
758  ethernet_set_rx_redirect (vnet_main, hi, 0);
759  }
760  }
761 
762  /* Set up the L2/L3 flag in the interface parsing tables */
763  ethernet_sw_interface_set_l2_mode (vnm, sw_if_index, (mode != MODE_L3));
764 
765  return 0;
766 }
767 
768 /**
769  * Set subinterface in bridging mode with a bridge-domain ID.
770  * The CLI format is:
771  * set interface l2 bridge <interface> <bd> [bvi] [split-horizon-group]
772  */
773 static clib_error_t *
775  unformat_input_t * input, vlib_cli_command_t * cmd)
776 {
777  vnet_main_t *vnm = vnet_get_main ();
778  clib_error_t *error = 0;
779  u32 bd_index, bd_id;
780  u32 sw_if_index;
781  u32 bvi;
782  u32 rc;
783  u32 shg;
784 
785  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
786  {
787  error = clib_error_return (0, "unknown interface `%U'",
788  format_unformat_error, input);
789  goto done;
790  }
791 
792  if (!unformat (input, "%d", &bd_id))
793  {
794  error = clib_error_return (0, "expected bridge domain ID `%U'",
795  format_unformat_error, input);
796  goto done;
797  }
798 
799  bd_index = bd_find_or_add_bd_index (&bd_main, bd_id);
800 
801  /* optional bvi */
802  bvi = unformat (input, "bvi");
803 
804  /* optional split horizon group */
805  shg = 0;
806  (void) unformat (input, "%d", &shg);
807 
808  /* set the interface mode */
809  if ((rc =
810  set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE, sw_if_index, bd_index, bvi,
811  shg, 0)))
812  {
813  if (rc == MODE_ERROR_ETH)
814  {
815  error = clib_error_return (0, "bridged interface must be ethernet",
816  format_unformat_error, input);
817  }
818  else if (rc == MODE_ERROR_BVI_DEF)
819  {
820  error =
821  clib_error_return (0, "bridge-domain already has a bvi interface",
822  format_unformat_error, input);
823  }
824  else
825  {
826  error = clib_error_return (0, "invalid configuration for interface",
827  format_unformat_error, input);
828  }
829  goto done;
830  }
831 
832 done:
833  return error;
834 }
835 
836 /* *INDENT-OFF* */
837 /*?
838  *
839  * @cliexpar
840  * @cliexstart{set interface l2 bridge}
841  * Interfaces in a bridge-domain forward packets to other interfaces in the same bridge-domain based on destination mac address.
842  * To add an interface to bridge-domain 5 use:
843  * vpp# set interface l2 bridge GigabitEthernet2/0/0 5
844  * A split-horizon group can also be specified. This defaults to 0 if not specified.
845  * vpp# set interface l2 bridge GigabitEthernet2/0/0 5 1
846  * @cliexend
847  ?*/
848 VLIB_CLI_COMMAND (int_l2_bridge_cli, static) = {
849  .path = "set interface l2 bridge",
850  .short_help = "set interface to L2 bridging mode in <bridge-domain ID> [bvi] [shg]",
851  .function = int_l2_bridge,
852 };
853 /* *INDENT-ON* */
854 
855 /**
856  * Set subinterface in xconnect mode with another interface.
857  * The CLI format is:
858  * set interface l2 xconnect <interface> <peer interface>
859  */
860 static clib_error_t *
862  unformat_input_t * input, vlib_cli_command_t * cmd)
863 {
864  vnet_main_t *vnm = vnet_get_main ();
865  clib_error_t *error = 0;
866  u32 sw_if_index;
867  u32 xc_sw_if_index;
868 
869  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
870  {
871  error = clib_error_return (0, "unknown interface `%U'",
872  format_unformat_error, input);
873  goto done;
874  }
875 
876  if (!unformat_user
877  (input, unformat_vnet_sw_interface, vnm, &xc_sw_if_index))
878  {
879  error = clib_error_return (0, "unknown peer interface `%U'",
880  format_unformat_error, input);
881  goto done;
882  }
883 
884  /* set the interface mode */
885  if (set_int_l2_mode
886  (vm, vnm, MODE_L2_XC, sw_if_index, 0, 0, 0, xc_sw_if_index))
887  {
888  error = clib_error_return (0, "invalid configuration for interface",
889  format_unformat_error, input);
890  goto done;
891  }
892 
893 done:
894  return error;
895 }
896 
897 /* *INDENT-OFF* */
898 /*?
899  * L2 Cross-connect two interfaces
900  * @cliexpar
901  * @cliexstart{set interface l2 xconnect}
902  * To cross-connect two interfaces, put both into L2 cross-connect mode. All packets received on one interface will be transmitted to the other.
903  * vpp# set interface l2 xconnect GigabitEthernet2/0/0 GigabitEthernet2/0/1
904  * vpp# set interface l2 xconnect GigabitEthernet2/0/1 GigabitEthernet2/0/0
905  * @cliexend
906  ?*/
907 VLIB_CLI_COMMAND (int_l2_xc_cli, static) = {
908  .path = "set interface l2 xconnect",
909  .short_help = "set interface l2 xconnect <interface> <peer interface>",
910  .function = int_l2_xc,
911 };
912 /* *INDENT-ON* */
913 
914 /**
915  * Set subinterface in L3 mode.
916  * The CLI format is:
917  * set interface l3 <interface>
918  */
919 static clib_error_t *
921 {
922  vnet_main_t *vnm = vnet_get_main ();
923  clib_error_t *error = 0;
924  u32 sw_if_index;
925 
926  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
927  {
928  error = clib_error_return (0, "unknown interface `%U'",
929  format_unformat_error, input);
930  goto done;
931  }
932 
933  /* set the interface mode */
934  if (set_int_l2_mode (vm, vnm, MODE_L3, sw_if_index, 0, 0, 0, 0))
935  {
936  error = clib_error_return (0, "invalid configuration for interface",
937  format_unformat_error, input);
938  goto done;
939  }
940 
941 done:
942  return error;
943 }
944 
945 /* *INDENT-OFF* */
946 /*?
947  *
948  * @cliexpar
949  * @cliexstart{cmd}
950  * Interfaces can be set in either L3 (routed) mode or L2 (xconnect or bridged) mode.
951  * Interfaces are in L3 mode by default. To return an interface to L3 mode, use:
952  * vpp# set interface l3 GigabitEthernet2/0/0
953  * @cliexend
954  ?*/
955  VLIB_CLI_COMMAND (int_l3_cli, static) = {
956  .path = "set interface l3",
957  .short_help = "set interface to L3 mode",
958  .function = int_l3,
959 };
960 /* *INDENT-ON* */
961 
962 /**
963  * Show interface mode.
964  * The CLI format is:
965  * show mode [<if-name1> <if-name2> ...]
966  */
967 static clib_error_t *
969  unformat_input_t * input, vlib_cli_command_t * cmd)
970 {
971  vnet_main_t *vnm = vnet_get_main ();
972  clib_error_t *error = 0;
973  char *mode;
974  u8 *args;
976  vnet_sw_interface_t *si, *sis = 0;
978  l2_input_config_t *config;
979 
981  {
982  u32 sw_if_index;
983 
984  /* See if user wants to show specific interface */
985  if (unformat
986  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
987  {
988  si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
989  vec_add1 (sis, si[0]);
990  }
991  else
992  {
993  error = clib_error_return (0, "unknown input `%U'",
994  format_unformat_error, input);
995  goto done;
996  }
997 
998  }
999 
1000  if (vec_len (sis) == 0) /* Get all interfaces */
1001  {
1002  /* Gather interfaces. */
1004  _vec_len (sis) = 0;
1005  /* *INDENT-OFF* */
1006  pool_foreach (si, im->sw_interfaces, ({ vec_add1 (sis, si[0]); }));
1007  /* *INDENT-ON* */
1008  }
1009 
1010  vec_foreach (si, sis)
1011  {
1012  vec_validate (mp->configs, si->sw_if_index);
1013  config = vec_elt_at_index (mp->configs, si->sw_if_index);
1014  if (config->bridge)
1015  {
1016  u32 bd_id;
1017  mode = "l2 bridge";
1018  bd_id = l2input_main.bd_configs[config->bd_index].bd_id;
1019 
1020  args = format (0, "bd_id %d%s%d", bd_id,
1021  config->bvi ? " bvi shg " : " shg ", config->shg);
1022  }
1023  else if (config->xconnect)
1024  {
1025  mode = "l2 xconnect";
1026  args = format (0, "%U",
1028  vnm, config->output_sw_if_index);
1029  }
1030  else
1031  {
1032  mode = "l3";
1033  args = format (0, " ");
1034  }
1035  vlib_cli_output (vm, "%s %U %v\n",
1036  mode,
1038  vnm, si->sw_if_index, args);
1039  vec_free (args);
1040  }
1041 
1042 done:
1043  vec_free (sis);
1044 
1045  return error;
1046 }
1047 
1048 /* *INDENT-OFF* */
1049 VLIB_CLI_COMMAND (show_l2_mode, static) = {
1050  .path = "show mode",
1051  .short_help = "show mode [<if-name1> <if-name2> ...]",
1052  .function = show_int_mode,
1053 };
1054 /* *INDENT-ON* */
1055 
1056 #define foreach_l2_init_function \
1057 _(feat_bitmap_drop_init) \
1058 _(l2fib_init) \
1059 _(l2_classify_init) \
1060 _(l2bd_init) \
1061 _(l2fwd_init) \
1062 _(l2_inacl_init) \
1063 _(l2input_init) \
1064 _(l2_vtr_init) \
1065 _(l2_invtr_init) \
1066 _(l2_efp_filter_init) \
1067 _(l2learn_init) \
1068 _(l2flood_init) \
1069 _(l2_outacl_init) \
1070 _(l2output_init) \
1071 _(l2_patch_init) \
1072 _(l2_xcrw_init)
1073 
1074 clib_error_t *
1076 {
1077  clib_error_t *error;
1078 
1079 #define _(a) do { \
1080  if ((error = vlib_call_init_function (vm, a))) return error; } \
1081 while (0);
1083 #undef _
1084  return 0;
1085 }
1086 
1088 
1089 /*
1090  * fd.io coding-style-patch-verification: ON
1091  *
1092  * Local Variables:
1093  * eval: (c-set-style "gnu")
1094  * End:
1095  */
void bd_validate(l2_bridge_domain_t *bd_config)
Init bridge domain if not done already.
Definition: l2_bd.c:42
#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
static char * l2input_feat_names[]
Definition: l2_input.c:39
vmrglw vmrglh hi
static clib_error_t * int_l3(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set subinterface in L3 mode.
Definition: l2_input.c:920
u32 error_heap_index
Definition: node.h:278
l2_input_config_t * configs
Definition: l2_input.h:66
#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
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 bvi_sw_if_index
Definition: l2_bd.h:65
vnet_interface_main_t interface_main
Definition: vnet.h:64
u32 l2input_set_bridge_features(u32 bd_index, u32 feat_mask, u32 feat_value)
Definition: l2_input.c:522
l2_input_config_t * l2input_intf_config(u32 sw_if_index)
Get a pointer to the config for the given interface.
Definition: l2_input.c:491
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u8 src_address[6]
Definition: packet.h:54
u32 l2fib_del_entry(u64 mac, u32 bd_index)
Delete an entry from the l2fib.
Definition: l2_fib.c:490
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
vlib_node_registration_t l2input_node
(constructor) VLIB_REGISTER_NODE (l2input_node)
Definition: l2_input.c:439
#define STATS_IF_LAYER2_BCAST_INPUT_CNT
unformat_function_t unformat_vnet_sw_interface
#define STATS_IF_LAYER2_MCAST_INPUT_CNT
u32 bd_remove_member(l2_bridge_domain_t *bd_config, u32 sw_if_index)
Definition: l2_bd.c:137
#define L2_FLOOD_MEMBER_BVI
Definition: l2_bd.h:42
static clib_error_t * int_l2_bridge(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set subinterface in bridging mode with a bridge-domain ID.
Definition: l2_input.c:774
l2_output_next_nodes_st next_nodes
Definition: l2_output.h:76
format_function_t format_vnet_sw_if_index_name
l2input_error_t
Definition: l2_input.c:82
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 pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static uword ethernet_address_cast(u8 *a)
Definition: packet.h:65
u32 output_sw_if_index
Definition: l2_input.h:35
#define MODE_L2_BRIDGE
Definition: l2_input.h:216
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
#define vec_new(T, N)
Create new vector of given type and length (unspecified alignment, no header).
Definition: vec.h:270
u8 dst_address[6]
Definition: packet.h:53
void bd_add_member(l2_bridge_domain_t *bd_config, l2_flood_member_t *member)
Definition: l2_bd.c:108
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
u32 set_int_l2_mode(vlib_main_t *vm, vnet_main_t *vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, u32 bvi, u32 shg, u32 xc_sw_if_index)
Set the subinterface to run in l2 or l3 mode.
Definition: l2_input.c:542
void ethernet_set_rx_redirect(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 enable)
#define foreach_l2input_error
Definition: l2_input.c:78
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:656
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
vnet_main_t * vnet_main
Definition: l2_input.h:73
vlib_error_main_t error_main
Definition: main.h:124
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define PREDICT_FALSE(x)
Definition: clib.h:97
vnet_main_t vnet_main
Definition: misc.c:42
l2output_main_t l2output_main
Definition: l2_output.c:43
#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
u32 feat_next_node_index[32]
Definition: l2_input.h:63
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 clib_error_t * int_l2_xc(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set subinterface in xconnect mode with another interface.
Definition: l2_input.c:861
vnet_hw_interface_class_t ethernet_hw_interface_class
u64 * counters
Definition: error.h:78
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:91
#define foreach_l2_init_function
Definition: l2_input.c:1056
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
static_always_inline void classify_and_dispatch(vlib_main_t *vm, vlib_node_runtime_t *node, u32 cpu_index, l2input_main_t *msm, vlib_buffer_t *b0, u32 *next0)
Definition: l2_input.c:106
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
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 MODE_ERROR_ETH
Definition: l2_input.h:220
void ethernet_register_l2_input(vlib_main_t *vm, u32 node_index)
Definition: node.c:1213
#define clib_memcpy(a, b, c)
Definition: string.h:63
#define VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
Definition: ethernet.h:85
#define ARRAY_LEN(x)
Definition: clib.h:59
#define IP6_FEAT_MASK
Definition: l2_input.h:181
void l2fib_add_entry(u64 mac, u32 bd_index, u32 sw_if_index, u32 static_mac, u32 filter_mac, u32 bvi_mac)
Add an entry to the l2fib.
Definition: l2_fib.c:256
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:46
u16 cached_next_index
Definition: node.h:462
#define ASSERT(truth)
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
#define IP_UDP_TCP_FEAT_MASK
Definition: l2_input.h:187
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
static clib_error_t * show_int_mode(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Show interface mode.
Definition: l2_input.c:968
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
#define MODE_L2_XC
Definition: l2_input.h:217
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
clib_error_t * l2_init(vlib_main_t *vm)
Definition: l2_input.c:1075
static uword l2input_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l2_input.c:277
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 u8 * format_l2input_trace(u8 *s, va_list *args)
Definition: l2_input.c:63
clib_error_t * l2input_init(vlib_main_t *vm)
Definition: l2_input.c:462
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)
void ethernet_sw_interface_set_l2_mode(vnet_main_t *vnm, u32 sw_if_index, u32 l2)
Definition: node.c:854
u32 bd_find_or_add_bd_index(bd_main_t *bdm, u32 bd_id)
Get or create a bridge domain.
Definition: l2_bd.c:54
u32 feature_bitmap
Definition: l2_bd.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static char * l2input_error_strings[]
Definition: l2_input.c:90
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:492
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
#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 MODE_ERROR_BVI_DEF
Definition: l2_input.h:221
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
#define IP4_FEAT_MASK
Masks for eliminating features that do not apply to a packet.
Definition: l2_input.h:175
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
#define MODE_L2_CLASSIFY
Definition: l2_input.h:218
#define vec_foreach(var, vec)
Vector iterator.
#define get_u16(addr)
u32 sw_if_index
Definition: l2_bd.h:46
#define STATS_IF_LAYER2_UCAST_INPUT_CNT
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
l2input_next_t
Definition: l2_input.c:96
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:213
#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:445
bd_main_t bd_main
Definition: l2_bd.c:35
#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 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
#define MODE_L3
Definition: l2_input.h:215
vlib_main_t * vlib_main
Definition: l2_input.h:72
u32 ethernet_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:274
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109