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 (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->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)))
232 ethernet_header_t *e0;
233 ethernet_interface_t *ei0;
235 e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
236 dmacs[0] = *(u64 *) e0;
237 ei0 = ethernet_get_interface (ðernet_main, hi->hw_if_index);
239 if (ei0 && vec_len (ei0->secondary_addrs))
240 ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
241 1 /* n_packets */ , ei0,
242 1 /* have_sec_dmac */ );
244 ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad,
245 1 /* n_packets */ , ei0,
246 0 /* have_sec_dmac */ );
248 *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
251 // Check for down subinterface
252 *error0 = (*new_sw_if_index) != ~0 ? (*error0) : ETHERNET_ERROR_DOWN;
256 static_always_inline void
257 determine_next_node (ethernet_main_t * em,
258 ethernet_input_variant_t variant,
260 u32 type0, vlib_buffer_t * b0, u8 * error0, u8 * next0)
262 vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
263 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
265 if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE))
267 // some error occurred
268 *next0 = ETHERNET_INPUT_NEXT_DROP;
272 // record the L2 len and reset the buffer so the L2 header is preserved
273 u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
274 vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
275 *next0 = em->l2_next;
276 ASSERT (vnet_buffer (b0)->l2.l2_len ==
277 ethernet_buffer_header_size (b0));
278 vlib_buffer_advance (b0, -(vnet_buffer (b0)->l2.l2_len));
280 // check for common IP/MPLS ethertypes
282 else if (type0 == ETHERNET_TYPE_IP4)
284 *next0 = em->l3_next.input_next_ip4;
286 else if (type0 == ETHERNET_TYPE_IP6)
288 *next0 = em->l3_next.input_next_ip6;
290 else if (type0 == ETHERNET_TYPE_MPLS)
292 *next0 = em->l3_next.input_next_mpls;
295 else if (em->redirect_l3)
297 // L3 Redirect is on, the cached common next nodes will be
298 // pointing to the redirect node, catch the uncommon types here
299 *next0 = em->redirect_l3_next;
303 // uncommon ethertype, check table
305 i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
306 *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
309 SPARSE_VEC_INVALID_INDEX ? ETHERNET_ERROR_UNKNOWN_TYPE : *error0;
311 // The table is not populated with LLC values, so check that now.
312 // If variant is variant_ethernet then we came from LLC processing. Don't
313 // go back there; drop instead using by keeping the drop/bad table result.
314 if ((type0 < 0x600) && (variant == ETHERNET_INPUT_VARIANT_ETHERNET))
316 *next0 = ETHERNET_INPUT_NEXT_LLC;
322 /* following vector code relies on following assumptions */
323 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_data, 0);
324 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_length, 2);
325 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, flags, 4);
326 STATIC_ASSERT (STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l2_hdr_offset) ==
327 STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l3_hdr_offset) - 2,
328 "l3_hdr_offset must follow l2_hdr_offset");
330 static_always_inline void
331 eth_input_adv_and_flags_x4 (vlib_buffer_t ** b, int is_l3)
333 i16 adv = sizeof (ethernet_header_t);
334 u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
335 VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
337 #ifdef CLIB_HAVE_VEC256
338 /* to reduce number of small loads/stores we are loading first 64 bits
339 of each buffer metadata into 256-bit register so we can advance
340 current_data, current_length and flags.
341 Observed saving of this code is ~2 clocks per packet */
344 /* vector if signed 16 bit integers used in signed vector add operation
345 to advnce current_data and current_length */
346 u32x8 flags4 = { 0, flags, 0, flags, 0, flags, 0, flags };
348 adv, -adv, 0, 0, adv, -adv, 0, 0,
349 adv, -adv, 0, 0, adv, -adv, 0, 0
352 /* load 4 x 64 bits */
353 r = u64x4_gather (b[0], b[1], b[2], b[3]);
359 radv = (u64x4) ((i16x16) r + adv4);
361 /* write 4 x 64 bits */
362 u64x4_scatter (is_l3 ? radv : r, b[0], b[1], b[2], b[3]);
364 /* use old current_data as l2_hdr_offset and new current_data as
366 r = (u64x4) u16x16_blend (r, radv << 16, 0xaa);
368 /* store both l2_hdr_offset and l3_hdr_offset in single store operation */
369 u32x8_scatter_one ((u32x8) r, 0, &vnet_buffer (b[0])->l2_hdr_offset);
370 u32x8_scatter_one ((u32x8) r, 2, &vnet_buffer (b[1])->l2_hdr_offset);
371 u32x8_scatter_one ((u32x8) r, 4, &vnet_buffer (b[2])->l2_hdr_offset);
372 u32x8_scatter_one ((u32x8) r, 6, &vnet_buffer (b[3])->l2_hdr_offset);
376 ASSERT (b[0]->current_data == vnet_buffer (b[0])->l3_hdr_offset);
377 ASSERT (b[1]->current_data == vnet_buffer (b[1])->l3_hdr_offset);
378 ASSERT (b[2]->current_data == vnet_buffer (b[2])->l3_hdr_offset);
379 ASSERT (b[3]->current_data == vnet_buffer (b[3])->l3_hdr_offset);
381 ASSERT (b[0]->current_data - vnet_buffer (b[0])->l2_hdr_offset == adv);
382 ASSERT (b[1]->current_data - vnet_buffer (b[1])->l2_hdr_offset == adv);
383 ASSERT (b[2]->current_data - vnet_buffer (b[2])->l2_hdr_offset == adv);
384 ASSERT (b[3]->current_data - vnet_buffer (b[3])->l2_hdr_offset == adv);
388 ASSERT (b[0]->current_data == vnet_buffer (b[0])->l2_hdr_offset);
389 ASSERT (b[1]->current_data == vnet_buffer (b[1])->l2_hdr_offset);
390 ASSERT (b[2]->current_data == vnet_buffer (b[2])->l2_hdr_offset);
391 ASSERT (b[3]->current_data == vnet_buffer (b[3])->l2_hdr_offset);
393 ASSERT (b[0]->current_data - vnet_buffer (b[0])->l3_hdr_offset == -adv);
394 ASSERT (b[1]->current_data - vnet_buffer (b[1])->l3_hdr_offset == -adv);
395 ASSERT (b[2]->current_data - vnet_buffer (b[2])->l3_hdr_offset == -adv);
396 ASSERT (b[3]->current_data - vnet_buffer (b[3])->l3_hdr_offset == -adv);
400 vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
401 vnet_buffer (b[1])->l2_hdr_offset = b[1]->current_data;
402 vnet_buffer (b[2])->l2_hdr_offset = b[2]->current_data;
403 vnet_buffer (b[3])->l2_hdr_offset = b[3]->current_data;
404 vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
405 vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data + adv;
406 vnet_buffer (b[2])->l3_hdr_offset = b[2]->current_data + adv;
407 vnet_buffer (b[3])->l3_hdr_offset = b[3]->current_data + adv;
411 vlib_buffer_advance (b[0], adv);
412 vlib_buffer_advance (b[1], adv);
413 vlib_buffer_advance (b[2], adv);
414 vlib_buffer_advance (b[3], adv);
417 b[0]->flags |= flags;
418 b[1]->flags |= flags;
419 b[2]->flags |= flags;
420 b[3]->flags |= flags;
425 vnet_buffer (b[0])->l2.l2_len = adv;
426 vnet_buffer (b[1])->l2.l2_len = adv;
427 vnet_buffer (b[2])->l2.l2_len = adv;
428 vnet_buffer (b[3])->l2.l2_len = adv;
432 static_always_inline void
433 eth_input_adv_and_flags_x1 (vlib_buffer_t ** b, int is_l3)
435 i16 adv = sizeof (ethernet_header_t);
436 u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
437 VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
439 vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
440 vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
443 vlib_buffer_advance (b[0], adv);
444 b[0]->flags |= flags;
446 vnet_buffer (b[0])->l2.l2_len = adv;
450 static_always_inline void
451 eth_input_get_etype_and_tags (vlib_buffer_t ** b, u16 * etype, u64 * tags,
452 u64 * dmacs, int offset, int dmac_check)
454 ethernet_header_t *e;
455 e = vlib_buffer_get_current (b[offset]);
456 #ifdef CLIB_HAVE_VEC128
457 u64x2 r = u64x2_load_unaligned (((u8 *) & e->type) - 6);
458 etype[offset] = ((u16x8) r)[3];
461 etype[offset] = e->type;
462 tags[offset] = *(u64 *) (e + 1);
466 dmacs[offset] = *(u64 *) e;
469 static_always_inline u16
470 eth_input_next_by_type (u16 etype)
472 ethernet_main_t *em = ðernet_main;
474 return (etype < 0x600) ? ETHERNET_INPUT_NEXT_LLC :
475 vec_elt (em->l3_next.input_next_by_type,
476 sparse_vec_index (em->l3_next.input_next_by_type, etype));
486 u64 n_packets, n_bytes;
487 } eth_input_tag_lookup_t;
489 static_always_inline void
490 eth_input_update_if_counters (vlib_main_t * vm, vnet_main_t * vnm,
491 eth_input_tag_lookup_t * l)
493 if (l->n_packets == 0 || l->sw_if_index == ~0)
497 l->n_bytes += l->n_packets * l->len;
499 vlib_increment_combined_counter
500 (vnm->interface_main.combined_sw_if_counters +
501 VNET_INTERFACE_COUNTER_RX, vm->thread_index, l->sw_if_index,
502 l->n_packets, l->n_bytes);
505 static_always_inline void
506 eth_input_tag_lookup (vlib_main_t * vm, vnet_main_t * vnm,
507 vlib_node_runtime_t * node, vnet_hw_interface_t * hi,
508 u64 tag, u16 * next, vlib_buffer_t * b,
509 eth_input_tag_lookup_t * l, u8 dmac_bad, int is_dot1ad,
510 int main_is_l3, int check_dmac)
512 ethernet_main_t *em = ðernet_main;
514 if ((tag ^ l->tag) & l->mask)
516 main_intf_t *mif = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
519 vlan_table_t *vlan_table;
520 qinq_table_t *qinq_table;
521 u16 *t = (u16 *) & tag;
522 u16 vlan1 = clib_net_to_host_u16 (t[0]) & 0xFFF;
523 u16 vlan2 = clib_net_to_host_u16 (t[2]) & 0xFFF;
524 u32 matched, is_l2, new_sw_if_index;
526 vlan_table = vec_elt_at_index (em->vlan_pool, is_dot1ad ?
527 mif->dot1ad_vlans : mif->dot1q_vlans);
528 vif = &vlan_table->vlans[vlan1];
529 qinq_table = vec_elt_at_index (em->qinq_pool, vif->qinqs);
530 qif = &qinq_table->vlans[vlan2];
531 l->err = ETHERNET_ERROR_NONE;
532 l->type = clib_net_to_host_u16 (t[1]);
534 if (l->type == ETHERNET_TYPE_VLAN)
536 l->type = clib_net_to_host_u16 (t[3]);
538 matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
539 SUBINT_CONFIG_MATCH_2_TAG, mif, vif,
540 qif, &new_sw_if_index, &l->err,
548 new_sw_if_index = hi->sw_if_index;
549 l->err = ETHERNET_ERROR_NONE;
551 is_l2 = main_is_l3 == 0;
554 matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
555 SUBINT_CONFIG_MATCH_1_TAG, mif,
556 vif, qif, &new_sw_if_index,
560 if (l->sw_if_index != new_sw_if_index)
562 eth_input_update_if_counters (vm, vnm, l);
565 l->sw_if_index = new_sw_if_index;
568 l->mask = (l->n_tags == 2) ?
569 clib_net_to_host_u64 (0xffffffffffffffff) :
570 clib_net_to_host_u64 (0xffffffff00000000);
572 if (matched && l->sw_if_index == ~0)
573 l->err = ETHERNET_ERROR_DOWN;
575 l->len = sizeof (ethernet_header_t) +
576 l->n_tags * sizeof (ethernet_vlan_header_t);
578 l->adv = is_l2 ? -(int) sizeof (ethernet_header_t) :
579 l->n_tags * sizeof (ethernet_vlan_header_t);
581 l->adv = is_l2 ? 0 : l->len;
583 if (PREDICT_FALSE (l->err != ETHERNET_ERROR_NONE))
584 l->next = ETHERNET_INPUT_NEXT_DROP;
586 l->next = em->l2_next;
587 else if (l->type == ETHERNET_TYPE_IP4)
588 l->next = em->l3_next.input_next_ip4;
589 else if (l->type == ETHERNET_TYPE_IP6)
590 l->next = em->l3_next.input_next_ip6;
591 else if (l->type == ETHERNET_TYPE_MPLS)
592 l->next = em->l3_next.input_next_mpls;
593 else if (em->redirect_l3)
594 l->next = em->redirect_l3_next;
597 l->next = eth_input_next_by_type (l->type);
598 if (l->next == ETHERNET_INPUT_NEXT_PUNT)
599 l->err = ETHERNET_ERROR_UNKNOWN_TYPE;
603 if (check_dmac && l->adv > 0 && dmac_bad)
605 l->err = ETHERNET_ERROR_L3_MAC_MISMATCH;
606 next[0] = ETHERNET_INPUT_NEXT_PUNT;
611 vlib_buffer_advance (b, l->adv);
612 vnet_buffer (b)->l2.l2_len = l->len;
613 vnet_buffer (b)->l3_hdr_offset = vnet_buffer (b)->l2_hdr_offset + l->len;
615 if (l->err == ETHERNET_ERROR_NONE)
617 vnet_buffer (b)->sw_if_index[VLIB_RX] = l->sw_if_index;
618 ethernet_buffer_set_vlan_count (b, l->n_tags);
621 b->error = node->errors[l->err];
623 /* update counters */
625 l->n_bytes += vlib_buffer_length_in_chain (vm, b);
628 #define DMAC_MASK clib_net_to_host_u64 (0xFFFFFFFFFFFF0000)
629 #define DMAC_IGBIT clib_net_to_host_u64 (0x0100000000000000)
631 #ifdef CLIB_HAVE_VEC256
632 static_always_inline u32
633 is_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
635 u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
636 r0 = (r0 != u64x4_splat (hwaddr)) & ((r0 & u64x4_splat (DMAC_IGBIT)) == 0);
637 return u8x32_msb_mask ((u8x32) (r0));
641 static_always_inline u8
642 is_dmac_bad (u64 dmac, u64 hwaddr)
644 u64 r0 = dmac & DMAC_MASK;
645 return (r0 != hwaddr) && ((r0 & DMAC_IGBIT) == 0);
648 static_always_inline u8
649 is_sec_dmac_bad (u64 dmac, u64 hwaddr)
651 return ((dmac & DMAC_MASK) != hwaddr);
654 #ifdef CLIB_HAVE_VEC256
655 static_always_inline u32
656 is_sec_dmac_bad_x4 (u64 * dmacs, u64 hwaddr)
658 u64x4 r0 = u64x4_load_unaligned (dmacs) & u64x4_splat (DMAC_MASK);
659 r0 = (r0 != u64x4_splat (hwaddr));
660 return u8x32_msb_mask ((u8x32) (r0));
664 static_always_inline u8
665 eth_input_sec_dmac_check_x1 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
667 dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
671 static_always_inline u32
672 eth_input_sec_dmac_check_x4 (u64 hwaddr, u64 * dmac, u8 * dmac_bad)
674 #ifdef CLIB_HAVE_VEC256
675 *(u32 *) (dmac_bad + 0) &= is_sec_dmac_bad_x4 (dmac + 0, hwaddr);
677 dmac_bad[0] &= is_sec_dmac_bad (dmac[0], hwaddr);
678 dmac_bad[1] &= is_sec_dmac_bad (dmac[1], hwaddr);
679 dmac_bad[2] &= is_sec_dmac_bad (dmac[2], hwaddr);
680 dmac_bad[3] &= is_sec_dmac_bad (dmac[3], hwaddr);
682 return *(u32 *) dmac_bad;
686 * DMAC check for ethernet_input_inline()
688 * dmacs and dmacs_bad are arrays that are 2 elements long
689 * n_packets should be 1 or 2 for ethernet_input_inline()
691 static_always_inline void
692 ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi,
693 u64 * dmacs, u8 * dmacs_bad,
694 u32 n_packets, ethernet_interface_t * ei,
697 u64 hwaddr = (*(u64 *) hi->hw_address) & DMAC_MASK;
700 dmacs_bad[0] = is_dmac_bad (dmacs[0], hwaddr);
701 dmacs_bad[1] = ((n_packets > 1) & is_dmac_bad (dmacs[1], hwaddr));
703 bad = dmacs_bad[0] | dmacs_bad[1];
705 if (PREDICT_FALSE (bad && have_sec_dmac))
707 mac_address_t *sec_addr;
709 vec_foreach (sec_addr, ei->secondary_addrs)
711 hwaddr = (*(u64 *) sec_addr) & DMAC_MASK;
713 bad = (eth_input_sec_dmac_check_x1 (hwaddr, dmacs, dmacs_bad) |
714 eth_input_sec_dmac_check_x1 (hwaddr, dmacs + 1,
723 static_always_inline void
724 eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi,
725 u64 * dmacs, u8 * dmacs_bad,
726 u32 n_packets, ethernet_interface_t * ei,
729 u64 hwaddr = (*(u64 *) hi->hw_address) & DMAC_MASK;
731 u8 *dmac_bad = dmacs_bad;
733 i32 n_left = n_packets;
735 #ifdef CLIB_HAVE_VEC256
738 bad |= *(u32 *) (dmac_bad + 0) = is_dmac_bad_x4 (dmac + 0, hwaddr);
739 bad |= *(u32 *) (dmac_bad + 4) = is_dmac_bad_x4 (dmac + 4, hwaddr);
749 bad |= dmac_bad[0] = is_dmac_bad (dmac[0], hwaddr);
750 bad |= dmac_bad[1] = is_dmac_bad (dmac[1], hwaddr);
751 bad |= dmac_bad[2] = is_dmac_bad (dmac[2], hwaddr);
752 bad |= dmac_bad[3] = is_dmac_bad (dmac[3], hwaddr);
761 if (have_sec_dmac && bad)
765 vec_foreach (addr, ei->secondary_addrs)
767 u64 hwaddr = ((u64 *) addr)[0] & DMAC_MASK;
768 i32 n_left = n_packets;
770 u8 *dmac_bad = dmacs_bad;
779 /* skip any that have already matched */
788 n_bad = clib_min (4, n_left);
790 /* If >= 4 left, compare 4 together */
793 bad |= eth_input_sec_dmac_check_x4 (hwaddr, dmac, dmac_bad);
798 /* handle individually */
801 bad |= eth_input_sec_dmac_check_x1 (hwaddr, dmac + adv,
812 if (!bad) /* can stop looping if everything matched */
818 /* process frame of buffers, store ethertype into array and update
819 buffer metadata fields depending on interface being l2 or l3 assuming that
820 packets are untagged. For tagged packets those fields are updated later.
821 Optionally store Destionation MAC address and tag data into arrays
822 for further processing */
824 STATIC_ASSERT (VLIB_FRAME_SIZE % 8 == 0,
825 "VLIB_FRAME_SIZE must be power of 8");
826 static_always_inline void
827 eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
828 vnet_hw_interface_t * hi,
829 u32 * buffer_indices, u32 n_packets, int main_is_l3,
830 int ip4_cksum_ok, int dmac_check)
832 ethernet_main_t *em = ðernet_main;
833 u16 nexts[VLIB_FRAME_SIZE], *next;
834 u16 etypes[VLIB_FRAME_SIZE], *etype = etypes;
835 u64 dmacs[VLIB_FRAME_SIZE], *dmac = dmacs;
836 u8 dmacs_bad[VLIB_FRAME_SIZE];
837 u64 tags[VLIB_FRAME_SIZE], *tag = tags;
838 u16 slowpath_indices[VLIB_FRAME_SIZE];
840 u16 next_ip4, next_ip6, next_mpls, next_l2;
841 u16 et_ip4 = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
842 u16 et_ip6 = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
843 u16 et_mpls = clib_host_to_net_u16 (ETHERNET_TYPE_MPLS);
844 u16 et_vlan = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
845 u16 et_dot1ad = clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD);
846 i32 n_left = n_packets;
847 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
848 vlib_buffer_t **b = bufs;
849 ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index);
851 vlib_get_buffers (vm, buffer_indices, b, n_left);
855 vlib_buffer_t **ph = b + 16, **pd = b + 8;
857 vlib_prefetch_buffer_header (ph[0], LOAD);
858 vlib_prefetch_buffer_data (pd[0], LOAD);
859 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
861 vlib_prefetch_buffer_header (ph[1], LOAD);
862 vlib_prefetch_buffer_data (pd[1], LOAD);
863 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
865 vlib_prefetch_buffer_header (ph[2], LOAD);
866 vlib_prefetch_buffer_data (pd[2], LOAD);
867 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
869 vlib_prefetch_buffer_header (ph[3], LOAD);
870 vlib_prefetch_buffer_data (pd[3], LOAD);
871 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
873 eth_input_adv_and_flags_x4 (b, main_is_l3);
884 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
885 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
886 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
887 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
888 eth_input_adv_and_flags_x4 (b, main_is_l3);
899 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
900 eth_input_adv_and_flags_x1 (b, main_is_l3);
912 if (ei && vec_len (ei->secondary_addrs))
913 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
914 ei, 1 /* have_sec_dmac */ );
916 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
917 ei, 0 /* have_sec_dmac */ );
920 next_ip4 = em->l3_next.input_next_ip4;
921 next_ip6 = em->l3_next.input_next_ip6;
922 next_mpls = em->l3_next.input_next_mpls;
923 next_l2 = em->l2_next;
925 if (next_ip4 == ETHERNET_INPUT_NEXT_IP4_INPUT && ip4_cksum_ok)
926 next_ip4 = ETHERNET_INPUT_NEXT_IP4_INPUT_NCS;
928 #ifdef CLIB_HAVE_VEC256
929 u16x16 et16_ip4 = u16x16_splat (et_ip4);
930 u16x16 et16_ip6 = u16x16_splat (et_ip6);
931 u16x16 et16_mpls = u16x16_splat (et_mpls);
932 u16x16 et16_vlan = u16x16_splat (et_vlan);
933 u16x16 et16_dot1ad = u16x16_splat (et_dot1ad);
934 u16x16 next16_ip4 = u16x16_splat (next_ip4);
935 u16x16 next16_ip6 = u16x16_splat (next_ip6);
936 u16x16 next16_mpls = u16x16_splat (next_mpls);
937 u16x16 next16_l2 = u16x16_splat (next_l2);
939 u16x16 stairs = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
948 /* fastpath - in l3 mode hadles ip4, ip6 and mpls packets, other packets
949 are considered as slowpath, in l2 mode all untagged packets are
950 considered as fastpath */
953 #ifdef CLIB_HAVE_VEC256
957 u16x16 e16 = u16x16_load_unaligned (etype);
960 r += (e16 == et16_ip4) & next16_ip4;
961 r += (e16 == et16_ip6) & next16_ip6;
962 r += (e16 == et16_mpls) & next16_mpls;
965 r = ((e16 != et16_vlan) & (e16 != et16_dot1ad)) & next16_l2;
966 u16x16_store_unaligned (r, next);
968 if (!u16x16_is_all_zero (r == zero))
970 if (u16x16_is_all_zero (r))
972 u16x16_store_unaligned (u16x16_splat (i) + stairs,
973 slowpath_indices + n_slowpath);
978 for (int j = 0; j < 16; j++)
980 slowpath_indices[n_slowpath++] = i + j;
991 if (main_is_l3 && etype[0] == et_ip4)
993 else if (main_is_l3 && etype[0] == et_ip6)
995 else if (main_is_l3 && etype[0] == et_mpls)
997 else if (main_is_l3 == 0 &&
998 etype[0] != et_vlan && etype[0] != et_dot1ad)
1003 slowpath_indices[n_slowpath++] = i;
1014 vnet_main_t *vnm = vnet_get_main ();
1015 n_left = n_slowpath;
1016 u16 *si = slowpath_indices;
1017 u32 last_unknown_etype = ~0;
1018 u32 last_unknown_next = ~0;
1019 eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
1021 .tag = tags[si[0]] ^ -1LL,
1025 clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
1030 u16 etype = etypes[i];
1032 if (etype == et_vlan)
1034 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1035 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1036 &dot1q_lookup, dmacs_bad[i], 0,
1037 main_is_l3, dmac_check);
1040 else if (etype == et_dot1ad)
1042 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1043 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1044 &dot1ad_lookup, dmacs_bad[i], 1,
1045 main_is_l3, dmac_check);
1049 /* untagged packet with not well known etyertype */
1050 if (last_unknown_etype != etype)
1052 last_unknown_etype = etype;
1053 etype = clib_host_to_net_u16 (etype);
1054 last_unknown_next = eth_input_next_by_type (etype);
1056 if (dmac_check && main_is_l3 && dmacs_bad[i])
1058 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1059 b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
1060 nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
1063 nexts[i] = last_unknown_next;
1071 eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
1072 eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
1075 vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
1078 static_always_inline void
1079 eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node,
1080 vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
1083 ethernet_main_t *em = ðernet_main;
1084 ethernet_interface_t *ei;
1085 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
1086 main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1087 subint_config_t *subint0 = &intf0->untagged_subint;
1089 int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
1090 int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3;
1094 if (int_is_l3 || /* DMAC filter already done by NIC */
1095 ((hi->l2_if_count != 0) && (hi->l3_if_count == 0)))
1096 { /* All L2 usage - DMAC check not needed */
1097 eth_input_process_frame (vm, node, hi, from, n_pkts,
1098 /*is_l3 */ 1, ip4_cksum_ok, 0);
1101 { /* DMAC check needed for L3 */
1102 eth_input_process_frame (vm, node, hi, from, n_pkts,
1103 /*is_l3 */ 1, ip4_cksum_ok, 1);
1109 if (hi->l3_if_count == 0)
1110 { /* All L2 usage - DMAC check not needed */
1111 eth_input_process_frame (vm, node, hi, from, n_pkts,
1112 /*is_l3 */ 0, ip4_cksum_ok, 0);
1115 { /* DMAC check needed for L3 */
1116 eth_input_process_frame (vm, node, hi, from, n_pkts,
1117 /*is_l3 */ 0, ip4_cksum_ok, 1);
1123 static_always_inline void
1124 ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
1125 vlib_frame_t * from_frame)
1128 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1130 from = vlib_frame_vector_args (from_frame);
1131 n_left = from_frame->n_vectors;
1135 ethernet_input_trace_t *t0;
1136 vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1138 if (b0->flags & VLIB_BUFFER_IS_TRACED)
1140 t0 = vlib_add_trace (vm, node, b0,
1141 sizeof (ethernet_input_trace_t));
1142 clib_memcpy_fast (t0->packet_data, b0->data + b0->current_data,
1143 sizeof (t0->packet_data));
1144 t0->frame_flags = from_frame->flags;
1145 clib_memcpy_fast (&t0->frame_data,
1146 vlib_frame_scalar_args (from_frame),
1147 sizeof (ethernet_input_frame_t));
1154 /* rx pcap capture if enabled */
1155 if (PREDICT_FALSE (vlib_global_main.pcap.pcap_rx_enable))
1158 vnet_pcap_t *pp = &vlib_global_main.pcap;
1160 from = vlib_frame_vector_args (from_frame);
1161 n_left = from_frame->n_vectors;
1164 int classify_filter_result;
1169 b0 = vlib_get_buffer (vm, bi0);
1170 if (pp->filter_classify_table_index != ~0)
1172 classify_filter_result =
1173 vnet_is_packet_traced_inline
1174 (b0, pp->filter_classify_table_index, 0 /* full classify */ );
1175 if (classify_filter_result)
1176 pcap_add_buffer (&pp->pcap_main, vm, bi0,
1177 pp->max_bytes_per_pkt);
1181 if (pp->pcap_sw_if_index == 0 ||
1182 pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1184 vnet_main_t *vnm = vnet_get_main ();
1185 vnet_hw_interface_t *hi =
1186 vnet_get_sup_hw_interface
1187 (vnm, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1189 /* Capture pkt if not filtered, or if filter hits */
1190 if (hi->trace_classify_table_index == ~0 ||
1191 vnet_is_packet_traced_inline
1192 (b0, hi->trace_classify_table_index,
1193 0 /* full classify */ ))
1194 pcap_add_buffer (&pp->pcap_main, vm, bi0,
1195 pp->max_bytes_per_pkt);
1201 static_always_inline void
1202 ethernet_input_inline (vlib_main_t * vm,
1203 vlib_node_runtime_t * node,
1204 u32 * from, u32 n_packets,
1205 ethernet_input_variant_t variant)
1207 vnet_main_t *vnm = vnet_get_main ();
1208 ethernet_main_t *em = ðernet_main;
1209 vlib_node_runtime_t *error_node;
1210 u32 n_left_from, next_index, *to_next;
1211 u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1212 u32 thread_index = vm->thread_index;
1213 u32 cached_sw_if_index = ~0;
1214 u32 cached_is_l2 = 0; /* shut up gcc */
1215 vnet_hw_interface_t *hi = NULL; /* used for main interface only */
1216 ethernet_interface_t *ei = NULL;
1217 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
1218 vlib_buffer_t **b = bufs;
1220 if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1221 error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1225 n_left_from = n_packets;
1227 next_index = node->cached_next_index;
1228 stats_sw_if_index = node->runtime_data[0];
1229 stats_n_packets = stats_n_bytes = 0;
1230 vlib_get_buffers (vm, from, bufs, n_left_from);
1232 while (n_left_from > 0)
1236 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1238 while (n_left_from >= 4 && n_left_to_next >= 2)
1241 vlib_buffer_t *b0, *b1;
1242 u8 next0, next1, error0, error1;
1243 u16 type0, orig_type0, type1, orig_type1;
1244 u16 outer_id0, inner_id0, outer_id1, inner_id1;
1245 u32 match_flags0, match_flags1;
1246 u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1247 new_sw_if_index1, len1;
1248 vnet_hw_interface_t *hi0, *hi1;
1249 main_intf_t *main_intf0, *main_intf1;
1250 vlan_intf_t *vlan_intf0, *vlan_intf1;
1251 qinq_intf_t *qinq_intf0, *qinq_intf1;
1253 ethernet_header_t *e0, *e1;
1257 /* Prefetch next iteration. */
1259 vlib_prefetch_buffer_header (b[2], STORE);
1260 vlib_prefetch_buffer_header (b[3], STORE);
1262 CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1263 CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1272 n_left_to_next -= 2;
1279 error0 = error1 = ETHERNET_ERROR_NONE;
1280 e0 = vlib_buffer_get_current (b0);
1281 type0 = clib_net_to_host_u16 (e0->type);
1282 e1 = vlib_buffer_get_current (b1);
1283 type1 = clib_net_to_host_u16 (e1->type);
1285 /* Set the L2 header offset for all packets */
1286 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1287 vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1288 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1289 b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1291 /* Speed-path for the untagged case */
1292 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1293 && !ethernet_frame_is_any_tagged_x2 (type0,
1297 subint_config_t *subint0;
1298 u32 sw_if_index0, sw_if_index1;
1300 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1301 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1302 is_l20 = cached_is_l2;
1304 /* This is probably wholly unnecessary */
1305 if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1308 /* Now sw_if_index0 == sw_if_index1 */
1309 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1311 cached_sw_if_index = sw_if_index0;
1312 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1313 ei = ethernet_get_interface (em, hi->hw_if_index);
1314 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1315 subint0 = &intf0->untagged_subint;
1316 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1319 if (PREDICT_TRUE (is_l20 != 0))
1321 vnet_buffer (b0)->l3_hdr_offset =
1322 vnet_buffer (b0)->l2_hdr_offset +
1323 sizeof (ethernet_header_t);
1324 vnet_buffer (b1)->l3_hdr_offset =
1325 vnet_buffer (b1)->l2_hdr_offset +
1326 sizeof (ethernet_header_t);
1327 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1328 b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1329 next0 = em->l2_next;
1330 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1331 next1 = em->l2_next;
1332 vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1336 if (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1337 goto skip_dmac_check01;
1339 dmacs[0] = *(u64 *) e0;
1340 dmacs[1] = *(u64 *) e1;
1342 if (ei && vec_len (ei->secondary_addrs))
1343 ethernet_input_inline_dmac_check (hi, dmacs,
1347 1 /* have_sec_dmac */ );
1349 ethernet_input_inline_dmac_check (hi, dmacs,
1353 0 /* have_sec_dmac */ );
1356 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1358 error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1361 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1362 determine_next_node (em, variant, 0, type0, b0,
1364 vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1365 determine_next_node (em, variant, 0, type1, b1,
1371 /* Slow-path for the tagged case */
1373 parse_header (variant,
1376 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1378 parse_header (variant,
1381 &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1383 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1384 old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1386 eth_vlan_table_lookups (em,
1393 &main_intf0, &vlan_intf0, &qinq_intf0);
1395 eth_vlan_table_lookups (em,
1402 &main_intf1, &vlan_intf1, &qinq_intf1);
1404 identify_subint (em,
1410 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1412 identify_subint (em,
1418 qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1420 // Save RX sw_if_index for later nodes
1421 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1423 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1424 vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1426 ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1428 // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1429 if (((new_sw_if_index0 != ~0)
1430 && (new_sw_if_index0 != old_sw_if_index0))
1431 || ((new_sw_if_index1 != ~0)
1432 && (new_sw_if_index1 != old_sw_if_index1)))
1435 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1436 - vnet_buffer (b0)->l2_hdr_offset;
1437 len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1438 - vnet_buffer (b1)->l2_hdr_offset;
1440 stats_n_packets += 2;
1441 stats_n_bytes += len0 + len1;
1444 (!(new_sw_if_index0 == stats_sw_if_index
1445 && new_sw_if_index1 == stats_sw_if_index)))
1447 stats_n_packets -= 2;
1448 stats_n_bytes -= len0 + len1;
1450 if (new_sw_if_index0 != old_sw_if_index0
1451 && new_sw_if_index0 != ~0)
1452 vlib_increment_combined_counter (vnm->
1453 interface_main.combined_sw_if_counters
1455 VNET_INTERFACE_COUNTER_RX,
1457 new_sw_if_index0, 1,
1459 if (new_sw_if_index1 != old_sw_if_index1
1460 && new_sw_if_index1 != ~0)
1461 vlib_increment_combined_counter (vnm->
1462 interface_main.combined_sw_if_counters
1464 VNET_INTERFACE_COUNTER_RX,
1466 new_sw_if_index1, 1,
1469 if (new_sw_if_index0 == new_sw_if_index1)
1471 if (stats_n_packets > 0)
1473 vlib_increment_combined_counter
1474 (vnm->interface_main.combined_sw_if_counters
1475 + VNET_INTERFACE_COUNTER_RX,
1478 stats_n_packets, stats_n_bytes);
1479 stats_n_packets = stats_n_bytes = 0;
1481 stats_sw_if_index = new_sw_if_index0;
1486 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1487 is_l20 = is_l21 = 0;
1489 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1491 determine_next_node (em, variant, is_l21, type1, b1, &error1,
1495 b0->error = error_node->errors[error0];
1496 b1->error = error_node->errors[error1];
1498 // verify speculative enqueue
1499 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1500 n_left_to_next, bi0, bi1, next0,
1504 while (n_left_from > 0 && n_left_to_next > 0)
1509 u16 type0, orig_type0;
1510 u16 outer_id0, inner_id0;
1512 u32 old_sw_if_index0, new_sw_if_index0, len0;
1513 vnet_hw_interface_t *hi0;
1514 main_intf_t *main_intf0;
1515 vlan_intf_t *vlan_intf0;
1516 qinq_intf_t *qinq_intf0;
1517 ethernet_header_t *e0;
1522 // Prefetch next iteration
1523 if (n_left_from > 1)
1525 vlib_prefetch_buffer_header (b[1], STORE);
1526 CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1534 n_left_to_next -= 1;
1539 error0 = ETHERNET_ERROR_NONE;
1540 e0 = vlib_buffer_get_current (b0);
1541 type0 = clib_net_to_host_u16 (e0->type);
1543 /* Set the L2 header offset for all packets */
1544 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1545 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1547 /* Speed-path for the untagged case */
1548 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1549 && !ethernet_frame_is_tagged (type0)))
1552 subint_config_t *subint0;
1555 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1556 is_l20 = cached_is_l2;
1558 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1560 cached_sw_if_index = sw_if_index0;
1561 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1562 ei = ethernet_get_interface (em, hi->hw_if_index);
1563 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1564 subint0 = &intf0->untagged_subint;
1565 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1569 if (PREDICT_TRUE (is_l20 != 0))
1571 vnet_buffer (b0)->l3_hdr_offset =
1572 vnet_buffer (b0)->l2_hdr_offset +
1573 sizeof (ethernet_header_t);
1574 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1575 next0 = em->l2_next;
1576 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1580 if (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1581 goto skip_dmac_check0;
1583 dmacs[0] = *(u64 *) e0;
1585 if (ei && vec_len (ei->secondary_addrs))
1586 ethernet_input_inline_dmac_check (hi, dmacs,
1590 1 /* have_sec_dmac */ );
1592 ethernet_input_inline_dmac_check (hi, dmacs,
1596 0 /* have_sec_dmac */ );
1599 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1602 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1603 determine_next_node (em, variant, 0, type0, b0,
1609 /* Slow-path for the tagged case */
1610 parse_header (variant,
1613 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1615 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1617 eth_vlan_table_lookups (em,
1624 &main_intf0, &vlan_intf0, &qinq_intf0);
1626 identify_subint (em,
1632 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1634 // Save RX sw_if_index for later nodes
1635 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1637 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1639 // Increment subinterface stats
1640 // Note that interface-level counters have already been incremented
1641 // prior to calling this function. Thus only subinterface counters
1642 // are incremented here.
1644 // Interface level counters include packets received on the main
1645 // interface and all subinterfaces. Subinterface level counters
1646 // include only those packets received on that subinterface
1647 // Increment stats if the subint is valid and it is not the main intf
1648 if ((new_sw_if_index0 != ~0)
1649 && (new_sw_if_index0 != old_sw_if_index0))
1652 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1653 - vnet_buffer (b0)->l2_hdr_offset;
1655 stats_n_packets += 1;
1656 stats_n_bytes += len0;
1658 // Batch stat increments from the same subinterface so counters
1659 // don't need to be incremented for every packet.
1660 if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1662 stats_n_packets -= 1;
1663 stats_n_bytes -= len0;
1665 if (new_sw_if_index0 != ~0)
1666 vlib_increment_combined_counter
1667 (vnm->interface_main.combined_sw_if_counters
1668 + VNET_INTERFACE_COUNTER_RX,
1669 thread_index, new_sw_if_index0, 1, len0);
1670 if (stats_n_packets > 0)
1672 vlib_increment_combined_counter
1673 (vnm->interface_main.combined_sw_if_counters
1674 + VNET_INTERFACE_COUNTER_RX,
1676 stats_sw_if_index, stats_n_packets, stats_n_bytes);
1677 stats_n_packets = stats_n_bytes = 0;
1679 stats_sw_if_index = new_sw_if_index0;
1683 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1686 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1690 b0->error = error_node->errors[error0];
1692 // verify speculative enqueue
1693 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1694 to_next, n_left_to_next,
1698 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1701 // Increment any remaining batched stats
1702 if (stats_n_packets > 0)
1704 vlib_increment_combined_counter
1705 (vnm->interface_main.combined_sw_if_counters
1706 + VNET_INTERFACE_COUNTER_RX,
1707 thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1708 node->runtime_data[0] = stats_sw_if_index;
1712 VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
1713 vlib_node_runtime_t * node,
1714 vlib_frame_t * frame)
1716 vnet_main_t *vnm = vnet_get_main ();
1717 u32 *from = vlib_frame_vector_args (frame);
1718 u32 n_packets = frame->n_vectors;
1720 ethernet_input_trace (vm, node, frame);
1722 if (frame->flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
1724 ethernet_input_frame_t *ef = vlib_frame_scalar_args (frame);
1725 int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1726 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ef->hw_if_index);
1727 eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1730 ethernet_input_inline (vm, node, from, n_packets,
1731 ETHERNET_INPUT_VARIANT_ETHERNET);
1735 VLIB_NODE_FN (ethernet_input_type_node) (vlib_main_t * vm,
1736 vlib_node_runtime_t * node,
1737 vlib_frame_t * from_frame)
1739 u32 *from = vlib_frame_vector_args (from_frame);
1740 u32 n_packets = from_frame->n_vectors;
1741 ethernet_input_trace (vm, node, from_frame);
1742 ethernet_input_inline (vm, node, from, n_packets,
1743 ETHERNET_INPUT_VARIANT_ETHERNET_TYPE);
1747 VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
1748 vlib_node_runtime_t * node,
1749 vlib_frame_t * from_frame)
1751 u32 *from = vlib_frame_vector_args (from_frame);
1752 u32 n_packets = from_frame->n_vectors;
1753 ethernet_input_trace (vm, node, from_frame);
1754 ethernet_input_inline (vm, node, from, n_packets,
1755 ETHERNET_INPUT_VARIANT_NOT_L2);
1760 // Return the subinterface config struct for the given sw_if_index
1761 // Also return via parameter the appropriate match flags for the
1762 // configured number of tags.
1763 // On error (unsupported or not ethernet) return 0.
1764 static subint_config_t *
1765 ethernet_sw_interface_get_config (vnet_main_t * vnm,
1767 u32 * flags, u32 * unsupported)
1769 ethernet_main_t *em = ðernet_main;
1770 vnet_hw_interface_t *hi;
1771 vnet_sw_interface_t *si;
1772 main_intf_t *main_intf;
1773 vlan_table_t *vlan_table;
1774 qinq_table_t *qinq_table;
1775 subint_config_t *subint = 0;
1777 hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1779 if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1782 goto done; // non-ethernet interface
1785 // ensure there's an entry for the main intf (shouldn't really be necessary)
1786 vec_validate (em->main_intfs, hi->hw_if_index);
1787 main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1789 // Locate the subint for the given ethernet config
1790 si = vnet_get_sw_interface (vnm, sw_if_index);
1792 if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1794 p2p_ethernet_main_t *p2pm = &p2p_main;
1795 u32 p2pe_sw_if_index =
1796 p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
1797 if (p2pe_sw_if_index == ~0)
1799 pool_get (p2pm->p2p_subif_pool, subint);
1800 si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1803 subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1804 *flags = SUBINT_CONFIG_P2P;
1806 else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1810 pipe = pipe_get (sw_if_index);
1811 subint = &pipe->subint;
1812 *flags = SUBINT_CONFIG_P2P;
1814 else if (si->sub.eth.flags.default_sub)
1816 subint = &main_intf->default_subint;
1817 *flags = SUBINT_CONFIG_MATCH_1_TAG |
1818 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1820 else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1822 // if no flags are set then this is a main interface
1823 // so treat as untagged
1824 subint = &main_intf->untagged_subint;
1825 *flags = SUBINT_CONFIG_MATCH_0_TAG;
1830 // first get the vlan table
1831 if (si->sub.eth.flags.dot1ad)
1833 if (main_intf->dot1ad_vlans == 0)
1835 // Allocate a vlan table from the pool
1836 pool_get (em->vlan_pool, vlan_table);
1837 main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1841 // Get ptr to existing vlan table
1843 vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1848 if (main_intf->dot1q_vlans == 0)
1850 // Allocate a vlan table from the pool
1851 pool_get (em->vlan_pool, vlan_table);
1852 main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1856 // Get ptr to existing vlan table
1858 vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1862 if (si->sub.eth.flags.one_tag)
1864 *flags = si->sub.eth.flags.exact_match ?
1865 SUBINT_CONFIG_MATCH_1_TAG :
1866 (SUBINT_CONFIG_MATCH_1_TAG |
1867 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1869 if (si->sub.eth.flags.outer_vlan_id_any)
1871 // not implemented yet
1877 // a single vlan, a common case
1879 &vlan_table->vlans[si->sub.eth.
1880 outer_vlan_id].single_tag_subint;
1887 *flags = si->sub.eth.flags.exact_match ?
1888 SUBINT_CONFIG_MATCH_2_TAG :
1889 (SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1891 if (si->sub.eth.flags.outer_vlan_id_any
1892 && si->sub.eth.flags.inner_vlan_id_any)
1894 // not implemented yet
1899 if (si->sub.eth.flags.inner_vlan_id_any)
1901 // a specific outer and "any" inner
1902 // don't need a qinq table for this
1904 &vlan_table->vlans[si->sub.eth.
1905 outer_vlan_id].inner_any_subint;
1906 if (si->sub.eth.flags.exact_match)
1908 *flags = SUBINT_CONFIG_MATCH_2_TAG;
1912 *flags = SUBINT_CONFIG_MATCH_2_TAG |
1913 SUBINT_CONFIG_MATCH_3_TAG;
1918 // a specific outer + specifc innner vlan id, a common case
1920 // get the qinq table
1921 if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1923 // Allocate a qinq table from the pool
1924 pool_get (em->qinq_pool, qinq_table);
1925 vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1926 qinq_table - em->qinq_pool;
1930 // Get ptr to existing qinq table
1932 vec_elt_at_index (em->qinq_pool,
1933 vlan_table->vlans[si->sub.
1937 subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1946 static clib_error_t *
1947 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
1949 subint_config_t *subint;
1950 u32 placeholder_flags;
1951 u32 placeholder_unsup;
1952 clib_error_t *error = 0;
1954 // Find the config for this subinterface
1956 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1957 &placeholder_unsup);
1961 // not implemented yet or not ethernet
1965 subint->sw_if_index =
1966 ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1972 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
1975 #ifndef CLIB_MARCH_VARIANT
1976 // Set the L2/L3 mode for the subinterface
1978 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
1980 subint_config_t *subint;
1981 u32 placeholder_flags;
1982 u32 placeholder_unsup;
1984 vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1986 is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1988 // Find the config for this subinterface
1990 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1991 &placeholder_unsup);
1995 // unimplemented or not ethernet
1999 // Double check that the config we found is for our interface (or the interface is down)
2000 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2004 subint->flags |= SUBINT_CONFIG_L2;
2007 SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
2008 | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
2012 subint->flags &= ~SUBINT_CONFIG_L2;
2015 ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
2016 | SUBINT_CONFIG_MATCH_3_TAG);
2024 * Set the L2/L3 mode for the subinterface regardless of port
2027 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
2028 u32 sw_if_index, u32 l2)
2030 subint_config_t *subint;
2031 u32 placeholder_flags;
2032 u32 placeholder_unsup;
2034 /* Find the config for this subinterface */
2036 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
2037 &placeholder_unsup);
2041 /* unimplemented or not ethernet */
2046 * Double check that the config we found is for our interface (or the
2047 * interface is down)
2049 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2053 subint->flags |= SUBINT_CONFIG_L2;
2057 subint->flags &= ~SUBINT_CONFIG_L2;
2065 static clib_error_t *
2066 ethernet_sw_interface_add_del (vnet_main_t * vnm,
2067 u32 sw_if_index, u32 is_create)
2069 clib_error_t *error = 0;
2070 subint_config_t *subint;
2072 u32 unsupported = 0;
2074 // Find the config for this subinterface
2076 ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2081 // not implemented yet or not ethernet
2084 // this is the NYI case
2085 error = clib_error_return (0, "not implemented yet");
2096 // Initialize the subint
2097 if (subint->flags & SUBINT_CONFIG_VALID)
2099 // Error vlan already in use
2100 error = clib_error_return (0, "vlan is already in use");
2104 // Note that config is L3 by default
2105 subint->flags = SUBINT_CONFIG_VALID | match_flags;
2106 subint->sw_if_index = ~0; // because interfaces are initially down
2113 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
2115 static char *ethernet_error_strings[] = {
2116 #define ethernet_error(n,c,s) s,
2117 #include "error.def"
2118 #undef ethernet_error
2122 VLIB_REGISTER_NODE (ethernet_input_node) = {
2123 .name = "ethernet-input",
2124 /* Takes a vector of packets. */
2125 .vector_size = sizeof (u32),
2126 .scalar_size = sizeof (ethernet_input_frame_t),
2127 .n_errors = ETHERNET_N_ERROR,
2128 .error_strings = ethernet_error_strings,
2129 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2131 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2132 foreach_ethernet_input_next
2135 .format_buffer = format_ethernet_header_with_length,
2136 .format_trace = format_ethernet_input_trace,
2137 .unformat_buffer = unformat_ethernet_header,
2140 VLIB_REGISTER_NODE (ethernet_input_type_node) = {
2141 .name = "ethernet-input-type",
2142 /* Takes a vector of packets. */
2143 .vector_size = sizeof (u32),
2144 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2146 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2147 foreach_ethernet_input_next
2152 VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
2153 .name = "ethernet-input-not-l2",
2154 /* Takes a vector of packets. */
2155 .vector_size = sizeof (u32),
2156 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2158 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2159 foreach_ethernet_input_next
2165 #ifndef CLIB_MARCH_VARIANT
2167 ethernet_set_rx_redirect (vnet_main_t * vnm,
2168 vnet_hw_interface_t * hi, u32 enable)
2170 // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2171 // don't go directly to ip4-input)
2172 vnet_hw_interface_rx_redirect_to_node
2173 (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2178 * Initialization and registration for the next_by_ethernet structure
2182 next_by_ethertype_init (next_by_ethertype_t * l3_next)
2184 l3_next->input_next_by_type = sparse_vec_new
2185 ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2186 /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2188 vec_validate (l3_next->sparse_index_by_input_next_index,
2189 ETHERNET_INPUT_NEXT_DROP);
2190 vec_validate (l3_next->sparse_index_by_input_next_index,
2191 ETHERNET_INPUT_NEXT_PUNT);
2192 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2193 SPARSE_VEC_INVALID_INDEX;
2194 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2195 SPARSE_VEC_INVALID_INDEX;
2198 * Make sure we don't wipe out an ethernet registration by mistake
2199 * Can happen if init function ordering constraints are missing.
2203 ethernet_main_t *em = ðernet_main;
2204 ASSERT (em->next_by_ethertype_register_called == 0);
2210 // Add an ethertype -> next index mapping to the structure
2212 next_by_ethertype_register (next_by_ethertype_t * l3_next,
2213 u32 ethertype, u32 next_index)
2217 ethernet_main_t *em = ðernet_main;
2221 ethernet_main_t *em = ðernet_main;
2222 em->next_by_ethertype_register_called = 1;
2225 /* Setup ethernet type -> next index sparse vector mapping. */
2226 n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2229 /* Rebuild next index -> sparse index inverse mapping when sparse vector
2231 vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2232 for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2234 sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2236 // do not allow the cached next index's to be updated if L3
2237 // redirect is enabled, as it will have overwritten them
2238 if (!em->redirect_l3)
2240 // Cache common ethertypes directly
2241 if (ethertype == ETHERNET_TYPE_IP4)
2243 l3_next->input_next_ip4 = next_index;
2245 else if (ethertype == ETHERNET_TYPE_IP6)
2247 l3_next->input_next_ip6 = next_index;
2249 else if (ethertype == ETHERNET_TYPE_MPLS)
2251 l3_next->input_next_mpls = next_index;
2258 ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
2260 __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2261 __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2263 ethernet_setup_node (vm, ethernet_input_node.index);
2264 ethernet_setup_node (vm, ethernet_input_type_node.index);
2265 ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
2267 next_by_ethertype_init (&em->l3_next);
2269 // Initialize pools and vector for vlan parsing
2270 vec_validate (em->main_intfs, 10); // 10 main interfaces
2271 pool_alloc (em->vlan_pool, 10);
2272 pool_alloc (em->qinq_pool, 1);
2274 // The first vlan pool will always be reserved for an invalid table
2275 pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2276 // The first qinq pool will always be reserved for an invalid table
2277 pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2281 ethernet_register_input_type (vlib_main_t * vm,
2282 ethernet_type_t type, u32 node_index)
2284 ethernet_main_t *em = ðernet_main;
2285 ethernet_type_info_t *ti;
2289 clib_error_t *error = vlib_call_init_function (vm, ethernet_init);
2291 clib_error_report (error);
2294 ti = ethernet_get_type_info (em, type);
2297 clib_warning ("type_info NULL for type %d", type);
2300 ti->node_index = node_index;
2301 ti->next_index = vlib_node_add_next (vm,
2302 ethernet_input_node.index, node_index);
2303 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2304 ASSERT (i == ti->next_index);
2306 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2307 ASSERT (i == ti->next_index);
2309 // Add the L3 node for this ethertype to the next nodes structure
2310 next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2312 // Call the registration functions for other nodes that want a mapping
2313 l2bvi_register_input_type (vm, type, node_index);
2317 ethernet_register_l2_input (vlib_main_t * vm, u32 node_index)
2319 ethernet_main_t *em = ðernet_main;
2323 vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2326 * Even if we never use these arcs, we have to align the next indices...
2328 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2330 ASSERT (i == em->l2_next);
2332 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2333 ASSERT (i == em->l2_next);
2336 // Register a next node for L3 redirect, and enable L3 redirect
2338 ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
2340 ethernet_main_t *em = ðernet_main;
2343 em->redirect_l3 = 1;
2344 em->redirect_l3_next = vlib_node_add_next (vm,
2345 ethernet_input_node.index,
2348 * Change the cached next nodes to the redirect node
2350 em->l3_next.input_next_ip4 = em->redirect_l3_next;
2351 em->l3_next.input_next_ip6 = em->redirect_l3_next;
2352 em->l3_next.input_next_mpls = em->redirect_l3_next;
2355 * Even if we never use these arcs, we have to align the next indices...
2357 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2359 ASSERT (i == em->redirect_l3_next);
2361 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2363 ASSERT (i == em->redirect_l3_next);
2368 * fd.io coding-style-patch-verification: ON
2371 * eval: (c-set-style "gnu")