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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 * ethernet_node.c: ethernet packet processing
18 * Copyright (c) 2008 Eliot Dresselhaus
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:
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
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.
40 #include <vlib/vlib.h>
41 #include <vnet/pg/pg.h>
42 #include <vnet/ethernet/ethernet.h>
43 #include <vnet/ethernet/p2p_ethernet.h>
44 #include <vnet/devices/pipe/pipe.h>
45 #include <vppinfra/sparse_vec.h>
46 #include <vnet/l2/l2_bvi.h>
47 #include <vnet/classify/pcap_classify.h>
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")
58 #define _(s,n) ETHERNET_INPUT_NEXT_##s,
59 foreach_ethernet_input_next
61 ETHERNET_INPUT_N_NEXT,
62 } ethernet_input_next_t;
68 ethernet_input_frame_t frame_data;
69 } ethernet_input_trace_t;
72 format_ethernet_input_trace (u8 * s, va_list * va)
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 *);
76 ethernet_input_trace_t *t = va_arg (*va, ethernet_input_trace_t *);
77 u32 indent = format_get_indent (s);
81 s = format (s, "frame: flags 0x%x", t->frame_flags);
82 if (t->frame_flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
83 s = format (s, ", hw-if-index %u, sw-if-index %u",
84 t->frame_data.hw_if_index, t->frame_data.sw_if_index);
85 s = format (s, "\n%U", format_white_space, indent);
87 s = format (s, "%U", format_ethernet_header, t->packet_data);
92 extern vlib_node_registration_t ethernet_input_node;
96 ETHERNET_INPUT_VARIANT_ETHERNET,
97 ETHERNET_INPUT_VARIANT_ETHERNET_TYPE,
98 ETHERNET_INPUT_VARIANT_NOT_L2,
99 } ethernet_input_variant_t;
102 // Parse the ethernet header to extract vlan tags and innermost ethertype
103 static_always_inline void
104 parse_header (ethernet_input_variant_t variant,
108 u16 * outer_id, u16 * inner_id, u32 * match_flags)
112 if (variant == ETHERNET_INPUT_VARIANT_ETHERNET
113 || variant == ETHERNET_INPUT_VARIANT_NOT_L2)
115 ethernet_header_t *e0;
117 e0 = vlib_buffer_get_current (b0);
119 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
120 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
122 vlib_buffer_advance (b0, sizeof (e0[0]));
124 *type = clib_net_to_host_u16 (e0->type);
126 else if (variant == ETHERNET_INPUT_VARIANT_ETHERNET_TYPE)
128 // here when prior node was LLC/SNAP processing
131 e0 = vlib_buffer_get_current (b0);
133 vlib_buffer_advance (b0, sizeof (e0[0]));
135 *type = clib_net_to_host_u16 (e0[0]);
138 // save for distinguishing between dot1q and dot1ad later
141 // default the tags to 0 (used if there is no corresponding tag)
145 *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_0_TAG;
148 // check for vlan encaps
149 if (ethernet_frame_is_tagged (*type))
151 ethernet_vlan_header_t *h0;
154 *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_1_TAG;
156 h0 = vlib_buffer_get_current (b0);
158 tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
160 *outer_id = tag & 0xfff;
162 *match_flags &= ~SUBINT_CONFIG_MATCH_1_TAG;
164 *type = clib_net_to_host_u16 (h0->type);
166 vlib_buffer_advance (b0, sizeof (h0[0]));
169 if (*type == ETHERNET_TYPE_VLAN)
171 // Double tagged packet
172 *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_2_TAG;
174 h0 = vlib_buffer_get_current (b0);
176 tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
178 *inner_id = tag & 0xfff;
180 *type = clib_net_to_host_u16 (h0->type);
182 vlib_buffer_advance (b0, sizeof (h0[0]));
184 if (*type == ETHERNET_TYPE_VLAN)
186 // More than double tagged packet
187 *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_3_TAG;
189 vlib_buffer_advance (b0, sizeof (h0[0]));
190 vlan_count = 3; // "unknown" number, aka, 3-or-more
194 ethernet_buffer_set_vlan_count (b0, vlan_count);
197 static_always_inline void
198 ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi,
199 u64 * dmacs, u8 * dmacs_bad,
200 u32 n_packets, ethernet_interface_t * ei,
203 // Determine the subinterface for this packet, given the result of the
204 // vlan table lookups and vlan header parsing. Check the most specific
206 static_always_inline void
207 identify_subint (ethernet_main_t * em,
208 vnet_hw_interface_t * hi,
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)
217 ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index);
219 matched = eth_identify_subint (hi, match_flags, main_intf, vlan_intf,
220 qinq_intf, new_sw_if_index, error0, is_l2);
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 &&
229 (!(ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)))
233 ethernet_header_t *e0;
235 e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
236 dmacs[0] = *(u64 *) e0;
238 if (vec_len (ei->secondary_addrs))
239 ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
240 1 /* n_packets */, ei,
241 1 /* have_sec_dmac */);
243 ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
244 1 /* n_packets */, ei,
245 0 /* have_sec_dmac */);
247 *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
250 // Check for down subinterface
251 *error0 = (*new_sw_if_index) != ~0 ? (*error0) : ETHERNET_ERROR_DOWN;
255 static_always_inline void
256 determine_next_node (ethernet_main_t * em,
257 ethernet_input_variant_t variant,
259 u32 type0, vlib_buffer_t * b0, u8 * error0, u8 * next0)
261 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
262 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
264 if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE))
266 // some error occurred
267 *next0 = ETHERNET_INPUT_NEXT_DROP;
271 // record the L2 len and reset the buffer so the L2 header is preserved
272 u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
273 vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
274 *next0 = em->l2_next;
275 ASSERT (vnet_buffer (b0)->l2.l2_len ==
276 ethernet_buffer_header_size (b0));
277 vlib_buffer_advance (b0, -(vnet_buffer (b0)->l2.l2_len));
279 // check for common IP/MPLS ethertypes
281 else if (type0 == ETHERNET_TYPE_IP4)
283 *next0 = em->l3_next.input_next_ip4;
285 else if (type0 == ETHERNET_TYPE_IP6)
287 *next0 = em->l3_next.input_next_ip6;
289 else if (type0 == ETHERNET_TYPE_MPLS)
291 *next0 = em->l3_next.input_next_mpls;
294 else if (em->redirect_l3)
296 // L3 Redirect is on, the cached common next nodes will be
297 // pointing to the redirect node, catch the uncommon types here
298 *next0 = em->redirect_l3_next;
302 // uncommon ethertype, check table
304 i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
305 *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
308 SPARSE_VEC_INVALID_INDEX ? ETHERNET_ERROR_UNKNOWN_TYPE : *error0;
310 // The table is not populated with LLC values, so check that now.
311 // If variant is variant_ethernet then we came from LLC processing. Don't
312 // go back there; drop instead using by keeping the drop/bad table result.
313 if ((type0 < 0x600) && (variant == ETHERNET_INPUT_VARIANT_ETHERNET))
315 *next0 = ETHERNET_INPUT_NEXT_LLC;
321 /* following vector code relies on following assumptions */
322 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_data, 0);
323 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_length, 2);
324 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, flags, 4);
325 STATIC_ASSERT (STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l2_hdr_offset) ==
326 STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l3_hdr_offset) - 2,
327 "l3_hdr_offset must follow l2_hdr_offset");
329 static_always_inline void
330 eth_input_adv_and_flags_x4 (vlib_buffer_t ** b, int is_l3)
332 i16 adv = sizeof (ethernet_header_t);
333 u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
334 VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
336 #ifdef CLIB_HAVE_VEC256
337 /* to reduce number of small loads/stores we are loading first 64 bits
338 of each buffer metadata into 256-bit register so we can advance
339 current_data, current_length and flags.
340 Observed saving of this code is ~2 clocks per packet */
343 /* vector if signed 16 bit integers used in signed vector add operation
344 to advnce current_data and current_length */
345 u32x8 flags4 = { 0, flags, 0, flags, 0, flags, 0, flags };
347 adv, -adv, 0, 0, adv, -adv, 0, 0,
348 adv, -adv, 0, 0, adv, -adv, 0, 0
351 /* load 4 x 64 bits */
352 r = u64x4_gather (b[0], b[1], b[2], b[3]);
358 radv = (u64x4) ((i16x16) r + adv4);
360 /* write 4 x 64 bits */
361 u64x4_scatter (is_l3 ? radv : r, b[0], b[1], b[2], b[3]);
363 /* use old current_data as l2_hdr_offset and new current_data as
365 r = (u64x4) u16x16_blend (r, radv << 16, 0xaa);
367 /* store both l2_hdr_offset and l3_hdr_offset in single store operation */
368 u32x8_scatter_one ((u32x8) r, 0, &vnet_buffer (b[0])->l2_hdr_offset);
369 u32x8_scatter_one ((u32x8) r, 2, &vnet_buffer (b[1])->l2_hdr_offset);
370 u32x8_scatter_one ((u32x8) r, 4, &vnet_buffer (b[2])->l2_hdr_offset);
371 u32x8_scatter_one ((u32x8) r, 6, &vnet_buffer (b[3])->l2_hdr_offset);
375 ASSERT (b[0]->current_data == vnet_buffer (b[0])->l3_hdr_offset);
376 ASSERT (b[1]->current_data == vnet_buffer (b[1])->l3_hdr_offset);
377 ASSERT (b[2]->current_data == vnet_buffer (b[2])->l3_hdr_offset);
378 ASSERT (b[3]->current_data == vnet_buffer (b[3])->l3_hdr_offset);
380 ASSERT (b[0]->current_data - vnet_buffer (b[0])->l2_hdr_offset == adv);
381 ASSERT (b[1]->current_data - vnet_buffer (b[1])->l2_hdr_offset == adv);
382 ASSERT (b[2]->current_data - vnet_buffer (b[2])->l2_hdr_offset == adv);
383 ASSERT (b[3]->current_data - vnet_buffer (b[3])->l2_hdr_offset == adv);
387 ASSERT (b[0]->current_data == vnet_buffer (b[0])->l2_hdr_offset);
388 ASSERT (b[1]->current_data == vnet_buffer (b[1])->l2_hdr_offset);
389 ASSERT (b[2]->current_data == vnet_buffer (b[2])->l2_hdr_offset);
390 ASSERT (b[3]->current_data == vnet_buffer (b[3])->l2_hdr_offset);
392 ASSERT (b[0]->current_data - vnet_buffer (b[0])->l3_hdr_offset == -adv);
393 ASSERT (b[1]->current_data - vnet_buffer (b[1])->l3_hdr_offset == -adv);
394 ASSERT (b[2]->current_data - vnet_buffer (b[2])->l3_hdr_offset == -adv);
395 ASSERT (b[3]->current_data - vnet_buffer (b[3])->l3_hdr_offset == -adv);
399 vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
400 vnet_buffer (b[1])->l2_hdr_offset = b[1]->current_data;
401 vnet_buffer (b[2])->l2_hdr_offset = b[2]->current_data;
402 vnet_buffer (b[3])->l2_hdr_offset = b[3]->current_data;
403 vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
404 vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data + adv;
405 vnet_buffer (b[2])->l3_hdr_offset = b[2]->current_data + adv;
406 vnet_buffer (b[3])->l3_hdr_offset = b[3]->current_data + adv;
410 vlib_buffer_advance (b[0], adv);
411 vlib_buffer_advance (b[1], adv);
412 vlib_buffer_advance (b[2], adv);
413 vlib_buffer_advance (b[3], adv);
416 b[0]->flags |= flags;
417 b[1]->flags |= flags;
418 b[2]->flags |= flags;
419 b[3]->flags |= flags;
424 vnet_buffer (b[0])->l2.l2_len = adv;
425 vnet_buffer (b[1])->l2.l2_len = adv;
426 vnet_buffer (b[2])->l2.l2_len = adv;
427 vnet_buffer (b[3])->l2.l2_len = adv;
431 static_always_inline void
432 eth_input_adv_and_flags_x1 (vlib_buffer_t ** b, int is_l3)
434 i16 adv = sizeof (ethernet_header_t);
435 u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
436 VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
438 vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
439 vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
442 vlib_buffer_advance (b[0], adv);
443 b[0]->flags |= flags;
445 vnet_buffer (b[0])->l2.l2_len = adv;
449 static_always_inline void
450 eth_input_get_etype_and_tags (vlib_buffer_t ** b, u16 * etype, u64 * tags,
451 u64 * dmacs, int offset, int dmac_check)
453 ethernet_header_t *e;
454 e = vlib_buffer_get_current (b[offset]);
455 #ifdef CLIB_HAVE_VEC128
456 u64x2 r = u64x2_load_unaligned (((u8 *) & e->type) - 6);
457 etype[offset] = ((u16x8) r)[3];
460 etype[offset] = e->type;
461 tags[offset] = *(u64 *) (e + 1);
465 dmacs[offset] = *(u64 *) e;
468 static_always_inline u16
469 eth_input_next_by_type (u16 etype)
471 ethernet_main_t *em = ðernet_main;
473 return (etype < 0x600) ? ETHERNET_INPUT_NEXT_LLC :
474 vec_elt (em->l3_next.input_next_by_type,
475 sparse_vec_index (em->l3_next.input_next_by_type, etype));
485 u64 n_packets, n_bytes;
486 } eth_input_tag_lookup_t;
488 static_always_inline void
489 eth_input_update_if_counters (vlib_main_t * vm, vnet_main_t * vnm,
490 eth_input_tag_lookup_t * l)
492 if (l->n_packets == 0 || l->sw_if_index == ~0)
496 l->n_bytes += l->n_packets * l->len;
498 vlib_increment_combined_counter
499 (vnm->interface_main.combined_sw_if_counters +
500 VNET_INTERFACE_COUNTER_RX, vm->thread_index, l->sw_if_index,
501 l->n_packets, l->n_bytes);
504 static_always_inline void
505 eth_input_tag_lookup (vlib_main_t * vm, vnet_main_t * vnm,
506 vlib_node_runtime_t * node, vnet_hw_interface_t * hi,
507 u64 tag, u16 * next, vlib_buffer_t * b,
508 eth_input_tag_lookup_t * l, u8 dmac_bad, int is_dot1ad,
509 int main_is_l3, int check_dmac)
511 ethernet_main_t *em = ðernet_main;
513 if ((tag ^ l->tag) & l->mask)
515 main_intf_t *mif = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
518 vlan_table_t *vlan_table;
519 qinq_table_t *qinq_table;
520 u16 *t = (u16 *) & tag;
521 u16 vlan1 = clib_net_to_host_u16 (t[0]) & 0xFFF;
522 u16 vlan2 = clib_net_to_host_u16 (t[2]) & 0xFFF;
523 u32 matched, is_l2, new_sw_if_index;
525 vlan_table = vec_elt_at_index (em->vlan_pool, is_dot1ad ?
526 mif->dot1ad_vlans : mif->dot1q_vlans);
527 vif = &vlan_table->vlans[vlan1];
528 qinq_table = vec_elt_at_index (em->qinq_pool, vif->qinqs);
529 qif = &qinq_table->vlans[vlan2];
530 l->err = ETHERNET_ERROR_NONE;
531 l->type = clib_net_to_host_u16 (t[1]);
533 if (l->type == ETHERNET_TYPE_VLAN)
535 l->type = clib_net_to_host_u16 (t[3]);
537 matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
538 SUBINT_CONFIG_MATCH_2_TAG, mif, vif,
539 qif, &new_sw_if_index, &l->err,
547 new_sw_if_index = hi->sw_if_index;
548 l->err = ETHERNET_ERROR_NONE;
550 is_l2 = main_is_l3 == 0;
553 matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
554 SUBINT_CONFIG_MATCH_1_TAG, mif,
555 vif, qif, &new_sw_if_index,
559 if (l->sw_if_index != new_sw_if_index)
561 eth_input_update_if_counters (vm, vnm, l);
564 l->sw_if_index = new_sw_if_index;
567 l->mask = (l->n_tags == 2) ?
568 clib_net_to_host_u64 (0xffffffffffffffff) :
569 clib_net_to_host_u64 (0xffffffff00000000);
571 if (matched && l->sw_if_index == ~0)
572 l->err = ETHERNET_ERROR_DOWN;
574 l->len = sizeof (ethernet_header_t) +
575 l->n_tags * sizeof (ethernet_vlan_header_t);
577 l->adv = is_l2 ? -(int) sizeof (ethernet_header_t) :
578 l->n_tags * sizeof (ethernet_vlan_header_t);
580 l->adv = is_l2 ? 0 : l->len;
582 if (PREDICT_FALSE (l->err != ETHERNET_ERROR_NONE))
583 l->next = ETHERNET_INPUT_NEXT_DROP;
585 l->next = em->l2_next;
586 else if (l->type == ETHERNET_TYPE_IP4)
587 l->next = em->l3_next.input_next_ip4;
588 else if (l->type == ETHERNET_TYPE_IP6)
589 l->next = em->l3_next.input_next_ip6;
590 else if (l->type == ETHERNET_TYPE_MPLS)
591 l->next = em->l3_next.input_next_mpls;
592 else if (em->redirect_l3)
593 l->next = em->redirect_l3_next;
596 l->next = eth_input_next_by_type (l->type);
597 if (l->next == ETHERNET_INPUT_NEXT_PUNT)
598 l->err = ETHERNET_ERROR_UNKNOWN_TYPE;
602 if (check_dmac && l->adv > 0 && dmac_bad)
604 l->err = ETHERNET_ERROR_L3_MAC_MISMATCH;
605 next[0] = ETHERNET_INPUT_NEXT_PUNT;
610 vlib_buffer_advance (b, l->adv);
611 vnet_buffer (b)->l2.l2_len = l->len;
612 vnet_buffer (b)->l3_hdr_offset = vnet_buffer (b)->l2_hdr_offset + l->len;
614 if (l->err == ETHERNET_ERROR_NONE)
616 vnet_buffer (b)->sw_if_index[VLIB_RX] = l->sw_if_index;
617 ethernet_buffer_set_vlan_count (b, l->n_tags);
620 b->error = node->errors[l->err];
622 /* update counters */
624 l->n_bytes += vlib_buffer_length_in_chain (vm, b);
627 #define DMAC_MASK clib_net_to_host_u64 (0xFFFFFFFFFFFF0000)
628 #define DMAC_IGBIT clib_net_to_host_u64 (0x0100000000000000)
630 #ifdef CLIB_HAVE_VEC256
631 static_always_inline u32
632 is_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
634 u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
635 r0 = (r0 != u64x4_splat (hwaddr)) & ((r0 & u64x4_splat (DMAC_IGBIT)) == 0);
636 return u8x32_msb_mask ((u8x32) (r0));
640 static_always_inline u8
641 is_dmac_bad (u64 dmac, u64 hwaddr)
643 u64 r0 = dmac & DMAC_MASK;
644 return (r0 != hwaddr) && ((r0 & DMAC_IGBIT) == 0);
647 static_always_inline u8
648 is_sec_dmac_bad (u64 dmac, u64 hwaddr)
650 return ((dmac & DMAC_MASK) != hwaddr);
653 #ifdef CLIB_HAVE_VEC256
654 static_always_inline u32
655 is_sec_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
657 u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
658 r0 = (r0 != u64x4_splat (hwaddr));
659 return u8x32_msb_mask ((u8x32) (r0));
663 static_always_inline u8
664 eth_input_sec_dmac_check_x1 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
666 dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
670 static_always_inline u32
671 eth_input_sec_dmac_check_x4 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
673 #ifdef CLIB_HAVE_VEC256
674 *(u32 *) (dmac_bad + 0) &= is_sec_dmac_bad_x4 (dmac + 0, hwaddr);
676 dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
677 dmac_bad[1] &= is_sec_dmac_bad (dmac[1], hwaddr);
678 dmac_bad[2] &= is_sec_dmac_bad (dmac[2], hwaddr);
679 dmac_bad[3] &= is_sec_dmac_bad (dmac[3], hwaddr);
681 return *(u32 *) dmac_bad;
685 * DMAC check for ethernet_input_inline()
687 * dmacs and dmacs_bad are arrays that are 2 elements long
688 * n_packets should be 1 or 2 for ethernet_input_inline()
690 static_always_inline void
691 ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi,
692 u64 * dmacs, u8 * dmacs_bad,
693 u32 n_packets, ethernet_interface_t * ei,
696 u64 hwaddr = ei->address.as_u64;
699 ASSERT (0 == ei->address.zero);
701 dmacs_bad[0] = is_dmac_bad (dmacs[0], hwaddr);
702 dmacs_bad[1] = ((n_packets > 1) & is_dmac_bad (dmacs[1], hwaddr));
704 bad = dmacs_bad[0] | dmacs_bad[1];
706 if (PREDICT_FALSE (bad && have_sec_dmac))
708 ethernet_interface_address_t *sec_addr;
710 vec_foreach (sec_addr, ei->secondary_addrs)
712 ASSERT (0 == sec_addr->zero);
713 hwaddr = sec_addr->as_u64;
715 bad = (eth_input_sec_dmac_check_x1 (hwaddr, dmacs, dmacs_bad) |
716 eth_input_sec_dmac_check_x1 (hwaddr, dmacs + 1,
725 static_always_inline void
726 eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi,
727 u64 * dmacs, u8 * dmacs_bad,
728 u32 n_packets, ethernet_interface_t * ei,
731 u64 hwaddr = ei->address.as_u64;
733 u8 *dmac_bad = dmacs_bad;
735 i32 n_left = n_packets;
737 ASSERT (0 == ei->address.zero);
739 #ifdef CLIB_HAVE_VEC256
742 bad |= *(u32 *) (dmac_bad + 0) = is_dmac_bad_x4 (dmac + 0, hwaddr);
743 bad |= *(u32 *) (dmac_bad + 4) = is_dmac_bad_x4 (dmac + 4, hwaddr);
753 bad |= dmac_bad[0] = is_dmac_bad (dmac[0], hwaddr);
754 bad |= dmac_bad[1] = is_dmac_bad (dmac[1], hwaddr);
755 bad |= dmac_bad[2] = is_dmac_bad (dmac[2], hwaddr);
756 bad |= dmac_bad[3] = is_dmac_bad (dmac[3], hwaddr);
765 if (have_sec_dmac && bad)
767 ethernet_interface_address_t *addr;
769 vec_foreach (addr, ei->secondary_addrs)
771 u64 hwaddr = addr->as_u64;
772 i32 n_left = n_packets;
774 u8 *dmac_bad = dmacs_bad;
776 ASSERT (0 == addr->zero);
785 /* skip any that have already matched */
794 n_bad = clib_min (4, n_left);
796 /* If >= 4 left, compare 4 together */
799 bad |= eth_input_sec_dmac_check_x4 (hwaddr, dmac, dmac_bad);
804 /* handle individually */
807 bad |= eth_input_sec_dmac_check_x1 (hwaddr, dmac + adv,
818 if (!bad) /* can stop looping if everything matched */
824 /* process frame of buffers, store ethertype into array and update
825 buffer metadata fields depending on interface being l2 or l3 assuming that
826 packets are untagged. For tagged packets those fields are updated later.
827 Optionally store Destionation MAC address and tag data into arrays
828 for further processing */
830 STATIC_ASSERT (VLIB_FRAME_SIZE % 8 == 0,
831 "VLIB_FRAME_SIZE must be power of 8");
832 static_always_inline void
833 eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
834 vnet_hw_interface_t * hi,
835 u32 * buffer_indices, u32 n_packets, int main_is_l3,
836 int ip4_cksum_ok, int dmac_check)
838 ethernet_main_t *em = ðernet_main;
839 u16 nexts[VLIB_FRAME_SIZE], *next;
840 u16 etypes[VLIB_FRAME_SIZE], *etype = etypes;
841 u64 dmacs[VLIB_FRAME_SIZE], *dmac = dmacs;
842 u8 dmacs_bad[VLIB_FRAME_SIZE];
843 u64 tags[VLIB_FRAME_SIZE], *tag = tags;
844 u16 slowpath_indices[VLIB_FRAME_SIZE];
846 u16 next_ip4, next_ip6, next_mpls, next_l2;
847 u16 et_ip4 = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
848 u16 et_ip6 = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
849 u16 et_mpls = clib_host_to_net_u16 (ETHERNET_TYPE_MPLS);
850 u16 et_vlan = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
851 u16 et_dot1ad = clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD);
852 i32 n_left = n_packets;
853 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
854 vlib_buffer_t **b = bufs;
855 ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index);
857 vlib_get_buffers (vm, buffer_indices, b, n_left);
861 vlib_buffer_t **ph = b + 16, **pd = b + 8;
863 vlib_prefetch_buffer_header (ph[0], LOAD);
864 vlib_prefetch_buffer_data (pd[0], LOAD);
865 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
867 vlib_prefetch_buffer_header (ph[1], LOAD);
868 vlib_prefetch_buffer_data (pd[1], LOAD);
869 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
871 vlib_prefetch_buffer_header (ph[2], LOAD);
872 vlib_prefetch_buffer_data (pd[2], LOAD);
873 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
875 vlib_prefetch_buffer_header (ph[3], LOAD);
876 vlib_prefetch_buffer_data (pd[3], LOAD);
877 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
879 eth_input_adv_and_flags_x4 (b, main_is_l3);
890 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
891 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
892 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
893 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
894 eth_input_adv_and_flags_x4 (b, main_is_l3);
905 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
906 eth_input_adv_and_flags_x1 (b, main_is_l3);
918 if (ei && vec_len (ei->secondary_addrs))
919 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
920 ei, 1 /* have_sec_dmac */ );
922 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
923 ei, 0 /* have_sec_dmac */ );
926 next_ip4 = em->l3_next.input_next_ip4;
927 next_ip6 = em->l3_next.input_next_ip6;
928 next_mpls = em->l3_next.input_next_mpls;
929 next_l2 = em->l2_next;
931 if (next_ip4 == ETHERNET_INPUT_NEXT_IP4_INPUT && ip4_cksum_ok)
932 next_ip4 = ETHERNET_INPUT_NEXT_IP4_INPUT_NCS;
934 #ifdef CLIB_HAVE_VEC256
935 u16x16 et16_ip4 = u16x16_splat (et_ip4);
936 u16x16 et16_ip6 = u16x16_splat (et_ip6);
937 u16x16 et16_mpls = u16x16_splat (et_mpls);
938 u16x16 et16_vlan = u16x16_splat (et_vlan);
939 u16x16 et16_dot1ad = u16x16_splat (et_dot1ad);
940 u16x16 next16_ip4 = u16x16_splat (next_ip4);
941 u16x16 next16_ip6 = u16x16_splat (next_ip6);
942 u16x16 next16_mpls = u16x16_splat (next_mpls);
943 u16x16 next16_l2 = u16x16_splat (next_l2);
945 u16x16 stairs = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
954 /* fastpath - in l3 mode hadles ip4, ip6 and mpls packets, other packets
955 are considered as slowpath, in l2 mode all untagged packets are
956 considered as fastpath */
959 #ifdef CLIB_HAVE_VEC256
963 u16x16 e16 = u16x16_load_unaligned (etype);
966 r += (e16 == et16_ip4) & next16_ip4;
967 r += (e16 == et16_ip6) & next16_ip6;
968 r += (e16 == et16_mpls) & next16_mpls;
971 r = ((e16 != et16_vlan) & (e16 != et16_dot1ad)) & next16_l2;
972 u16x16_store_unaligned (r, next);
974 if (!u16x16_is_all_zero (r == zero))
976 if (u16x16_is_all_zero (r))
978 u16x16_store_unaligned (u16x16_splat (i) + stairs,
979 slowpath_indices + n_slowpath);
984 for (int j = 0; j < 16; j++)
987 slowpath_indices[n_slowpath++] = i + j;
988 else if (dmac_check && main_is_l3 && dmacs_bad[i + j])
991 slowpath_indices[n_slowpath++] = i + j;
998 if (dmac_check && main_is_l3)
1000 u8x16 dmac_bad = u8x16_load_unaligned (&dmacs_bad[i]);
1001 if (!u8x16_is_all_zero (dmac_bad))
1003 for (int j = 0; j < 16; j++)
1004 if (dmacs_bad[i + j])
1007 slowpath_indices[n_slowpath++] = i + j;
1020 if (dmac_check && main_is_l3 && dmacs_bad[i])
1023 slowpath_indices[n_slowpath++] = i;
1025 else if (main_is_l3 && etype[0] == et_ip4)
1027 else if (main_is_l3 && etype[0] == et_ip6)
1029 else if (main_is_l3 && etype[0] == et_mpls)
1030 next[0] = next_mpls;
1031 else if (main_is_l3 == 0 &&
1032 etype[0] != et_vlan && etype[0] != et_dot1ad)
1037 slowpath_indices[n_slowpath++] = i;
1048 vnet_main_t *vnm = vnet_get_main ();
1049 n_left = n_slowpath;
1050 u16 *si = slowpath_indices;
1051 u32 last_unknown_etype = ~0;
1052 u32 last_unknown_next = ~0;
1053 eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
1055 .tag = tags[si[0]] ^ -1LL,
1059 clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
1064 u16 etype = etypes[i];
1066 if (etype == et_vlan)
1068 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1069 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1070 &dot1q_lookup, dmacs_bad[i], 0,
1071 main_is_l3, dmac_check);
1074 else if (etype == et_dot1ad)
1076 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1077 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1078 &dot1ad_lookup, dmacs_bad[i], 1,
1079 main_is_l3, dmac_check);
1083 /* untagged packet with not well known ethertype */
1084 if (last_unknown_etype != etype)
1086 last_unknown_etype = etype;
1087 etype = clib_host_to_net_u16 (etype);
1088 last_unknown_next = eth_input_next_by_type (etype);
1090 if (dmac_check && main_is_l3 && dmacs_bad[i])
1092 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1093 b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
1094 nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
1097 nexts[i] = last_unknown_next;
1105 eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
1106 eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
1109 vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
1112 static_always_inline void
1113 eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node,
1114 vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
1117 ethernet_main_t *em = ðernet_main;
1118 ethernet_interface_t *ei;
1119 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
1120 main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1121 subint_config_t *subint0 = &intf0->untagged_subint;
1123 int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
1124 int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3;
1128 if (int_is_l3 || /* DMAC filter already done by NIC */
1129 ((hi->l2_if_count != 0) && (hi->l3_if_count == 0)))
1130 { /* All L2 usage - DMAC check not needed */
1131 eth_input_process_frame (vm, node, hi, from, n_pkts,
1132 /*is_l3 */ 1, ip4_cksum_ok, 0);
1135 { /* DMAC check needed for L3 */
1136 eth_input_process_frame (vm, node, hi, from, n_pkts,
1137 /*is_l3 */ 1, ip4_cksum_ok, 1);
1143 if (hi->l3_if_count == 0)
1144 { /* All L2 usage - DMAC check not needed */
1145 eth_input_process_frame (vm, node, hi, from, n_pkts,
1146 /*is_l3 */ 0, ip4_cksum_ok, 0);
1149 { /* DMAC check needed for L3 */
1150 eth_input_process_frame (vm, node, hi, from, n_pkts,
1151 /*is_l3 */ 0, ip4_cksum_ok, 1);
1157 static_always_inline void
1158 ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
1159 vlib_frame_t * from_frame)
1161 vnet_main_t *vnm = vnet_get_main ();
1163 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1165 from = vlib_frame_vector_args (from_frame);
1166 n_left = from_frame->n_vectors;
1170 ethernet_input_trace_t *t0;
1171 vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1173 if (b0->flags & VLIB_BUFFER_IS_TRACED)
1175 t0 = vlib_add_trace (vm, node, b0,
1176 sizeof (ethernet_input_trace_t));
1177 clib_memcpy_fast (t0->packet_data, b0->data + b0->current_data,
1178 sizeof (t0->packet_data));
1179 t0->frame_flags = from_frame->flags;
1180 clib_memcpy_fast (&t0->frame_data,
1181 vlib_frame_scalar_args (from_frame),
1182 sizeof (ethernet_input_frame_t));
1189 /* rx pcap capture if enabled */
1190 if (PREDICT_FALSE (vnm->pcap.pcap_rx_enable))
1193 vnet_pcap_t *pp = &vnm->pcap;
1195 from = vlib_frame_vector_args (from_frame);
1196 n_left = from_frame->n_vectors;
1203 b0 = vlib_get_buffer (vm, bi0);
1204 if (vnet_is_packet_pcaped (pp, b0, ~0))
1205 pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
1210 static_always_inline void
1211 ethernet_input_inline (vlib_main_t * vm,
1212 vlib_node_runtime_t * node,
1213 u32 * from, u32 n_packets,
1214 ethernet_input_variant_t variant)
1216 vnet_main_t *vnm = vnet_get_main ();
1217 ethernet_main_t *em = ðernet_main;
1218 vlib_node_runtime_t *error_node;
1219 u32 n_left_from, next_index, *to_next;
1220 u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1221 u32 thread_index = vm->thread_index;
1222 u32 cached_sw_if_index = ~0;
1223 u32 cached_is_l2 = 0; /* shut up gcc */
1224 vnet_hw_interface_t *hi = NULL; /* used for main interface only */
1225 ethernet_interface_t *ei = NULL;
1226 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
1227 vlib_buffer_t **b = bufs;
1229 if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1230 error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1234 n_left_from = n_packets;
1236 next_index = node->cached_next_index;
1237 stats_sw_if_index = node->runtime_data[0];
1238 stats_n_packets = stats_n_bytes = 0;
1239 vlib_get_buffers (vm, from, bufs, n_left_from);
1241 while (n_left_from > 0)
1245 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1247 while (n_left_from >= 4 && n_left_to_next >= 2)
1250 vlib_buffer_t *b0, *b1;
1251 u8 next0, next1, error0, error1;
1252 u16 type0, orig_type0, type1, orig_type1;
1253 u16 outer_id0, inner_id0, outer_id1, inner_id1;
1254 u32 match_flags0, match_flags1;
1255 u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1256 new_sw_if_index1, len1;
1257 vnet_hw_interface_t *hi0, *hi1;
1258 main_intf_t *main_intf0, *main_intf1;
1259 vlan_intf_t *vlan_intf0, *vlan_intf1;
1260 qinq_intf_t *qinq_intf0, *qinq_intf1;
1262 ethernet_header_t *e0, *e1;
1266 /* Prefetch next iteration. */
1268 vlib_prefetch_buffer_header (b[2], STORE);
1269 vlib_prefetch_buffer_header (b[3], STORE);
1271 CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1272 CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1281 n_left_to_next -= 2;
1288 error0 = error1 = ETHERNET_ERROR_NONE;
1289 e0 = vlib_buffer_get_current (b0);
1290 type0 = clib_net_to_host_u16 (e0->type);
1291 e1 = vlib_buffer_get_current (b1);
1292 type1 = clib_net_to_host_u16 (e1->type);
1294 /* Set the L2 header offset for all packets */
1295 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1296 vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1297 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1298 b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1300 /* Speed-path for the untagged case */
1301 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1302 && !ethernet_frame_is_any_tagged_x2 (type0,
1306 subint_config_t *subint0;
1307 u32 sw_if_index0, sw_if_index1;
1309 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1310 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1311 is_l20 = cached_is_l2;
1313 /* This is probably wholly unnecessary */
1314 if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1317 /* Now sw_if_index0 == sw_if_index1 */
1318 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1320 cached_sw_if_index = sw_if_index0;
1321 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1322 ei = ethernet_get_interface (em, hi->hw_if_index);
1323 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1324 subint0 = &intf0->untagged_subint;
1325 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1328 if (PREDICT_TRUE (is_l20 != 0))
1330 vnet_buffer (b0)->l3_hdr_offset =
1331 vnet_buffer (b0)->l2_hdr_offset +
1332 sizeof (ethernet_header_t);
1333 vnet_buffer (b1)->l3_hdr_offset =
1334 vnet_buffer (b1)->l2_hdr_offset +
1335 sizeof (ethernet_header_t);
1336 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1337 b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1338 next0 = em->l2_next;
1339 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1340 next1 = em->l2_next;
1341 vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1345 if (ei && (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3))
1346 goto skip_dmac_check01;
1348 dmacs[0] = *(u64 *) e0;
1349 dmacs[1] = *(u64 *) e1;
1351 if (ei && vec_len (ei->secondary_addrs))
1352 ethernet_input_inline_dmac_check (hi, dmacs,
1356 1 /* have_sec_dmac */ );
1358 ethernet_input_inline_dmac_check (hi, dmacs,
1362 0 /* have_sec_dmac */ );
1365 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1367 error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1370 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1371 determine_next_node (em, variant, 0, type0, b0,
1373 vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1374 determine_next_node (em, variant, 0, type1, b1,
1380 /* Slow-path for the tagged case */
1382 parse_header (variant,
1385 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1387 parse_header (variant,
1390 &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1392 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1393 old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1395 eth_vlan_table_lookups (em,
1402 &main_intf0, &vlan_intf0, &qinq_intf0);
1404 eth_vlan_table_lookups (em,
1411 &main_intf1, &vlan_intf1, &qinq_intf1);
1413 identify_subint (em,
1419 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1421 identify_subint (em,
1427 qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1429 // Save RX sw_if_index for later nodes
1430 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1432 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1433 vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1435 ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1437 // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1438 if (((new_sw_if_index0 != ~0)
1439 && (new_sw_if_index0 != old_sw_if_index0))
1440 || ((new_sw_if_index1 != ~0)
1441 && (new_sw_if_index1 != old_sw_if_index1)))
1444 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1445 - vnet_buffer (b0)->l2_hdr_offset;
1446 len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1447 - vnet_buffer (b1)->l2_hdr_offset;
1449 stats_n_packets += 2;
1450 stats_n_bytes += len0 + len1;
1453 (!(new_sw_if_index0 == stats_sw_if_index
1454 && new_sw_if_index1 == stats_sw_if_index)))
1456 stats_n_packets -= 2;
1457 stats_n_bytes -= len0 + len1;
1459 if (new_sw_if_index0 != old_sw_if_index0
1460 && new_sw_if_index0 != ~0)
1461 vlib_increment_combined_counter (vnm->
1462 interface_main.combined_sw_if_counters
1464 VNET_INTERFACE_COUNTER_RX,
1466 new_sw_if_index0, 1,
1468 if (new_sw_if_index1 != old_sw_if_index1
1469 && new_sw_if_index1 != ~0)
1470 vlib_increment_combined_counter (vnm->
1471 interface_main.combined_sw_if_counters
1473 VNET_INTERFACE_COUNTER_RX,
1475 new_sw_if_index1, 1,
1478 if (new_sw_if_index0 == new_sw_if_index1)
1480 if (stats_n_packets > 0)
1482 vlib_increment_combined_counter
1483 (vnm->interface_main.combined_sw_if_counters
1484 + VNET_INTERFACE_COUNTER_RX,
1487 stats_n_packets, stats_n_bytes);
1488 stats_n_packets = stats_n_bytes = 0;
1490 stats_sw_if_index = new_sw_if_index0;
1495 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1496 is_l20 = is_l21 = 0;
1498 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1500 determine_next_node (em, variant, is_l21, type1, b1, &error1,
1504 b0->error = error_node->errors[error0];
1505 b1->error = error_node->errors[error1];
1507 // verify speculative enqueue
1508 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1509 n_left_to_next, bi0, bi1, next0,
1513 while (n_left_from > 0 && n_left_to_next > 0)
1518 u16 type0, orig_type0;
1519 u16 outer_id0, inner_id0;
1521 u32 old_sw_if_index0, new_sw_if_index0, len0;
1522 vnet_hw_interface_t *hi0;
1523 main_intf_t *main_intf0;
1524 vlan_intf_t *vlan_intf0;
1525 qinq_intf_t *qinq_intf0;
1526 ethernet_header_t *e0;
1531 // Prefetch next iteration
1532 if (n_left_from > 1)
1534 vlib_prefetch_buffer_header (b[1], STORE);
1535 clib_prefetch_load (b[1]->data);
1543 n_left_to_next -= 1;
1548 error0 = ETHERNET_ERROR_NONE;
1549 e0 = vlib_buffer_get_current (b0);
1550 type0 = clib_net_to_host_u16 (e0->type);
1552 /* Set the L2 header offset for all packets */
1553 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1554 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1556 /* Speed-path for the untagged case */
1557 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1558 && !ethernet_frame_is_tagged (type0)))
1561 subint_config_t *subint0;
1564 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1565 is_l20 = cached_is_l2;
1567 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1569 cached_sw_if_index = sw_if_index0;
1570 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1571 ei = ethernet_get_interface (em, hi->hw_if_index);
1572 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1573 subint0 = &intf0->untagged_subint;
1574 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1578 if (PREDICT_TRUE (is_l20 != 0))
1580 vnet_buffer (b0)->l3_hdr_offset =
1581 vnet_buffer (b0)->l2_hdr_offset +
1582 sizeof (ethernet_header_t);
1583 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1584 next0 = em->l2_next;
1585 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1589 if (ei && ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1590 goto skip_dmac_check0;
1592 dmacs[0] = *(u64 *) e0;
1596 if (vec_len (ei->secondary_addrs))
1597 ethernet_input_inline_dmac_check (
1598 hi, dmacs, dmacs_bad, 1 /* n_packets */, ei,
1599 1 /* have_sec_dmac */);
1601 ethernet_input_inline_dmac_check (
1602 hi, dmacs, dmacs_bad, 1 /* n_packets */, ei,
1603 0 /* have_sec_dmac */);
1606 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1610 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1611 determine_next_node (em, variant, 0, type0, b0,
1617 /* Slow-path for the tagged case */
1618 parse_header (variant,
1621 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1623 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1625 eth_vlan_table_lookups (em,
1632 &main_intf0, &vlan_intf0, &qinq_intf0);
1634 identify_subint (em,
1640 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1642 // Save RX sw_if_index for later nodes
1643 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1645 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1647 // Increment subinterface stats
1648 // Note that interface-level counters have already been incremented
1649 // prior to calling this function. Thus only subinterface counters
1650 // are incremented here.
1652 // Interface level counters include packets received on the main
1653 // interface and all subinterfaces. Subinterface level counters
1654 // include only those packets received on that subinterface
1655 // Increment stats if the subint is valid and it is not the main intf
1656 if ((new_sw_if_index0 != ~0)
1657 && (new_sw_if_index0 != old_sw_if_index0))
1660 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1661 - vnet_buffer (b0)->l2_hdr_offset;
1663 stats_n_packets += 1;
1664 stats_n_bytes += len0;
1666 // Batch stat increments from the same subinterface so counters
1667 // don't need to be incremented for every packet.
1668 if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1670 stats_n_packets -= 1;
1671 stats_n_bytes -= len0;
1673 if (new_sw_if_index0 != ~0)
1674 vlib_increment_combined_counter
1675 (vnm->interface_main.combined_sw_if_counters
1676 + VNET_INTERFACE_COUNTER_RX,
1677 thread_index, new_sw_if_index0, 1, len0);
1678 if (stats_n_packets > 0)
1680 vlib_increment_combined_counter
1681 (vnm->interface_main.combined_sw_if_counters
1682 + VNET_INTERFACE_COUNTER_RX,
1684 stats_sw_if_index, stats_n_packets, stats_n_bytes);
1685 stats_n_packets = stats_n_bytes = 0;
1687 stats_sw_if_index = new_sw_if_index0;
1691 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1694 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1698 b0->error = error_node->errors[error0];
1700 // verify speculative enqueue
1701 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1702 to_next, n_left_to_next,
1706 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1709 // Increment any remaining batched stats
1710 if (stats_n_packets > 0)
1712 vlib_increment_combined_counter
1713 (vnm->interface_main.combined_sw_if_counters
1714 + VNET_INTERFACE_COUNTER_RX,
1715 thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1716 node->runtime_data[0] = stats_sw_if_index;
1720 VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
1721 vlib_node_runtime_t * node,
1722 vlib_frame_t * frame)
1724 vnet_main_t *vnm = vnet_get_main ();
1725 u32 *from = vlib_frame_vector_args (frame);
1726 u32 n_packets = frame->n_vectors;
1728 ethernet_input_trace (vm, node, frame);
1730 if (frame->flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
1732 ethernet_input_frame_t *ef = vlib_frame_scalar_args (frame);
1733 int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1734 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ef->hw_if_index);
1735 eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1738 ethernet_input_inline (vm, node, from, n_packets,
1739 ETHERNET_INPUT_VARIANT_ETHERNET);
1743 VLIB_NODE_FN (ethernet_input_type_node) (vlib_main_t * vm,
1744 vlib_node_runtime_t * node,
1745 vlib_frame_t * from_frame)
1747 u32 *from = vlib_frame_vector_args (from_frame);
1748 u32 n_packets = from_frame->n_vectors;
1749 ethernet_input_trace (vm, node, from_frame);
1750 ethernet_input_inline (vm, node, from, n_packets,
1751 ETHERNET_INPUT_VARIANT_ETHERNET_TYPE);
1755 VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
1756 vlib_node_runtime_t * node,
1757 vlib_frame_t * from_frame)
1759 u32 *from = vlib_frame_vector_args (from_frame);
1760 u32 n_packets = from_frame->n_vectors;
1761 ethernet_input_trace (vm, node, from_frame);
1762 ethernet_input_inline (vm, node, from, n_packets,
1763 ETHERNET_INPUT_VARIANT_NOT_L2);
1768 // Return the subinterface config struct for the given sw_if_index
1769 // Also return via parameter the appropriate match flags for the
1770 // configured number of tags.
1771 // On error (unsupported or not ethernet) return 0.
1772 static subint_config_t *
1773 ethernet_sw_interface_get_config (vnet_main_t * vnm,
1775 u32 * flags, u32 * unsupported)
1777 ethernet_main_t *em = ðernet_main;
1778 vnet_hw_interface_t *hi;
1779 vnet_sw_interface_t *si;
1780 main_intf_t *main_intf;
1781 vlan_table_t *vlan_table;
1782 qinq_table_t *qinq_table;
1783 subint_config_t *subint = 0;
1785 hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1787 if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1790 goto done; // non-ethernet interface
1793 // ensure there's an entry for the main intf (shouldn't really be necessary)
1794 vec_validate (em->main_intfs, hi->hw_if_index);
1795 main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1797 // Locate the subint for the given ethernet config
1798 si = vnet_get_sw_interface (vnm, sw_if_index);
1800 if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1802 p2p_ethernet_main_t *p2pm = &p2p_main;
1803 u32 p2pe_sw_if_index =
1804 p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
1805 if (p2pe_sw_if_index == ~0)
1807 pool_get (p2pm->p2p_subif_pool, subint);
1808 si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1811 subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1812 *flags = SUBINT_CONFIG_P2P;
1814 else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1818 pipe = pipe_get (sw_if_index);
1819 subint = &pipe->subint;
1820 *flags = SUBINT_CONFIG_P2P;
1822 else if (si->sub.eth.flags.default_sub)
1824 subint = &main_intf->default_subint;
1825 *flags = SUBINT_CONFIG_MATCH_1_TAG |
1826 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1828 else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1830 // if no flags are set then this is a main interface
1831 // so treat as untagged
1832 subint = &main_intf->untagged_subint;
1833 *flags = SUBINT_CONFIG_MATCH_0_TAG;
1838 // first get the vlan table
1839 if (si->sub.eth.flags.dot1ad)
1841 if (main_intf->dot1ad_vlans == 0)
1843 // Allocate a vlan table from the pool
1844 pool_get (em->vlan_pool, vlan_table);
1845 main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1849 // Get ptr to existing vlan table
1851 vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1856 if (main_intf->dot1q_vlans == 0)
1858 // Allocate a vlan table from the pool
1859 pool_get (em->vlan_pool, vlan_table);
1860 main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1864 // Get ptr to existing vlan table
1866 vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1870 if (si->sub.eth.flags.one_tag)
1872 *flags = si->sub.eth.flags.exact_match ?
1873 SUBINT_CONFIG_MATCH_1_TAG :
1874 (SUBINT_CONFIG_MATCH_1_TAG |
1875 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1877 if (si->sub.eth.flags.outer_vlan_id_any)
1879 // not implemented yet
1885 // a single vlan, a common case
1887 &vlan_table->vlans[si->sub.eth.
1888 outer_vlan_id].single_tag_subint;
1895 *flags = si->sub.eth.flags.exact_match ?
1896 SUBINT_CONFIG_MATCH_2_TAG :
1897 (SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1899 if (si->sub.eth.flags.outer_vlan_id_any
1900 && si->sub.eth.flags.inner_vlan_id_any)
1902 // not implemented yet
1907 if (si->sub.eth.flags.inner_vlan_id_any)
1909 // a specific outer and "any" inner
1910 // don't need a qinq table for this
1912 &vlan_table->vlans[si->sub.eth.
1913 outer_vlan_id].inner_any_subint;
1914 if (si->sub.eth.flags.exact_match)
1916 *flags = SUBINT_CONFIG_MATCH_2_TAG;
1920 *flags = SUBINT_CONFIG_MATCH_2_TAG |
1921 SUBINT_CONFIG_MATCH_3_TAG;
1926 // a specific outer + specific innner vlan id, a common case
1928 // get the qinq table
1929 if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1931 // Allocate a qinq table from the pool
1932 pool_get (em->qinq_pool, qinq_table);
1933 vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1934 qinq_table - em->qinq_pool;
1938 // Get ptr to existing qinq table
1940 vec_elt_at_index (em->qinq_pool,
1941 vlan_table->vlans[si->sub.
1945 subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1954 static clib_error_t *
1955 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
1957 subint_config_t *subint;
1958 u32 placeholder_flags;
1959 u32 placeholder_unsup;
1960 clib_error_t *error = 0;
1962 // Find the config for this subinterface
1964 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1965 &placeholder_unsup);
1969 // not implemented yet or not ethernet
1973 subint->sw_if_index =
1974 ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1980 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
1983 #ifndef CLIB_MARCH_VARIANT
1984 // Set the L2/L3 mode for the subinterface
1986 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
1988 subint_config_t *subint;
1989 u32 placeholder_flags;
1990 u32 placeholder_unsup;
1992 vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1994 is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1996 // Find the config for this subinterface
1998 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1999 &placeholder_unsup);
2003 // unimplemented or not ethernet
2007 // Double check that the config we found is for our interface (or the interface is down)
2008 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2012 subint->flags |= SUBINT_CONFIG_L2;
2015 SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
2016 | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
2020 subint->flags &= ~SUBINT_CONFIG_L2;
2023 ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
2024 | SUBINT_CONFIG_MATCH_3_TAG);
2032 * Set the L2/L3 mode for the subinterface regardless of port
2035 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
2036 u32 sw_if_index, u32 l2)
2038 subint_config_t *subint;
2039 u32 placeholder_flags;
2040 u32 placeholder_unsup;
2042 /* Find the config for this subinterface */
2044 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
2045 &placeholder_unsup);
2049 /* unimplemented or not ethernet */
2054 * Double check that the config we found is for our interface (or the
2055 * interface is down)
2057 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2061 subint->flags |= SUBINT_CONFIG_L2;
2065 subint->flags &= ~SUBINT_CONFIG_L2;
2073 static clib_error_t *
2074 ethernet_sw_interface_add_del (vnet_main_t * vnm,
2075 u32 sw_if_index, u32 is_create)
2077 clib_error_t *error = 0;
2078 subint_config_t *subint;
2080 u32 unsupported = 0;
2082 // Find the config for this subinterface
2084 ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2089 // not implemented yet or not ethernet
2092 // this is the NYI case
2093 error = clib_error_return (0, "not implemented yet");
2104 // Initialize the subint
2105 if (subint->flags & SUBINT_CONFIG_VALID)
2107 // Error vlan already in use
2108 error = clib_error_return (0, "vlan is already in use");
2112 // Note that config is L3 by default
2113 subint->flags = SUBINT_CONFIG_VALID | match_flags;
2114 subint->sw_if_index = ~0; // because interfaces are initially down
2121 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
2123 static char *ethernet_error_strings[] = {
2124 #define ethernet_error(n,c,s) s,
2125 #include "error.def"
2126 #undef ethernet_error
2129 VLIB_REGISTER_NODE (ethernet_input_node) = {
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,
2138 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2139 foreach_ethernet_input_next
2142 .format_buffer = format_ethernet_header_with_length,
2143 .format_trace = format_ethernet_input_trace,
2144 .unformat_buffer = unformat_ethernet_header,
2147 VLIB_REGISTER_NODE (ethernet_input_type_node) = {
2148 .name = "ethernet-input-type",
2149 /* Takes a vector of packets. */
2150 .vector_size = sizeof (u32),
2151 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2153 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2154 foreach_ethernet_input_next
2159 VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
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,
2165 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2166 foreach_ethernet_input_next
2171 #ifndef CLIB_MARCH_VARIANT
2173 ethernet_set_rx_redirect (vnet_main_t * vnm,
2174 vnet_hw_interface_t * hi, u32 enable)
2176 // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2177 // don't go directly to ip4-input)
2178 vnet_hw_interface_rx_redirect_to_node
2179 (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2184 * Initialization and registration for the next_by_ethernet structure
2188 next_by_ethertype_init (next_by_ethertype_t * l3_next)
2190 l3_next->input_next_by_type = sparse_vec_new
2191 ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2192 /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2194 vec_validate (l3_next->sparse_index_by_input_next_index,
2195 ETHERNET_INPUT_NEXT_DROP);
2196 vec_validate (l3_next->sparse_index_by_input_next_index,
2197 ETHERNET_INPUT_NEXT_PUNT);
2198 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2199 SPARSE_VEC_INVALID_INDEX;
2200 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2201 SPARSE_VEC_INVALID_INDEX;
2204 * Make sure we don't wipe out an ethernet registration by mistake
2205 * Can happen if init function ordering constraints are missing.
2209 ethernet_main_t *em = ðernet_main;
2210 ASSERT (em->next_by_ethertype_register_called == 0);
2216 // Add an ethertype -> next index mapping to the structure
2218 next_by_ethertype_register (next_by_ethertype_t * l3_next,
2219 u32 ethertype, u32 next_index)
2223 ethernet_main_t *em = ðernet_main;
2227 ethernet_main_t *em = ðernet_main;
2228 em->next_by_ethertype_register_called = 1;
2231 /* Setup ethernet type -> next index sparse vector mapping. */
2232 n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2235 /* Rebuild next index -> sparse index inverse mapping when sparse vector
2237 vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2238 for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2240 sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2242 // do not allow the cached next index's to be updated if L3
2243 // redirect is enabled, as it will have overwritten them
2244 if (!em->redirect_l3)
2246 // Cache common ethertypes directly
2247 if (ethertype == ETHERNET_TYPE_IP4)
2249 l3_next->input_next_ip4 = next_index;
2251 else if (ethertype == ETHERNET_TYPE_IP6)
2253 l3_next->input_next_ip6 = next_index;
2255 else if (ethertype == ETHERNET_TYPE_MPLS)
2257 l3_next->input_next_mpls = next_index;
2264 ethernet_setup_node (vlib_main_t *vm, u32 node_index)
2266 vlib_node_t *n = vlib_get_node (vm, node_index);
2267 pg_node_t *pn = pg_get_node (node_index);
2269 n->format_buffer = format_ethernet_header_with_length;
2270 n->unformat_buffer = unformat_ethernet_header;
2271 pn->unformat_edit = unformat_pg_ethernet_header;
2275 ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
2277 __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2278 __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2280 ethernet_setup_node (vm, ethernet_input_node.index);
2281 ethernet_setup_node (vm, ethernet_input_type_node.index);
2282 ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
2284 next_by_ethertype_init (&em->l3_next);
2286 // Initialize pools and vector for vlan parsing
2287 vec_validate (em->main_intfs, 10); // 10 main interfaces
2288 pool_alloc (em->vlan_pool, 10);
2289 pool_alloc (em->qinq_pool, 1);
2291 // The first vlan pool will always be reserved for an invalid table
2292 pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2293 // The first qinq pool will always be reserved for an invalid table
2294 pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2298 ethernet_register_input_type (vlib_main_t * vm,
2299 ethernet_type_t type, u32 node_index)
2301 ethernet_main_t *em = ðernet_main;
2302 ethernet_type_info_t *ti;
2306 clib_error_t *error = vlib_call_init_function (vm, ethernet_init);
2308 clib_error_report (error);
2311 ti = ethernet_get_type_info (em, type);
2314 clib_warning ("type_info NULL for type %d", type);
2317 ti->node_index = node_index;
2318 ti->next_index = vlib_node_add_next (vm,
2319 ethernet_input_node.index, node_index);
2320 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2321 ASSERT (i == ti->next_index);
2323 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2324 ASSERT (i == ti->next_index);
2326 // Add the L3 node for this ethertype to the next nodes structure
2327 next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2329 // Call the registration functions for other nodes that want a mapping
2330 l2bvi_register_input_type (vm, type, node_index);
2334 ethernet_register_l2_input (vlib_main_t * vm, u32 node_index)
2336 ethernet_main_t *em = ðernet_main;
2340 vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2343 * Even if we never use these arcs, we have to align the next indices...
2345 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2347 ASSERT (i == em->l2_next);
2349 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2350 ASSERT (i == em->l2_next);
2353 // Register a next node for L3 redirect, and enable L3 redirect
2355 ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
2357 ethernet_main_t *em = ðernet_main;
2360 em->redirect_l3 = 1;
2361 em->redirect_l3_next = vlib_node_add_next (vm,
2362 ethernet_input_node.index,
2365 * Change the cached next nodes to the redirect node
2367 em->l3_next.input_next_ip4 = em->redirect_l3_next;
2368 em->l3_next.input_next_ip6 = em->redirect_l3_next;
2369 em->l3_next.input_next_mpls = em->redirect_l3_next;
2372 * Even if we never use these arcs, we have to align the next indices...
2374 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2376 ASSERT (i == em->redirect_l3_next);
2378 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2380 ASSERT (i == em->redirect_l3_next);
2385 * fd.io coding-style-patch-verification: ON
2388 * eval: (c-set-style "gnu")