FD.io VPP  v21.01.1
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 {
483  u16 type, len, next;
485  u8 err, n_tags;
486  u64 n_packets, n_bytes;
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 {
840  u16 nexts[VLIB_FRAME_SIZE], *next;
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 
1132  vlib_frame_t * from_frame)
1133 {
1134  u32 *from, n_left;
1135  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1136  {
1137  from = vlib_frame_vector_args (from_frame);
1138  n_left = from_frame->n_vectors;
1139 
1140  while (n_left)
1141  {
1143  vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1144 
1145  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1146  {
1147  t0 = vlib_add_trace (vm, node, b0,
1148  sizeof (ethernet_input_trace_t));
1150  sizeof (t0->packet_data));
1151  t0->frame_flags = from_frame->flags;
1153  vlib_frame_scalar_args (from_frame),
1154  sizeof (ethernet_input_frame_t));
1155  }
1156  from += 1;
1157  n_left -= 1;
1158  }
1159  }
1160 
1161  /* rx pcap capture if enabled */
1163  {
1164  u32 bi0;
1166 
1167  from = vlib_frame_vector_args (from_frame);
1168  n_left = from_frame->n_vectors;
1169  while (n_left > 0)
1170  {
1171  int classify_filter_result;
1172  vlib_buffer_t *b0;
1173  bi0 = from[0];
1174  from++;
1175  n_left--;
1176  b0 = vlib_get_buffer (vm, bi0);
1177  if (pp->filter_classify_table_index != ~0)
1178  {
1179  classify_filter_result =
1181  (b0, pp->filter_classify_table_index, 0 /* full classify */ );
1182  if (classify_filter_result)
1183  pcap_add_buffer (&pp->pcap_main, vm, bi0,
1184  pp->max_bytes_per_pkt);
1185  continue;
1186  }
1187 
1188  if (pp->pcap_sw_if_index == 0 ||
1190  {
1191  vnet_main_t *vnm = vnet_get_main ();
1192  vnet_hw_interface_t *hi =
1194  (vnm, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1195 
1196  /* Capture pkt if not filtered, or if filter hits */
1197  if (hi->trace_classify_table_index == ~0 ||
1199  (b0, hi->trace_classify_table_index,
1200  0 /* full classify */ ))
1201  pcap_add_buffer (&pp->pcap_main, vm, bi0,
1202  pp->max_bytes_per_pkt);
1203  }
1204  }
1205  }
1206 }
1207 
1211  u32 * from, u32 n_packets,
1212  ethernet_input_variant_t variant)
1213 {
1214  vnet_main_t *vnm = vnet_get_main ();
1216  vlib_node_runtime_t *error_node;
1217  u32 n_left_from, next_index, *to_next;
1218  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1219  u32 thread_index = vm->thread_index;
1220  u32 cached_sw_if_index = ~0;
1221  u32 cached_is_l2 = 0; /* shut up gcc */
1222  vnet_hw_interface_t *hi = NULL; /* used for main interface only */
1223  ethernet_interface_t *ei = NULL;
1225  vlib_buffer_t **b = bufs;
1226 
1227  if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1228  error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1229  else
1230  error_node = node;
1231 
1232  n_left_from = n_packets;
1233 
1234  next_index = node->cached_next_index;
1235  stats_sw_if_index = node->runtime_data[0];
1236  stats_n_packets = stats_n_bytes = 0;
1237  vlib_get_buffers (vm, from, bufs, n_left_from);
1238 
1239  while (n_left_from > 0)
1240  {
1241  u32 n_left_to_next;
1242 
1243  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1244 
1245  while (n_left_from >= 4 && n_left_to_next >= 2)
1246  {
1247  u32 bi0, bi1;
1248  vlib_buffer_t *b0, *b1;
1249  u8 next0, next1, error0, error1;
1250  u16 type0, orig_type0, type1, orig_type1;
1251  u16 outer_id0, inner_id0, outer_id1, inner_id1;
1252  u32 match_flags0, match_flags1;
1253  u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1254  new_sw_if_index1, len1;
1255  vnet_hw_interface_t *hi0, *hi1;
1256  main_intf_t *main_intf0, *main_intf1;
1257  vlan_intf_t *vlan_intf0, *vlan_intf1;
1258  qinq_intf_t *qinq_intf0, *qinq_intf1;
1259  u32 is_l20, is_l21;
1260  ethernet_header_t *e0, *e1;
1261  u64 dmacs[2];
1262  u8 dmacs_bad[2];
1263 
1264  /* Prefetch next iteration. */
1265  {
1266  vlib_prefetch_buffer_header (b[2], STORE);
1267  vlib_prefetch_buffer_header (b[3], STORE);
1268 
1269  CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1270  CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1271  }
1272 
1273  bi0 = from[0];
1274  bi1 = from[1];
1275  to_next[0] = bi0;
1276  to_next[1] = bi1;
1277  from += 2;
1278  to_next += 2;
1279  n_left_to_next -= 2;
1280  n_left_from -= 2;
1281 
1282  b0 = b[0];
1283  b1 = b[1];
1284  b += 2;
1285 
1286  error0 = error1 = ETHERNET_ERROR_NONE;
1287  e0 = vlib_buffer_get_current (b0);
1288  type0 = clib_net_to_host_u16 (e0->type);
1289  e1 = vlib_buffer_get_current (b1);
1290  type1 = clib_net_to_host_u16 (e1->type);
1291 
1292  /* Set the L2 header offset for all packets */
1293  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1294  vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1295  b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1296  b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1297 
1298  /* Speed-path for the untagged case */
1301  type1)))
1302  {
1303  main_intf_t *intf0;
1304  subint_config_t *subint0;
1305  u32 sw_if_index0, sw_if_index1;
1306 
1307  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1308  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1309  is_l20 = cached_is_l2;
1310 
1311  /* This is probably wholly unnecessary */
1312  if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1313  goto slowpath;
1314 
1315  /* Now sw_if_index0 == sw_if_index1 */
1316  if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1317  {
1318  cached_sw_if_index = sw_if_index0;
1319  hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1320  ei = ethernet_get_interface (em, hi->hw_if_index);
1321  intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1322  subint0 = &intf0->untagged_subint;
1323  cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1324  }
1325 
1326  if (PREDICT_TRUE (is_l20 != 0))
1327  {
1328  vnet_buffer (b0)->l3_hdr_offset =
1329  vnet_buffer (b0)->l2_hdr_offset +
1330  sizeof (ethernet_header_t);
1331  vnet_buffer (b1)->l3_hdr_offset =
1332  vnet_buffer (b1)->l2_hdr_offset +
1333  sizeof (ethernet_header_t);
1334  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1335  b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1336  next0 = em->l2_next;
1337  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1338  next1 = em->l2_next;
1339  vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1340  }
1341  else
1342  {
1344  goto skip_dmac_check01;
1345 
1346  dmacs[0] = *(u64 *) e0;
1347  dmacs[1] = *(u64 *) e1;
1348 
1349  if (ei && vec_len (ei->secondary_addrs))
1351  dmacs_bad,
1352  2 /* n_packets */ ,
1353  ei,
1354  1 /* have_sec_dmac */ );
1355  else
1357  dmacs_bad,
1358  2 /* n_packets */ ,
1359  ei,
1360  0 /* have_sec_dmac */ );
1361 
1362  if (dmacs_bad[0])
1363  error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1364  if (dmacs_bad[1])
1365  error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1366 
1367  skip_dmac_check01:
1368  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1369  determine_next_node (em, variant, 0, type0, b0,
1370  &error0, &next0);
1371  vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1372  determine_next_node (em, variant, 0, type1, b1,
1373  &error1, &next1);
1374  }
1375  goto ship_it01;
1376  }
1377 
1378  /* Slow-path for the tagged case */
1379  slowpath:
1380  parse_header (variant,
1381  b0,
1382  &type0,
1383  &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1384 
1385  parse_header (variant,
1386  b1,
1387  &type1,
1388  &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1389 
1390  old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1391  old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1392 
1394  vnm,
1395  old_sw_if_index0,
1396  orig_type0,
1397  outer_id0,
1398  inner_id0,
1399  &hi0,
1400  &main_intf0, &vlan_intf0, &qinq_intf0);
1401 
1403  vnm,
1404  old_sw_if_index1,
1405  orig_type1,
1406  outer_id1,
1407  inner_id1,
1408  &hi1,
1409  &main_intf1, &vlan_intf1, &qinq_intf1);
1410 
1411  identify_subint (em,
1412  hi0,
1413  b0,
1414  match_flags0,
1415  main_intf0,
1416  vlan_intf0,
1417  qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1418 
1419  identify_subint (em,
1420  hi1,
1421  b1,
1422  match_flags1,
1423  main_intf1,
1424  vlan_intf1,
1425  qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1426 
1427  // Save RX sw_if_index for later nodes
1428  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1429  error0 !=
1430  ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1431  vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1432  error1 !=
1433  ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1434 
1435  // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1436  if (((new_sw_if_index0 != ~0)
1437  && (new_sw_if_index0 != old_sw_if_index0))
1438  || ((new_sw_if_index1 != ~0)
1439  && (new_sw_if_index1 != old_sw_if_index1)))
1440  {
1441 
1442  len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1443  - vnet_buffer (b0)->l2_hdr_offset;
1444  len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1445  - vnet_buffer (b1)->l2_hdr_offset;
1446 
1447  stats_n_packets += 2;
1448  stats_n_bytes += len0 + len1;
1449 
1450  if (PREDICT_FALSE
1451  (!(new_sw_if_index0 == stats_sw_if_index
1452  && new_sw_if_index1 == stats_sw_if_index)))
1453  {
1454  stats_n_packets -= 2;
1455  stats_n_bytes -= len0 + len1;
1456 
1457  if (new_sw_if_index0 != old_sw_if_index0
1458  && new_sw_if_index0 != ~0)
1460  interface_main.combined_sw_if_counters
1461  +
1463  thread_index,
1464  new_sw_if_index0, 1,
1465  len0);
1466  if (new_sw_if_index1 != old_sw_if_index1
1467  && new_sw_if_index1 != ~0)
1469  interface_main.combined_sw_if_counters
1470  +
1472  thread_index,
1473  new_sw_if_index1, 1,
1474  len1);
1475 
1476  if (new_sw_if_index0 == new_sw_if_index1)
1477  {
1478  if (stats_n_packets > 0)
1479  {
1483  thread_index,
1484  stats_sw_if_index,
1485  stats_n_packets, stats_n_bytes);
1486  stats_n_packets = stats_n_bytes = 0;
1487  }
1488  stats_sw_if_index = new_sw_if_index0;
1489  }
1490  }
1491  }
1492 
1493  if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1494  is_l20 = is_l21 = 0;
1495 
1496  determine_next_node (em, variant, is_l20, type0, b0, &error0,
1497  &next0);
1498  determine_next_node (em, variant, is_l21, type1, b1, &error1,
1499  &next1);
1500 
1501  ship_it01:
1502  b0->error = error_node->errors[error0];
1503  b1->error = error_node->errors[error1];
1504 
1505  // verify speculative enqueue
1506  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1507  n_left_to_next, bi0, bi1, next0,
1508  next1);
1509  }
1510 
1511  while (n_left_from > 0 && n_left_to_next > 0)
1512  {
1513  u32 bi0;
1514  vlib_buffer_t *b0;
1515  u8 error0, next0;
1516  u16 type0, orig_type0;
1517  u16 outer_id0, inner_id0;
1518  u32 match_flags0;
1519  u32 old_sw_if_index0, new_sw_if_index0, len0;
1520  vnet_hw_interface_t *hi0;
1521  main_intf_t *main_intf0;
1522  vlan_intf_t *vlan_intf0;
1523  qinq_intf_t *qinq_intf0;
1524  ethernet_header_t *e0;
1525  u32 is_l20;
1526  u64 dmacs[2];
1527  u8 dmacs_bad[2];
1528 
1529  // Prefetch next iteration
1530  if (n_left_from > 1)
1531  {
1532  vlib_prefetch_buffer_header (b[1], STORE);
1533  CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1534  }
1535 
1536  bi0 = from[0];
1537  to_next[0] = bi0;
1538  from += 1;
1539  to_next += 1;
1540  n_left_from -= 1;
1541  n_left_to_next -= 1;
1542 
1543  b0 = b[0];
1544  b += 1;
1545 
1546  error0 = ETHERNET_ERROR_NONE;
1547  e0 = vlib_buffer_get_current (b0);
1548  type0 = clib_net_to_host_u16 (e0->type);
1549 
1550  /* Set the L2 header offset for all packets */
1551  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1552  b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1553 
1554  /* Speed-path for the untagged case */
1556  && !ethernet_frame_is_tagged (type0)))
1557  {
1558  main_intf_t *intf0;
1559  subint_config_t *subint0;
1560  u32 sw_if_index0;
1561 
1562  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1563  is_l20 = cached_is_l2;
1564 
1565  if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1566  {
1567  cached_sw_if_index = sw_if_index0;
1568  hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1569  ei = ethernet_get_interface (em, hi->hw_if_index);
1570  intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1571  subint0 = &intf0->untagged_subint;
1572  cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1573  }
1574 
1575 
1576  if (PREDICT_TRUE (is_l20 != 0))
1577  {
1578  vnet_buffer (b0)->l3_hdr_offset =
1579  vnet_buffer (b0)->l2_hdr_offset +
1580  sizeof (ethernet_header_t);
1581  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1582  next0 = em->l2_next;
1583  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1584  }
1585  else
1586  {
1588  goto skip_dmac_check0;
1589 
1590  dmacs[0] = *(u64 *) e0;
1591 
1592  if (ei && vec_len (ei->secondary_addrs))
1594  dmacs_bad,
1595  1 /* n_packets */ ,
1596  ei,
1597  1 /* have_sec_dmac */ );
1598  else
1600  dmacs_bad,
1601  1 /* n_packets */ ,
1602  ei,
1603  0 /* have_sec_dmac */ );
1604 
1605  if (dmacs_bad[0])
1606  error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1607 
1608  skip_dmac_check0:
1609  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1610  determine_next_node (em, variant, 0, type0, b0,
1611  &error0, &next0);
1612  }
1613  goto ship_it0;
1614  }
1615 
1616  /* Slow-path for the tagged case */
1617  parse_header (variant,
1618  b0,
1619  &type0,
1620  &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1621 
1622  old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1623 
1625  vnm,
1626  old_sw_if_index0,
1627  orig_type0,
1628  outer_id0,
1629  inner_id0,
1630  &hi0,
1631  &main_intf0, &vlan_intf0, &qinq_intf0);
1632 
1633  identify_subint (em,
1634  hi0,
1635  b0,
1636  match_flags0,
1637  main_intf0,
1638  vlan_intf0,
1639  qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1640 
1641  // Save RX sw_if_index for later nodes
1642  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1643  error0 !=
1644  ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1645 
1646  // Increment subinterface stats
1647  // Note that interface-level counters have already been incremented
1648  // prior to calling this function. Thus only subinterface counters
1649  // are incremented here.
1650  //
1651  // Interface level counters include packets received on the main
1652  // interface and all subinterfaces. Subinterface level counters
1653  // include only those packets received on that subinterface
1654  // Increment stats if the subint is valid and it is not the main intf
1655  if ((new_sw_if_index0 != ~0)
1656  && (new_sw_if_index0 != old_sw_if_index0))
1657  {
1658 
1659  len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1660  - vnet_buffer (b0)->l2_hdr_offset;
1661 
1662  stats_n_packets += 1;
1663  stats_n_bytes += len0;
1664 
1665  // Batch stat increments from the same subinterface so counters
1666  // don't need to be incremented for every packet.
1667  if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1668  {
1669  stats_n_packets -= 1;
1670  stats_n_bytes -= len0;
1671 
1672  if (new_sw_if_index0 != ~0)
1676  thread_index, new_sw_if_index0, 1, len0);
1677  if (stats_n_packets > 0)
1678  {
1682  thread_index,
1683  stats_sw_if_index, stats_n_packets, stats_n_bytes);
1684  stats_n_packets = stats_n_bytes = 0;
1685  }
1686  stats_sw_if_index = new_sw_if_index0;
1687  }
1688  }
1689 
1690  if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1691  is_l20 = 0;
1692 
1693  determine_next_node (em, variant, is_l20, type0, b0, &error0,
1694  &next0);
1695 
1696  ship_it0:
1697  b0->error = error_node->errors[error0];
1698 
1699  // verify speculative enqueue
1700  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1701  to_next, n_left_to_next,
1702  bi0, next0);
1703  }
1704 
1705  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1706  }
1707 
1708  // Increment any remaining batched stats
1709  if (stats_n_packets > 0)
1710  {
1714  thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1715  node->runtime_data[0] = stats_sw_if_index;
1716  }
1717 }
1718 
1721  vlib_frame_t * frame)
1722 {
1723  vnet_main_t *vnm = vnet_get_main ();
1724  u32 *from = vlib_frame_vector_args (frame);
1725  u32 n_packets = frame->n_vectors;
1726 
1728 
1730  {
1732  int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1734  eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1735  }
1736  else
1737  ethernet_input_inline (vm, node, from, n_packets,
1739  return n_packets;
1740 }
1741 
1744  vlib_frame_t * from_frame)
1745 {
1746  u32 *from = vlib_frame_vector_args (from_frame);
1747  u32 n_packets = from_frame->n_vectors;
1748  ethernet_input_trace (vm, node, from_frame);
1749  ethernet_input_inline (vm, node, from, n_packets,
1751  return n_packets;
1752 }
1753 
1756  vlib_frame_t * from_frame)
1757 {
1758  u32 *from = vlib_frame_vector_args (from_frame);
1759  u32 n_packets = from_frame->n_vectors;
1760  ethernet_input_trace (vm, node, from_frame);
1761  ethernet_input_inline (vm, node, from, n_packets,
1763  return n_packets;
1764 }
1765 
1766 
1767 // Return the subinterface config struct for the given sw_if_index
1768 // Also return via parameter the appropriate match flags for the
1769 // configured number of tags.
1770 // On error (unsupported or not ethernet) return 0.
1771 static subint_config_t *
1773  u32 sw_if_index,
1774  u32 * flags, u32 * unsupported)
1775 {
1779  main_intf_t *main_intf;
1780  vlan_table_t *vlan_table;
1781  qinq_table_t *qinq_table;
1782  subint_config_t *subint = 0;
1783 
1784  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1785 
1786  if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1787  {
1788  *unsupported = 0;
1789  goto done; // non-ethernet interface
1790  }
1791 
1792  // ensure there's an entry for the main intf (shouldn't really be necessary)
1793  vec_validate (em->main_intfs, hi->hw_if_index);
1794  main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1795 
1796  // Locate the subint for the given ethernet config
1797  si = vnet_get_sw_interface (vnm, sw_if_index);
1798 
1799  if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1800  {
1801  p2p_ethernet_main_t *p2pm = &p2p_main;
1802  u32 p2pe_sw_if_index =
1804  if (p2pe_sw_if_index == ~0)
1805  {
1806  pool_get (p2pm->p2p_subif_pool, subint);
1807  si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1808  }
1809  else
1810  subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1811  *flags = SUBINT_CONFIG_P2P;
1812  }
1813  else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1814  {
1815  pipe_t *pipe;
1816 
1817  pipe = pipe_get (sw_if_index);
1818  subint = &pipe->subint;
1819  *flags = SUBINT_CONFIG_P2P;
1820  }
1821  else if (si->sub.eth.flags.default_sub)
1822  {
1823  subint = &main_intf->default_subint;
1824  *flags = SUBINT_CONFIG_MATCH_1_TAG |
1826  }
1827  else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1828  {
1829  // if no flags are set then this is a main interface
1830  // so treat as untagged
1831  subint = &main_intf->untagged_subint;
1832  *flags = SUBINT_CONFIG_MATCH_0_TAG;
1833  }
1834  else
1835  {
1836  // one or two tags
1837  // first get the vlan table
1838  if (si->sub.eth.flags.dot1ad)
1839  {
1840  if (main_intf->dot1ad_vlans == 0)
1841  {
1842  // Allocate a vlan table from the pool
1843  pool_get (em->vlan_pool, vlan_table);
1844  main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1845  }
1846  else
1847  {
1848  // Get ptr to existing vlan table
1849  vlan_table =
1850  vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1851  }
1852  }
1853  else
1854  { // dot1q
1855  if (main_intf->dot1q_vlans == 0)
1856  {
1857  // Allocate a vlan table from the pool
1858  pool_get (em->vlan_pool, vlan_table);
1859  main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1860  }
1861  else
1862  {
1863  // Get ptr to existing vlan table
1864  vlan_table =
1865  vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1866  }
1867  }
1868 
1869  if (si->sub.eth.flags.one_tag)
1870  {
1871  *flags = si->sub.eth.flags.exact_match ?
1875 
1876  if (si->sub.eth.flags.outer_vlan_id_any)
1877  {
1878  // not implemented yet
1879  *unsupported = 1;
1880  goto done;
1881  }
1882  else
1883  {
1884  // a single vlan, a common case
1885  subint =
1886  &vlan_table->vlans[si->sub.eth.
1887  outer_vlan_id].single_tag_subint;
1888  }
1889 
1890  }
1891  else
1892  {
1893  // Two tags
1894  *flags = si->sub.eth.flags.exact_match ?
1897 
1898  if (si->sub.eth.flags.outer_vlan_id_any
1899  && si->sub.eth.flags.inner_vlan_id_any)
1900  {
1901  // not implemented yet
1902  *unsupported = 1;
1903  goto done;
1904  }
1905 
1906  if (si->sub.eth.flags.inner_vlan_id_any)
1907  {
1908  // a specific outer and "any" inner
1909  // don't need a qinq table for this
1910  subint =
1911  &vlan_table->vlans[si->sub.eth.
1912  outer_vlan_id].inner_any_subint;
1913  if (si->sub.eth.flags.exact_match)
1914  {
1915  *flags = SUBINT_CONFIG_MATCH_2_TAG;
1916  }
1917  else
1918  {
1919  *flags = SUBINT_CONFIG_MATCH_2_TAG |
1921  }
1922  }
1923  else
1924  {
1925  // a specific outer + specifc innner vlan id, a common case
1926 
1927  // get the qinq table
1928  if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1929  {
1930  // Allocate a qinq table from the pool
1931  pool_get (em->qinq_pool, qinq_table);
1932  vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1933  qinq_table - em->qinq_pool;
1934  }
1935  else
1936  {
1937  // Get ptr to existing qinq table
1938  qinq_table =
1940  vlan_table->vlans[si->sub.
1941  eth.outer_vlan_id].
1942  qinqs);
1943  }
1944  subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1945  }
1946  }
1947  }
1948 
1949 done:
1950  return subint;
1951 }
1952 
1953 static clib_error_t *
1955 {
1956  subint_config_t *subint;
1957  u32 placeholder_flags;
1958  u32 placeholder_unsup;
1959  clib_error_t *error = 0;
1960 
1961  // Find the config for this subinterface
1962  subint =
1963  ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1964  &placeholder_unsup);
1965 
1966  if (subint == 0)
1967  {
1968  // not implemented yet or not ethernet
1969  goto done;
1970  }
1971 
1972  subint->sw_if_index =
1973  ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1974 
1975 done:
1976  return error;
1977 }
1978 
1980 
1981 
1982 #ifndef CLIB_MARCH_VARIANT
1983 // Set the L2/L3 mode for the subinterface
1984 void
1986 {
1987  subint_config_t *subint;
1988  u32 placeholder_flags;
1989  u32 placeholder_unsup;
1990  int is_port;
1991  vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1992 
1993  is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1994 
1995  // Find the config for this subinterface
1996  subint =
1997  ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1998  &placeholder_unsup);
1999 
2000  if (subint == 0)
2001  {
2002  // unimplemented or not ethernet
2003  goto done;
2004  }
2005 
2006  // Double check that the config we found is for our interface (or the interface is down)
2007  ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2008 
2009  if (l2)
2010  {
2011  subint->flags |= SUBINT_CONFIG_L2;
2012  if (is_port)
2013  subint->flags |=
2016  }
2017  else
2018  {
2019  subint->flags &= ~SUBINT_CONFIG_L2;
2020  if (is_port)
2021  subint->flags &=
2024  }
2025 
2026 done:
2027  return;
2028 }
2029 
2030 /*
2031  * Set the L2/L3 mode for the subinterface regardless of port
2032  */
2033 void
2035  u32 sw_if_index, u32 l2)
2036 {
2037  subint_config_t *subint;
2038  u32 placeholder_flags;
2039  u32 placeholder_unsup;
2040 
2041  /* Find the config for this subinterface */
2042  subint =
2043  ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
2044  &placeholder_unsup);
2045 
2046  if (subint == 0)
2047  {
2048  /* unimplemented or not ethernet */
2049  goto done;
2050  }
2051 
2052  /*
2053  * Double check that the config we found is for our interface (or the
2054  * interface is down)
2055  */
2056  ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2057 
2058  if (l2)
2059  {
2060  subint->flags |= SUBINT_CONFIG_L2;
2061  }
2062  else
2063  {
2064  subint->flags &= ~SUBINT_CONFIG_L2;
2065  }
2066 
2067 done:
2068  return;
2069 }
2070 #endif
2071 
2072 static clib_error_t *
2074  u32 sw_if_index, u32 is_create)
2075 {
2076  clib_error_t *error = 0;
2077  subint_config_t *subint;
2078  u32 match_flags;
2079  u32 unsupported = 0;
2080 
2081  // Find the config for this subinterface
2082  subint =
2083  ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2084  &unsupported);
2085 
2086  if (subint == 0)
2087  {
2088  // not implemented yet or not ethernet
2089  if (unsupported)
2090  {
2091  // this is the NYI case
2092  error = clib_error_return (0, "not implemented yet");
2093  }
2094  goto done;
2095  }
2096 
2097  if (!is_create)
2098  {
2099  subint->flags = 0;
2100  return error;
2101  }
2102 
2103  // Initialize the subint
2104  if (subint->flags & SUBINT_CONFIG_VALID)
2105  {
2106  // Error vlan already in use
2107  error = clib_error_return (0, "vlan is already in use");
2108  }
2109  else
2110  {
2111  // Note that config is L3 by default
2112  subint->flags = SUBINT_CONFIG_VALID | match_flags;
2113  subint->sw_if_index = ~0; // because interfaces are initially down
2114  }
2115 
2116 done:
2117  return error;
2118 }
2119 
2121 
2122 static char *ethernet_error_strings[] = {
2123 #define ethernet_error(n,c,s) s,
2124 #include "error.def"
2125 #undef ethernet_error
2126 };
2127 
2128 /* *INDENT-OFF* */
2130  .name = "ethernet-input",
2131  /* Takes a vector of packets. */
2132  .vector_size = sizeof (u32),
2133  .scalar_size = sizeof (ethernet_input_frame_t),
2134  .n_errors = ETHERNET_N_ERROR,
2135  .error_strings = ethernet_error_strings,
2136  .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2137  .next_nodes = {
2138 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2140 #undef _
2141  },
2142  .format_buffer = format_ethernet_header_with_length,
2143  .format_trace = format_ethernet_input_trace,
2144  .unformat_buffer = unformat_ethernet_header,
2145 };
2146 
2148  .name = "ethernet-input-type",
2149  /* Takes a vector of packets. */
2150  .vector_size = sizeof (u32),
2151  .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2152  .next_nodes = {
2153 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2155 #undef _
2156  },
2157 };
2158 
2160  .name = "ethernet-input-not-l2",
2161  /* Takes a vector of packets. */
2162  .vector_size = sizeof (u32),
2163  .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2164  .next_nodes = {
2165 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2167 #undef _
2168  },
2169 };
2170 /* *INDENT-ON* */
2171 
2172 #ifndef CLIB_MARCH_VARIANT
2173 void
2175  vnet_hw_interface_t * hi, u32 enable)
2176 {
2177  // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2178  // don't go directly to ip4-input)
2180  (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2181 }
2182 
2183 
2184 /*
2185  * Initialization and registration for the next_by_ethernet structure
2186  */
2187 
2188 clib_error_t *
2190 {
2192  ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2193  /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2194 
2196  ETHERNET_INPUT_NEXT_DROP);
2198  ETHERNET_INPUT_NEXT_PUNT);
2199  l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2201  l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2203 
2204  /*
2205  * Make sure we don't wipe out an ethernet registration by mistake
2206  * Can happen if init function ordering constraints are missing.
2207  */
2208  if (CLIB_DEBUG > 0)
2209  {
2212  }
2213 
2214  return 0;
2215 }
2216 
2217 // Add an ethertype -> next index mapping to the structure
2218 clib_error_t *
2220  u32 ethertype, u32 next_index)
2221 {
2222  u32 i;
2223  u16 *n;
2225 
2226  if (CLIB_DEBUG > 0)
2227  {
2230  }
2231 
2232  /* Setup ethernet type -> next index sparse vector mapping. */
2233  n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2234  n[0] = next_index;
2235 
2236  /* Rebuild next index -> sparse index inverse mapping when sparse vector
2237  is updated. */
2238  vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2239  for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2240  l3_next->
2241  sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2242 
2243  // do not allow the cached next index's to be updated if L3
2244  // redirect is enabled, as it will have overwritten them
2245  if (!em->redirect_l3)
2246  {
2247  // Cache common ethertypes directly
2248  if (ethertype == ETHERNET_TYPE_IP4)
2249  {
2250  l3_next->input_next_ip4 = next_index;
2251  }
2252  else if (ethertype == ETHERNET_TYPE_IP6)
2253  {
2254  l3_next->input_next_ip6 = next_index;
2255  }
2256  else if (ethertype == ETHERNET_TYPE_MPLS)
2257  {
2258  l3_next->input_next_mpls = next_index;
2259  }
2260  }
2261  return 0;
2262 }
2263 
2264 void
2266 {
2267  __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2268  __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2269 
2273 
2275 
2276  // Initialize pools and vector for vlan parsing
2277  vec_validate (em->main_intfs, 10); // 10 main interfaces
2278  pool_alloc (em->vlan_pool, 10);
2279  pool_alloc (em->qinq_pool, 1);
2280 
2281  // The first vlan pool will always be reserved for an invalid table
2282  pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2283  // The first qinq pool will always be reserved for an invalid table
2284  pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2285 }
2286 
2287 void
2289  ethernet_type_t type, u32 node_index)
2290 {
2293  u32 i;
2294 
2295  {
2297  if (error)
2298  clib_error_report (error);
2299  }
2300 
2301  ti = ethernet_get_type_info (em, type);
2302  if (ti == 0)
2303  {
2304  clib_warning ("type_info NULL for type %d", type);
2305  return;
2306  }
2307  ti->node_index = node_index;
2308  ti->next_index = vlib_node_add_next (vm,
2309  ethernet_input_node.index, node_index);
2310  i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2311  ASSERT (i == ti->next_index);
2312 
2313  i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2314  ASSERT (i == ti->next_index);
2315 
2316  // Add the L3 node for this ethertype to the next nodes structure
2317  next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2318 
2319  // Call the registration functions for other nodes that want a mapping
2320  l2bvi_register_input_type (vm, type, node_index);
2321 }
2322 
2323 void
2325 {
2327  u32 i;
2328 
2329  em->l2_next =
2330  vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2331 
2332  /*
2333  * Even if we never use these arcs, we have to align the next indices...
2334  */
2335  i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2336 
2337  ASSERT (i == em->l2_next);
2338 
2339  i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2340  ASSERT (i == em->l2_next);
2341 }
2342 
2343 // Register a next node for L3 redirect, and enable L3 redirect
2344 void
2346 {
2348  u32 i;
2349 
2350  em->redirect_l3 = 1;
2352  ethernet_input_node.index,
2353  node_index);
2354  /*
2355  * Change the cached next nodes to the redirect node
2356  */
2360 
2361  /*
2362  * Even if we never use these arcs, we have to align the next indices...
2363  */
2364  i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2365 
2366  ASSERT (i == em->redirect_l3_next);
2367 
2368  i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2369 
2370  ASSERT (i == em->redirect_l3_next);
2371 }
2372 #endif
2373 
2374 /*
2375  * fd.io coding-style-patch-verification: ON
2376  *
2377  * Local Variables:
2378  * eval: (c-set-style "gnu")
2379  * End:
2380  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
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:124
static char * ethernet_error_strings[]
Definition: node.c:2122
subint_config_t subint
Definition: ethernet.h:254
pcap_main_t pcap_main
Definition: main.h:73
vlib_main_t vlib_global_main
Definition: main.c:2041
#define clib_min(x, y)
Definition: clib.h:328
vlib_node_registration_t ethernet_input_type_node
(constructor) VLIB_REGISTER_NODE (ethernet_input_type_node)
Definition: node.c:2147
#define CLIB_UNUSED(x)
Definition: clib.h:87
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:239
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:519
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ethernet_sw_interface_add_del)
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 max_bytes_per_pkt
Definition: main.h:71
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:360
vnet_interface_main_t interface_main
Definition: vnet.h:65
vnet_p2p_sub_interface_t p2p
Definition: interface.h:762
#define PREDICT_TRUE(x)
Definition: clib.h:122
void ethernet_input_init(vlib_main_t *vm, ethernet_main_t *em)
Definition: node.c:2265
ethernet_type_t
Definition: packet.h:45
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
u16x16 u64x4 static_always_inline u32 u8x32_msb_mask(u8x32 v)
Definition: vector_avx2.h:108
#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
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#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:2324
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:250
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
void ethernet_register_l3_redirect(vlib_main_t *vm, u32 node_index)
Definition: node.c:2345
static clib_error_t * ethernet_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
Definition: node.c:2073
static u32 format_get_indent(u8 *s)
Definition: format.h:72
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_main_t * vm
Definition: in2out_ed.c:1580
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:203
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
u16 mask
Definition: flow_types.api:52
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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:402
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
vhost_vring_addr_t addr
Definition: vhost_user.h:111
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1173
unsigned char u8
Definition: types.h:56
static_always_inline void u64x4_scatter(u64x4 r, void *p0, void *p1, void *p2, void *p3)
Definition: vector_avx2.h:264
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:90
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
epu16_epi64 epu8_epi64 epu8_epi64 epi16_epi64 i16x16
Definition: vector_avx2.h:129
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
#define static_always_inline
Definition: clib.h:109
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:1954
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:882
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:2174
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:207
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.
u32 filter_classify_table_index
Definition: main.h:74
#define clib_error_return(e, args...)
Definition: error.h:99
const cJSON *const b
Definition: cJSON.h:255
u8 pcap_rx_enable
Definition: main.h:65
vlib_node_registration_t ethernet_input_node
(constructor) VLIB_REGISTER_NODE (ethernet_input_node)
Definition: node.c:2129
u32 redirect_l3_next
Definition: ethernet.h:301
unsigned int u32
Definition: types.h:88
#define vlib_call_init_function(vm, x)
Definition: init.h:270
#define VLIB_FRAME_SIZE
Definition: node.h:378
ethernet_interface_address_t * secondary_addrs
Definition: ethernet.h:177
Use the vpp classifier to decide whether to trace packets.
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:691
clib_error_t * next_by_ethertype_init(next_by_ethertype_t *l3_next)
Definition: node.c:2189
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:136
Definition: cJSON.c:84
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
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
subint_config_t single_tag_subint
Definition: ethernet.h:242
vnet_sub_interface_t sub
Definition: interface.h:759
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:2219
struct vnet_sub_interface_t::@376::@377::@379 flags
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:243
#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:233
#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:121
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:2159
u16 dot1ad_vlans
Definition: ethernet.h:237
u32 pcap_sw_if_index
Definition: main.h:72
#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:391
#define SUBINT_CONFIG_MATCH_3_TAG
Definition: ethernet.h:218
struct vnet_sub_interface_t::@376 eth
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:293
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:1236
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
u8 next_by_ethertype_register_called
Definition: ethernet.h:325
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
qinq_intf_t vlans[ETHERNET_N_VLAN]
Definition: ethernet.h:259
u16 n_vectors
Definition: node.h:397
ethernet_input_variant_t
Definition: node.c:94
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:339
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#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:115
u8 data[]
Packet data.
Definition: buffer.h:181
#define vlib_prefetch_buffer_data(b, type)
Definition: buffer.h:208
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:311
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:483
static int vnet_is_packet_traced_inline(vlib_buffer_t *b, u32 classify_table_index, int func)
vnet_is_packet_traced
#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:1772
u32 trace_classify_table_index
Definition: interface.h:622
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:511
#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:2288
u8 * format_ethernet_header(u8 *s, va_list *args)
Definition: format.c:178
u16 flags
Definition: node.h:388
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
static_always_inline int ethernet_frame_is_tagged(u16 type)
Definition: ethernet.h:78
#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:252
vlan_intf_t vlans[ETHERNET_N_VLAN]
Definition: ethernet.h:249
#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:1985
vl_api_ip4_address_t hi
Definition: arp.api:37
#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)
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:1209
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
static_always_inline int ethernet_frame_is_any_tagged_x2(u16 type0, u16 type1)
Definition: ethernet.h:92
VLIB buffer representation.
Definition: buffer.h:102
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
static clib_error_t * ethernet_init(vlib_main_t *vm)
Definition: init.c:83
void ethernet_sw_interface_set_l2_mode_noport(vnet_main_t *vnm, u32 sw_if_index, u32 l2)
Definition: node.c:2034
struct clib_bihash_value offset
template key/value backing page structure
u64x4
Definition: vector_avx2.h:121
#define vnet_buffer(b)
Definition: buffer.h:417
p2p_ethernet_main_t p2p_main
Definition: p2p_ethernet.c:23
vnet_sw_interface_type_t type
Definition: interface.h:737
#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:239
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:501
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
u8 si
Definition: lisp_types.api:47
subint_config_t * p2p_subif_pool
Definition: p2p_ethernet.h:31
vnet_pcap_t pcap
Definition: main.h:204
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
#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
epu16_epi64 u16x16
Definition: vector_avx2.h:123
ethernet_input_frame_t frame_data
Definition: node.c:68
#define BITS(x)
Definition: clib.h:66
static_always_inline u16 eth_input_next_by_type(u16 etype)
Definition: node.c:470
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.
Definition: pcap_funcs.h:67
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static void ethernet_setup_node(vlib_main_t *vm, u32 node_index)
Definition: ethernet.h:408
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
Definition: defs.h:46
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