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 = ei->address.as_u64;
700 ASSERT (0 == ei->address.zero);
702 dmacs_bad[0] = is_dmac_bad (dmacs[0], hwaddr);
703 dmacs_bad[1] = ((n_packets > 1) & is_dmac_bad (dmacs[1], hwaddr));
705 bad = dmacs_bad[0] | dmacs_bad[1];
707 if (PREDICT_FALSE (bad && have_sec_dmac))
709 ethernet_interface_address_t *sec_addr;
711 vec_foreach (sec_addr, ei->secondary_addrs)
713 ASSERT (0 == sec_addr->zero);
714 hwaddr = sec_addr->as_u64;
716 bad = (eth_input_sec_dmac_check_x1 (hwaddr, dmacs, dmacs_bad) |
717 eth_input_sec_dmac_check_x1 (hwaddr, dmacs + 1,
726 static_always_inline void
727 eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi,
728 u64 * dmacs, u8 * dmacs_bad,
729 u32 n_packets, ethernet_interface_t * ei,
732 u64 hwaddr = ei->address.as_u64;
734 u8 *dmac_bad = dmacs_bad;
736 i32 n_left = n_packets;
738 ASSERT (0 == ei->address.zero);
740 #ifdef CLIB_HAVE_VEC256
743 bad |= *(u32 *) (dmac_bad + 0) = is_dmac_bad_x4 (dmac + 0, hwaddr);
744 bad |= *(u32 *) (dmac_bad + 4) = is_dmac_bad_x4 (dmac + 4, hwaddr);
754 bad |= dmac_bad[0] = is_dmac_bad (dmac[0], hwaddr);
755 bad |= dmac_bad[1] = is_dmac_bad (dmac[1], hwaddr);
756 bad |= dmac_bad[2] = is_dmac_bad (dmac[2], hwaddr);
757 bad |= dmac_bad[3] = is_dmac_bad (dmac[3], hwaddr);
766 if (have_sec_dmac && bad)
768 ethernet_interface_address_t *addr;
770 vec_foreach (addr, ei->secondary_addrs)
772 u64 hwaddr = addr->as_u64;
773 i32 n_left = n_packets;
775 u8 *dmac_bad = dmacs_bad;
777 ASSERT (0 == addr->zero);
786 /* skip any that have already matched */
795 n_bad = clib_min (4, n_left);
797 /* If >= 4 left, compare 4 together */
800 bad |= eth_input_sec_dmac_check_x4 (hwaddr, dmac, dmac_bad);
805 /* handle individually */
808 bad |= eth_input_sec_dmac_check_x1 (hwaddr, dmac + adv,
819 if (!bad) /* can stop looping if everything matched */
825 /* process frame of buffers, store ethertype into array and update
826 buffer metadata fields depending on interface being l2 or l3 assuming that
827 packets are untagged. For tagged packets those fields are updated later.
828 Optionally store Destionation MAC address and tag data into arrays
829 for further processing */
831 STATIC_ASSERT (VLIB_FRAME_SIZE % 8 == 0,
832 "VLIB_FRAME_SIZE must be power of 8");
833 static_always_inline void
834 eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
835 vnet_hw_interface_t * hi,
836 u32 * buffer_indices, u32 n_packets, int main_is_l3,
837 int ip4_cksum_ok, int dmac_check)
839 ethernet_main_t *em = ðernet_main;
840 u16 nexts[VLIB_FRAME_SIZE], *next;
841 u16 etypes[VLIB_FRAME_SIZE], *etype = etypes;
842 u64 dmacs[VLIB_FRAME_SIZE], *dmac = dmacs;
843 u8 dmacs_bad[VLIB_FRAME_SIZE];
844 u64 tags[VLIB_FRAME_SIZE], *tag = tags;
845 u16 slowpath_indices[VLIB_FRAME_SIZE];
847 u16 next_ip4, next_ip6, next_mpls, next_l2;
848 u16 et_ip4 = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
849 u16 et_ip6 = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
850 u16 et_mpls = clib_host_to_net_u16 (ETHERNET_TYPE_MPLS);
851 u16 et_vlan = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
852 u16 et_dot1ad = clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD);
853 i32 n_left = n_packets;
854 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
855 vlib_buffer_t **b = bufs;
856 ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index);
858 vlib_get_buffers (vm, buffer_indices, b, n_left);
862 vlib_buffer_t **ph = b + 16, **pd = b + 8;
864 vlib_prefetch_buffer_header (ph[0], LOAD);
865 vlib_prefetch_buffer_data (pd[0], LOAD);
866 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
868 vlib_prefetch_buffer_header (ph[1], LOAD);
869 vlib_prefetch_buffer_data (pd[1], LOAD);
870 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
872 vlib_prefetch_buffer_header (ph[2], LOAD);
873 vlib_prefetch_buffer_data (pd[2], LOAD);
874 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
876 vlib_prefetch_buffer_header (ph[3], LOAD);
877 vlib_prefetch_buffer_data (pd[3], LOAD);
878 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
880 eth_input_adv_and_flags_x4 (b, main_is_l3);
891 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
892 eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
893 eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
894 eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
895 eth_input_adv_and_flags_x4 (b, main_is_l3);
906 eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
907 eth_input_adv_and_flags_x1 (b, main_is_l3);
919 if (ei && vec_len (ei->secondary_addrs))
920 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
921 ei, 1 /* have_sec_dmac */ );
923 eth_input_process_frame_dmac_check (hi, dmacs, dmacs_bad, n_packets,
924 ei, 0 /* have_sec_dmac */ );
927 next_ip4 = em->l3_next.input_next_ip4;
928 next_ip6 = em->l3_next.input_next_ip6;
929 next_mpls = em->l3_next.input_next_mpls;
930 next_l2 = em->l2_next;
932 if (next_ip4 == ETHERNET_INPUT_NEXT_IP4_INPUT && ip4_cksum_ok)
933 next_ip4 = ETHERNET_INPUT_NEXT_IP4_INPUT_NCS;
935 #ifdef CLIB_HAVE_VEC256
936 u16x16 et16_ip4 = u16x16_splat (et_ip4);
937 u16x16 et16_ip6 = u16x16_splat (et_ip6);
938 u16x16 et16_mpls = u16x16_splat (et_mpls);
939 u16x16 et16_vlan = u16x16_splat (et_vlan);
940 u16x16 et16_dot1ad = u16x16_splat (et_dot1ad);
941 u16x16 next16_ip4 = u16x16_splat (next_ip4);
942 u16x16 next16_ip6 = u16x16_splat (next_ip6);
943 u16x16 next16_mpls = u16x16_splat (next_mpls);
944 u16x16 next16_l2 = u16x16_splat (next_l2);
946 u16x16 stairs = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
955 /* fastpath - in l3 mode hadles ip4, ip6 and mpls packets, other packets
956 are considered as slowpath, in l2 mode all untagged packets are
957 considered as fastpath */
960 #ifdef CLIB_HAVE_VEC256
964 u16x16 e16 = u16x16_load_unaligned (etype);
967 r += (e16 == et16_ip4) & next16_ip4;
968 r += (e16 == et16_ip6) & next16_ip6;
969 r += (e16 == et16_mpls) & next16_mpls;
972 r = ((e16 != et16_vlan) & (e16 != et16_dot1ad)) & next16_l2;
973 u16x16_store_unaligned (r, next);
975 if (!u16x16_is_all_zero (r == zero))
977 if (u16x16_is_all_zero (r))
979 u16x16_store_unaligned (u16x16_splat (i) + stairs,
980 slowpath_indices + n_slowpath);
985 for (int j = 0; j < 16; j++)
987 slowpath_indices[n_slowpath++] = i + j;
998 if (main_is_l3 && etype[0] == et_ip4)
1000 else if (main_is_l3 && etype[0] == et_ip6)
1002 else if (main_is_l3 && etype[0] == et_mpls)
1003 next[0] = next_mpls;
1004 else if (main_is_l3 == 0 &&
1005 etype[0] != et_vlan && etype[0] != et_dot1ad)
1010 slowpath_indices[n_slowpath++] = i;
1021 vnet_main_t *vnm = vnet_get_main ();
1022 n_left = n_slowpath;
1023 u16 *si = slowpath_indices;
1024 u32 last_unknown_etype = ~0;
1025 u32 last_unknown_next = ~0;
1026 eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
1028 .tag = tags[si[0]] ^ -1LL,
1032 clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
1037 u16 etype = etypes[i];
1039 if (etype == et_vlan)
1041 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1042 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1043 &dot1q_lookup, dmacs_bad[i], 0,
1044 main_is_l3, dmac_check);
1047 else if (etype == et_dot1ad)
1049 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1050 eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1051 &dot1ad_lookup, dmacs_bad[i], 1,
1052 main_is_l3, dmac_check);
1056 /* untagged packet with not well known etyertype */
1057 if (last_unknown_etype != etype)
1059 last_unknown_etype = etype;
1060 etype = clib_host_to_net_u16 (etype);
1061 last_unknown_next = eth_input_next_by_type (etype);
1063 if (dmac_check && main_is_l3 && dmacs_bad[i])
1065 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1066 b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
1067 nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
1070 nexts[i] = last_unknown_next;
1078 eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
1079 eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
1082 vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
1085 static_always_inline void
1086 eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node,
1087 vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
1090 ethernet_main_t *em = ðernet_main;
1091 ethernet_interface_t *ei;
1092 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
1093 main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1094 subint_config_t *subint0 = &intf0->untagged_subint;
1096 int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
1097 int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3;
1101 if (int_is_l3 || /* DMAC filter already done by NIC */
1102 ((hi->l2_if_count != 0) && (hi->l3_if_count == 0)))
1103 { /* All L2 usage - DMAC check not needed */
1104 eth_input_process_frame (vm, node, hi, from, n_pkts,
1105 /*is_l3 */ 1, ip4_cksum_ok, 0);
1108 { /* DMAC check needed for L3 */
1109 eth_input_process_frame (vm, node, hi, from, n_pkts,
1110 /*is_l3 */ 1, ip4_cksum_ok, 1);
1116 if (hi->l3_if_count == 0)
1117 { /* All L2 usage - DMAC check not needed */
1118 eth_input_process_frame (vm, node, hi, from, n_pkts,
1119 /*is_l3 */ 0, ip4_cksum_ok, 0);
1122 { /* DMAC check needed for L3 */
1123 eth_input_process_frame (vm, node, hi, from, n_pkts,
1124 /*is_l3 */ 0, ip4_cksum_ok, 1);
1130 static_always_inline void
1131 ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
1132 vlib_frame_t * from_frame)
1135 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1137 from = vlib_frame_vector_args (from_frame);
1138 n_left = from_frame->n_vectors;
1142 ethernet_input_trace_t *t0;
1143 vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1145 if (b0->flags & VLIB_BUFFER_IS_TRACED)
1147 t0 = vlib_add_trace (vm, node, b0,
1148 sizeof (ethernet_input_trace_t));
1149 clib_memcpy_fast (t0->packet_data, b0->data + b0->current_data,
1150 sizeof (t0->packet_data));
1151 t0->frame_flags = from_frame->flags;
1152 clib_memcpy_fast (&t0->frame_data,
1153 vlib_frame_scalar_args (from_frame),
1154 sizeof (ethernet_input_frame_t));
1161 /* rx pcap capture if enabled */
1162 if (PREDICT_FALSE (vlib_global_main.pcap.pcap_rx_enable))
1165 vnet_pcap_t *pp = &vlib_global_main.pcap;
1167 from = vlib_frame_vector_args (from_frame);
1168 n_left = from_frame->n_vectors;
1171 int classify_filter_result;
1176 b0 = vlib_get_buffer (vm, bi0);
1177 if (pp->filter_classify_table_index != ~0)
1179 classify_filter_result =
1180 vnet_is_packet_traced_inline
1181 (b0, pp->filter_classify_table_index, 0 /* full classify */ );
1182 if (classify_filter_result)
1183 pcap_add_buffer (&pp->pcap_main, vm, bi0,
1184 pp->max_bytes_per_pkt);
1188 if (pp->pcap_sw_if_index == 0 ||
1189 pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1191 vnet_main_t *vnm = vnet_get_main ();
1192 vnet_hw_interface_t *hi =
1193 vnet_get_sup_hw_interface
1194 (vnm, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1196 /* Capture pkt if not filtered, or if filter hits */
1197 if (hi->trace_classify_table_index == ~0 ||
1198 vnet_is_packet_traced_inline
1199 (b0, hi->trace_classify_table_index,
1200 0 /* full classify */ ))
1201 pcap_add_buffer (&pp->pcap_main, vm, bi0,
1202 pp->max_bytes_per_pkt);
1208 static_always_inline void
1209 ethernet_input_inline (vlib_main_t * vm,
1210 vlib_node_runtime_t * node,
1211 u32 * from, u32 n_packets,
1212 ethernet_input_variant_t variant)
1214 vnet_main_t *vnm = vnet_get_main ();
1215 ethernet_main_t *em = ðernet_main;
1216 vlib_node_runtime_t *error_node;
1217 u32 n_left_from, next_index, *to_next;
1218 u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1219 u32 thread_index = vm->thread_index;
1220 u32 cached_sw_if_index = ~0;
1221 u32 cached_is_l2 = 0; /* shut up gcc */
1222 vnet_hw_interface_t *hi = NULL; /* used for main interface only */
1223 ethernet_interface_t *ei = NULL;
1224 vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
1225 vlib_buffer_t **b = bufs;
1227 if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1228 error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1232 n_left_from = n_packets;
1234 next_index = node->cached_next_index;
1235 stats_sw_if_index = node->runtime_data[0];
1236 stats_n_packets = stats_n_bytes = 0;
1237 vlib_get_buffers (vm, from, bufs, n_left_from);
1239 while (n_left_from > 0)
1243 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1245 while (n_left_from >= 4 && n_left_to_next >= 2)
1248 vlib_buffer_t *b0, *b1;
1249 u8 next0, next1, error0, error1;
1250 u16 type0, orig_type0, type1, orig_type1;
1251 u16 outer_id0, inner_id0, outer_id1, inner_id1;
1252 u32 match_flags0, match_flags1;
1253 u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1254 new_sw_if_index1, len1;
1255 vnet_hw_interface_t *hi0, *hi1;
1256 main_intf_t *main_intf0, *main_intf1;
1257 vlan_intf_t *vlan_intf0, *vlan_intf1;
1258 qinq_intf_t *qinq_intf0, *qinq_intf1;
1260 ethernet_header_t *e0, *e1;
1264 /* Prefetch next iteration. */
1266 vlib_prefetch_buffer_header (b[2], STORE);
1267 vlib_prefetch_buffer_header (b[3], STORE);
1269 CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1270 CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1279 n_left_to_next -= 2;
1286 error0 = error1 = ETHERNET_ERROR_NONE;
1287 e0 = vlib_buffer_get_current (b0);
1288 type0 = clib_net_to_host_u16 (e0->type);
1289 e1 = vlib_buffer_get_current (b1);
1290 type1 = clib_net_to_host_u16 (e1->type);
1292 /* Set the L2 header offset for all packets */
1293 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1294 vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1295 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1296 b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1298 /* Speed-path for the untagged case */
1299 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1300 && !ethernet_frame_is_any_tagged_x2 (type0,
1304 subint_config_t *subint0;
1305 u32 sw_if_index0, sw_if_index1;
1307 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1308 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1309 is_l20 = cached_is_l2;
1311 /* This is probably wholly unnecessary */
1312 if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1315 /* Now sw_if_index0 == sw_if_index1 */
1316 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1318 cached_sw_if_index = sw_if_index0;
1319 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1320 ei = ethernet_get_interface (em, hi->hw_if_index);
1321 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1322 subint0 = &intf0->untagged_subint;
1323 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1326 if (PREDICT_TRUE (is_l20 != 0))
1328 vnet_buffer (b0)->l3_hdr_offset =
1329 vnet_buffer (b0)->l2_hdr_offset +
1330 sizeof (ethernet_header_t);
1331 vnet_buffer (b1)->l3_hdr_offset =
1332 vnet_buffer (b1)->l2_hdr_offset +
1333 sizeof (ethernet_header_t);
1334 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1335 b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1336 next0 = em->l2_next;
1337 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1338 next1 = em->l2_next;
1339 vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1343 if (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1344 goto skip_dmac_check01;
1346 dmacs[0] = *(u64 *) e0;
1347 dmacs[1] = *(u64 *) e1;
1349 if (ei && vec_len (ei->secondary_addrs))
1350 ethernet_input_inline_dmac_check (hi, dmacs,
1354 1 /* have_sec_dmac */ );
1356 ethernet_input_inline_dmac_check (hi, dmacs,
1360 0 /* have_sec_dmac */ );
1363 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1365 error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1368 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1369 determine_next_node (em, variant, 0, type0, b0,
1371 vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1372 determine_next_node (em, variant, 0, type1, b1,
1378 /* Slow-path for the tagged case */
1380 parse_header (variant,
1383 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1385 parse_header (variant,
1388 &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1390 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1391 old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1393 eth_vlan_table_lookups (em,
1400 &main_intf0, &vlan_intf0, &qinq_intf0);
1402 eth_vlan_table_lookups (em,
1409 &main_intf1, &vlan_intf1, &qinq_intf1);
1411 identify_subint (em,
1417 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1419 identify_subint (em,
1425 qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1427 // Save RX sw_if_index for later nodes
1428 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1430 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1431 vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1433 ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1435 // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1436 if (((new_sw_if_index0 != ~0)
1437 && (new_sw_if_index0 != old_sw_if_index0))
1438 || ((new_sw_if_index1 != ~0)
1439 && (new_sw_if_index1 != old_sw_if_index1)))
1442 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1443 - vnet_buffer (b0)->l2_hdr_offset;
1444 len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1445 - vnet_buffer (b1)->l2_hdr_offset;
1447 stats_n_packets += 2;
1448 stats_n_bytes += len0 + len1;
1451 (!(new_sw_if_index0 == stats_sw_if_index
1452 && new_sw_if_index1 == stats_sw_if_index)))
1454 stats_n_packets -= 2;
1455 stats_n_bytes -= len0 + len1;
1457 if (new_sw_if_index0 != old_sw_if_index0
1458 && new_sw_if_index0 != ~0)
1459 vlib_increment_combined_counter (vnm->
1460 interface_main.combined_sw_if_counters
1462 VNET_INTERFACE_COUNTER_RX,
1464 new_sw_if_index0, 1,
1466 if (new_sw_if_index1 != old_sw_if_index1
1467 && new_sw_if_index1 != ~0)
1468 vlib_increment_combined_counter (vnm->
1469 interface_main.combined_sw_if_counters
1471 VNET_INTERFACE_COUNTER_RX,
1473 new_sw_if_index1, 1,
1476 if (new_sw_if_index0 == new_sw_if_index1)
1478 if (stats_n_packets > 0)
1480 vlib_increment_combined_counter
1481 (vnm->interface_main.combined_sw_if_counters
1482 + VNET_INTERFACE_COUNTER_RX,
1485 stats_n_packets, stats_n_bytes);
1486 stats_n_packets = stats_n_bytes = 0;
1488 stats_sw_if_index = new_sw_if_index0;
1493 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1494 is_l20 = is_l21 = 0;
1496 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1498 determine_next_node (em, variant, is_l21, type1, b1, &error1,
1502 b0->error = error_node->errors[error0];
1503 b1->error = error_node->errors[error1];
1505 // verify speculative enqueue
1506 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1507 n_left_to_next, bi0, bi1, next0,
1511 while (n_left_from > 0 && n_left_to_next > 0)
1516 u16 type0, orig_type0;
1517 u16 outer_id0, inner_id0;
1519 u32 old_sw_if_index0, new_sw_if_index0, len0;
1520 vnet_hw_interface_t *hi0;
1521 main_intf_t *main_intf0;
1522 vlan_intf_t *vlan_intf0;
1523 qinq_intf_t *qinq_intf0;
1524 ethernet_header_t *e0;
1529 // Prefetch next iteration
1530 if (n_left_from > 1)
1532 vlib_prefetch_buffer_header (b[1], STORE);
1533 CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1541 n_left_to_next -= 1;
1546 error0 = ETHERNET_ERROR_NONE;
1547 e0 = vlib_buffer_get_current (b0);
1548 type0 = clib_net_to_host_u16 (e0->type);
1550 /* Set the L2 header offset for all packets */
1551 vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1552 b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1554 /* Speed-path for the untagged case */
1555 if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1556 && !ethernet_frame_is_tagged (type0)))
1559 subint_config_t *subint0;
1562 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1563 is_l20 = cached_is_l2;
1565 if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1567 cached_sw_if_index = sw_if_index0;
1568 hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1569 ei = ethernet_get_interface (em, hi->hw_if_index);
1570 intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1571 subint0 = &intf0->untagged_subint;
1572 cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1576 if (PREDICT_TRUE (is_l20 != 0))
1578 vnet_buffer (b0)->l3_hdr_offset =
1579 vnet_buffer (b0)->l2_hdr_offset +
1580 sizeof (ethernet_header_t);
1581 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1582 next0 = em->l2_next;
1583 vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1587 if (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1588 goto skip_dmac_check0;
1590 dmacs[0] = *(u64 *) e0;
1592 if (ei && vec_len (ei->secondary_addrs))
1593 ethernet_input_inline_dmac_check (hi, dmacs,
1597 1 /* have_sec_dmac */ );
1599 ethernet_input_inline_dmac_check (hi, dmacs,
1603 0 /* have_sec_dmac */ );
1606 error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1609 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1610 determine_next_node (em, variant, 0, type0, b0,
1616 /* Slow-path for the tagged case */
1617 parse_header (variant,
1620 &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1622 old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1624 eth_vlan_table_lookups (em,
1631 &main_intf0, &vlan_intf0, &qinq_intf0);
1633 identify_subint (em,
1639 qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1641 // Save RX sw_if_index for later nodes
1642 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1644 ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1646 // Increment subinterface stats
1647 // Note that interface-level counters have already been incremented
1648 // prior to calling this function. Thus only subinterface counters
1649 // are incremented here.
1651 // Interface level counters include packets received on the main
1652 // interface and all subinterfaces. Subinterface level counters
1653 // include only those packets received on that subinterface
1654 // Increment stats if the subint is valid and it is not the main intf
1655 if ((new_sw_if_index0 != ~0)
1656 && (new_sw_if_index0 != old_sw_if_index0))
1659 len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1660 - vnet_buffer (b0)->l2_hdr_offset;
1662 stats_n_packets += 1;
1663 stats_n_bytes += len0;
1665 // Batch stat increments from the same subinterface so counters
1666 // don't need to be incremented for every packet.
1667 if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1669 stats_n_packets -= 1;
1670 stats_n_bytes -= len0;
1672 if (new_sw_if_index0 != ~0)
1673 vlib_increment_combined_counter
1674 (vnm->interface_main.combined_sw_if_counters
1675 + VNET_INTERFACE_COUNTER_RX,
1676 thread_index, new_sw_if_index0, 1, len0);
1677 if (stats_n_packets > 0)
1679 vlib_increment_combined_counter
1680 (vnm->interface_main.combined_sw_if_counters
1681 + VNET_INTERFACE_COUNTER_RX,
1683 stats_sw_if_index, stats_n_packets, stats_n_bytes);
1684 stats_n_packets = stats_n_bytes = 0;
1686 stats_sw_if_index = new_sw_if_index0;
1690 if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1693 determine_next_node (em, variant, is_l20, type0, b0, &error0,
1697 b0->error = error_node->errors[error0];
1699 // verify speculative enqueue
1700 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1701 to_next, n_left_to_next,
1705 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1708 // Increment any remaining batched stats
1709 if (stats_n_packets > 0)
1711 vlib_increment_combined_counter
1712 (vnm->interface_main.combined_sw_if_counters
1713 + VNET_INTERFACE_COUNTER_RX,
1714 thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1715 node->runtime_data[0] = stats_sw_if_index;
1719 VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
1720 vlib_node_runtime_t * node,
1721 vlib_frame_t * frame)
1723 vnet_main_t *vnm = vnet_get_main ();
1724 u32 *from = vlib_frame_vector_args (frame);
1725 u32 n_packets = frame->n_vectors;
1727 ethernet_input_trace (vm, node, frame);
1729 if (frame->flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
1731 ethernet_input_frame_t *ef = vlib_frame_scalar_args (frame);
1732 int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1733 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ef->hw_if_index);
1734 eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1737 ethernet_input_inline (vm, node, from, n_packets,
1738 ETHERNET_INPUT_VARIANT_ETHERNET);
1742 VLIB_NODE_FN (ethernet_input_type_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_ETHERNET_TYPE);
1754 VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
1755 vlib_node_runtime_t * node,
1756 vlib_frame_t * from_frame)
1758 u32 *from = vlib_frame_vector_args (from_frame);
1759 u32 n_packets = from_frame->n_vectors;
1760 ethernet_input_trace (vm, node, from_frame);
1761 ethernet_input_inline (vm, node, from, n_packets,
1762 ETHERNET_INPUT_VARIANT_NOT_L2);
1767 // Return the subinterface config struct for the given sw_if_index
1768 // Also return via parameter the appropriate match flags for the
1769 // configured number of tags.
1770 // On error (unsupported or not ethernet) return 0.
1771 static subint_config_t *
1772 ethernet_sw_interface_get_config (vnet_main_t * vnm,
1774 u32 * flags, u32 * unsupported)
1776 ethernet_main_t *em = ðernet_main;
1777 vnet_hw_interface_t *hi;
1778 vnet_sw_interface_t *si;
1779 main_intf_t *main_intf;
1780 vlan_table_t *vlan_table;
1781 qinq_table_t *qinq_table;
1782 subint_config_t *subint = 0;
1784 hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1786 if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1789 goto done; // non-ethernet interface
1792 // ensure there's an entry for the main intf (shouldn't really be necessary)
1793 vec_validate (em->main_intfs, hi->hw_if_index);
1794 main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1796 // Locate the subint for the given ethernet config
1797 si = vnet_get_sw_interface (vnm, sw_if_index);
1799 if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1801 p2p_ethernet_main_t *p2pm = &p2p_main;
1802 u32 p2pe_sw_if_index =
1803 p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
1804 if (p2pe_sw_if_index == ~0)
1806 pool_get (p2pm->p2p_subif_pool, subint);
1807 si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1810 subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1811 *flags = SUBINT_CONFIG_P2P;
1813 else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1817 pipe = pipe_get (sw_if_index);
1818 subint = &pipe->subint;
1819 *flags = SUBINT_CONFIG_P2P;
1821 else if (si->sub.eth.flags.default_sub)
1823 subint = &main_intf->default_subint;
1824 *flags = SUBINT_CONFIG_MATCH_1_TAG |
1825 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1827 else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1829 // if no flags are set then this is a main interface
1830 // so treat as untagged
1831 subint = &main_intf->untagged_subint;
1832 *flags = SUBINT_CONFIG_MATCH_0_TAG;
1837 // first get the vlan table
1838 if (si->sub.eth.flags.dot1ad)
1840 if (main_intf->dot1ad_vlans == 0)
1842 // Allocate a vlan table from the pool
1843 pool_get (em->vlan_pool, vlan_table);
1844 main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1848 // Get ptr to existing vlan table
1850 vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1855 if (main_intf->dot1q_vlans == 0)
1857 // Allocate a vlan table from the pool
1858 pool_get (em->vlan_pool, vlan_table);
1859 main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1863 // Get ptr to existing vlan table
1865 vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1869 if (si->sub.eth.flags.one_tag)
1871 *flags = si->sub.eth.flags.exact_match ?
1872 SUBINT_CONFIG_MATCH_1_TAG :
1873 (SUBINT_CONFIG_MATCH_1_TAG |
1874 SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1876 if (si->sub.eth.flags.outer_vlan_id_any)
1878 // not implemented yet
1884 // a single vlan, a common case
1886 &vlan_table->vlans[si->sub.eth.
1887 outer_vlan_id].single_tag_subint;
1894 *flags = si->sub.eth.flags.exact_match ?
1895 SUBINT_CONFIG_MATCH_2_TAG :
1896 (SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1898 if (si->sub.eth.flags.outer_vlan_id_any
1899 && si->sub.eth.flags.inner_vlan_id_any)
1901 // not implemented yet
1906 if (si->sub.eth.flags.inner_vlan_id_any)
1908 // a specific outer and "any" inner
1909 // don't need a qinq table for this
1911 &vlan_table->vlans[si->sub.eth.
1912 outer_vlan_id].inner_any_subint;
1913 if (si->sub.eth.flags.exact_match)
1915 *flags = SUBINT_CONFIG_MATCH_2_TAG;
1919 *flags = SUBINT_CONFIG_MATCH_2_TAG |
1920 SUBINT_CONFIG_MATCH_3_TAG;
1925 // a specific outer + specifc innner vlan id, a common case
1927 // get the qinq table
1928 if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1930 // Allocate a qinq table from the pool
1931 pool_get (em->qinq_pool, qinq_table);
1932 vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1933 qinq_table - em->qinq_pool;
1937 // Get ptr to existing qinq table
1939 vec_elt_at_index (em->qinq_pool,
1940 vlan_table->vlans[si->sub.
1944 subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1953 static clib_error_t *
1954 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
1956 subint_config_t *subint;
1957 u32 placeholder_flags;
1958 u32 placeholder_unsup;
1959 clib_error_t *error = 0;
1961 // Find the config for this subinterface
1963 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1964 &placeholder_unsup);
1968 // not implemented yet or not ethernet
1972 subint->sw_if_index =
1973 ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1979 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
1982 #ifndef CLIB_MARCH_VARIANT
1983 // Set the L2/L3 mode for the subinterface
1985 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
1987 subint_config_t *subint;
1988 u32 placeholder_flags;
1989 u32 placeholder_unsup;
1991 vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1993 is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1995 // Find the config for this subinterface
1997 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1998 &placeholder_unsup);
2002 // unimplemented or not ethernet
2006 // Double check that the config we found is for our interface (or the interface is down)
2007 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2011 subint->flags |= SUBINT_CONFIG_L2;
2014 SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
2015 | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
2019 subint->flags &= ~SUBINT_CONFIG_L2;
2022 ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
2023 | SUBINT_CONFIG_MATCH_3_TAG);
2031 * Set the L2/L3 mode for the subinterface regardless of port
2034 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
2035 u32 sw_if_index, u32 l2)
2037 subint_config_t *subint;
2038 u32 placeholder_flags;
2039 u32 placeholder_unsup;
2041 /* Find the config for this subinterface */
2043 ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
2044 &placeholder_unsup);
2048 /* unimplemented or not ethernet */
2053 * Double check that the config we found is for our interface (or the
2054 * interface is down)
2056 ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2060 subint->flags |= SUBINT_CONFIG_L2;
2064 subint->flags &= ~SUBINT_CONFIG_L2;
2072 static clib_error_t *
2073 ethernet_sw_interface_add_del (vnet_main_t * vnm,
2074 u32 sw_if_index, u32 is_create)
2076 clib_error_t *error = 0;
2077 subint_config_t *subint;
2079 u32 unsupported = 0;
2081 // Find the config for this subinterface
2083 ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2088 // not implemented yet or not ethernet
2091 // this is the NYI case
2092 error = clib_error_return (0, "not implemented yet");
2103 // Initialize the subint
2104 if (subint->flags & SUBINT_CONFIG_VALID)
2106 // Error vlan already in use
2107 error = clib_error_return (0, "vlan is already in use");
2111 // Note that config is L3 by default
2112 subint->flags = SUBINT_CONFIG_VALID | match_flags;
2113 subint->sw_if_index = ~0; // because interfaces are initially down
2120 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
2122 static char *ethernet_error_strings[] = {
2123 #define ethernet_error(n,c,s) s,
2124 #include "error.def"
2125 #undef ethernet_error
2129 VLIB_REGISTER_NODE (ethernet_input_node) = {
2130 .name = "ethernet-input",
2131 /* Takes a vector of packets. */
2132 .vector_size = sizeof (u32),
2133 .scalar_size = sizeof (ethernet_input_frame_t),
2134 .n_errors = ETHERNET_N_ERROR,
2135 .error_strings = ethernet_error_strings,
2136 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2138 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2139 foreach_ethernet_input_next
2142 .format_buffer = format_ethernet_header_with_length,
2143 .format_trace = format_ethernet_input_trace,
2144 .unformat_buffer = unformat_ethernet_header,
2147 VLIB_REGISTER_NODE (ethernet_input_type_node) = {
2148 .name = "ethernet-input-type",
2149 /* Takes a vector of packets. */
2150 .vector_size = sizeof (u32),
2151 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2153 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2154 foreach_ethernet_input_next
2159 VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
2160 .name = "ethernet-input-not-l2",
2161 /* Takes a vector of packets. */
2162 .vector_size = sizeof (u32),
2163 .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2165 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2166 foreach_ethernet_input_next
2172 #ifndef CLIB_MARCH_VARIANT
2174 ethernet_set_rx_redirect (vnet_main_t * vnm,
2175 vnet_hw_interface_t * hi, u32 enable)
2177 // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2178 // don't go directly to ip4-input)
2179 vnet_hw_interface_rx_redirect_to_node
2180 (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2185 * Initialization and registration for the next_by_ethernet structure
2189 next_by_ethertype_init (next_by_ethertype_t * l3_next)
2191 l3_next->input_next_by_type = sparse_vec_new
2192 ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2193 /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2195 vec_validate (l3_next->sparse_index_by_input_next_index,
2196 ETHERNET_INPUT_NEXT_DROP);
2197 vec_validate (l3_next->sparse_index_by_input_next_index,
2198 ETHERNET_INPUT_NEXT_PUNT);
2199 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2200 SPARSE_VEC_INVALID_INDEX;
2201 l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2202 SPARSE_VEC_INVALID_INDEX;
2205 * Make sure we don't wipe out an ethernet registration by mistake
2206 * Can happen if init function ordering constraints are missing.
2210 ethernet_main_t *em = ðernet_main;
2211 ASSERT (em->next_by_ethertype_register_called == 0);
2217 // Add an ethertype -> next index mapping to the structure
2219 next_by_ethertype_register (next_by_ethertype_t * l3_next,
2220 u32 ethertype, u32 next_index)
2224 ethernet_main_t *em = ðernet_main;
2228 ethernet_main_t *em = ðernet_main;
2229 em->next_by_ethertype_register_called = 1;
2232 /* Setup ethernet type -> next index sparse vector mapping. */
2233 n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2236 /* Rebuild next index -> sparse index inverse mapping when sparse vector
2238 vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2239 for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2241 sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2243 // do not allow the cached next index's to be updated if L3
2244 // redirect is enabled, as it will have overwritten them
2245 if (!em->redirect_l3)
2247 // Cache common ethertypes directly
2248 if (ethertype == ETHERNET_TYPE_IP4)
2250 l3_next->input_next_ip4 = next_index;
2252 else if (ethertype == ETHERNET_TYPE_IP6)
2254 l3_next->input_next_ip6 = next_index;
2256 else if (ethertype == ETHERNET_TYPE_MPLS)
2258 l3_next->input_next_mpls = next_index;
2265 ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
2267 __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2268 __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2270 ethernet_setup_node (vm, ethernet_input_node.index);
2271 ethernet_setup_node (vm, ethernet_input_type_node.index);
2272 ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
2274 next_by_ethertype_init (&em->l3_next);
2276 // Initialize pools and vector for vlan parsing
2277 vec_validate (em->main_intfs, 10); // 10 main interfaces
2278 pool_alloc (em->vlan_pool, 10);
2279 pool_alloc (em->qinq_pool, 1);
2281 // The first vlan pool will always be reserved for an invalid table
2282 pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2283 // The first qinq pool will always be reserved for an invalid table
2284 pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2288 ethernet_register_input_type (vlib_main_t * vm,
2289 ethernet_type_t type, u32 node_index)
2291 ethernet_main_t *em = ðernet_main;
2292 ethernet_type_info_t *ti;
2296 clib_error_t *error = vlib_call_init_function (vm, ethernet_init);
2298 clib_error_report (error);
2301 ti = ethernet_get_type_info (em, type);
2304 clib_warning ("type_info NULL for type %d", type);
2307 ti->node_index = node_index;
2308 ti->next_index = vlib_node_add_next (vm,
2309 ethernet_input_node.index, node_index);
2310 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2311 ASSERT (i == ti->next_index);
2313 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2314 ASSERT (i == ti->next_index);
2316 // Add the L3 node for this ethertype to the next nodes structure
2317 next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2319 // Call the registration functions for other nodes that want a mapping
2320 l2bvi_register_input_type (vm, type, node_index);
2324 ethernet_register_l2_input (vlib_main_t * vm, u32 node_index)
2326 ethernet_main_t *em = ðernet_main;
2330 vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2333 * Even if we never use these arcs, we have to align the next indices...
2335 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2337 ASSERT (i == em->l2_next);
2339 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2340 ASSERT (i == em->l2_next);
2343 // Register a next node for L3 redirect, and enable L3 redirect
2345 ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
2347 ethernet_main_t *em = ðernet_main;
2350 em->redirect_l3 = 1;
2351 em->redirect_l3_next = vlib_node_add_next (vm,
2352 ethernet_input_node.index,
2355 * Change the cached next nodes to the redirect node
2357 em->l3_next.input_next_ip4 = em->redirect_l3_next;
2358 em->l3_next.input_next_ip6 = em->redirect_l3_next;
2359 em->l3_next.input_next_mpls = em->redirect_l3_next;
2362 * Even if we never use these arcs, we have to align the next indices...
2364 i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2366 ASSERT (i == em->redirect_l3_next);
2368 i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2370 ASSERT (i == em->redirect_l3_next);
2375 * fd.io coding-style-patch-verification: ON
2378 * eval: (c-set-style "gnu")