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/trace_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 (vnet_hw_interface_t * hi,
210 main_intf_t * main_intf,
211 vlan_intf_t * vlan_intf,
212 qinq_intf_t * qinq_intf,
213 u32 * new_sw_if_index, u8 * error0, u32 * is_l2)
217 matched = eth_identify_subint (hi, match_flags, main_intf, vlan_intf,
218 qinq_intf, new_sw_if_index, error0, is_l2);
222 // Perform L3 my-mac filter
223 // A unicast packet arriving on an L3 interface must have a dmac
224 // matching the interface mac. If interface has STATUS_L3 bit set
225 // mac filter is already done.
226 if (!(*is_l2 || (hi->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)))
230 ethernet_header_t *e0;
231 ethernet_interface_t *ei0;
233 e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
234 dmacs[0] = *(u64 *) e0;
235 ei0 = ethernet_get_interface (ðernet_main, hi->hw_if_index);
237 if (ei0 && vec_len (ei0->secondary_addrs))
238 ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
239 1 /* n_packets */ , ei0,
240 1 /* have_sec_dmac */ );
242 ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
243 1 /* n_packets */ , ei0,
244 0 /* have_sec_dmac */ );
246 *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
249 // Check for down subinterface
250 *error0 = (*new_sw_if_index) != ~0 ? (*error0) : ETHERNET_ERROR_DOWN;
254 static_always_inline void
255 determine_next_node (ethernet_main_t * em,
256 ethernet_input_variant_t variant,
258 u32 type0, vlib_buffer_t * b0, u8 * error0, u8 * next0)
260 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
261 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
263 if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE))
265 // some error occurred
266 *next0 = ETHERNET_INPUT_NEXT_DROP;
270 // record the L2 len and reset the buffer so the L2 header is preserved
271 u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
272 vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
273 *next0 = em->l2_next;
274 ASSERT (vnet_buffer (b0)->l2.l2_len ==
275 ethernet_buffer_header_size (b0));
276 vlib_buffer_advance (b0, -(vnet_buffer (b0)->l2.l2_len));
278 // check for common IP/MPLS ethertypes
280 else if (type0 == ETHERNET_TYPE_IP4)
282 *next0 = em->l3_next.input_next_ip4;
284 else if (type0 == ETHERNET_TYPE_IP6)
286 *next0 = em->l3_next.input_next_ip6;
288 else if (type0 == ETHERNET_TYPE_MPLS)
290 *next0 = em->l3_next.input_next_mpls;
293 else if (em->redirect_l3)
295 // L3 Redirect is on, the cached common next nodes will be
296 // pointing to the redirect node, catch the uncommon types here
297 *next0 = em->redirect_l3_next;
301 // uncommon ethertype, check table
303 i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
304 *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
307 SPARSE_VEC_INVALID_INDEX ? ETHERNET_ERROR_UNKNOWN_TYPE : *error0;
309 // The table is not populated with LLC values, so check that now.
310 // If variant is variant_ethernet then we came from LLC processing. Don't
311 // go back there; drop instead using by keeping the drop/bad table result.
312 if ((type0 < 0x600) && (variant == ETHERNET_INPUT_VARIANT_ETHERNET))
314 *next0 = ETHERNET_INPUT_NEXT_LLC;
320 /* following vector code relies on following assumptions */
321 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_data, 0);
322 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_length, 2);
323 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, flags, 4);
324 STATIC_ASSERT (STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l2_hdr_offset) ==
325 STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l3_hdr_offset) - 2,
326 "l3_hdr_offset must follow l2_hdr_offset");
328 static_always_inline void
329 eth_input_adv_and_flags_x4 (vlib_buffer_t ** b, int is_l3)
331 i16 adv = sizeof (ethernet_header_t);
332 u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
333 VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
335 #ifdef CLIB_HAVE_VEC256
336 /* to reduce number of small loads/stores we are loading first 64 bits
337 of each buffer metadata into 256-bit register so we can advance
338 current_data, current_length and flags.
339 Observed saving of this code is ~2 clocks per packet */
342 /* vector if signed 16 bit integers used in signed vector add operation
343 to advnce current_data and current_length */
344 u32x8 flags4 = { 0, flags, 0, flags, 0, flags, 0, flags };
346 adv, -adv, 0, 0, adv, -adv, 0, 0,
347 adv, -adv, 0, 0, adv, -adv, 0, 0
350 /* load 4 x 64 bits */
351 r = u64x4_gather (b[0], b[1], b[2], b[3]);
357 radv = (u64x4) ((i16x16) r + adv4);
359 /* write 4 x 64 bits */
360 u64x4_scatter (is_l3 ? radv : r, b[0], b[1], b[2], b[3]);
362 /* use old current_data as l2_hdr_offset and new current_data as
364 r = (u64x4) u16x16_blend (r, radv << 16, 0xaa);
366 /* store both l2_hdr_offset and l3_hdr_offset in single store operation */
367 u32x8_scatter_one ((u32x8) r, 0, &vnet_buffer (b[0])->l2_hdr_offset);
368 u32x8_scatter_one ((u32x8) r, 2, &vnet_buffer (b[1])->l2_hdr_offset);
369 u32x8_scatter_one ((u32x8) r, 4, &vnet_buffer (b[2])->l2_hdr_offset);
370 u32x8_scatter_one ((u32x8) r, 6, &vnet_buffer (b[3])->l2_hdr_offset);
374 ASSERT (b[0]->current_data == vnet_buffer (b[0])->l3_hdr_offset);
375 ASSERT (b[1]->current_data == vnet_buffer (b[1])->l3_hdr_offset);
376 ASSERT (b[2]->current_data == vnet_buffer (b[2])->l3_hdr_offset);
377 ASSERT (b[3]->current_data == vnet_buffer (b[3])->l3_hdr_offset);
379 ASSERT (b[0]->current_data - vnet_buffer (b[0])->l2_hdr_offset == adv);
380 ASSERT (b[1]->current_data - vnet_buffer (b[1])->l2_hdr_offset == adv);
381 ASSERT (b[2]->current_data - vnet_buffer (b[2])->l2_hdr_offset == adv);
382 ASSERT (b[3]->current_data - vnet_buffer (b[3])->l2_hdr_offset == adv);
386 ASSERT (b[0]->current_data == vnet_buffer (b[0])->l2_hdr_offset);
387 ASSERT (b[1]->current_data == vnet_buffer (b[1])->l2_hdr_offset);
388 ASSERT (b[2]->current_data == vnet_buffer (b[2])->l2_hdr_offset);
389 ASSERT (b[3]->current_data == vnet_buffer (b[3])->l2_hdr_offset);
391 ASSERT (b[0]->current_data - vnet_buffer (b[0])->l3_hdr_offset == -adv);
392 ASSERT (b[1]->current_data - vnet_buffer (b[1])->l3_hdr_offset == -adv);
393 ASSERT (b[2]->current_data - vnet_buffer (b[2])->l3_hdr_offset == -adv);
394 ASSERT (b[3]->current_data - vnet_buffer (b[3])->l3_hdr_offset == -adv);
398 vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
399 vnet_buffer (b[1])->l2_hdr_offset = b[1]->current_data;
400 vnet_buffer (b[2])->l2_hdr_offset = b[2]->current_data;
401 vnet_buffer (b[3])->l2_hdr_offset = b[3]->current_data;
402 vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
403 vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data + adv;
404 vnet_buffer (b[2])->l3_hdr_offset = b[2]->current_data + adv;
405 vnet_buffer (b[3])->l3_hdr_offset = b[3]->current_data + adv;
409 vlib_buffer_advance (b[0], adv);
410 vlib_buffer_advance (b[1], adv);
411 vlib_buffer_advance (b[2], adv);
412 vlib_buffer_advance (b[3], adv);
415 b[0]->flags |= flags;
416 b[1]->flags |= flags;
417 b[2]->flags |= flags;
418 b[3]->flags |= flags;
423 vnet_buffer (b[0])->l2.l2_len = adv;
424 vnet_buffer (b[1])->l2.l2_len = adv;
425 vnet_buffer (b[2])->l2.l2_len = adv;
426 vnet_buffer (b[3])->l2.l2_len = adv;
430 static_always_inline void
431 eth_input_adv_and_flags_x1 (vlib_buffer_t ** b, int is_l3)
433 i16 adv = sizeof (ethernet_header_t);
434 u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
435 VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
437 vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
438 vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
441 vlib_buffer_advance (b[0], adv);
442 b[0]->flags |= flags;
444 vnet_buffer (b[0])->l2.l2_len = adv;
448 static_always_inline void
449 eth_input_get_etype_and_tags (vlib_buffer_t ** b, u16 * etype, u64 * tags,
450 u64 * dmacs, int offset, int dmac_check)
452 ethernet_header_t *e;
453 e = vlib_buffer_get_current (b[offset]);
454 #ifdef CLIB_HAVE_VEC128
455 u64x2 r = u64x2_load_unaligned (((u8 *) & e->type) - 6);
456 etype[offset] = ((u16x8) r)[3];
459 etype[offset] = e->type;
460 tags[offset] = *(u64 *) (e + 1);
464 dmacs[offset] = *(u64 *) e;
467 static_always_inline u16
468 eth_input_next_by_type (u16 etype)
470 ethernet_main_t *em = ðernet_main;
472 return (etype < 0x600) ? ETHERNET_INPUT_NEXT_LLC :
473 vec_elt (em->l3_next.input_next_by_type,
474 sparse_vec_index (em->l3_next.input_next_by_type, etype));
484 u64 n_packets, n_bytes;
485 } eth_input_tag_lookup_t;
487 static_always_inline void
488 eth_input_update_if_counters (vlib_main_t * vm, vnet_main_t * vnm,
489 eth_input_tag_lookup_t * l)
491 if (l->n_packets == 0 || l->sw_if_index == ~0)
495 l->n_bytes += l->n_packets * l->len;
497 vlib_increment_combined_counter
498 (vnm->interface_main.combined_sw_if_counters +
499 VNET_INTERFACE_COUNTER_RX, vm->thread_index, l->sw_if_index,
500 l->n_packets, l->n_bytes);
503 static_always_inline void
504 eth_input_tag_lookup (vlib_main_t * vm, vnet_main_t * vnm,
505 vlib_node_runtime_t * node, vnet_hw_interface_t * hi,
506 u64 tag, u16 * next, vlib_buffer_t * b,
507 eth_input_tag_lookup_t * l, u8 dmac_bad, int is_dot1ad,
508 int main_is_l3, int check_dmac)
510 ethernet_main_t *em = ðernet_main;
512 if ((tag ^ l->tag) & l->mask)
514 main_intf_t *mif = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
517 vlan_table_t *vlan_table;
518 qinq_table_t *qinq_table;
519 u16 *t = (u16 *) & tag;
520 u16 vlan1 = clib_net_to_host_u16 (t[0]) & 0xFFF;
521 u16 vlan2 = clib_net_to_host_u16 (t[2]) & 0xFFF;
522 u32 matched, is_l2, new_sw_if_index;
524 vlan_table = vec_elt_at_index (em->vlan_pool, is_dot1ad ?
525 mif->dot1ad_vlans : mif->dot1q_vlans);
526 vif = &vlan_table->vlans[vlan1];
527 qinq_table = vec_elt_at_index (em->qinq_pool, vif->qinqs);
528 qif = &qinq_table->vlans[vlan2];
529 l->err = ETHERNET_ERROR_NONE;
530 l->type = clib_net_to_host_u16 (t[1]);
532 if (l->type == ETHERNET_TYPE_VLAN)
534 l->type = clib_net_to_host_u16 (t[3]);
536 matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
537 SUBINT_CONFIG_MATCH_2_TAG, mif, vif,
538 qif, &new_sw_if_index, &l->err,
546 new_sw_if_index = hi->sw_if_index;
547 l->err = ETHERNET_ERROR_NONE;
549 is_l2 = main_is_l3 == 0;
552 matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
553 SUBINT_CONFIG_MATCH_1_TAG, mif,
554 vif, qif, &new_sw_if_index,
558 if (l->sw_if_index != new_sw_if_index)
560 eth_input_update_if_counters (vm, vnm, l);
563 l->sw_if_index = new_sw_if_index;
566 l->mask = (l->n_tags == 2) ?
567 clib_net_to_host_u64 (0xffffffffffffffff) :
568 clib_net_to_host_u64 (0xffffffff00000000);
570 if (matched && l->sw_if_index == ~0)
571 l->err = ETHERNET_ERROR_DOWN;
573 l->len = sizeof (ethernet_header_t) +
574 l->n_tags * sizeof (ethernet_vlan_header_t);
576 l->adv = is_l2 ? -(int) sizeof (ethernet_header_t) :
577 l->n_tags * sizeof (ethernet_vlan_header_t);
579 l->adv = is_l2 ? 0 : l->len;
581 if (PREDICT_FALSE (l->err != ETHERNET_ERROR_NONE))
582 l->next = ETHERNET_INPUT_NEXT_DROP;
584 l->next = em->l2_next;
585 else if (l->type == ETHERNET_TYPE_IP4)
586 l->next = em->l3_next.input_next_ip4;
587 else if (l->type == ETHERNET_TYPE_IP6)
588 l->next = em->l3_next.input_next_ip6;
589 else if (l->type == ETHERNET_TYPE_MPLS)
590 l->next = em->l3_next.input_next_mpls;
591 else if (em->redirect_l3)
592 l->next = em->redirect_l3_next;
595 l->next = eth_input_next_by_type (l->type);
596 if (l->next == ETHERNET_INPUT_NEXT_PUNT)
597 l->err = ETHERNET_ERROR_UNKNOWN_TYPE;
601 if (check_dmac && l->adv > 0 && dmac_bad)
603 l->err = ETHERNET_ERROR_L3_MAC_MISMATCH;
604 next[0] = ETHERNET_INPUT_NEXT_PUNT;
609 vlib_buffer_advance (b, l->adv);
610 vnet_buffer (b)->l2.l2_len = l->len;
611 vnet_buffer (b)->l3_hdr_offset = vnet_buffer (b)->l2_hdr_offset + l->len;
613 if (l->err == ETHERNET_ERROR_NONE)
615 vnet_buffer (b)->sw_if_index[VLIB_RX] = l->sw_if_index;
616 ethernet_buffer_set_vlan_count (b, l->n_tags);
619 b->error = node->errors[l->err];
621 /* update counters */
623 l->n_bytes += vlib_buffer_length_in_chain (vm, b);
626 #define DMAC_MASK clib_net_to_host_u64 (0xFFFFFFFFFFFF0000)
627 #define DMAC_IGBIT clib_net_to_host_u64 (0x0100000000000000)
629 #ifdef CLIB_HAVE_VEC256
630 static_always_inline u32
631 is_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
633 u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
634 r0 = (r0 != u64x4_splat (hwaddr)) & ((r0 & u64x4_splat (DMAC_IGBIT)) == 0);
635 return u8x32_msb_mask ((u8x32) (r0));
639 static_always_inline u8
640 is_dmac_bad (u64 dmac, u64 hwaddr)
642 u64 r0 = dmac & DMAC_MASK;
643 return (r0 != hwaddr) && ((r0 & DMAC_IGBIT) == 0);
646 static_always_inline u8
647 is_sec_dmac_bad (u64 dmac, u64 hwaddr)
649 return ((dmac & DMAC_MASK) != hwaddr);
652 #ifdef CLIB_HAVE_VEC256
653 static_always_inline u32
654 is_sec_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
656 u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
657 r0 = (r0 != u64x4_splat (hwaddr));
658 return u8x32_msb_mask ((u8x32) (r0));
662 static_always_inline u8
663 eth_input_sec_dmac_check_x1 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
665 dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
669 static_always_inline u32
670 eth_input_sec_dmac_check_x4 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
672 #ifdef CLIB_HAVE_VEC256
673 *(u32 *) (dmac_bad + 0) &= is_sec_dmac_bad_x4 (dmac + 0, hwaddr);
675 dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
676 dmac_bad[1] &= is_sec_dmac_bad (dmac[1], hwaddr);
677 dmac_bad[2] &= is_sec_dmac_bad (dmac[2], hwaddr);
678 dmac_bad[3] &= is_sec_dmac_bad (dmac[3], hwaddr);
680 return *(u32 *) dmac_bad;
684 * DMAC check for ethernet_input_inline()
686 * dmacs and dmacs_bad are arrays that are 2 elements long
687 * n_packets should be 1 or 2 for ethernet_input_inline()
689 static_always_inline void
690 ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi,
691 u64 * dmacs, u8 * dmacs_bad,
692 u32 n_packets, ethernet_interface_t * ei,
695 u64 hwaddr = (*(u64 *) hi->hw_address) & DMAC_MASK;
698 dmacs_bad[0] = is_dmac_bad (dmacs[0], hwaddr);
699 dmacs_bad[1] = ((n_packets > 1) & is_dmac_bad (dmacs[1], hwaddr));
701 bad = dmacs_bad[0] | dmacs_bad[1];
703 if (PREDICT_FALSE (bad && have_sec_dmac))
705 mac_address_t *sec_addr;
707 vec_foreach (sec_addr, ei->secondary_addrs)
709 hwaddr = (*(u64 *) sec_addr) & DMAC_MASK;
711 bad = (eth_input_sec_dmac_check_x1 (hwaddr, dmacs, dmacs_bad) |
712 eth_input_sec_dmac_check_x1 (hwaddr, dmacs + 1,
721 static_always_inline void
722 eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi,
723 u64 * dmacs, u8 * dmacs_bad,
724 u32 n_packets, ethernet_interface_t * ei,
727 u64 hwaddr = (*(u64 *) hi->hw_address) & DMAC_MASK;
729 u8 *dmac_bad = dmacs_bad;
731 i32 n_left = n_packets;
733 #ifdef CLIB_HAVE_VEC256
736 bad |= *(u32 *) (dmac_bad + 0) = is_dmac_bad_x4 (dmac + 0, hwaddr);
737 bad |= *(u32 *) (dmac_bad + 4) = is_dmac_bad_x4 (dmac + 4, hwaddr);
747 bad |= dmac_bad[0] = is_dmac_bad (dmac[0], hwaddr);
748 bad |= dmac_bad[1] = is_dmac_bad (dmac[1], hwaddr);
749 bad |= dmac_bad[2] = is_dmac_bad (dmac[2], hwaddr);
750 bad |= dmac_bad[3] = is_dmac_bad (dmac[3], hwaddr);
759 if (have_sec_dmac && bad)
763 vec_foreach (addr, ei->secondary_addrs)
765 u64 hwaddr = ((u64 *) addr)[0] & DMAC_MASK;
766 i32 n_left = n_packets;
768 u8 *dmac_bad = dmacs_bad;
777 /* skip any that have already matched */
786 n_bad = clib_min (4, n_left);
788 /* If >= 4 left, compare 4 together */
791 bad |= eth_input_sec_dmac_check_x4 (hwaddr, dmac, dmac_bad);
796 /* handle individually */
799 bad |= eth_input_sec_dmac_check_x1 (hwaddr, dmac + adv,
810 if (!bad) /* can stop looping if everything matched */
816 /* process frame of buffers, store ethertype into array and update
817 buffer metadata fields depending on interface being l2 or l3 assuming that
818 packets are untagged. For tagged packets those fields are updated later.
819 Optionally store Destionation MAC address and tag data into arrays
820 for further processing */
822 STATIC_ASSERT (VLIB_FRAME_SIZE % 8 == 0,
823 "VLIB_FRAME_SIZE must be power of 8");
824 static_always_inline void
825 eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
826 vnet_hw_interface_t * hi,
827 u32 * buffer_indices, u32 n_packets, int main_is_l3,
828 int ip4_cksum_ok, int dmac_check)
830 ethernet_main_t *em = ðernet_main;
831 u16 nexts[VLIB_FRAME_SIZE], *next;
832 u16 etypes[VLIB_FRAME_SIZE], *etype = etypes;
833 u64 dmacs[VLIB_FRAME_SIZE], *dmac = dmacs;
834 u8 dmacs_bad[VLIB_FRAME_SIZE];
835 u64 tags[VLIB_FRAME_SIZE], *tag = tags;
836 u16 slowpath_indices[VLIB_FRAME_SIZE];
838 u16 next_ip4, next_ip6, next_mpls, next_l2;
839 u16 et_ip4 = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
840 u16 et_ip6 = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
841 u16 et_mpls = clib_host_to_net_u16 (ETHERNET_TYPE_MPLS);
842 u16 et_vlan = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
843 u16 et_dot1ad = clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD);
844 i32 n_left = n_packets;
845 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
846 vlib_buffer_t **b = bufs;
847 ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index);
849 vlib_get_buffers (vm, buffer_indices, b, n_left);
853 vlib_buffer_t **ph = b + 16, **pd = b + 8;
855 vlib_prefetch_buffer_header (ph[0], LOAD);
856 vlib_prefetch_buffer_data (pd[0], LOAD);
857 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
859 vlib_prefetch_buffer_header (ph[1], LOAD);
860 vlib_prefetch_buffer_data (pd[1], LOAD);
861 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
863 vlib_prefetch_buffer_header (ph[2], LOAD);
864 vlib_prefetch_buffer_data (pd[2], LOAD);
865 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
867 vlib_prefetch_buffer_header (ph[3], LOAD);
868 vlib_prefetch_buffer_data (pd[3], LOAD);
869 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
871 eth_input_adv_and_flags_x4 (b, main_is_l3);
882 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
883 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
884 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
885 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
886 eth_input_adv_and_flags_x4 (b, main_is_l3);
897 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
898 eth_input_adv_and_flags_x1 (b, main_is_l3);
910 if (ei && vec_len (ei->secondary_addrs))
911 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
912 ei, 1 /* have_sec_dmac */ );
914 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
915 ei, 0 /* have_sec_dmac */ );
918 next_ip4 = em->l3_next.input_next_ip4;
919 next_ip6 = em->l3_next.input_next_ip6;
920 next_mpls = em->l3_next.input_next_mpls;
921 next_l2 = em->l2_next;
923 if (next_ip4 == ETHERNET_INPUT_NEXT_IP4_INPUT && ip4_cksum_ok)
924 next_ip4 = ETHERNET_INPUT_NEXT_IP4_INPUT_NCS;
926 #ifdef CLIB_HAVE_VEC256
927 u16x16 et16_ip4 = u16x16_splat (et_ip4);
928 u16x16 et16_ip6 = u16x16_splat (et_ip6);
929 u16x16 et16_mpls = u16x16_splat (et_mpls);
930 u16x16 et16_vlan = u16x16_splat (et_vlan);
931 u16x16 et16_dot1ad = u16x16_splat (et_dot1ad);
932 u16x16 next16_ip4 = u16x16_splat (next_ip4);
933 u16x16 next16_ip6 = u16x16_splat (next_ip6);
934 u16x16 next16_mpls = u16x16_splat (next_mpls);
935 u16x16 next16_l2 = u16x16_splat (next_l2);
937 u16x16 stairs = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
946 /* fastpath - in l3 mode hadles ip4, ip6 and mpls packets, other packets
947 are considered as slowpath, in l2 mode all untagged packets are
948 considered as fastpath */
951 #ifdef CLIB_HAVE_VEC256
955 u16x16 e16 = u16x16_load_unaligned (etype);
958 r += (e16 == et16_ip4) & next16_ip4;
959 r += (e16 == et16_ip6) & next16_ip6;
960 r += (e16 == et16_mpls) & next16_mpls;
963 r = ((e16 != et16_vlan) & (e16 != et16_dot1ad)) & next16_l2;
964 u16x16_store_unaligned (r, next);
966 if (!u16x16_is_all_zero (r == zero))
968 if (u16x16_is_all_zero (r))
970 u16x16_store_unaligned (u16x16_splat (i) + stairs,
971 slowpath_indices + n_slowpath);
976 for (int j = 0; j < 16; j++)
978 slowpath_indices[n_slowpath++] = i + j;
989 if (main_is_l3 && etype[0] == et_ip4)
991 else if (main_is_l3 && etype[0] == et_ip6)
993 else if (main_is_l3 && etype[0] == et_mpls)
995 else if (main_is_l3 == 0 &&
996 etype[0] != et_vlan && etype[0] != et_dot1ad)
1001 slowpath_indices[n_slowpath++] = i;
1012 vnet_main_t *vnm = vnet_get_main ();
1013 n_left = n_slowpath;
1014 u16 *si = slowpath_indices;
1015 u32 last_unknown_etype = ~0;
1016 u32 last_unknown_next = ~0;
1017 eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
1019 .tag = tags[si[0]] ^ -1LL,
1023 clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
1028 u16 etype = etypes[i];
1030 if (etype == et_vlan)
1032 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1033 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1034 &dot1q_lookup, dmacs_bad[i], 0,
1035 main_is_l3, dmac_check);
1038 else if (etype == et_dot1ad)
1040 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1041 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1042 &dot1ad_lookup, dmacs_bad[i], 1,
1043 main_is_l3, dmac_check);
1047 /* untagged packet with not well known etyertype */
1048 if (last_unknown_etype != etype)
1050 last_unknown_etype = etype;
1051 etype = clib_host_to_net_u16 (etype);
1052 last_unknown_next = eth_input_next_by_type (etype);
1054 if (dmac_check && main_is_l3 && dmacs_bad[i])
1056 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1057 b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
1058 nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
1061 nexts[i] = last_unknown_next;
1069 eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
1070 eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
1073 vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
1076 static_always_inline void
1077 eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node,
1078 vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
1081 ethernet_main_t *em = ðernet_main;
1082 ethernet_interface_t *ei;
1083 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
1084 main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1085 subint_config_t *subint0 = &intf0->untagged_subint;
1087 int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
1088 int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3;
1092 if (int_is_l3 || /* DMAC filter already done by NIC */
1093 ((hi->l2_if_count != 0) && (hi->l3_if_count == 0)))
1094 { /* All L2 usage - DMAC check not needed */
1095 eth_input_process_frame (vm, node, hi, from, n_pkts,
1096 /*is_l3 */ 1, ip4_cksum_ok, 0);
1099 { /* DMAC check needed for L3 */
1100 eth_input_process_frame (vm, node, hi, from, n_pkts,
1101 /*is_l3 */ 1, ip4_cksum_ok, 1);
1107 if (hi->l3_if_count == 0)
1108 { /* All L2 usage - DMAC check not needed */
1109 eth_input_process_frame (vm, node, hi, from, n_pkts,
1110 /*is_l3 */ 0, ip4_cksum_ok, 0);
1113 { /* DMAC check needed for L3 */
1114 eth_input_process_frame (vm, node, hi, from, n_pkts,
1115 /*is_l3 */ 0, ip4_cksum_ok, 1);
1121 static_always_inline void
1122 ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
1123 vlib_frame_t * from_frame)
1126 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1128 from = vlib_frame_vector_args (from_frame);
1129 n_left = from_frame->n_vectors;
1133 ethernet_input_trace_t *t0;
1134 vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1136 if (b0->flags & VLIB_BUFFER_IS_TRACED)
1138 t0 = vlib_add_trace (vm, node, b0,
1139 sizeof (ethernet_input_trace_t));
1140 clib_memcpy_fast (t0->packet_data, b0->data + b0->current_data,
1141 sizeof (t0->packet_data));
1142 t0->frame_flags = from_frame->flags;
1143 clib_memcpy_fast (&t0->frame_data,
1144 vlib_frame_scalar_args (from_frame),
1145 sizeof (ethernet_input_frame_t));
1152 /* rx pcap capture if enabled */
1153 if (PREDICT_FALSE (vlib_global_main.pcap.pcap_rx_enable))
1156 vnet_pcap_t *pp = &vlib_global_main.pcap;
1158 from = vlib_frame_vector_args (from_frame);
1159 n_left = from_frame->n_vectors;
1162 int classify_filter_result;
1167 b0 = vlib_get_buffer (vm, bi0);
1168 if (pp->filter_classify_table_index != ~0)
1170 classify_filter_result =
1171 vnet_is_packet_traced_inline
1172 (b0, pp->filter_classify_table_index, 0 /* full classify */ );
1173 if (classify_filter_result)
1174 pcap_add_buffer (&pp->pcap_main, vm, bi0,
1175 pp->max_bytes_per_pkt);
1179 if (pp->pcap_sw_if_index == 0 ||
1180 pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1182 vnet_main_t *vnm = vnet_get_main ();
1183 vnet_hw_interface_t *hi =
1184 vnet_get_sup_hw_interface
1185 (vnm, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1187 /* Capture pkt if not filtered, or if filter hits */
1188 if (hi->trace_classify_table_index == ~0 ||
1189 vnet_is_packet_traced_inline
1190 (b0, hi->trace_classify_table_index,
1191 0 /* full classify */ ))
1192 pcap_add_buffer (&pp->pcap_main, vm, bi0,
1193 pp->max_bytes_per_pkt);
1199 static_always_inline void
1200 ethernet_input_inline (vlib_main_t * vm,
1201 vlib_node_runtime_t * node,
1202 u32 * from, u32 n_packets,
1203 ethernet_input_variant_t variant)
1205 vnet_main_t *vnm = vnet_get_main ();
1206 ethernet_main_t *em = ðernet_main;
1207 vlib_node_runtime_t *error_node;
1208 u32 n_left_from, next_index, *to_next;
1209 u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1210 u32 thread_index = vm->thread_index;
1211 u32 cached_sw_if_index = ~0;
1212 u32 cached_is_l2 = 0; /* shut up gcc */
1213 vnet_hw_interface_t *hi = NULL; /* used for main interface only */
1214 ethernet_interface_t *ei = NULL;
1215 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
1216 vlib_buffer_t **b = bufs;
1218 if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1219 error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1223 n_left_from = n_packets;
1225 next_index = node->cached_next_index;
1226 stats_sw_if_index = node->runtime_data[0];
1227 stats_n_packets = stats_n_bytes = 0;
1228 vlib_get_buffers (vm, from, bufs, n_left_from);
1230 while (n_left_from > 0)
1234 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1236 while (n_left_from >= 4 && n_left_to_next >= 2)
1239 vlib_buffer_t *b0, *b1;
1240 u8 next0, next1, error0, error1;
1241 u16 type0, orig_type0, type1, orig_type1;
1242 u16 outer_id0, inner_id0, outer_id1, inner_id1;
1243 u32 match_flags0, match_flags1;
1244 u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1245 new_sw_if_index1, len1;
1246 vnet_hw_interface_t *hi0, *hi1;
1247 main_intf_t *main_intf0, *main_intf1;
1248 vlan_intf_t *vlan_intf0, *vlan_intf1;
1249 qinq_intf_t *qinq_intf0, *qinq_intf1;
1251 ethernet_header_t *e0, *e1;
1255 /* Prefetch next iteration. */
1257 vlib_prefetch_buffer_header (b[2], STORE);
1258 vlib_prefetch_buffer_header (b[3], STORE);
1260 CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1261 CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1270 n_left_to_next -= 2;
1277 error0 = error1 = ETHERNET_ERROR_NONE;
1278 e0 = vlib_buffer_get_current (b0);
1279 type0 = clib_net_to_host_u16 (e0->type);
1280 e1 = vlib_buffer_get_current (b1);
1281 type1 = clib_net_to_host_u16 (e1->type);
1283 /* Set the L2 header offset for all packets */
1284 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1285 vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1286 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1287 b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1289 /* Speed-path for the untagged case */
1290 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1291 && !ethernet_frame_is_any_tagged_x2 (type0,
1295 subint_config_t *subint0;
1296 u32 sw_if_index0, sw_if_index1;
1298 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1299 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1300 is_l20 = cached_is_l2;
1302 /* This is probably wholly unnecessary */
1303 if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1306 /* Now sw_if_index0 == sw_if_index1 */
1307 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1309 cached_sw_if_index = sw_if_index0;
1310 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1311 ei = ethernet_get_interface (em, hi->hw_if_index);
1312 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1313 subint0 = &intf0->untagged_subint;
1314 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1317 if (PREDICT_TRUE (is_l20 != 0))
1319 vnet_buffer (b0)->l3_hdr_offset =
1320 vnet_buffer (b0)->l2_hdr_offset +
1321 sizeof (ethernet_header_t);
1322 vnet_buffer (b1)->l3_hdr_offset =
1323 vnet_buffer (b1)->l2_hdr_offset +
1324 sizeof (ethernet_header_t);
1325 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1326 b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1327 next0 = em->l2_next;
1328 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1329 next1 = em->l2_next;
1330 vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1334 if (hi->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1335 goto skip_dmac_check01;
1337 dmacs[0] = *(u64 *) e0;
1338 dmacs[1] = *(u64 *) e1;
1340 if (ei && vec_len (ei->secondary_addrs))
1341 ethernet_input_inline_dmac_check (hi, dmacs,
1345 1 /* have_sec_dmac */ );
1347 ethernet_input_inline_dmac_check (hi, dmacs,
1351 0 /* have_sec_dmac */ );
1354 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1356 error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1359 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1360 determine_next_node (em, variant, 0, type0, b0,
1362 vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1363 determine_next_node (em, variant, 0, type1, b1,
1369 /* Slow-path for the tagged case */
1371 parse_header (variant,
1374 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1376 parse_header (variant,
1379 &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1381 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1382 old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1384 eth_vlan_table_lookups (em,
1391 &main_intf0, &vlan_intf0, &qinq_intf0);
1393 eth_vlan_table_lookups (em,
1400 &main_intf1, &vlan_intf1, &qinq_intf1);
1402 identify_subint (hi0,
1407 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1409 identify_subint (hi1,
1414 qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1416 // Save RX sw_if_index for later nodes
1417 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1419 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1420 vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1422 ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1424 // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1425 if (((new_sw_if_index0 != ~0)
1426 && (new_sw_if_index0 != old_sw_if_index0))
1427 || ((new_sw_if_index1 != ~0)
1428 && (new_sw_if_index1 != old_sw_if_index1)))
1431 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1432 - vnet_buffer (b0)->l2_hdr_offset;
1433 len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1434 - vnet_buffer (b1)->l2_hdr_offset;
1436 stats_n_packets += 2;
1437 stats_n_bytes += len0 + len1;
1440 (!(new_sw_if_index0 == stats_sw_if_index
1441 && new_sw_if_index1 == stats_sw_if_index)))
1443 stats_n_packets -= 2;
1444 stats_n_bytes -= len0 + len1;
1446 if (new_sw_if_index0 != old_sw_if_index0
1447 && new_sw_if_index0 != ~0)
1448 vlib_increment_combined_counter (vnm->
1449 interface_main.combined_sw_if_counters
1451 VNET_INTERFACE_COUNTER_RX,
1453 new_sw_if_index0, 1,
1455 if (new_sw_if_index1 != old_sw_if_index1
1456 && new_sw_if_index1 != ~0)
1457 vlib_increment_combined_counter (vnm->
1458 interface_main.combined_sw_if_counters
1460 VNET_INTERFACE_COUNTER_RX,
1462 new_sw_if_index1, 1,
1465 if (new_sw_if_index0 == new_sw_if_index1)
1467 if (stats_n_packets > 0)
1469 vlib_increment_combined_counter
1470 (vnm->interface_main.combined_sw_if_counters
1471 + VNET_INTERFACE_COUNTER_RX,
1474 stats_n_packets, stats_n_bytes);
1475 stats_n_packets = stats_n_bytes = 0;
1477 stats_sw_if_index = new_sw_if_index0;
1482 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1483 is_l20 = is_l21 = 0;
1485 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1487 determine_next_node (em, variant, is_l21, type1, b1, &error1,
1491 b0->error = error_node->errors[error0];
1492 b1->error = error_node->errors[error1];
1494 // verify speculative enqueue
1495 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1496 n_left_to_next, bi0, bi1, next0,
1500 while (n_left_from > 0 && n_left_to_next > 0)
1505 u16 type0, orig_type0;
1506 u16 outer_id0, inner_id0;
1508 u32 old_sw_if_index0, new_sw_if_index0, len0;
1509 vnet_hw_interface_t *hi0;
1510 main_intf_t *main_intf0;
1511 vlan_intf_t *vlan_intf0;
1512 qinq_intf_t *qinq_intf0;
1513 ethernet_header_t *e0;
1518 // Prefetch next iteration
1519 if (n_left_from > 1)
1521 vlib_prefetch_buffer_header (b[1], STORE);
1522 CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1530 n_left_to_next -= 1;
1535 error0 = ETHERNET_ERROR_NONE;
1536 e0 = vlib_buffer_get_current (b0);
1537 type0 = clib_net_to_host_u16 (e0->type);
1539 /* Set the L2 header offset for all packets */
1540 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1541 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1543 /* Speed-path for the untagged case */
1544 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1545 && !ethernet_frame_is_tagged (type0)))
1548 subint_config_t *subint0;
1551 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1552 is_l20 = cached_is_l2;
1554 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1556 cached_sw_if_index = sw_if_index0;
1557 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1558 ei = ethernet_get_interface (em, hi->hw_if_index);
1559 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1560 subint0 = &intf0->untagged_subint;
1561 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1565 if (PREDICT_TRUE (is_l20 != 0))
1567 vnet_buffer (b0)->l3_hdr_offset =
1568 vnet_buffer (b0)->l2_hdr_offset +
1569 sizeof (ethernet_header_t);
1570 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1571 next0 = em->l2_next;
1572 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1576 if (hi->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1577 goto skip_dmac_check0;
1579 dmacs[0] = *(u64 *) e0;
1581 if (ei && vec_len (ei->secondary_addrs))
1582 ethernet_input_inline_dmac_check (hi, dmacs,
1586 1 /* have_sec_dmac */ );
1588 ethernet_input_inline_dmac_check (hi, dmacs,
1592 0 /* have_sec_dmac */ );
1595 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1598 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1599 determine_next_node (em, variant, 0, type0, b0,
1605 /* Slow-path for the tagged case */
1606 parse_header (variant,
1609 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1611 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1613 eth_vlan_table_lookups (em,
1620 &main_intf0, &vlan_intf0, &qinq_intf0);
1622 identify_subint (hi0,
1627 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1629 // Save RX sw_if_index for later nodes
1630 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1632 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1634 // Increment subinterface stats
1635 // Note that interface-level counters have already been incremented
1636 // prior to calling this function. Thus only subinterface counters
1637 // are incremented here.
1639 // Interface level counters include packets received on the main
1640 // interface and all subinterfaces. Subinterface level counters
1641 // include only those packets received on that subinterface
1642 // Increment stats if the subint is valid and it is not the main intf
1643 if ((new_sw_if_index0 != ~0)
1644 && (new_sw_if_index0 != old_sw_if_index0))
1647 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1648 - vnet_buffer (b0)->l2_hdr_offset;
1650 stats_n_packets += 1;
1651 stats_n_bytes += len0;
1653 // Batch stat increments from the same subinterface so counters
1654 // don't need to be incremented for every packet.
1655 if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1657 stats_n_packets -= 1;
1658 stats_n_bytes -= len0;
1660 if (new_sw_if_index0 != ~0)
1661 vlib_increment_combined_counter
1662 (vnm->interface_main.combined_sw_if_counters
1663 + VNET_INTERFACE_COUNTER_RX,
1664 thread_index, new_sw_if_index0, 1, len0);
1665 if (stats_n_packets > 0)
1667 vlib_increment_combined_counter
1668 (vnm->interface_main.combined_sw_if_counters
1669 + VNET_INTERFACE_COUNTER_RX,
1671 stats_sw_if_index, stats_n_packets, stats_n_bytes);
1672 stats_n_packets = stats_n_bytes = 0;
1674 stats_sw_if_index = new_sw_if_index0;
1678 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1681 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1685 b0->error = error_node->errors[error0];
1687 // verify speculative enqueue
1688 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1689 to_next, n_left_to_next,
1693 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1696 // Increment any remaining batched stats
1697 if (stats_n_packets > 0)
1699 vlib_increment_combined_counter
1700 (vnm->interface_main.combined_sw_if_counters
1701 + VNET_INTERFACE_COUNTER_RX,
1702 thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1703 node->runtime_data[0] = stats_sw_if_index;
1707 VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
1708 vlib_node_runtime_t * node,
1709 vlib_frame_t * frame)
1711 vnet_main_t *vnm = vnet_get_main ();
1712 u32 *from = vlib_frame_vector_args (frame);
1713 u32 n_packets = frame->n_vectors;
1715 ethernet_input_trace (vm, node, frame);
1717 if (frame->flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
1719 ethernet_input_frame_t *ef = vlib_frame_scalar_args (frame);
1720 int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1721 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ef->hw_if_index);
1722 eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1725 ethernet_input_inline (vm, node, from, n_packets,
1726 ETHERNET_INPUT_VARIANT_ETHERNET);
1730 VLIB_NODE_FN (ethernet_input_type_node) (vlib_main_t * vm,
1731 vlib_node_runtime_t * node,
1732 vlib_frame_t * from_frame)
1734 u32 *from = vlib_frame_vector_args (from_frame);
1735 u32 n_packets = from_frame->n_vectors;
1736 ethernet_input_trace (vm, node, from_frame);
1737 ethernet_input_inline (vm, node, from, n_packets,
1738 ETHERNET_INPUT_VARIANT_ETHERNET_TYPE);
1742 VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
1743 vlib_node_runtime_t * node,
1744 vlib_frame_t * from_frame)
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,
1750 ETHERNET_INPUT_VARIANT_NOT_L2);
1755 // Return the subinterface config struct for the given sw_if_index
1756 // Also return via parameter the appropriate match flags for the
1757 // configured number of tags.
1758 // On error (unsupported or not ethernet) return 0.
1759 static subint_config_t *
1760 ethernet_sw_interface_get_config (vnet_main_t * vnm,
1762 u32 * flags, u32 * unsupported)
1764 ethernet_main_t *em = ðernet_main;
1765 vnet_hw_interface_t *hi;
1766 vnet_sw_interface_t *si;
1767 main_intf_t *main_intf;
1768 vlan_table_t *vlan_table;
1769 qinq_table_t *qinq_table;
1770 subint_config_t *subint = 0;
1772 hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1774 if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1777 goto done; // non-ethernet interface
1780 // ensure there's an entry for the main intf (shouldn't really be necessary)
1781 vec_validate (em->main_intfs, hi->hw_if_index);
1782 main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1784 // Locate the subint for the given ethernet config
1785 si = vnet_get_sw_interface (vnm, sw_if_index);
1787 if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1789 p2p_ethernet_main_t *p2pm = &p2p_main;
1790 u32 p2pe_sw_if_index =
1791 p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
1792 if (p2pe_sw_if_index == ~0)
1794 pool_get (p2pm->p2p_subif_pool, subint);
1795 si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1798 subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1799 *flags = SUBINT_CONFIG_P2P;
1801 else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1805 pipe = pipe_get (sw_if_index);
1806 subint = &pipe->subint;
1807 *flags = SUBINT_CONFIG_P2P;
1809 else if (si->sub.eth.flags.default_sub)
1811 subint = &main_intf->default_subint;
1812 *flags = SUBINT_CONFIG_MATCH_1_TAG |
1813 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1815 else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1817 // if no flags are set then this is a main interface
1818 // so treat as untagged
1819 subint = &main_intf->untagged_subint;
1820 *flags = SUBINT_CONFIG_MATCH_0_TAG;
1825 // first get the vlan table
1826 if (si->sub.eth.flags.dot1ad)
1828 if (main_intf->dot1ad_vlans == 0)
1830 // Allocate a vlan table from the pool
1831 pool_get (em->vlan_pool, vlan_table);
1832 main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1836 // Get ptr to existing vlan table
1838 vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1843 if (main_intf->dot1q_vlans == 0)
1845 // Allocate a vlan table from the pool
1846 pool_get (em->vlan_pool, vlan_table);
1847 main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1851 // Get ptr to existing vlan table
1853 vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1857 if (si->sub.eth.flags.one_tag)
1859 *flags = si->sub.eth.flags.exact_match ?
1860 SUBINT_CONFIG_MATCH_1_TAG :
1861 (SUBINT_CONFIG_MATCH_1_TAG |
1862 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1864 if (si->sub.eth.flags.outer_vlan_id_any)
1866 // not implemented yet
1872 // a single vlan, a common case
1874 &vlan_table->vlans[si->sub.eth.
1875 outer_vlan_id].single_tag_subint;
1882 *flags = si->sub.eth.flags.exact_match ?
1883 SUBINT_CONFIG_MATCH_2_TAG :
1884 (SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1886 if (si->sub.eth.flags.outer_vlan_id_any
1887 && si->sub.eth.flags.inner_vlan_id_any)
1889 // not implemented yet
1894 if (si->sub.eth.flags.inner_vlan_id_any)
1896 // a specific outer and "any" inner
1897 // don't need a qinq table for this
1899 &vlan_table->vlans[si->sub.eth.
1900 outer_vlan_id].inner_any_subint;
1901 if (si->sub.eth.flags.exact_match)
1903 *flags = SUBINT_CONFIG_MATCH_2_TAG;
1907 *flags = SUBINT_CONFIG_MATCH_2_TAG |
1908 SUBINT_CONFIG_MATCH_3_TAG;
1913 // a specific outer + specifc innner vlan id, a common case
1915 // get the qinq table
1916 if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1918 // Allocate a qinq table from the pool
1919 pool_get (em->qinq_pool, qinq_table);
1920 vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1921 qinq_table - em->qinq_pool;
1925 // Get ptr to existing qinq table
1927 vec_elt_at_index (em->qinq_pool,
1928 vlan_table->vlans[si->sub.
1932 subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1941 static clib_error_t *
1942 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
1944 subint_config_t *subint;
1947 clib_error_t *error = 0;
1949 // Find the config for this subinterface
1951 ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags,
1956 // not implemented yet or not ethernet
1960 subint->sw_if_index =
1961 ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1967 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
1970 #ifndef CLIB_MARCH_VARIANT
1971 // Set the L2/L3 mode for the subinterface
1973 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
1975 subint_config_t *subint;
1979 vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1981 is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1983 // Find the config for this subinterface
1985 ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags,
1990 // unimplemented or not ethernet
1994 // Double check that the config we found is for our interface (or the interface is down)
1995 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
1999 subint->flags |= SUBINT_CONFIG_L2;
2002 SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
2003 | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
2007 subint->flags &= ~SUBINT_CONFIG_L2;
2010 ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
2011 | SUBINT_CONFIG_MATCH_3_TAG);
2019 * Set the L2/L3 mode for the subinterface regardless of port
2022 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
2023 u32 sw_if_index, u32 l2)
2025 subint_config_t *subint;
2029 /* Find the config for this subinterface */
2031 ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags,
2036 /* unimplemented or not ethernet */
2041 * Double check that the config we found is for our interface (or the
2042 * interface is down)
2044 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2048 subint->flags |= SUBINT_CONFIG_L2;
2052 subint->flags &= ~SUBINT_CONFIG_L2;
2060 static clib_error_t *
2061 ethernet_sw_interface_add_del (vnet_main_t * vnm,
2062 u32 sw_if_index, u32 is_create)
2064 clib_error_t *error = 0;
2065 subint_config_t *subint;
2067 u32 unsupported = 0;
2069 // Find the config for this subinterface
2071 ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2076 // not implemented yet or not ethernet
2079 // this is the NYI case
2080 error = clib_error_return (0, "not implemented yet");
2091 // Initialize the subint
2092 if (subint->flags & SUBINT_CONFIG_VALID)
2094 // Error vlan already in use
2095 error = clib_error_return (0, "vlan is already in use");
2099 // Note that config is L3 by default
2100 subint->flags = SUBINT_CONFIG_VALID | match_flags;
2101 subint->sw_if_index = ~0; // because interfaces are initially down
2108 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
2110 static char *ethernet_error_strings[] = {
2111 #define ethernet_error(n,c,s) s,
2112 #include "error.def"
2113 #undef ethernet_error
2117 VLIB_REGISTER_NODE (ethernet_input_node) = {
2118 .name = "ethernet-input",
2119 /* Takes a vector of packets. */
2120 .vector_size = sizeof (u32),
2121 .scalar_size = sizeof (ethernet_input_frame_t),
2122 .n_errors = ETHERNET_N_ERROR,
2123 .error_strings = ethernet_error_strings,
2124 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2126 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2127 foreach_ethernet_input_next
2130 .format_buffer = format_ethernet_header_with_length,
2131 .format_trace = format_ethernet_input_trace,
2132 .unformat_buffer = unformat_ethernet_header,
2135 VLIB_REGISTER_NODE (ethernet_input_type_node) = {
2136 .name = "ethernet-input-type",
2137 /* Takes a vector of packets. */
2138 .vector_size = sizeof (u32),
2139 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2141 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2142 foreach_ethernet_input_next
2147 VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
2148 .name = "ethernet-input-not-l2",
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
2160 #ifndef CLIB_MARCH_VARIANT
2162 ethernet_set_rx_redirect (vnet_main_t * vnm,
2163 vnet_hw_interface_t * hi, u32 enable)
2165 // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2166 // don't go directly to ip4-input)
2167 vnet_hw_interface_rx_redirect_to_node
2168 (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2173 * Initialization and registration for the next_by_ethernet structure
2177 next_by_ethertype_init (next_by_ethertype_t * l3_next)
2179 l3_next->input_next_by_type = sparse_vec_new
2180 ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2181 /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2183 vec_validate (l3_next->sparse_index_by_input_next_index,
2184 ETHERNET_INPUT_NEXT_DROP);
2185 vec_validate (l3_next->sparse_index_by_input_next_index,
2186 ETHERNET_INPUT_NEXT_PUNT);
2187 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2188 SPARSE_VEC_INVALID_INDEX;
2189 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2190 SPARSE_VEC_INVALID_INDEX;
2193 * Make sure we don't wipe out an ethernet registration by mistake
2194 * Can happen if init function ordering constraints are missing.
2198 ethernet_main_t *em = ðernet_main;
2199 ASSERT (em->next_by_ethertype_register_called == 0);
2205 // Add an ethertype -> next index mapping to the structure
2207 next_by_ethertype_register (next_by_ethertype_t * l3_next,
2208 u32 ethertype, u32 next_index)
2212 ethernet_main_t *em = ðernet_main;
2216 ethernet_main_t *em = ðernet_main;
2217 em->next_by_ethertype_register_called = 1;
2220 /* Setup ethernet type -> next index sparse vector mapping. */
2221 n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2224 /* Rebuild next index -> sparse index inverse mapping when sparse vector
2226 vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2227 for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2229 sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2231 // do not allow the cached next index's to be updated if L3
2232 // redirect is enabled, as it will have overwritten them
2233 if (!em->redirect_l3)
2235 // Cache common ethertypes directly
2236 if (ethertype == ETHERNET_TYPE_IP4)
2238 l3_next->input_next_ip4 = next_index;
2240 else if (ethertype == ETHERNET_TYPE_IP6)
2242 l3_next->input_next_ip6 = next_index;
2244 else if (ethertype == ETHERNET_TYPE_MPLS)
2246 l3_next->input_next_mpls = next_index;
2253 ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
2255 __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2256 __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2258 ethernet_setup_node (vm, ethernet_input_node.index);
2259 ethernet_setup_node (vm, ethernet_input_type_node.index);
2260 ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
2262 next_by_ethertype_init (&em->l3_next);
2264 // Initialize pools and vector for vlan parsing
2265 vec_validate (em->main_intfs, 10); // 10 main interfaces
2266 pool_alloc (em->vlan_pool, 10);
2267 pool_alloc (em->qinq_pool, 1);
2269 // The first vlan pool will always be reserved for an invalid table
2270 pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2271 // The first qinq pool will always be reserved for an invalid table
2272 pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2276 ethernet_register_input_type (vlib_main_t * vm,
2277 ethernet_type_t type, u32 node_index)
2279 ethernet_main_t *em = ðernet_main;
2280 ethernet_type_info_t *ti;
2284 clib_error_t *error = vlib_call_init_function (vm, ethernet_init);
2286 clib_error_report (error);
2289 ti = ethernet_get_type_info (em, type);
2292 clib_warning ("type_info NULL for type %d", type);
2295 ti->node_index = node_index;
2296 ti->next_index = vlib_node_add_next (vm,
2297 ethernet_input_node.index, node_index);
2298 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2299 ASSERT (i == ti->next_index);
2301 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2302 ASSERT (i == ti->next_index);
2304 // Add the L3 node for this ethertype to the next nodes structure
2305 next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2307 // Call the registration functions for other nodes that want a mapping
2308 l2bvi_register_input_type (vm, type, node_index);
2312 ethernet_register_l2_input (vlib_main_t * vm, u32 node_index)
2314 ethernet_main_t *em = ðernet_main;
2318 vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2321 * Even if we never use these arcs, we have to align the next indices...
2323 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2325 ASSERT (i == em->l2_next);
2327 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2328 ASSERT (i == em->l2_next);
2331 // Register a next node for L3 redirect, and enable L3 redirect
2333 ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
2335 ethernet_main_t *em = ðernet_main;
2338 em->redirect_l3 = 1;
2339 em->redirect_l3_next = vlib_node_add_next (vm,
2340 ethernet_input_node.index,
2343 * Change the cached next nodes to the redirect node
2345 em->l3_next.input_next_ip4 = em->redirect_l3_next;
2346 em->l3_next.input_next_ip6 = em->redirect_l3_next;
2347 em->l3_next.input_next_mpls = em->redirect_l3_next;
2350 * Even if we never use these arcs, we have to align the next indices...
2352 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2354 ASSERT (i == em->redirect_l3_next);
2356 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2358 ASSERT (i == em->redirect_l3_next);
2363 * fd.io coding-style-patch-verification: ON
2366 * eval: (c-set-style "gnu")