FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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  * ethernet_node.c: ethernet packet processing
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vnet/pg/pg.h>
42 #include <vnet/ethernet/ethernet.h>
44 #include <vnet/devices/pipe/pipe.h>
45 #include <vppinfra/sparse_vec.h>
46 #include <vnet/l2/l2_bvi.h>
48 
49 #define foreach_ethernet_input_next \
50  _ (PUNT, "error-punt") \
51  _ (DROP, "error-drop") \
52  _ (LLC, "llc-input") \
53  _ (IP4_INPUT, "ip4-input") \
54  _ (IP4_INPUT_NCS, "ip4-input-no-checksum")
55 
56 typedef enum
57 {
58 #define _(s,n) ETHERNET_INPUT_NEXT_##s,
60 #undef _
63 
64 typedef struct
65 {
66  u8 packet_data[32];
70 
71 static u8 *
72 format_ethernet_input_trace (u8 * s, va_list * va)
73 {
74  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
75  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
77  u32 indent = format_get_indent (s);
78 
79  if (t->frame_flags)
80  {
81  s = format (s, "frame: flags 0x%x", t->frame_flags);
83  s = format (s, ", hw-if-index %u, sw-if-index %u",
85  s = format (s, "\n%U", format_white_space, indent);
86  }
87  s = format (s, "%U", format_ethernet_header, t->packet_data);
88 
89  return s;
90 }
91 
93 
94 typedef enum
95 {
100 
101 
102 // Parse the ethernet header to extract vlan tags and innermost ethertype
105  vlib_buffer_t * b0,
106  u16 * type,
107  u16 * orig_type,
108  u16 * outer_id, u16 * inner_id, u32 * match_flags)
109 {
110  u8 vlan_count;
111 
112  if (variant == ETHERNET_INPUT_VARIANT_ETHERNET
113  || variant == ETHERNET_INPUT_VARIANT_NOT_L2)
114  {
115  ethernet_header_t *e0;
116 
117  e0 = vlib_buffer_get_current (b0);
118 
119  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
120  b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
121 
122  vlib_buffer_advance (b0, sizeof (e0[0]));
123 
124  *type = clib_net_to_host_u16 (e0->type);
125  }
126  else if (variant == ETHERNET_INPUT_VARIANT_ETHERNET_TYPE)
127  {
128  // here when prior node was LLC/SNAP processing
129  u16 *e0;
130 
131  e0 = vlib_buffer_get_current (b0);
132 
133  vlib_buffer_advance (b0, sizeof (e0[0]));
134 
135  *type = clib_net_to_host_u16 (e0[0]);
136  }
137 
138  // save for distinguishing between dot1q and dot1ad later
139  *orig_type = *type;
140 
141  // default the tags to 0 (used if there is no corresponding tag)
142  *outer_id = 0;
143  *inner_id = 0;
144 
146  vlan_count = 0;
147 
148  // check for vlan encaps
149  if (ethernet_frame_is_tagged (*type))
150  {
152  u16 tag;
153 
155 
156  h0 = vlib_buffer_get_current (b0);
157 
158  tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
159 
160  *outer_id = tag & 0xfff;
161  if (0 == *outer_id)
162  *match_flags &= ~SUBINT_CONFIG_MATCH_1_TAG;
163 
164  *type = clib_net_to_host_u16 (h0->type);
165 
166  vlib_buffer_advance (b0, sizeof (h0[0]));
167  vlan_count = 1;
168 
169  if (*type == ETHERNET_TYPE_VLAN)
170  {
171  // Double tagged packet
173 
174  h0 = vlib_buffer_get_current (b0);
175 
176  tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
177 
178  *inner_id = tag & 0xfff;
179 
180  *type = clib_net_to_host_u16 (h0->type);
181 
182  vlib_buffer_advance (b0, sizeof (h0[0]));
183  vlan_count = 2;
184  if (*type == ETHERNET_TYPE_VLAN)
185  {
186  // More than double tagged packet
188 
189  vlib_buffer_advance (b0, sizeof (h0[0]));
190  vlan_count = 3; // "unknown" number, aka, 3-or-more
191  }
192  }
193  }
194  ethernet_buffer_set_vlan_count (b0, vlan_count);
195 }
196 
199  u64 * dmacs, u8 * dmacs_bad,
200  u32 n_packets, ethernet_interface_t * ei,
201  u8 have_sec_dmac);
202 
203 // Determine the subinterface for this packet, given the result of the
204 // vlan table lookups and vlan header parsing. Check the most specific
205 // matches first.
208  vnet_hw_interface_t * hi,
209  vlib_buffer_t * b0,
210  u32 match_flags,
211  main_intf_t * main_intf,
212  vlan_intf_t * vlan_intf,
213  qinq_intf_t * qinq_intf,
214  u32 * new_sw_if_index, u8 * error0, u32 * is_l2)
215 {
216  u32 matched;
218 
219  matched = eth_identify_subint (hi, match_flags, main_intf, vlan_intf,
220  qinq_intf, new_sw_if_index, error0, is_l2);
221 
222  if (matched)
223  {
224  // Perform L3 my-mac filter
225  // A unicast packet arriving on an L3 interface must have a dmac
226  // matching the interface mac. If interface has STATUS_L3 bit set
227  // mac filter is already done.
228  if (!(*is_l2 || (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)))
229  {
230  u64 dmacs[2];
231  u8 dmacs_bad[2];
232  ethernet_header_t *e0;
234 
235  e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
236  dmacs[0] = *(u64 *) e0;
238 
239  if (ei0 && vec_len (ei0->secondary_addrs))
240  ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
241  1 /* n_packets */ , ei0,
242  1 /* have_sec_dmac */ );
243  else
244  ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
245  1 /* n_packets */ , ei0,
246  0 /* have_sec_dmac */ );
247  if (dmacs_bad[0])
248  *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
249  }
250 
251  // Check for down subinterface
252  *error0 = (*new_sw_if_index) != ~0 ? (*error0) : ETHERNET_ERROR_DOWN;
253  }
254 }
255 
258  ethernet_input_variant_t variant,
259  u32 is_l20,
260  u32 type0, vlib_buffer_t * b0, u8 * error0, u8 * next0)
261 {
262  vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
263  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
264 
265  if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE))
266  {
267  // some error occurred
268  *next0 = ETHERNET_INPUT_NEXT_DROP;
269  }
270  else if (is_l20)
271  {
272  // record the L2 len and reset the buffer so the L2 header is preserved
273  u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
274  vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
275  *next0 = em->l2_next;
276  ASSERT (vnet_buffer (b0)->l2.l2_len ==
278  vlib_buffer_advance (b0, -(vnet_buffer (b0)->l2.l2_len));
279 
280  // check for common IP/MPLS ethertypes
281  }
282  else if (type0 == ETHERNET_TYPE_IP4)
283  {
284  *next0 = em->l3_next.input_next_ip4;
285  }
286  else if (type0 == ETHERNET_TYPE_IP6)
287  {
288  *next0 = em->l3_next.input_next_ip6;
289  }
290  else if (type0 == ETHERNET_TYPE_MPLS)
291  {
292  *next0 = em->l3_next.input_next_mpls;
293 
294  }
295  else if (em->redirect_l3)
296  {
297  // L3 Redirect is on, the cached common next nodes will be
298  // pointing to the redirect node, catch the uncommon types here
299  *next0 = em->redirect_l3_next;
300  }
301  else
302  {
303  // uncommon ethertype, check table
304  u32 i0;
305  i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
306  *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
307  *error0 =
308  i0 ==
309  SPARSE_VEC_INVALID_INDEX ? ETHERNET_ERROR_UNKNOWN_TYPE : *error0;
310 
311  // The table is not populated with LLC values, so check that now.
312  // If variant is variant_ethernet then we came from LLC processing. Don't
313  // go back there; drop instead using by keeping the drop/bad table result.
314  if ((type0 < 0x600) && (variant == ETHERNET_INPUT_VARIANT_ETHERNET))
315  {
316  *next0 = ETHERNET_INPUT_NEXT_LLC;
317  }
318  }
319 }
320 
321 
322 /* following vector code relies on following assumptions */
323 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_data, 0);
324 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_length, 2);
327  STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l3_hdr_offset) - 2,
328  "l3_hdr_offset must follow l2_hdr_offset");
329 
332 {
333  i16 adv = sizeof (ethernet_header_t);
334  u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
335  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
336 
337 #ifdef CLIB_HAVE_VEC256
338  /* to reduce number of small loads/stores we are loading first 64 bits
339  of each buffer metadata into 256-bit register so we can advance
340  current_data, current_length and flags.
341  Observed saving of this code is ~2 clocks per packet */
342  u64x4 r, radv;
343 
344  /* vector if signed 16 bit integers used in signed vector add operation
345  to advnce current_data and current_length */
346  u32x8 flags4 = { 0, flags, 0, flags, 0, flags, 0, flags };
347  i16x16 adv4 = {
348  adv, -adv, 0, 0, adv, -adv, 0, 0,
349  adv, -adv, 0, 0, adv, -adv, 0, 0
350  };
351 
352  /* load 4 x 64 bits */
353  r = u64x4_gather (b[0], b[1], b[2], b[3]);
354 
355  /* set flags */
356  r |= (u64x4) flags4;
357 
358  /* advance buffer */
359  radv = (u64x4) ((i16x16) r + adv4);
360 
361  /* write 4 x 64 bits */
362  u64x4_scatter (is_l3 ? radv : r, b[0], b[1], b[2], b[3]);
363 
364  /* use old current_data as l2_hdr_offset and new current_data as
365  l3_hdr_offset */
366  r = (u64x4) u16x16_blend (r, radv << 16, 0xaa);
367 
368  /* store both l2_hdr_offset and l3_hdr_offset in single store operation */
369  u32x8_scatter_one ((u32x8) r, 0, &vnet_buffer (b[0])->l2_hdr_offset);
370  u32x8_scatter_one ((u32x8) r, 2, &vnet_buffer (b[1])->l2_hdr_offset);
371  u32x8_scatter_one ((u32x8) r, 4, &vnet_buffer (b[2])->l2_hdr_offset);
372  u32x8_scatter_one ((u32x8) r, 6, &vnet_buffer (b[3])->l2_hdr_offset);
373 
374  if (is_l3)
375  {
376  ASSERT (b[0]->current_data == vnet_buffer (b[0])->l3_hdr_offset);
377  ASSERT (b[1]->current_data == vnet_buffer (b[1])->l3_hdr_offset);
378  ASSERT (b[2]->current_data == vnet_buffer (b[2])->l3_hdr_offset);
379  ASSERT (b[3]->current_data == vnet_buffer (b[3])->l3_hdr_offset);
380 
381  ASSERT (b[0]->current_data - vnet_buffer (b[0])->l2_hdr_offset == adv);
382  ASSERT (b[1]->current_data - vnet_buffer (b[1])->l2_hdr_offset == adv);
383  ASSERT (b[2]->current_data - vnet_buffer (b[2])->l2_hdr_offset == adv);
384  ASSERT (b[3]->current_data - vnet_buffer (b[3])->l2_hdr_offset == adv);
385  }
386  else
387  {
388  ASSERT (b[0]->current_data == vnet_buffer (b[0])->l2_hdr_offset);
389  ASSERT (b[1]->current_data == vnet_buffer (b[1])->l2_hdr_offset);
390  ASSERT (b[2]->current_data == vnet_buffer (b[2])->l2_hdr_offset);
391  ASSERT (b[3]->current_data == vnet_buffer (b[3])->l2_hdr_offset);
392 
393  ASSERT (b[0]->current_data - vnet_buffer (b[0])->l3_hdr_offset == -adv);
394  ASSERT (b[1]->current_data - vnet_buffer (b[1])->l3_hdr_offset == -adv);
395  ASSERT (b[2]->current_data - vnet_buffer (b[2])->l3_hdr_offset == -adv);
396  ASSERT (b[3]->current_data - vnet_buffer (b[3])->l3_hdr_offset == -adv);
397  }
398 
399 #else
400  vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
401  vnet_buffer (b[1])->l2_hdr_offset = b[1]->current_data;
402  vnet_buffer (b[2])->l2_hdr_offset = b[2]->current_data;
403  vnet_buffer (b[3])->l2_hdr_offset = b[3]->current_data;
404  vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
405  vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data + adv;
406  vnet_buffer (b[2])->l3_hdr_offset = b[2]->current_data + adv;
407  vnet_buffer (b[3])->l3_hdr_offset = b[3]->current_data + adv;
408 
409  if (is_l3)
410  {
411  vlib_buffer_advance (b[0], adv);
412  vlib_buffer_advance (b[1], adv);
413  vlib_buffer_advance (b[2], adv);
414  vlib_buffer_advance (b[3], adv);
415  }
416 
417  b[0]->flags |= flags;
418  b[1]->flags |= flags;
419  b[2]->flags |= flags;
420  b[3]->flags |= flags;
421 #endif
422 
423  if (!is_l3)
424  {
425  vnet_buffer (b[0])->l2.l2_len = adv;
426  vnet_buffer (b[1])->l2.l2_len = adv;
427  vnet_buffer (b[2])->l2.l2_len = adv;
428  vnet_buffer (b[3])->l2.l2_len = adv;
429  }
430 }
431 
434 {
435  i16 adv = sizeof (ethernet_header_t);
436  u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
437  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
438 
439  vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
440  vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
441 
442  if (is_l3)
443  vlib_buffer_advance (b[0], adv);
444  b[0]->flags |= flags;
445  if (!is_l3)
446  vnet_buffer (b[0])->l2.l2_len = adv;
447 }
448 
449 
452  u64 * dmacs, int offset, int dmac_check)
453 {
455  e = vlib_buffer_get_current (b[offset]);
456 #ifdef CLIB_HAVE_VEC128
457  u64x2 r = u64x2_load_unaligned (((u8 *) & e->type) - 6);
458  etype[offset] = ((u16x8) r)[3];
459  tags[offset] = r[1];
460 #else
461  etype[offset] = e->type;
462  tags[offset] = *(u64 *) (e + 1);
463 #endif
464 
465  if (dmac_check)
466  dmacs[offset] = *(u64 *) e;
467 }
468 
471 {
473 
474  return (etype < 0x600) ? ETHERNET_INPUT_NEXT_LLC :
477 }
478 
479 typedef struct
480 {
485  u8 err, n_tags;
488 
492 {
493  if (l->n_packets == 0 || l->sw_if_index == ~0)
494  return;
495 
496  if (l->adv > 0)
497  l->n_bytes += l->n_packets * l->len;
498 
502  l->n_packets, l->n_bytes);
503 }
504 
508  u64 tag, u16 * next, vlib_buffer_t * b,
509  eth_input_tag_lookup_t * l, u8 dmac_bad, int is_dot1ad,
510  int main_is_l3, int check_dmac)
511 {
513 
514  if ((tag ^ l->tag) & l->mask)
515  {
517  vlan_intf_t *vif;
518  qinq_intf_t *qif;
519  vlan_table_t *vlan_table;
520  qinq_table_t *qinq_table;
521  u16 *t = (u16 *) & tag;
522  u16 vlan1 = clib_net_to_host_u16 (t[0]) & 0xFFF;
523  u16 vlan2 = clib_net_to_host_u16 (t[2]) & 0xFFF;
524  u32 matched, is_l2, new_sw_if_index;
525 
526  vlan_table = vec_elt_at_index (em->vlan_pool, is_dot1ad ?
527  mif->dot1ad_vlans : mif->dot1q_vlans);
528  vif = &vlan_table->vlans[vlan1];
529  qinq_table = vec_elt_at_index (em->qinq_pool, vif->qinqs);
530  qif = &qinq_table->vlans[vlan2];
531  l->err = ETHERNET_ERROR_NONE;
532  l->type = clib_net_to_host_u16 (t[1]);
533 
534  if (l->type == ETHERNET_TYPE_VLAN)
535  {
536  l->type = clib_net_to_host_u16 (t[3]);
537  l->n_tags = 2;
539  SUBINT_CONFIG_MATCH_2_TAG, mif, vif,
540  qif, &new_sw_if_index, &l->err,
541  &is_l2);
542  }
543  else
544  {
545  l->n_tags = 1;
546  if (vlan1 == 0)
547  {
548  new_sw_if_index = hi->sw_if_index;
549  l->err = ETHERNET_ERROR_NONE;
550  matched = 1;
551  is_l2 = main_is_l3 == 0;
552  }
553  else
556  vif, qif, &new_sw_if_index,
557  &l->err, &is_l2);
558  }
559 
560  if (l->sw_if_index != new_sw_if_index)
561  {
562  eth_input_update_if_counters (vm, vnm, l);
563  l->n_packets = 0;
564  l->n_bytes = 0;
565  l->sw_if_index = new_sw_if_index;
566  }
567  l->tag = tag;
568  l->mask = (l->n_tags == 2) ?
569  clib_net_to_host_u64 (0xffffffffffffffff) :
570  clib_net_to_host_u64 (0xffffffff00000000);
571 
572  if (matched && l->sw_if_index == ~0)
573  l->err = ETHERNET_ERROR_DOWN;
574 
575  l->len = sizeof (ethernet_header_t) +
576  l->n_tags * sizeof (ethernet_vlan_header_t);
577  if (main_is_l3)
578  l->adv = is_l2 ? -(int) sizeof (ethernet_header_t) :
579  l->n_tags * sizeof (ethernet_vlan_header_t);
580  else
581  l->adv = is_l2 ? 0 : l->len;
582 
583  if (PREDICT_FALSE (l->err != ETHERNET_ERROR_NONE))
584  l->next = ETHERNET_INPUT_NEXT_DROP;
585  else if (is_l2)
586  l->next = em->l2_next;
587  else if (l->type == ETHERNET_TYPE_IP4)
588  l->next = em->l3_next.input_next_ip4;
589  else if (l->type == ETHERNET_TYPE_IP6)
590  l->next = em->l3_next.input_next_ip6;
591  else if (l->type == ETHERNET_TYPE_MPLS)
592  l->next = em->l3_next.input_next_mpls;
593  else if (em->redirect_l3)
594  l->next = em->redirect_l3_next;
595  else
596  {
597  l->next = eth_input_next_by_type (l->type);
598  if (l->next == ETHERNET_INPUT_NEXT_PUNT)
599  l->err = ETHERNET_ERROR_UNKNOWN_TYPE;
600  }
601  }
602 
603  if (check_dmac && l->adv > 0 && dmac_bad)
604  {
605  l->err = ETHERNET_ERROR_L3_MAC_MISMATCH;
606  next[0] = ETHERNET_INPUT_NEXT_PUNT;
607  }
608  else
609  next[0] = l->next;
610 
611  vlib_buffer_advance (b, l->adv);
612  vnet_buffer (b)->l2.l2_len = l->len;
613  vnet_buffer (b)->l3_hdr_offset = vnet_buffer (b)->l2_hdr_offset + l->len;
614 
615  if (l->err == ETHERNET_ERROR_NONE)
616  {
617  vnet_buffer (b)->sw_if_index[VLIB_RX] = l->sw_if_index;
619  }
620  else
621  b->error = node->errors[l->err];
622 
623  /* update counters */
624  l->n_packets += 1;
625  l->n_bytes += vlib_buffer_length_in_chain (vm, b);
626 }
627 
628 #define DMAC_MASK clib_net_to_host_u64 (0xFFFFFFFFFFFF0000)
629 #define DMAC_IGBIT clib_net_to_host_u64 (0x0100000000000000)
630 
631 #ifdef CLIB_HAVE_VEC256
633 is_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
634 {
635  u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
636  r0 = (r0 != u64x4_splat (hwaddr)) & ((r0 & u64x4_splat (DMAC_IGBIT)) == 0);
637  return u8x32_msb_mask ((u8x32) (r0));
638 }
639 #endif
640 
642 is_dmac_bad (u64 dmac, u64 hwaddr)
643 {
644  u64 r0 = dmac & DMAC_MASK;
645  return (r0 != hwaddr) && ((r0 & DMAC_IGBIT) == 0);
646 }
647 
649 is_sec_dmac_bad (u64 dmac, u64 hwaddr)
650 {
651  return ((dmac & DMAC_MASK) != hwaddr);
652 }
653 
654 #ifdef CLIB_HAVE_VEC256
656 is_sec_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
657 {
658  u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
659  r0 = (r0 != u64x4_splat (hwaddr));
660  return u8x32_msb_mask ((u8x32) (r0));
661 }
662 #endif
663 
665 eth_input_sec_dmac_check_x1 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
666 {
667  dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
668  return dmac_bad[0];
669 }
670 
672 eth_input_sec_dmac_check_x4 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
673 {
674 #ifdef CLIB_HAVE_VEC256
675  *(u32 *) (dmac_bad + 0) &= is_sec_dmac_bad_x4 (dmac + 0, hwaddr);
676 #else
677  dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
678  dmac_bad[1] &= is_sec_dmac_bad (dmac[1], hwaddr);
679  dmac_bad[2] &= is_sec_dmac_bad (dmac[2], hwaddr);
680  dmac_bad[3] &= is_sec_dmac_bad (dmac[3], hwaddr);
681 #endif
682  return *(u32 *) dmac_bad;
683 }
684 
685 /*
686  * DMAC check for ethernet_input_inline()
687  *
688  * dmacs and dmacs_bad are arrays that are 2 elements long
689  * n_packets should be 1 or 2 for ethernet_input_inline()
690  */
693  u64 * dmacs, u8 * dmacs_bad,
694  u32 n_packets, ethernet_interface_t * ei,
695  u8 have_sec_dmac)
696 {
697  u64 hwaddr = ei->address.as_u64;
698  u8 bad = 0;
699 
700  ASSERT (0 == ei->address.zero);
701 
702  dmacs_bad[0] = is_dmac_bad (dmacs[0], hwaddr);
703  dmacs_bad[1] = ((n_packets > 1) & is_dmac_bad (dmacs[1], hwaddr));
704 
705  bad = dmacs_bad[0] | dmacs_bad[1];
706 
707  if (PREDICT_FALSE (bad && have_sec_dmac))
708  {
710 
711  vec_foreach (sec_addr, ei->secondary_addrs)
712  {
713  ASSERT (0 == sec_addr->zero);
714  hwaddr = sec_addr->as_u64;
715 
716  bad = (eth_input_sec_dmac_check_x1 (hwaddr, dmacs, dmacs_bad) |
717  eth_input_sec_dmac_check_x1 (hwaddr, dmacs + 1,
718  dmacs_bad + 1));
719 
720  if (!bad)
721  return;
722  }
723  }
724 }
725 
728  u64 * dmacs, u8 * dmacs_bad,
729  u32 n_packets, ethernet_interface_t * ei,
730  u8 have_sec_dmac)
731 {
732  u64 hwaddr = ei->address.as_u64;
733  u64 *dmac = dmacs;
734  u8 *dmac_bad = dmacs_bad;
735  u32 bad = 0;
736  i32 n_left = n_packets;
737 
738  ASSERT (0 == ei->address.zero);
739 
740 #ifdef CLIB_HAVE_VEC256
741  while (n_left > 0)
742  {
743  bad |= *(u32 *) (dmac_bad + 0) = is_dmac_bad_x4 (dmac + 0, hwaddr);
744  bad |= *(u32 *) (dmac_bad + 4) = is_dmac_bad_x4 (dmac + 4, hwaddr);
745 
746  /* next */
747  dmac += 8;
748  dmac_bad += 8;
749  n_left -= 8;
750  }
751 #else
752  while (n_left > 0)
753  {
754  bad |= dmac_bad[0] = is_dmac_bad (dmac[0], hwaddr);
755  bad |= dmac_bad[1] = is_dmac_bad (dmac[1], hwaddr);
756  bad |= dmac_bad[2] = is_dmac_bad (dmac[2], hwaddr);
757  bad |= dmac_bad[3] = is_dmac_bad (dmac[3], hwaddr);
758 
759  /* next */
760  dmac += 4;
761  dmac_bad += 4;
762  n_left -= 4;
763  }
764 #endif
765 
766  if (have_sec_dmac && bad)
767  {
769 
770  vec_foreach (addr, ei->secondary_addrs)
771  {
772  u64 hwaddr = addr->as_u64;
773  i32 n_left = n_packets;
774  u64 *dmac = dmacs;
775  u8 *dmac_bad = dmacs_bad;
776 
777  ASSERT (0 == addr->zero);
778 
779  bad = 0;
780 
781  while (n_left > 0)
782  {
783  int adv = 0;
784  int n_bad;
785 
786  /* skip any that have already matched */
787  if (!dmac_bad[0])
788  {
789  dmac += 1;
790  dmac_bad += 1;
791  n_left -= 1;
792  continue;
793  }
794 
795  n_bad = clib_min (4, n_left);
796 
797  /* If >= 4 left, compare 4 together */
798  if (n_bad == 4)
799  {
800  bad |= eth_input_sec_dmac_check_x4 (hwaddr, dmac, dmac_bad);
801  adv = 4;
802  n_bad = 0;
803  }
804 
805  /* handle individually */
806  while (n_bad > 0)
807  {
808  bad |= eth_input_sec_dmac_check_x1 (hwaddr, dmac + adv,
809  dmac_bad + adv);
810  adv += 1;
811  n_bad -= 1;
812  }
813 
814  dmac += adv;
815  dmac_bad += adv;
816  n_left -= adv;
817  }
818 
819  if (!bad) /* can stop looping if everything matched */
820  break;
821  }
822  }
823 }
824 
825 /* process frame of buffers, store ethertype into array and update
826  buffer metadata fields depending on interface being l2 or l3 assuming that
827  packets are untagged. For tagged packets those fields are updated later.
828  Optionally store Destionation MAC address and tag data into arrays
829  for further processing */
830 
832  "VLIB_FRAME_SIZE must be power of 8");
835  vnet_hw_interface_t * hi,
836  u32 * buffer_indices, u32 n_packets, int main_is_l3,
837  int ip4_cksum_ok, int dmac_check)
838 {
841  u16 etypes[VLIB_FRAME_SIZE], *etype = etypes;
842  u64 dmacs[VLIB_FRAME_SIZE], *dmac = dmacs;
843  u8 dmacs_bad[VLIB_FRAME_SIZE];
844  u64 tags[VLIB_FRAME_SIZE], *tag = tags;
845  u16 slowpath_indices[VLIB_FRAME_SIZE];
846  u16 n_slowpath, i;
847  u16 next_ip4, next_ip6, next_mpls, next_l2;
848  u16 et_ip4 = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
849  u16 et_ip6 = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
850  u16 et_mpls = clib_host_to_net_u16 (ETHERNET_TYPE_MPLS);
851  u16 et_vlan = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
852  u16 et_dot1ad = clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD);
853  i32 n_left = n_packets;
855  vlib_buffer_t **b = bufs;
857 
858  vlib_get_buffers (vm, buffer_indices, b, n_left);
859 
860  while (n_left >= 20)
861  {
862  vlib_buffer_t **ph = b + 16, **pd = b + 8;
863 
864  vlib_prefetch_buffer_header (ph[0], LOAD);
865  vlib_prefetch_buffer_data (pd[0], LOAD);
866  eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
867 
868  vlib_prefetch_buffer_header (ph[1], LOAD);
869  vlib_prefetch_buffer_data (pd[1], LOAD);
870  eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
871 
872  vlib_prefetch_buffer_header (ph[2], LOAD);
873  vlib_prefetch_buffer_data (pd[2], LOAD);
874  eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
875 
876  vlib_prefetch_buffer_header (ph[3], LOAD);
877  vlib_prefetch_buffer_data (pd[3], LOAD);
878  eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
879 
880  eth_input_adv_and_flags_x4 (b, main_is_l3);
881 
882  /* next */
883  b += 4;
884  n_left -= 4;
885  etype += 4;
886  tag += 4;
887  dmac += 4;
888  }
889  while (n_left >= 4)
890  {
891  eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
892  eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
893  eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
894  eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
895  eth_input_adv_and_flags_x4 (b, main_is_l3);
896 
897  /* next */
898  b += 4;
899  n_left -= 4;
900  etype += 4;
901  tag += 4;
902  dmac += 4;
903  }
904  while (n_left)
905  {
906  eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
907  eth_input_adv_and_flags_x1 (b, main_is_l3);
908 
909  /* next */
910  b += 1;
911  n_left -= 1;
912  etype += 1;
913  tag += 1;
914  dmac += 1;
915  }
916 
917  if (dmac_check)
918  {
919  if (ei && vec_len (ei->secondary_addrs))
920  eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
921  ei, 1 /* have_sec_dmac */ );
922  else
923  eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
924  ei, 0 /* have_sec_dmac */ );
925  }
926 
927  next_ip4 = em->l3_next.input_next_ip4;
928  next_ip6 = em->l3_next.input_next_ip6;
929  next_mpls = em->l3_next.input_next_mpls;
930  next_l2 = em->l2_next;
931 
932  if (next_ip4 == ETHERNET_INPUT_NEXT_IP4_INPUT && ip4_cksum_ok)
933  next_ip4 = ETHERNET_INPUT_NEXT_IP4_INPUT_NCS;
934 
935 #ifdef CLIB_HAVE_VEC256
936  u16x16 et16_ip4 = u16x16_splat (et_ip4);
937  u16x16 et16_ip6 = u16x16_splat (et_ip6);
938  u16x16 et16_mpls = u16x16_splat (et_mpls);
939  u16x16 et16_vlan = u16x16_splat (et_vlan);
940  u16x16 et16_dot1ad = u16x16_splat (et_dot1ad);
941  u16x16 next16_ip4 = u16x16_splat (next_ip4);
942  u16x16 next16_ip6 = u16x16_splat (next_ip6);
943  u16x16 next16_mpls = u16x16_splat (next_mpls);
944  u16x16 next16_l2 = u16x16_splat (next_l2);
945  u16x16 zero = { 0 };
946  u16x16 stairs = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
947 #endif
948 
949  etype = etypes;
950  n_left = n_packets;
951  next = nexts;
952  n_slowpath = 0;
953  i = 0;
954 
955  /* fastpath - in l3 mode hadles ip4, ip6 and mpls packets, other packets
956  are considered as slowpath, in l2 mode all untagged packets are
957  considered as fastpath */
958  while (n_left > 0)
959  {
960 #ifdef CLIB_HAVE_VEC256
961  if (n_left >= 16)
962  {
963  u16x16 r = zero;
964  u16x16 e16 = u16x16_load_unaligned (etype);
965  if (main_is_l3)
966  {
967  r += (e16 == et16_ip4) & next16_ip4;
968  r += (e16 == et16_ip6) & next16_ip6;
969  r += (e16 == et16_mpls) & next16_mpls;
970  }
971  else
972  r = ((e16 != et16_vlan) & (e16 != et16_dot1ad)) & next16_l2;
973  u16x16_store_unaligned (r, next);
974 
975  if (!u16x16_is_all_zero (r == zero))
976  {
977  if (u16x16_is_all_zero (r))
978  {
979  u16x16_store_unaligned (u16x16_splat (i) + stairs,
980  slowpath_indices + n_slowpath);
981  n_slowpath += 16;
982  }
983  else
984  {
985  for (int j = 0; j < 16; j++)
986  if (next[j] == 0)
987  slowpath_indices[n_slowpath++] = i + j;
988  }
989  }
990 
991  etype += 16;
992  next += 16;
993  n_left -= 16;
994  i += 16;
995  continue;
996  }
997 #endif
998  if (main_is_l3 && etype[0] == et_ip4)
999  next[0] = next_ip4;
1000  else if (main_is_l3 && etype[0] == et_ip6)
1001  next[0] = next_ip6;
1002  else if (main_is_l3 && etype[0] == et_mpls)
1003  next[0] = next_mpls;
1004  else if (main_is_l3 == 0 &&
1005  etype[0] != et_vlan && etype[0] != et_dot1ad)
1006  next[0] = next_l2;
1007  else
1008  {
1009  next[0] = 0;
1010  slowpath_indices[n_slowpath++] = i;
1011  }
1012 
1013  etype += 1;
1014  next += 1;
1015  n_left -= 1;
1016  i += 1;
1017  }
1018 
1019  if (n_slowpath)
1020  {
1021  vnet_main_t *vnm = vnet_get_main ();
1022  n_left = n_slowpath;
1023  u16 *si = slowpath_indices;
1024  u32 last_unknown_etype = ~0;
1025  u32 last_unknown_next = ~0;
1026  eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
1027  .mask = -1LL,
1028  .tag = tags[si[0]] ^ -1LL,
1029  .sw_if_index = ~0
1030  };
1031 
1032  clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
1033 
1034  while (n_left)
1035  {
1036  i = si[0];
1037  u16 etype = etypes[i];
1038 
1039  if (etype == et_vlan)
1040  {
1041  vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1042  eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1043  &dot1q_lookup, dmacs_bad[i], 0,
1044  main_is_l3, dmac_check);
1045 
1046  }
1047  else if (etype == et_dot1ad)
1048  {
1049  vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1050  eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1051  &dot1ad_lookup, dmacs_bad[i], 1,
1052  main_is_l3, dmac_check);
1053  }
1054  else
1055  {
1056  /* untagged packet with not well known etyertype */
1057  if (last_unknown_etype != etype)
1058  {
1059  last_unknown_etype = etype;
1060  etype = clib_host_to_net_u16 (etype);
1061  last_unknown_next = eth_input_next_by_type (etype);
1062  }
1063  if (dmac_check && main_is_l3 && dmacs_bad[i])
1064  {
1065  vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1066  b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
1067  nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
1068  }
1069  else
1070  nexts[i] = last_unknown_next;
1071  }
1072 
1073  /* next */
1074  n_left--;
1075  si++;
1076  }
1077 
1078  eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
1079  eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
1080  }
1081 
1082  vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
1083 }
1084 
1087  vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
1088  int ip4_cksum_ok)
1089 {
1092  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
1093  main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1094  subint_config_t *subint0 = &intf0->untagged_subint;
1095 
1096  int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
1097  int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3;
1098 
1099  if (main_is_l3)
1100  {
1101  if (int_is_l3 || /* DMAC filter already done by NIC */
1102  ((hi->l2_if_count != 0) && (hi->l3_if_count == 0)))
1103  { /* All L2 usage - DMAC check not needed */
1104  eth_input_process_frame (vm, node, hi, from, n_pkts,
1105  /*is_l3 */ 1, ip4_cksum_ok, 0);
1106  }
1107  else
1108  { /* DMAC check needed for L3 */
1109  eth_input_process_frame (vm, node, hi, from, n_pkts,
1110  /*is_l3 */ 1, ip4_cksum_ok, 1);
1111  }
1112  return;
1113  }
1114  else
1115  {
1116  if (hi->l3_if_count == 0)
1117  { /* All L2 usage - DMAC check not needed */
1118  eth_input_process_frame (vm, node, hi, from, n_pkts,
1119  /*is_l3 */ 0, ip4_cksum_ok, 0);
1120  }
1121  else
1122  { /* DMAC check needed for L3 */
1123  eth_input_process_frame (vm, node, hi, from, n_pkts,
1124  /*is_l3 */ 0, ip4_cksum_ok, 1);
1125  }
1126  return;
1127  }
1128 }
1129 
1133 {
1134  vnet_main_t *vnm = vnet_get_main ();
1135  u32 *from, n_left;
1136  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1137  {
1138  from = vlib_frame_vector_args (from_frame);
1139  n_left = from_frame->n_vectors;
1140 
1141  while (n_left)
1142  {
1144  vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1145 
1146  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1147  {
1148  t0 = vlib_add_trace (vm, node, b0,
1149  sizeof (ethernet_input_trace_t));
1151  sizeof (t0->packet_data));
1152  t0->frame_flags = from_frame->flags;
1154  vlib_frame_scalar_args (from_frame),
1155  sizeof (ethernet_input_frame_t));
1156  }
1157  from += 1;
1158  n_left -= 1;
1159  }
1160  }
1161 
1162  /* rx pcap capture if enabled */
1163  if (PREDICT_FALSE (vnm->pcap.pcap_rx_enable))
1164  {
1165  u32 bi0;
1166  vnet_pcap_t *pp = &vnm->pcap;
1167 
1168  from = vlib_frame_vector_args (from_frame);
1169  n_left = from_frame->n_vectors;
1170  while (n_left > 0)
1171  {
1172  vlib_buffer_t *b0;
1173  bi0 = from[0];
1174  from++;
1175  n_left--;
1176  b0 = vlib_get_buffer (vm, bi0);
1177  if (vnet_is_packet_pcaped (pp, b0, ~0))
1178  pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
1179  }
1180  }
1181 }
1182 
1186  u32 * from, u32 n_packets,
1187  ethernet_input_variant_t variant)
1188 {
1189  vnet_main_t *vnm = vnet_get_main ();
1191  vlib_node_runtime_t *error_node;
1192  u32 n_left_from, next_index, *to_next;
1193  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1195  u32 cached_sw_if_index = ~0;
1196  u32 cached_is_l2 = 0; /* shut up gcc */
1197  vnet_hw_interface_t *hi = NULL; /* used for main interface only */
1198  ethernet_interface_t *ei = NULL;
1200  vlib_buffer_t **b = bufs;
1201 
1202  if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1203  error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1204  else
1205  error_node = node;
1206 
1207  n_left_from = n_packets;
1208 
1209  next_index = node->cached_next_index;
1210  stats_sw_if_index = node->runtime_data[0];
1211  stats_n_packets = stats_n_bytes = 0;
1212  vlib_get_buffers (vm, from, bufs, n_left_from);
1213 
1214  while (n_left_from > 0)
1215  {
1216  u32 n_left_to_next;
1217 
1218  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1219 
1220  while (n_left_from >= 4 && n_left_to_next >= 2)
1221  {
1222  u32 bi0, bi1;
1223  vlib_buffer_t *b0, *b1;
1224  u8 next0, next1, error0, error1;
1225  u16 type0, orig_type0, type1, orig_type1;
1226  u16 outer_id0, inner_id0, outer_id1, inner_id1;
1227  u32 match_flags0, match_flags1;
1228  u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1229  new_sw_if_index1, len1;
1230  vnet_hw_interface_t *hi0, *hi1;
1231  main_intf_t *main_intf0, *main_intf1;
1232  vlan_intf_t *vlan_intf0, *vlan_intf1;
1233  qinq_intf_t *qinq_intf0, *qinq_intf1;
1234  u32 is_l20, is_l21;
1235  ethernet_header_t *e0, *e1;
1236  u64 dmacs[2];
1237  u8 dmacs_bad[2];
1238 
1239  /* Prefetch next iteration. */
1240  {
1241  vlib_prefetch_buffer_header (b[2], STORE);
1242  vlib_prefetch_buffer_header (b[3], STORE);
1243 
1244  CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1245  CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1246  }
1247 
1248  bi0 = from[0];
1249  bi1 = from[1];
1250  to_next[0] = bi0;
1251  to_next[1] = bi1;
1252  from += 2;
1253  to_next += 2;
1254  n_left_to_next -= 2;
1255  n_left_from -= 2;
1256 
1257  b0 = b[0];
1258  b1 = b[1];
1259  b += 2;
1260 
1261  error0 = error1 = ETHERNET_ERROR_NONE;
1262  e0 = vlib_buffer_get_current (b0);
1263  type0 = clib_net_to_host_u16 (e0->type);
1264  e1 = vlib_buffer_get_current (b1);
1265  type1 = clib_net_to_host_u16 (e1->type);
1266 
1267  /* Set the L2 header offset for all packets */
1268  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1269  vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1270  b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1271  b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1272 
1273  /* Speed-path for the untagged case */
1276  type1)))
1277  {
1278  main_intf_t *intf0;
1279  subint_config_t *subint0;
1280  u32 sw_if_index0, sw_if_index1;
1281 
1282  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1283  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1284  is_l20 = cached_is_l2;
1285 
1286  /* This is probably wholly unnecessary */
1287  if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1288  goto slowpath;
1289 
1290  /* Now sw_if_index0 == sw_if_index1 */
1291  if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1292  {
1293  cached_sw_if_index = sw_if_index0;
1294  hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1295  ei = ethernet_get_interface (em, hi->hw_if_index);
1296  intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1297  subint0 = &intf0->untagged_subint;
1298  cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1299  }
1300 
1301  if (PREDICT_TRUE (is_l20 != 0))
1302  {
1303  vnet_buffer (b0)->l3_hdr_offset =
1304  vnet_buffer (b0)->l2_hdr_offset +
1305  sizeof (ethernet_header_t);
1306  vnet_buffer (b1)->l3_hdr_offset =
1307  vnet_buffer (b1)->l2_hdr_offset +
1308  sizeof (ethernet_header_t);
1309  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1310  b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1311  next0 = em->l2_next;
1312  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1313  next1 = em->l2_next;
1314  vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1315  }
1316  else
1317  {
1318  if (ei && (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3))
1319  goto skip_dmac_check01;
1320 
1321  dmacs[0] = *(u64 *) e0;
1322  dmacs[1] = *(u64 *) e1;
1323 
1324  if (ei && vec_len (ei->secondary_addrs))
1326  dmacs_bad,
1327  2 /* n_packets */ ,
1328  ei,
1329  1 /* have_sec_dmac */ );
1330  else
1332  dmacs_bad,
1333  2 /* n_packets */ ,
1334  ei,
1335  0 /* have_sec_dmac */ );
1336 
1337  if (dmacs_bad[0])
1338  error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1339  if (dmacs_bad[1])
1340  error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1341 
1342  skip_dmac_check01:
1343  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1344  determine_next_node (em, variant, 0, type0, b0,
1345  &error0, &next0);
1346  vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1347  determine_next_node (em, variant, 0, type1, b1,
1348  &error1, &next1);
1349  }
1350  goto ship_it01;
1351  }
1352 
1353  /* Slow-path for the tagged case */
1354  slowpath:
1355  parse_header (variant,
1356  b0,
1357  &type0,
1358  &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1359 
1360  parse_header (variant,
1361  b1,
1362  &type1,
1363  &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1364 
1365  old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1366  old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1367 
1369  vnm,
1370  old_sw_if_index0,
1371  orig_type0,
1372  outer_id0,
1373  inner_id0,
1374  &hi0,
1375  &main_intf0, &vlan_intf0, &qinq_intf0);
1376 
1378  vnm,
1379  old_sw_if_index1,
1380  orig_type1,
1381  outer_id1,
1382  inner_id1,
1383  &hi1,
1384  &main_intf1, &vlan_intf1, &qinq_intf1);
1385 
1386  identify_subint (em,
1387  hi0,
1388  b0,
1389  match_flags0,
1390  main_intf0,
1391  vlan_intf0,
1392  qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1393 
1394  identify_subint (em,
1395  hi1,
1396  b1,
1397  match_flags1,
1398  main_intf1,
1399  vlan_intf1,
1400  qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1401 
1402  // Save RX sw_if_index for later nodes
1403  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1404  error0 !=
1405  ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1406  vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1407  error1 !=
1408  ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1409 
1410  // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1411  if (((new_sw_if_index0 != ~0)
1412  && (new_sw_if_index0 != old_sw_if_index0))
1413  || ((new_sw_if_index1 != ~0)
1414  && (new_sw_if_index1 != old_sw_if_index1)))
1415  {
1416 
1417  len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1418  - vnet_buffer (b0)->l2_hdr_offset;
1419  len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1420  - vnet_buffer (b1)->l2_hdr_offset;
1421 
1422  stats_n_packets += 2;
1423  stats_n_bytes += len0 + len1;
1424 
1425  if (PREDICT_FALSE
1426  (!(new_sw_if_index0 == stats_sw_if_index
1427  && new_sw_if_index1 == stats_sw_if_index)))
1428  {
1429  stats_n_packets -= 2;
1430  stats_n_bytes -= len0 + len1;
1431 
1432  if (new_sw_if_index0 != old_sw_if_index0
1433  && new_sw_if_index0 != ~0)
1435  interface_main.combined_sw_if_counters
1436  +
1438  thread_index,
1439  new_sw_if_index0, 1,
1440  len0);
1441  if (new_sw_if_index1 != old_sw_if_index1
1442  && new_sw_if_index1 != ~0)
1444  interface_main.combined_sw_if_counters
1445  +
1447  thread_index,
1448  new_sw_if_index1, 1,
1449  len1);
1450 
1451  if (new_sw_if_index0 == new_sw_if_index1)
1452  {
1453  if (stats_n_packets > 0)
1454  {
1458  thread_index,
1459  stats_sw_if_index,
1460  stats_n_packets, stats_n_bytes);
1461  stats_n_packets = stats_n_bytes = 0;
1462  }
1463  stats_sw_if_index = new_sw_if_index0;
1464  }
1465  }
1466  }
1467 
1468  if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1469  is_l20 = is_l21 = 0;
1470 
1471  determine_next_node (em, variant, is_l20, type0, b0, &error0,
1472  &next0);
1473  determine_next_node (em, variant, is_l21, type1, b1, &error1,
1474  &next1);
1475 
1476  ship_it01:
1477  b0->error = error_node->errors[error0];
1478  b1->error = error_node->errors[error1];
1479 
1480  // verify speculative enqueue
1481  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1482  n_left_to_next, bi0, bi1, next0,
1483  next1);
1484  }
1485 
1486  while (n_left_from > 0 && n_left_to_next > 0)
1487  {
1488  u32 bi0;
1489  vlib_buffer_t *b0;
1490  u8 error0, next0;
1491  u16 type0, orig_type0;
1492  u16 outer_id0, inner_id0;
1493  u32 match_flags0;
1494  u32 old_sw_if_index0, new_sw_if_index0, len0;
1495  vnet_hw_interface_t *hi0;
1496  main_intf_t *main_intf0;
1497  vlan_intf_t *vlan_intf0;
1498  qinq_intf_t *qinq_intf0;
1499  ethernet_header_t *e0;
1500  u32 is_l20;
1501  u64 dmacs[2];
1502  u8 dmacs_bad[2];
1503 
1504  // Prefetch next iteration
1505  if (n_left_from > 1)
1506  {
1507  vlib_prefetch_buffer_header (b[1], STORE);
1508  CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1509  }
1510 
1511  bi0 = from[0];
1512  to_next[0] = bi0;
1513  from += 1;
1514  to_next += 1;
1515  n_left_from -= 1;
1516  n_left_to_next -= 1;
1517 
1518  b0 = b[0];
1519  b += 1;
1520 
1521  error0 = ETHERNET_ERROR_NONE;
1522  e0 = vlib_buffer_get_current (b0);
1523  type0 = clib_net_to_host_u16 (e0->type);
1524 
1525  /* Set the L2 header offset for all packets */
1526  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1527  b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1528 
1529  /* Speed-path for the untagged case */
1531  && !ethernet_frame_is_tagged (type0)))
1532  {
1533  main_intf_t *intf0;
1534  subint_config_t *subint0;
1535  u32 sw_if_index0;
1536 
1537  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1538  is_l20 = cached_is_l2;
1539 
1540  if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1541  {
1542  cached_sw_if_index = sw_if_index0;
1543  hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1544  ei = ethernet_get_interface (em, hi->hw_if_index);
1545  intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1546  subint0 = &intf0->untagged_subint;
1547  cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1548  }
1549 
1550 
1551  if (PREDICT_TRUE (is_l20 != 0))
1552  {
1553  vnet_buffer (b0)->l3_hdr_offset =
1554  vnet_buffer (b0)->l2_hdr_offset +
1555  sizeof (ethernet_header_t);
1556  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1557  next0 = em->l2_next;
1558  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1559  }
1560  else
1561  {
1562  if (ei && ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1563  goto skip_dmac_check0;
1564 
1565  dmacs[0] = *(u64 *) e0;
1566 
1567  if (ei && vec_len (ei->secondary_addrs))
1569  dmacs_bad,
1570  1 /* n_packets */ ,
1571  ei,
1572  1 /* have_sec_dmac */ );
1573  else
1575  dmacs_bad,
1576  1 /* n_packets */ ,
1577  ei,
1578  0 /* have_sec_dmac */ );
1579 
1580  if (dmacs_bad[0])
1581  error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1582 
1583  skip_dmac_check0:
1584  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1585  determine_next_node (em, variant, 0, type0, b0,
1586  &error0, &next0);
1587  }
1588  goto ship_it0;
1589  }
1590 
1591  /* Slow-path for the tagged case */
1592  parse_header (variant,
1593  b0,
1594  &type0,
1595  &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1596 
1597  old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1598 
1600  vnm,
1601  old_sw_if_index0,
1602  orig_type0,
1603  outer_id0,
1604  inner_id0,
1605  &hi0,
1606  &main_intf0, &vlan_intf0, &qinq_intf0);
1607 
1608  identify_subint (em,
1609  hi0,
1610  b0,
1611  match_flags0,
1612  main_intf0,
1613  vlan_intf0,
1614  qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1615 
1616  // Save RX sw_if_index for later nodes
1617  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1618  error0 !=
1619  ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1620 
1621  // Increment subinterface stats
1622  // Note that interface-level counters have already been incremented
1623  // prior to calling this function. Thus only subinterface counters
1624  // are incremented here.
1625  //
1626  // Interface level counters include packets received on the main
1627  // interface and all subinterfaces. Subinterface level counters
1628  // include only those packets received on that subinterface
1629  // Increment stats if the subint is valid and it is not the main intf
1630  if ((new_sw_if_index0 != ~0)
1631  && (new_sw_if_index0 != old_sw_if_index0))
1632  {
1633 
1634  len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1635  - vnet_buffer (b0)->l2_hdr_offset;
1636 
1637  stats_n_packets += 1;
1638  stats_n_bytes += len0;
1639 
1640  // Batch stat increments from the same subinterface so counters
1641  // don't need to be incremented for every packet.
1642  if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1643  {
1644  stats_n_packets -= 1;
1645  stats_n_bytes -= len0;
1646 
1647  if (new_sw_if_index0 != ~0)
1651  thread_index, new_sw_if_index0, 1, len0);
1652  if (stats_n_packets > 0)
1653  {
1657  thread_index,
1658  stats_sw_if_index, stats_n_packets, stats_n_bytes);
1659  stats_n_packets = stats_n_bytes = 0;
1660  }
1661  stats_sw_if_index = new_sw_if_index0;
1662  }
1663  }
1664 
1665  if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1666  is_l20 = 0;
1667 
1668  determine_next_node (em, variant, is_l20, type0, b0, &error0,
1669  &next0);
1670 
1671  ship_it0:
1672  b0->error = error_node->errors[error0];
1673 
1674  // verify speculative enqueue
1675  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1676  to_next, n_left_to_next,
1677  bi0, next0);
1678  }
1679 
1680  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1681  }
1682 
1683  // Increment any remaining batched stats
1684  if (stats_n_packets > 0)
1685  {
1689  thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1690  node->runtime_data[0] = stats_sw_if_index;
1691  }
1692 }
1693 
1696  vlib_frame_t * frame)
1697 {
1698  vnet_main_t *vnm = vnet_get_main ();
1700  u32 n_packets = frame->n_vectors;
1701 
1703 
1705  {
1707  int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1709  eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1710  }
1711  else
1712  ethernet_input_inline (vm, node, from, n_packets,
1714  return n_packets;
1715 }
1716 
1720 {
1722  u32 n_packets = from_frame->n_vectors;
1724  ethernet_input_inline (vm, node, from, n_packets,
1726  return n_packets;
1727 }
1728 
1732 {
1734  u32 n_packets = from_frame->n_vectors;
1736  ethernet_input_inline (vm, node, from, n_packets,
1738  return n_packets;
1739 }
1740 
1741 
1742 // Return the subinterface config struct for the given sw_if_index
1743 // Also return via parameter the appropriate match flags for the
1744 // configured number of tags.
1745 // On error (unsupported or not ethernet) return 0.
1746 static subint_config_t *
1748  u32 sw_if_index,
1749  u32 * flags, u32 * unsupported)
1750 {
1754  main_intf_t *main_intf;
1755  vlan_table_t *vlan_table;
1756  qinq_table_t *qinq_table;
1757  subint_config_t *subint = 0;
1758 
1759  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1760 
1761  if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1762  {
1763  *unsupported = 0;
1764  goto done; // non-ethernet interface
1765  }
1766 
1767  // ensure there's an entry for the main intf (shouldn't really be necessary)
1768  vec_validate (em->main_intfs, hi->hw_if_index);
1769  main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1770 
1771  // Locate the subint for the given ethernet config
1772  si = vnet_get_sw_interface (vnm, sw_if_index);
1773 
1774  if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1775  {
1776  p2p_ethernet_main_t *p2pm = &p2p_main;
1777  u32 p2pe_sw_if_index =
1779  if (p2pe_sw_if_index == ~0)
1780  {
1781  pool_get (p2pm->p2p_subif_pool, subint);
1782  si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1783  }
1784  else
1785  subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1786  *flags = SUBINT_CONFIG_P2P;
1787  }
1788  else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1789  {
1790  pipe_t *pipe;
1791 
1792  pipe = pipe_get (sw_if_index);
1793  subint = &pipe->subint;
1794  *flags = SUBINT_CONFIG_P2P;
1795  }
1796  else if (si->sub.eth.flags.default_sub)
1797  {
1798  subint = &main_intf->default_subint;
1799  *flags = SUBINT_CONFIG_MATCH_1_TAG |
1801  }
1802  else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1803  {
1804  // if no flags are set then this is a main interface
1805  // so treat as untagged
1806  subint = &main_intf->untagged_subint;
1807  *flags = SUBINT_CONFIG_MATCH_0_TAG;
1808  }
1809  else
1810  {
1811  // one or two tags
1812  // first get the vlan table
1813  if (si->sub.eth.flags.dot1ad)
1814  {
1815  if (main_intf->dot1ad_vlans == 0)
1816  {
1817  // Allocate a vlan table from the pool
1818  pool_get (em->vlan_pool, vlan_table);
1819  main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1820  }
1821  else
1822  {
1823  // Get ptr to existing vlan table
1824  vlan_table =
1825  vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1826  }
1827  }
1828  else
1829  { // dot1q
1830  if (main_intf->dot1q_vlans == 0)
1831  {
1832  // Allocate a vlan table from the pool
1833  pool_get (em->vlan_pool, vlan_table);
1834  main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1835  }
1836  else
1837  {
1838  // Get ptr to existing vlan table
1839  vlan_table =
1840  vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1841  }
1842  }
1843 
1844  if (si->sub.eth.flags.one_tag)
1845  {
1846  *flags = si->sub.eth.flags.exact_match ?
1850 
1851  if (si->sub.eth.flags.outer_vlan_id_any)
1852  {
1853  // not implemented yet
1854  *unsupported = 1;
1855  goto done;
1856  }
1857  else
1858  {
1859  // a single vlan, a common case
1860  subint =
1861  &vlan_table->vlans[si->sub.eth.
1862  outer_vlan_id].single_tag_subint;
1863  }
1864 
1865  }
1866  else
1867  {
1868  // Two tags
1869  *flags = si->sub.eth.flags.exact_match ?
1872 
1873  if (si->sub.eth.flags.outer_vlan_id_any
1874  && si->sub.eth.flags.inner_vlan_id_any)
1875  {
1876  // not implemented yet
1877  *unsupported = 1;
1878  goto done;
1879  }
1880 
1881  if (si->sub.eth.flags.inner_vlan_id_any)
1882  {
1883  // a specific outer and "any" inner
1884  // don't need a qinq table for this
1885  subint =
1886  &vlan_table->vlans[si->sub.eth.
1887  outer_vlan_id].inner_any_subint;
1888  if (si->sub.eth.flags.exact_match)
1889  {
1890  *flags = SUBINT_CONFIG_MATCH_2_TAG;
1891  }
1892  else
1893  {
1894  *flags = SUBINT_CONFIG_MATCH_2_TAG |
1896  }
1897  }
1898  else
1899  {
1900  // a specific outer + specifc innner vlan id, a common case
1901 
1902  // get the qinq table
1903  if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1904  {
1905  // Allocate a qinq table from the pool
1906  pool_get (em->qinq_pool, qinq_table);
1907  vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1908  qinq_table - em->qinq_pool;
1909  }
1910  else
1911  {
1912  // Get ptr to existing qinq table
1913  qinq_table =
1915  vlan_table->vlans[si->sub.
1916  eth.outer_vlan_id].
1917  qinqs);
1918  }
1919  subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1920  }
1921  }
1922  }
1923 
1924 done:
1925  return subint;
1926 }
1927 
1928 static clib_error_t *
1930 {
1931  subint_config_t *subint;
1932  u32 placeholder_flags;
1933  u32 placeholder_unsup;
1934  clib_error_t *error = 0;
1935 
1936  // Find the config for this subinterface
1937  subint =
1938  ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1939  &placeholder_unsup);
1940 
1941  if (subint == 0)
1942  {
1943  // not implemented yet or not ethernet
1944  goto done;
1945  }
1946 
1947  subint->sw_if_index =
1948  ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1949 
1950 done:
1951  return error;
1952 }
1953 
1955 
1956 
1957 #ifndef CLIB_MARCH_VARIANT
1958 // Set the L2/L3 mode for the subinterface
1959 void
1961 {
1962  subint_config_t *subint;
1963  u32 placeholder_flags;
1964  u32 placeholder_unsup;
1965  int is_port;
1966  vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1967 
1968  is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1969 
1970  // Find the config for this subinterface
1971  subint =
1972  ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1973  &placeholder_unsup);
1974 
1975  if (subint == 0)
1976  {
1977  // unimplemented or not ethernet
1978  goto done;
1979  }
1980 
1981  // Double check that the config we found is for our interface (or the interface is down)
1982  ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
1983 
1984  if (l2)
1985  {
1986  subint->flags |= SUBINT_CONFIG_L2;
1987  if (is_port)
1988  subint->flags |=
1991  }
1992  else
1993  {
1994  subint->flags &= ~SUBINT_CONFIG_L2;
1995  if (is_port)
1996  subint->flags &=
1999  }
2000 
2001 done:
2002  return;
2003 }
2004 
2005 /*
2006  * Set the L2/L3 mode for the subinterface regardless of port
2007  */
2008 void
2010  u32 sw_if_index, u32 l2)
2011 {
2012  subint_config_t *subint;
2013  u32 placeholder_flags;
2014  u32 placeholder_unsup;
2015 
2016  /* Find the config for this subinterface */
2017  subint =
2018  ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
2019  &placeholder_unsup);
2020 
2021  if (subint == 0)
2022  {
2023  /* unimplemented or not ethernet */
2024  goto done;
2025  }
2026 
2027  /*
2028  * Double check that the config we found is for our interface (or the
2029  * interface is down)
2030  */
2031  ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2032 
2033  if (l2)
2034  {
2035  subint->flags |= SUBINT_CONFIG_L2;
2036  }
2037  else
2038  {
2039  subint->flags &= ~SUBINT_CONFIG_L2;
2040  }
2041 
2042 done:
2043  return;
2044 }
2045 #endif
2046 
2047 static clib_error_t *
2049  u32 sw_if_index, u32 is_create)
2050 {
2051  clib_error_t *error = 0;
2052  subint_config_t *subint;
2053  u32 match_flags;
2054  u32 unsupported = 0;
2055 
2056  // Find the config for this subinterface
2057  subint =
2058  ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2059  &unsupported);
2060 
2061  if (subint == 0)
2062  {
2063  // not implemented yet or not ethernet
2064  if (unsupported)
2065  {
2066  // this is the NYI case
2067  error = clib_error_return (0, "not implemented yet");
2068  }
2069  goto done;
2070  }
2071 
2072  if (!is_create)
2073  {
2074  subint->flags = 0;
2075  return error;
2076  }
2077 
2078  // Initialize the subint
2079  if (subint->flags & SUBINT_CONFIG_VALID)
2080  {
2081  // Error vlan already in use
2082  error = clib_error_return (0, "vlan is already in use");
2083  }
2084  else
2085  {
2086  // Note that config is L3 by default
2087  subint->flags = SUBINT_CONFIG_VALID | match_flags;
2088  subint->sw_if_index = ~0; // because interfaces are initially down
2089  }
2090 
2091 done:
2092  return error;
2093 }
2094 
2096 
2097 static char *ethernet_error_strings[] = {
2098 #define ethernet_error(n,c,s) s,
2099 #include "error.def"
2100 #undef ethernet_error
2101 };
2102 
2103 /* *INDENT-OFF* */
2105  .name = "ethernet-input",
2106  /* Takes a vector of packets. */
2107  .vector_size = sizeof (u32),
2108  .scalar_size = sizeof (ethernet_input_frame_t),
2109  .n_errors = ETHERNET_N_ERROR,
2110  .error_strings = ethernet_error_strings,
2111  .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2112  .next_nodes = {
2113 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2115 #undef _
2116  },
2117  .format_buffer = format_ethernet_header_with_length,
2118  .format_trace = format_ethernet_input_trace,
2119  .unformat_buffer = unformat_ethernet_header,
2120 };
2121 
2123  .name = "ethernet-input-type",
2124  /* Takes a vector of packets. */
2125  .vector_size = sizeof (u32),
2126  .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2127  .next_nodes = {
2128 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2130 #undef _
2131  },
2132 };
2133 
2135  .name = "ethernet-input-not-l2",
2136  /* Takes a vector of packets. */
2137  .vector_size = sizeof (u32),
2138  .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2139  .next_nodes = {
2140 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2142 #undef _
2143  },
2144 };
2145 /* *INDENT-ON* */
2146 
2147 #ifndef CLIB_MARCH_VARIANT
2148 void
2150  vnet_hw_interface_t * hi, u32 enable)
2151 {
2152  // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2153  // don't go directly to ip4-input)
2155  (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2156 }
2157 
2158 
2159 /*
2160  * Initialization and registration for the next_by_ethernet structure
2161  */
2162 
2163 clib_error_t *
2165 {
2167  ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2168  /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2169 
2171  ETHERNET_INPUT_NEXT_DROP);
2173  ETHERNET_INPUT_NEXT_PUNT);
2174  l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2176  l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2178 
2179  /*
2180  * Make sure we don't wipe out an ethernet registration by mistake
2181  * Can happen if init function ordering constraints are missing.
2182  */
2183  if (CLIB_DEBUG > 0)
2184  {
2187  }
2188 
2189  return 0;
2190 }
2191 
2192 // Add an ethertype -> next index mapping to the structure
2193 clib_error_t *
2195  u32 ethertype, u32 next_index)
2196 {
2197  u32 i;
2198  u16 *n;
2200 
2201  if (CLIB_DEBUG > 0)
2202  {
2205  }
2206 
2207  /* Setup ethernet type -> next index sparse vector mapping. */
2208  n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2209  n[0] = next_index;
2210 
2211  /* Rebuild next index -> sparse index inverse mapping when sparse vector
2212  is updated. */
2213  vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2214  for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2215  l3_next->
2216  sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2217 
2218  // do not allow the cached next index's to be updated if L3
2219  // redirect is enabled, as it will have overwritten them
2220  if (!em->redirect_l3)
2221  {
2222  // Cache common ethertypes directly
2223  if (ethertype == ETHERNET_TYPE_IP4)
2224  {
2225  l3_next->input_next_ip4 = next_index;
2226  }
2227  else if (ethertype == ETHERNET_TYPE_IP6)
2228  {
2229  l3_next->input_next_ip6 = next_index;
2230  }
2231  else if (ethertype == ETHERNET_TYPE_MPLS)
2232  {
2233  l3_next->input_next_mpls = next_index;
2234  }
2235  }
2236  return 0;
2237 }
2238 
2239 void
2241 {
2242  __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2243  __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2244 
2248 
2250 
2251  // Initialize pools and vector for vlan parsing
2252  vec_validate (em->main_intfs, 10); // 10 main interfaces
2253  pool_alloc (em->vlan_pool, 10);
2254  pool_alloc (em->qinq_pool, 1);
2255 
2256  // The first vlan pool will always be reserved for an invalid table
2257  pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2258  // The first qinq pool will always be reserved for an invalid table
2259  pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2260 }
2261 
2262 void
2265 {
2268  u32 i;
2269 
2270  {
2272  if (error)
2273  clib_error_report (error);
2274  }
2275 
2276  ti = ethernet_get_type_info (em, type);
2277  if (ti == 0)
2278  {
2279  clib_warning ("type_info NULL for type %d", type);
2280  return;
2281  }
2282  ti->node_index = node_index;
2283  ti->next_index = vlib_node_add_next (vm,
2284  ethernet_input_node.index, node_index);
2285  i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2286  ASSERT (i == ti->next_index);
2287 
2288  i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2289  ASSERT (i == ti->next_index);
2290 
2291  // Add the L3 node for this ethertype to the next nodes structure
2292  next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2293 
2294  // Call the registration functions for other nodes that want a mapping
2295  l2bvi_register_input_type (vm, type, node_index);
2296 }
2297 
2298 void
2300 {
2302  u32 i;
2303 
2304  em->l2_next =
2305  vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2306 
2307  /*
2308  * Even if we never use these arcs, we have to align the next indices...
2309  */
2310  i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2311 
2312  ASSERT (i == em->l2_next);
2313 
2314  i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2315  ASSERT (i == em->l2_next);
2316 }
2317 
2318 // Register a next node for L3 redirect, and enable L3 redirect
2319 void
2321 {
2323  u32 i;
2324 
2325  em->redirect_l3 = 1;
2327  ethernet_input_node.index,
2328  node_index);
2329  /*
2330  * Change the cached next nodes to the redirect node
2331  */
2335 
2336  /*
2337  * Even if we never use these arcs, we have to align the next indices...
2338  */
2339  i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2340 
2341  ASSERT (i == em->redirect_l3_next);
2342 
2343  i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2344 
2345  ASSERT (i == em->redirect_l3_next);
2346 }
2347 #endif
2348 
2349 /*
2350  * fd.io coding-style-patch-verification: ON
2351  *
2352  * Local Variables:
2353  * eval: (c-set-style "gnu")
2354  * End:
2355  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:133
static char * ethernet_error_strings[]
Definition: node.c:2097
subint_config_t subint
Definition: ethernet.h:254
pcap_main_t pcap_main
Definition: vnet.h:71
#define clib_min(x, y)
Definition: clib.h:342
vlib_node_registration_t ethernet_input_type_node
(constructor) VLIB_REGISTER_NODE (ethernet_input_type_node)
Definition: node.c:2122
#define CLIB_UNUSED(x)
Definition: clib.h:90
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:506
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ethernet_sw_interface_add_del)
vnet_hw_if_output_node_runtime_t * r
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 max_bytes_per_pkt
Definition: vnet.h:69
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
Definition: esp_encrypt.c:1328
static_always_inline void eth_input_single_int(vlib_main_t *vm, vlib_node_runtime_t *node, vnet_hw_interface_t *hi, u32 *from, u32 n_pkts, int ip4_cksum_ok)
Definition: node.c:1086
static_always_inline void eth_input_get_etype_and_tags(vlib_buffer_t **b, u16 *etype, u64 *tags, u64 *dmacs, int offset, int dmac_check)
Definition: node.c:451
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:367
vnet_interface_main_t interface_main
Definition: vnet.h:81
vnet_p2p_sub_interface_t p2p
Definition: interface.h:895
u32 n_bytes
u32 thread_index
#define PREDICT_TRUE(x)
Definition: clib.h:125
void ethernet_input_init(vlib_main_t *vm, ethernet_main_t *em)
Definition: node.c:2240
ethernet_type_t
Definition: packet.h:45
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
unsigned long u64
Definition: types.h:89
#define DMAC_MASK
Definition: node.c:628
static_always_inline u8 eth_input_sec_dmac_check_x1(u64 hwaddr, u64 *dmac, u8 *dmac_bad)
Definition: node.c:665
static_always_inline void eth_input_adv_and_flags_x4(vlib_buffer_t **b, int is_l3)
Definition: node.c:331
u16 nexts[VLIB_FRAME_SIZE]
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
#define DMAC_IGBIT
Definition: node.c:629
ethernet_interface_t * interfaces
Definition: ethernet.h:304
#define SUBINT_CONFIG_MATCH_0_TAG
Definition: ethernet.h:215
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:463
void ethernet_register_l2_input(vlib_main_t *vm, u32 node_index)
Definition: node.c:2299
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:213
static_always_inline void eth_input_tag_lookup(vlib_main_t *vm, vnet_main_t *vnm, vlib_node_runtime_t *node, vnet_hw_interface_t *hi, u64 tag, u16 *next, vlib_buffer_t *b, eth_input_tag_lookup_t *l, u8 dmac_bad, int is_dot1ad, int main_is_l3, int check_dmac)
Definition: node.c:506
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
void ethernet_register_l3_redirect(vlib_main_t *vm, u32 node_index)
Definition: node.c:2320
static clib_error_t * ethernet_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
Definition: node.c:2048
static u32 format_get_indent(u8 *s)
Definition: format.h:72
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:73
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
static_always_inline void eth_input_adv_and_flags_x1(vlib_buffer_t **b, int is_l3)
Definition: node.c:433
subint_config_t inner_any_subint
Definition: ethernet.h:243
u8 packet_data[32]
Definition: node.c:66
#define VLIB_NODE_FN(node)
Definition: node.h:202
static_always_inline void determine_next_node(ethernet_main_t *em, ethernet_input_variant_t variant, u32 is_l20, u32 type0, vlib_buffer_t *b0, u8 *error0, u8 *next0)
Definition: node.c:257
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:461
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
vhost_vring_addr_t addr
Definition: vhost_user.h:130
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1177
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
static_always_inline void u64x4_scatter(u64x4 r, void *p0, void *p1, void *p2, void *p3)
Definition: vector_avx2.h:277
static_always_inline void ethernet_input_inline_dmac_check(vnet_hw_interface_t *hi, u64 *dmacs, u8 *dmacs_bad, u32 n_packets, ethernet_interface_t *ei, u8 have_sec_dmac)
Definition: node.c:692
u8 data[128]
Definition: ipsec_types.api:92
static_always_inline void eth_input_process_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vnet_hw_interface_t *hi, u32 *buffer_indices, u32 n_packets, int main_is_l3, int ip4_cksum_ok, int dmac_check)
Definition: node.c:834
unsigned int u32
Definition: types.h:88
ethernet_main_t ethernet_main
Definition: init.c:45
static_always_inline u8 is_sec_dmac_bad(u64 dmac, u64 hwaddr)
Definition: node.c:649
representation of a pipe interface
Definition: pipe.h:24
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
#define static_always_inline
Definition: clib.h:112
vlib_get_buffers(vm, from, b, n_left_from)
static_always_inline void identify_subint(ethernet_main_t *em, vnet_hw_interface_t *hi, vlib_buffer_t *b0, u32 match_flags, main_intf_t *main_intf, vlan_intf_t *vlan_intf, qinq_intf_t *qinq_intf, u32 *new_sw_if_index, u8 *error0, u32 *is_l2)
Definition: node.c:207
static clib_error_t * ethernet_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: node.c:1929
main_intf_t * main_intfs
Definition: ethernet.h:313
#define ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX
Definition: ethernet.h:52
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:1023
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
void ethernet_set_rx_redirect(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 enable)
Definition: node.c:2149
description fragment has unexpected format
Definition: map.api:433
#define sparse_vec_validate(v, i)
Definition: sparse_vec.h:231
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
subint_config_t default_subint
Definition: ethernet.h:235
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
vnet_main_t * vnet_get_main(void)
u8 pcap_rx_enable
Definition: vnet.h:63
vlib_node_registration_t ethernet_input_node
(constructor) VLIB_REGISTER_NODE (ethernet_input_node)
Definition: node.c:2104
u32 redirect_l3_next
Definition: ethernet.h:301
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
#define vlib_call_init_function(vm, x)
Definition: init.h:259
#define VLIB_FRAME_SIZE
Definition: node.h:369
ethernet_interface_address_t * secondary_addrs
Definition: ethernet.h:177
pool_header_t * ph(void *p)
GDB callable function: ph - call pool_header - get pool header.
Definition: gdb_funcs.c:78
epu8_epi32 epu16_epi32 u64x2
Definition: vector_sse42.h:641
clib_error_t * next_by_ethertype_init(next_by_ethertype_t *l3_next)
Definition: node.c:2164
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
Definition: cJSON.c:88
static_always_inline u32 eth_input_sec_dmac_check_x4(u64 hwaddr, u64 *dmac, u8 *dmac_bad)
Definition: node.c:672
u16 dot1q_vlans
Definition: ethernet.h:236
u16 * next
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
subint_config_t single_tag_subint
Definition: ethernet.h:242
vnet_sub_interface_t sub
Definition: interface.h:892
u32 * sparse_index_by_input_next_index
Definition: ethernet.h:270
static u8 * format_ethernet_input_trace(u8 *s, va_list *va)
Definition: node.c:72
static ethernet_type_info_t * ethernet_get_type_info(ethernet_main_t *em, ethernet_type_t type)
Definition: ethernet.h:344
qinq_table_t * qinq_pool
Definition: ethernet.h:319
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(bond_sw_interface_up_down)
ethernet_input_next_t
Definition: node.c:56
clib_error_t * next_by_ethertype_register(next_by_ethertype_t *l3_next, u32 ethertype, u32 next_index)
Definition: node.c:2194
unsigned short u16
Definition: types.h:57
static_always_inline u64x4 u64x4_gather(void *p0, void *p1, void *p2, void *p3)
Definition: vector_avx2.h:256
_mm_packus_epi16 u16x8
Definition: vector_sse42.h:196
#define ETH_INPUT_FRAME_F_IP4_CKSUM_OK
Definition: ethernet.h:55
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
#define ETHERNET_INTERFACE_FLAG_STATUS_L3
Definition: ethernet.h:157
ethernet_interface_address_t address
Definition: ethernet.h:174
STATIC_ASSERT(STRUCT_OFFSET_OF(vnet_buffer_opaque_t, l2_hdr_offset)==STRUCT_OFFSET_OF(vnet_buffer_opaque_t, l3_hdr_offset) - 2, "l3_hdr_offset must follow l2_hdr_offset")
#define PREDICT_FALSE(x)
Definition: clib.h:124
static_always_inline void ethernet_input_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:1131
#define ethernet_buffer_set_vlan_count(b, v)
Sets the number of VLAN headers in the current Ethernet frame in the buffer.
Definition: ethernet.h:436
vlib_node_registration_t ethernet_input_not_l2_node
(constructor) VLIB_REGISTER_NODE (ethernet_input_not_l2_node)
Definition: node.c:2134
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
u16 dot1ad_vlans
Definition: ethernet.h:237
#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:224
static_always_inline void parse_header(ethernet_input_variant_t variant, vlib_buffer_t *b0, u16 *type, u16 *orig_type, u16 *outer_id, u16 *inner_id, u32 *match_flags)
Definition: node.c:104
#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:395
#define SUBINT_CONFIG_MATCH_3_TAG
Definition: ethernet.h:218
u32 n_left
STATIC_ASSERT_OFFSET_OF(vlib_buffer_t, current_data, 0)
vlan_table_t * vlan_pool
Definition: ethernet.h:316
vnet_hw_interface_class_t ethernet_hw_interface_class
subint_config_t untagged_subint
Definition: ethernet.h:234
u8 len
Definition: ip_types.api:103
static_always_inline void u32x8_scatter_one(u32x8 r, int index, void *p)
Definition: vector_avx2.h:306
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:1279
u32 p2p_ethernet_lookup(u32 parent_if_index, u8 *client_mac)
Definition: p2p_ethernet.c:35
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:97
#define SUBINT_CONFIG_VALID
Definition: ethernet.h:219
epu16_epi64 epu8_epi16 epu8_epi64 epi16_epi64 i16x16
Definition: vector_avx2.h:150
u8 next_by_ethertype_register_called
Definition: ethernet.h:325
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
qinq_intf_t vlans[ETHERNET_N_VLAN]
Definition: ethernet.h:259
u16 n_vectors
Definition: node.h:388
ethernet_input_variant_t
Definition: node.c:94
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
u32 ti
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
vl_api_pnat_mask_t mask
Definition: pnat.api:45
#define clib_warning(format, args...)
Definition: error.h:59
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:116
u8 data[]
Packet data.
Definition: buffer.h:204
#define vlib_prefetch_buffer_data(b, type)
Definition: buffer.h:232
static u32 eth_identify_subint(vnet_hw_interface_t *hi, u32 match_flags, main_intf_t *main_intf, vlan_intf_t *vlan_intf, qinq_intf_t *qinq_intf, u32 *new_sw_if_index, u8 *error0, u32 *is_l2)
Definition: ethernet.h:532
static void * vlib_frame_scalar_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:315
#define SUBINT_CONFIG_MATCH_1_TAG
Definition: ethernet.h:216
static subint_config_t * ethernet_sw_interface_get_config(vnet_main_t *vnm, u32 sw_if_index, u32 *flags, u32 *unsupported)
Definition: node.c:1747
static_always_inline void eth_input_process_frame_dmac_check(vnet_hw_interface_t *hi, u64 *dmacs, u8 *dmacs_bad, u32 n_packets, ethernet_interface_t *ei, u8 have_sec_dmac)
Definition: node.c:727
static void eth_vlan_table_lookups(ethernet_main_t *em, vnet_main_t *vnm, u32 port_sw_if_index0, u16 first_ethertype, u16 outer_id, u16 inner_id, vnet_hw_interface_t **hi, main_intf_t **main_intf, vlan_intf_t **vlan_intf, qinq_intf_t **qinq_intf)
Definition: ethernet.h:493
signed int i32
Definition: types.h:77
static uword sparse_vec_index(void *v, uword sparse_index)
Definition: sparse_vec.h:161
vnet_pcap_t pcap
Definition: vnet.h:103
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:498
#define SUBINT_CONFIG_L2
Definition: ethernet.h:220
#define ASSERT(truth)
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:2263
u8 * format_ethernet_header(u8 *s, va_list *args)
Definition: format.c:178
vnet_sw_interface_t * si
u16 flags
Definition: node.h:379
static_always_inline void eth_input_update_if_counters(vlib_main_t *vm, vnet_main_t *vnm, eth_input_tag_lookup_t *l)
Definition: node.c:490
u8x32
Definition: vector_avx2.h:116
static void pcap_add_buffer(pcap_main_t *pm, struct vlib_main_t *vm, u32 buffer_index, u32 n_bytes_in_trace)
Add buffer (vlib_buffer_t) to the trace.
static_always_inline int ethernet_frame_is_tagged(u16 type)
Definition: ethernet.h:78
vlib_put_next_frame(vm, node, next_index, 0)
#define clib_error_report(e)
Definition: error.h:113
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
vlan_intf_t vlans[ETHERNET_N_VLAN]
Definition: ethernet.h:249
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
#define SUBINT_CONFIG_MATCH_2_TAG
Definition: ethernet.h:217
void ethernet_sw_interface_set_l2_mode(vnet_main_t *vnm, u32 sw_if_index, u32 l2)
Definition: node.c:1960
nat44_ei_hairpin_src_next_t next_index
vl_api_ip4_address_t hi
Definition: arp.api:37
Use the vpp classifier to decide whether to capture packets.
_mm256_packus_epi16 _mm256_packus_epi32 static_always_inline u32 u8x32_msb_mask(u8x32 v)
Definition: vector_avx2.h:123
#define vec_elt(v, i)
Get vector value at index i.
subint_config_t subint
Sub-interface config.
Definition: pipe.h:30
struct _vlib_node_registration vlib_node_registration_t
next_by_ethertype_t l3_next
Definition: ethernet.h:294
template key/value backing page structure
Definition: bihash_doc.h:44
#define SUBINT_CONFIG_P2P
Definition: ethernet.h:221
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:982
void l2bvi_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: l2_bvi.c:29
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
pipe_t * pipe_get(u32 sw_if_index)
Get the pipe instnace based on one end.
Definition: pipe.c:95
static_always_inline void ethernet_input_inline(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *from, u32 n_packets, ethernet_input_variant_t variant)
Definition: node.c:1184
static_always_inline int ethernet_frame_is_any_tagged_x2(u16 type0, u16 type1)
Definition: ethernet.h:92
VLIB buffer representation.
Definition: buffer.h:111
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
static clib_error_t * ethernet_init(vlib_main_t *vm)
Definition: init.c:83
node node_index
void ethernet_sw_interface_set_l2_mode_noport(vnet_main_t *vnm, u32 sw_if_index, u32 l2)
Definition: node.c:2009
struct clib_bihash_value offset
template key/value backing page structure
#define vnet_buffer(b)
Definition: buffer.h:437
static_always_inline int vnet_is_packet_pcaped(vnet_pcap_t *pp, vlib_buffer_t *b, u32 sw_if_index)
vnet_is_packet_pcaped
Definition: pcap_classify.h:32
p2p_ethernet_main_t p2p_main
Definition: p2p_ethernet.c:23
vnet_sw_interface_type_t type
Definition: interface.h:870
struct vnet_sub_interface_t::@368::@369::@371 flags
#define vec_foreach(var, vec)
Vector iterator.
#define foreach_ethernet_input_next
Definition: node.c:49
#define u16x16_blend(v1, v2, mask)
Definition: vector_avx2.h:252
static_always_inline u8 is_dmac_bad(u64 dmac, u64 hwaddr)
Definition: node.c:642
u16 flags
Copy of main node flags.
Definition: node.h:492
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
subint_config_t * p2p_subif_pool
Definition: p2p_ethernet.h:31
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static void * sparse_vec_new(uword elt_bytes, uword sparse_index_bits)
Definition: sparse_vec.h:71
_mm256_packus_epi16 u16x16
Definition: vector_avx2.h:118
ethernet_input_frame_t frame_data
Definition: node.c:68
#define BITS(x)
Definition: clib.h:69
static_always_inline u16 eth_input_next_by_type(u16 etype)
Definition: node.c:470
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
u64x4
Definition: vector_avx2.h:142
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
static void ethernet_setup_node(vlib_main_t *vm, u32 node_index)
Definition: ethernet.h:408
Definition: defs.h:46
struct vnet_sub_interface_t::@368 eth
uword unformat_ethernet_header(unformat_input_t *input, va_list *args)
Definition: format.c:290
u16 * input_next_by_type
Definition: ethernet.h:269
#define SPARSE_VEC_INVALID_INDEX
Definition: sparse_vec.h:68
signed short i16
Definition: types.h:46