interface: fix issue that pcap rx/tx trace not available when there are worker threads
[vpp.git] / src / vnet / ethernet / node.c
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * ethernet_node.c: ethernet packet processing
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39
40 #include <vlib/vlib.h>
41 #include <vnet/pg/pg.h>
42 #include <vnet/ethernet/ethernet.h>
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
48 #define foreach_ethernet_input_next             \
49   _ (PUNT, "error-punt")                        \
50   _ (DROP, "error-drop")                        \
51   _ (LLC, "llc-input")                          \
52   _ (IP4_INPUT, "ip4-input")                    \
53   _ (IP4_INPUT_NCS, "ip4-input-no-checksum")
54
55 typedef enum
56 {
57 #define _(s,n) ETHERNET_INPUT_NEXT_##s,
58   foreach_ethernet_input_next
59 #undef _
60     ETHERNET_INPUT_N_NEXT,
61 } ethernet_input_next_t;
62
63 typedef struct
64 {
65   u8 packet_data[32];
66   u16 frame_flags;
67   ethernet_input_frame_t frame_data;
68 } ethernet_input_trace_t;
69
70 static u8 *
71 format_ethernet_input_trace (u8 * s, va_list * va)
72 {
73   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
74   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
75   ethernet_input_trace_t *t = va_arg (*va, ethernet_input_trace_t *);
76   u32 indent = format_get_indent (s);
77
78   if (t->frame_flags)
79     {
80       s = format (s, "frame: flags 0x%x", t->frame_flags);
81       if (t->frame_flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
82         s = format (s, ", hw-if-index %u, sw-if-index %u",
83                     t->frame_data.hw_if_index, t->frame_data.sw_if_index);
84       s = format (s, "\n%U", format_white_space, indent);
85     }
86   s = format (s, "%U", format_ethernet_header, t->packet_data);
87
88   return s;
89 }
90
91 extern vlib_node_registration_t ethernet_input_node;
92
93 typedef enum
94 {
95   ETHERNET_INPUT_VARIANT_ETHERNET,
96   ETHERNET_INPUT_VARIANT_ETHERNET_TYPE,
97   ETHERNET_INPUT_VARIANT_NOT_L2,
98 } ethernet_input_variant_t;
99
100
101 // Parse the ethernet header to extract vlan tags and innermost ethertype
102 static_always_inline void
103 parse_header (ethernet_input_variant_t variant,
104               vlib_buffer_t * b0,
105               u16 * type,
106               u16 * orig_type,
107               u16 * outer_id, u16 * inner_id, u32 * match_flags)
108 {
109   u8 vlan_count;
110
111   if (variant == ETHERNET_INPUT_VARIANT_ETHERNET
112       || variant == ETHERNET_INPUT_VARIANT_NOT_L2)
113     {
114       ethernet_header_t *e0;
115
116       e0 = (void *) (b0->data + b0->current_data);
117
118       vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
119       b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
120
121       vlib_buffer_advance (b0, sizeof (e0[0]));
122
123       *type = clib_net_to_host_u16 (e0->type);
124     }
125   else if (variant == ETHERNET_INPUT_VARIANT_ETHERNET_TYPE)
126     {
127       // here when prior node was LLC/SNAP processing
128       u16 *e0;
129
130       e0 = (void *) (b0->data + b0->current_data);
131
132       vlib_buffer_advance (b0, sizeof (e0[0]));
133
134       *type = clib_net_to_host_u16 (e0[0]);
135     }
136
137   // save for distinguishing between dot1q and dot1ad later
138   *orig_type = *type;
139
140   // default the tags to 0 (used if there is no corresponding tag)
141   *outer_id = 0;
142   *inner_id = 0;
143
144   *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_0_TAG;
145   vlan_count = 0;
146
147   // check for vlan encaps
148   if (ethernet_frame_is_tagged (*type))
149     {
150       ethernet_vlan_header_t *h0;
151       u16 tag;
152
153       *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_1_TAG;
154
155       h0 = (void *) (b0->data + b0->current_data);
156
157       tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
158
159       *outer_id = tag & 0xfff;
160       if (0 == *outer_id)
161         *match_flags &= ~SUBINT_CONFIG_MATCH_1_TAG;
162
163       *type = clib_net_to_host_u16 (h0->type);
164
165       vlib_buffer_advance (b0, sizeof (h0[0]));
166       vlan_count = 1;
167
168       if (*type == ETHERNET_TYPE_VLAN)
169         {
170           // Double tagged packet
171           *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_2_TAG;
172
173           h0 = (void *) (b0->data + b0->current_data);
174
175           tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
176
177           *inner_id = tag & 0xfff;
178
179           *type = clib_net_to_host_u16 (h0->type);
180
181           vlib_buffer_advance (b0, sizeof (h0[0]));
182           vlan_count = 2;
183           if (*type == ETHERNET_TYPE_VLAN)
184             {
185               // More than double tagged packet
186               *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_3_TAG;
187
188               vlib_buffer_advance (b0, sizeof (h0[0]));
189               vlan_count = 3;   // "unknown" number, aka, 3-or-more
190             }
191         }
192     }
193   ethernet_buffer_set_vlan_count (b0, vlan_count);
194 }
195
196 // Determine the subinterface for this packet, given the result of the
197 // vlan table lookups and vlan header parsing. Check the most specific
198 // matches first.
199 static_always_inline void
200 identify_subint (vnet_hw_interface_t * hi,
201                  vlib_buffer_t * b0,
202                  u32 match_flags,
203                  main_intf_t * main_intf,
204                  vlan_intf_t * vlan_intf,
205                  qinq_intf_t * qinq_intf,
206                  u32 * new_sw_if_index, u8 * error0, u32 * is_l2)
207 {
208   u32 matched;
209
210   matched = eth_identify_subint (hi, match_flags, main_intf, vlan_intf,
211                                  qinq_intf, new_sw_if_index, error0, is_l2);
212
213   if (matched)
214     {
215
216       // Perform L3 my-mac filter
217       // A unicast packet arriving on an L3 interface must have a dmac matching the interface mac.
218       // This is required for promiscuous mode, else we will forward packets we aren't supposed to.
219       if (!(*is_l2))
220         {
221           ethernet_header_t *e0;
222           e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
223
224           if (!(ethernet_address_cast (e0->dst_address)))
225             {
226               if (!ethernet_mac_address_equal ((u8 *) e0, hi->hw_address))
227                 {
228                   *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
229                 }
230             }
231         }
232
233       // Check for down subinterface
234       *error0 = (*new_sw_if_index) != ~0 ? (*error0) : ETHERNET_ERROR_DOWN;
235     }
236 }
237
238 static_always_inline void
239 determine_next_node (ethernet_main_t * em,
240                      ethernet_input_variant_t variant,
241                      u32 is_l20,
242                      u32 type0, vlib_buffer_t * b0, u8 * error0, u8 * next0)
243 {
244   vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
245   b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
246
247   if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE))
248     {
249       // some error occurred
250       *next0 = ETHERNET_INPUT_NEXT_DROP;
251     }
252   else if (is_l20)
253     {
254       // record the L2 len and reset the buffer so the L2 header is preserved
255       u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
256       vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
257       *next0 = em->l2_next;
258       ASSERT (vnet_buffer (b0)->l2.l2_len ==
259               ethernet_buffer_header_size (b0));
260       vlib_buffer_advance (b0, -(vnet_buffer (b0)->l2.l2_len));
261
262       // check for common IP/MPLS ethertypes
263     }
264   else if (type0 == ETHERNET_TYPE_IP4)
265     {
266       *next0 = em->l3_next.input_next_ip4;
267     }
268   else if (type0 == ETHERNET_TYPE_IP6)
269     {
270       *next0 = em->l3_next.input_next_ip6;
271     }
272   else if (type0 == ETHERNET_TYPE_MPLS)
273     {
274       *next0 = em->l3_next.input_next_mpls;
275
276     }
277   else if (em->redirect_l3)
278     {
279       // L3 Redirect is on, the cached common next nodes will be
280       // pointing to the redirect node, catch the uncommon types here
281       *next0 = em->redirect_l3_next;
282     }
283   else
284     {
285       // uncommon ethertype, check table
286       u32 i0;
287       i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
288       *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
289       *error0 =
290         i0 ==
291         SPARSE_VEC_INVALID_INDEX ? ETHERNET_ERROR_UNKNOWN_TYPE : *error0;
292
293       // The table is not populated with LLC values, so check that now.
294       // If variant is variant_ethernet then we came from LLC processing. Don't
295       // go back there; drop instead using by keeping the drop/bad table result.
296       if ((type0 < 0x600) && (variant == ETHERNET_INPUT_VARIANT_ETHERNET))
297         {
298           *next0 = ETHERNET_INPUT_NEXT_LLC;
299         }
300     }
301 }
302
303
304 /* following vector code relies on following assumptions */
305 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_data, 0);
306 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, current_length, 2);
307 STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, flags, 4);
308 STATIC_ASSERT (STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l2_hdr_offset) ==
309                STRUCT_OFFSET_OF (vnet_buffer_opaque_t, l3_hdr_offset) - 2,
310                "l3_hdr_offset must follow l2_hdr_offset");
311
312 static_always_inline void
313 eth_input_adv_and_flags_x4 (vlib_buffer_t ** b, int is_l3)
314 {
315   i16 adv = sizeof (ethernet_header_t);
316   u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
317     VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
318
319 #ifdef CLIB_HAVE_VEC256
320   /* to reduce number of small loads/stores we are loading first 64 bits
321      of each buffer metadata into 256-bit register so we can advance
322      current_data, current_length and flags.
323      Observed saving of this code is ~2 clocks per packet */
324   u64x4 r, radv;
325
326   /* vector if signed 16 bit integers used in signed vector add operation
327      to advnce current_data and current_length */
328   u32x8 flags4 = { 0, flags, 0, flags, 0, flags, 0, flags };
329   i16x16 adv4 = {
330     adv, -adv, 0, 0, adv, -adv, 0, 0,
331     adv, -adv, 0, 0, adv, -adv, 0, 0
332   };
333
334   /* load 4 x 64 bits */
335   r = u64x4_gather (b[0], b[1], b[2], b[3]);
336
337   /* set flags */
338   r |= (u64x4) flags4;
339
340   /* advance buffer */
341   radv = (u64x4) ((i16x16) r + adv4);
342
343   /* write 4 x 64 bits */
344   u64x4_scatter (is_l3 ? radv : r, b[0], b[1], b[2], b[3]);
345
346   /* use old current_data as l2_hdr_offset and new current_data as
347      l3_hdr_offset */
348   r = (u64x4) u16x16_blend (r, radv << 16, 0xaa);
349
350   /* store both l2_hdr_offset and l3_hdr_offset in single store operation */
351   u32x8_scatter_one ((u32x8) r, 0, &vnet_buffer (b[0])->l2_hdr_offset);
352   u32x8_scatter_one ((u32x8) r, 2, &vnet_buffer (b[1])->l2_hdr_offset);
353   u32x8_scatter_one ((u32x8) r, 4, &vnet_buffer (b[2])->l2_hdr_offset);
354   u32x8_scatter_one ((u32x8) r, 6, &vnet_buffer (b[3])->l2_hdr_offset);
355
356   if (is_l3)
357     {
358       ASSERT (b[0]->current_data == vnet_buffer (b[0])->l3_hdr_offset);
359       ASSERT (b[1]->current_data == vnet_buffer (b[1])->l3_hdr_offset);
360       ASSERT (b[2]->current_data == vnet_buffer (b[2])->l3_hdr_offset);
361       ASSERT (b[3]->current_data == vnet_buffer (b[3])->l3_hdr_offset);
362
363       ASSERT (b[0]->current_data - vnet_buffer (b[0])->l2_hdr_offset == adv);
364       ASSERT (b[1]->current_data - vnet_buffer (b[1])->l2_hdr_offset == adv);
365       ASSERT (b[2]->current_data - vnet_buffer (b[2])->l2_hdr_offset == adv);
366       ASSERT (b[3]->current_data - vnet_buffer (b[3])->l2_hdr_offset == adv);
367     }
368   else
369     {
370       ASSERT (b[0]->current_data == vnet_buffer (b[0])->l2_hdr_offset);
371       ASSERT (b[1]->current_data == vnet_buffer (b[1])->l2_hdr_offset);
372       ASSERT (b[2]->current_data == vnet_buffer (b[2])->l2_hdr_offset);
373       ASSERT (b[3]->current_data == vnet_buffer (b[3])->l2_hdr_offset);
374
375       ASSERT (b[0]->current_data - vnet_buffer (b[0])->l3_hdr_offset == -adv);
376       ASSERT (b[1]->current_data - vnet_buffer (b[1])->l3_hdr_offset == -adv);
377       ASSERT (b[2]->current_data - vnet_buffer (b[2])->l3_hdr_offset == -adv);
378       ASSERT (b[3]->current_data - vnet_buffer (b[3])->l3_hdr_offset == -adv);
379     }
380
381 #else
382   vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
383   vnet_buffer (b[1])->l2_hdr_offset = b[1]->current_data;
384   vnet_buffer (b[2])->l2_hdr_offset = b[2]->current_data;
385   vnet_buffer (b[3])->l2_hdr_offset = b[3]->current_data;
386   vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
387   vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data + adv;
388   vnet_buffer (b[2])->l3_hdr_offset = b[2]->current_data + adv;
389   vnet_buffer (b[3])->l3_hdr_offset = b[3]->current_data + adv;
390
391   if (is_l3)
392     {
393       vlib_buffer_advance (b[0], adv);
394       vlib_buffer_advance (b[1], adv);
395       vlib_buffer_advance (b[2], adv);
396       vlib_buffer_advance (b[3], adv);
397     }
398
399   b[0]->flags |= flags;
400   b[1]->flags |= flags;
401   b[2]->flags |= flags;
402   b[3]->flags |= flags;
403 #endif
404
405   if (!is_l3)
406     {
407       vnet_buffer (b[0])->l2.l2_len = adv;
408       vnet_buffer (b[1])->l2.l2_len = adv;
409       vnet_buffer (b[2])->l2.l2_len = adv;
410       vnet_buffer (b[3])->l2.l2_len = adv;
411     }
412 }
413
414 static_always_inline void
415 eth_input_adv_and_flags_x1 (vlib_buffer_t ** b, int is_l3)
416 {
417   i16 adv = sizeof (ethernet_header_t);
418   u32 flags = VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
419     VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
420
421   vnet_buffer (b[0])->l2_hdr_offset = b[0]->current_data;
422   vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data + adv;
423
424   if (is_l3)
425     vlib_buffer_advance (b[0], adv);
426   b[0]->flags |= flags;
427   if (!is_l3)
428     vnet_buffer (b[0])->l2.l2_len = adv;
429 }
430
431
432 static_always_inline void
433 eth_input_get_etype_and_tags (vlib_buffer_t ** b, u16 * etype, u64 * tags,
434                               u64 * dmacs, int offset, int dmac_check)
435 {
436   ethernet_header_t *e;
437   e = vlib_buffer_get_current (b[offset]);
438 #ifdef CLIB_HAVE_VEC128
439   u64x2 r = u64x2_load_unaligned (((u8 *) & e->type) - 6);
440   etype[offset] = ((u16x8) r)[3];
441   tags[offset] = r[1];
442 #else
443   etype[offset] = e->type;
444   tags[offset] = *(u64 *) (e + 1);
445 #endif
446
447   if (dmac_check)
448     dmacs[offset] = *(u64 *) e;
449 }
450
451 static_always_inline u16
452 eth_input_next_by_type (u16 etype)
453 {
454   ethernet_main_t *em = &ethernet_main;
455
456   return (etype < 0x600) ? ETHERNET_INPUT_NEXT_LLC :
457     vec_elt (em->l3_next.input_next_by_type,
458              sparse_vec_index (em->l3_next.input_next_by_type, etype));
459 }
460
461 typedef struct
462 {
463   u64 tag, mask;
464   u32 sw_if_index;
465   u16 type, len, next;
466   i16 adv;
467   u8 err, n_tags;
468   u64 n_packets, n_bytes;
469 } eth_input_tag_lookup_t;
470
471 static_always_inline void
472 eth_input_update_if_counters (vlib_main_t * vm, vnet_main_t * vnm,
473                               eth_input_tag_lookup_t * l)
474 {
475   if (l->n_packets == 0 || l->sw_if_index == ~0)
476     return;
477
478   if (l->adv > 0)
479     l->n_bytes += l->n_packets * l->len;
480
481   vlib_increment_combined_counter
482     (vnm->interface_main.combined_sw_if_counters +
483      VNET_INTERFACE_COUNTER_RX, vm->thread_index, l->sw_if_index,
484      l->n_packets, l->n_bytes);
485 }
486
487 static_always_inline void
488 eth_input_tag_lookup (vlib_main_t * vm, vnet_main_t * vnm,
489                       vlib_node_runtime_t * node, vnet_hw_interface_t * hi,
490                       u64 tag, u16 * next, vlib_buffer_t * b,
491                       eth_input_tag_lookup_t * l, u8 dmac_bad, int is_dot1ad,
492                       int main_is_l3, int check_dmac)
493 {
494   ethernet_main_t *em = &ethernet_main;
495
496   if ((tag ^ l->tag) & l->mask)
497     {
498       main_intf_t *mif = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
499       vlan_intf_t *vif;
500       qinq_intf_t *qif;
501       vlan_table_t *vlan_table;
502       qinq_table_t *qinq_table;
503       u16 *t = (u16 *) & tag;
504       u16 vlan1 = clib_net_to_host_u16 (t[0]) & 0xFFF;
505       u16 vlan2 = clib_net_to_host_u16 (t[2]) & 0xFFF;
506       u32 matched, is_l2, new_sw_if_index;
507
508       vlan_table = vec_elt_at_index (em->vlan_pool, is_dot1ad ?
509                                      mif->dot1ad_vlans : mif->dot1q_vlans);
510       vif = &vlan_table->vlans[vlan1];
511       qinq_table = vec_elt_at_index (em->qinq_pool, vif->qinqs);
512       qif = &qinq_table->vlans[vlan2];
513       l->err = ETHERNET_ERROR_NONE;
514       l->type = clib_net_to_host_u16 (t[1]);
515
516       if (l->type == ETHERNET_TYPE_VLAN)
517         {
518           l->type = clib_net_to_host_u16 (t[3]);
519           l->n_tags = 2;
520           matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
521                                          SUBINT_CONFIG_MATCH_2_TAG, mif, vif,
522                                          qif, &new_sw_if_index, &l->err,
523                                          &is_l2);
524         }
525       else
526         {
527           l->n_tags = 1;
528           if (vlan1 == 0)
529             {
530               new_sw_if_index = hi->sw_if_index;
531               l->err = ETHERNET_ERROR_NONE;
532               matched = 1;
533               is_l2 = main_is_l3 == 0;
534             }
535           else
536             matched = eth_identify_subint (hi, SUBINT_CONFIG_VALID |
537                                            SUBINT_CONFIG_MATCH_1_TAG, mif,
538                                            vif, qif, &new_sw_if_index,
539                                            &l->err, &is_l2);
540         }
541
542       if (l->sw_if_index != new_sw_if_index)
543         {
544           eth_input_update_if_counters (vm, vnm, l);
545           l->n_packets = 0;
546           l->n_bytes = 0;
547           l->sw_if_index = new_sw_if_index;
548         }
549       l->tag = tag;
550       l->mask = (l->n_tags == 2) ?
551         clib_net_to_host_u64 (0xffffffffffffffff) :
552         clib_net_to_host_u64 (0xffffffff00000000);
553
554       if (matched && l->sw_if_index == ~0)
555         l->err = ETHERNET_ERROR_DOWN;
556
557       l->len = sizeof (ethernet_header_t) +
558         l->n_tags * sizeof (ethernet_vlan_header_t);
559       if (main_is_l3)
560         l->adv = is_l2 ? -(int) sizeof (ethernet_header_t) :
561           l->n_tags * sizeof (ethernet_vlan_header_t);
562       else
563         l->adv = is_l2 ? 0 : l->len;
564
565       if (PREDICT_FALSE (l->err != ETHERNET_ERROR_NONE))
566         l->next = ETHERNET_INPUT_NEXT_DROP;
567       else if (is_l2)
568         l->next = em->l2_next;
569       else if (l->type == ETHERNET_TYPE_IP4)
570         l->next = em->l3_next.input_next_ip4;
571       else if (l->type == ETHERNET_TYPE_IP6)
572         l->next = em->l3_next.input_next_ip6;
573       else if (l->type == ETHERNET_TYPE_MPLS)
574         l->next = em->l3_next.input_next_mpls;
575       else if (em->redirect_l3)
576         l->next = em->redirect_l3_next;
577       else
578         {
579           l->next = eth_input_next_by_type (l->type);
580           if (l->next == ETHERNET_INPUT_NEXT_PUNT)
581             l->err = ETHERNET_ERROR_UNKNOWN_TYPE;
582         }
583     }
584
585   if (check_dmac && l->adv > 0 && dmac_bad)
586     {
587       l->err = ETHERNET_ERROR_L3_MAC_MISMATCH;
588       next[0] = ETHERNET_INPUT_NEXT_PUNT;
589     }
590   else
591     next[0] = l->next;
592
593   vlib_buffer_advance (b, l->adv);
594   vnet_buffer (b)->l2.l2_len = l->len;
595   vnet_buffer (b)->l3_hdr_offset = vnet_buffer (b)->l2_hdr_offset + l->len;
596
597   if (l->err == ETHERNET_ERROR_NONE)
598     {
599       vnet_buffer (b)->sw_if_index[VLIB_RX] = l->sw_if_index;
600       ethernet_buffer_set_vlan_count (b, l->n_tags);
601     }
602   else
603     b->error = node->errors[l->err];
604
605   /* update counters */
606   l->n_packets += 1;
607   l->n_bytes += vlib_buffer_length_in_chain (vm, b);
608 }
609
610 /* process frame of buffers, store ethertype into array and update
611    buffer metadata fields depending on interface being l2 or l3 assuming that
612    packets are untagged. For tagged packets those fields are updated later.
613    Optionally store Destionation MAC address and tag data into arrays
614    for further processing */
615
616 STATIC_ASSERT (VLIB_FRAME_SIZE % 8 == 0,
617                "VLIB_FRAME_SIZE must be power of 8");
618 static_always_inline void
619 eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
620                          vnet_hw_interface_t * hi,
621                          u32 * buffer_indices, u32 n_packets, int main_is_l3,
622                          int ip4_cksum_ok, int dmac_check)
623 {
624   ethernet_main_t *em = &ethernet_main;
625   u16 nexts[VLIB_FRAME_SIZE], *next;
626   u16 etypes[VLIB_FRAME_SIZE], *etype = etypes;
627   u64 dmacs[VLIB_FRAME_SIZE], *dmac = dmacs;
628   u8 dmacs_bad[VLIB_FRAME_SIZE];
629   u64 tags[VLIB_FRAME_SIZE], *tag = tags;
630   u16 slowpath_indices[VLIB_FRAME_SIZE];
631   u16 n_slowpath, i;
632   u16 next_ip4, next_ip6, next_mpls, next_l2;
633   u16 et_ip4 = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
634   u16 et_ip6 = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
635   u16 et_mpls = clib_host_to_net_u16 (ETHERNET_TYPE_MPLS);
636   u16 et_vlan = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
637   u16 et_dot1ad = clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD);
638   i32 n_left = n_packets;
639   vlib_buffer_t *b[20];
640   u32 *from;
641
642   from = buffer_indices;
643
644   while (n_left >= 20)
645     {
646       vlib_buffer_t **ph = b + 16, **pd = b + 8;
647       vlib_get_buffers (vm, from, b, 4);
648       vlib_get_buffers (vm, from + 8, pd, 4);
649       vlib_get_buffers (vm, from + 16, ph, 4);
650
651       vlib_prefetch_buffer_header (ph[0], LOAD);
652       vlib_prefetch_buffer_data (pd[0], LOAD);
653       eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
654
655       vlib_prefetch_buffer_header (ph[1], LOAD);
656       vlib_prefetch_buffer_data (pd[1], LOAD);
657       eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
658
659       vlib_prefetch_buffer_header (ph[2], LOAD);
660       vlib_prefetch_buffer_data (pd[2], LOAD);
661       eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
662
663       vlib_prefetch_buffer_header (ph[3], LOAD);
664       vlib_prefetch_buffer_data (pd[3], LOAD);
665       eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
666
667       eth_input_adv_and_flags_x4 (b, main_is_l3);
668
669       /* next */
670       n_left -= 4;
671       etype += 4;
672       tag += 4;
673       dmac += 4;
674       from += 4;
675     }
676   while (n_left >= 4)
677     {
678       vlib_get_buffers (vm, from, b, 4);
679       eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
680       eth_input_get_etype_and_tags (b, etype, tag, dmac, 1, dmac_check);
681       eth_input_get_etype_and_tags (b, etype, tag, dmac, 2, dmac_check);
682       eth_input_get_etype_and_tags (b, etype, tag, dmac, 3, dmac_check);
683       eth_input_adv_and_flags_x4 (b, main_is_l3);
684
685       /* next */
686       n_left -= 4;
687       etype += 4;
688       tag += 4;
689       dmac += 4;
690       from += 4;
691     }
692   while (n_left)
693     {
694       vlib_get_buffers (vm, from, b, 1);
695       eth_input_get_etype_and_tags (b, etype, tag, dmac, 0, dmac_check);
696       eth_input_adv_and_flags_x1 (b, main_is_l3);
697
698       /* next */
699       n_left -= 1;
700       etype += 1;
701       tag += 1;
702       dmac += 4;
703       from += 1;
704     }
705
706   if (dmac_check)
707     {
708       u64 mask = clib_net_to_host_u64 (0xFFFFFFFFFFFF0000);
709       u64 igbit = clib_net_to_host_u64 (0x0100000000000000);
710       u64 hwaddr = (*(u64 *) hi->hw_address) & mask;
711       u64 *dmac = dmacs;
712       u8 *dmac_bad = dmacs_bad;
713
714       n_left = n_packets;
715
716 #ifdef CLIB_HAVE_VEC256
717       u64x4 igbit4 = u64x4_splat (igbit);
718       u64x4 mask4 = u64x4_splat (mask);
719       u64x4 hwaddr4 = u64x4_splat (hwaddr);
720       while (n_left >= 0)
721         {
722           u64x4 r0, r1;
723           r0 = u64x4_load_unaligned (dmac + 0) & mask4;
724           r1 = u64x4_load_unaligned (dmac + 4) & mask4;
725
726           r0 = (r0 != hwaddr4) & ((r0 & igbit4) == 0);
727           r1 = (r1 != hwaddr4) & ((r1 & igbit4) == 0);
728
729           *(u32 *) (dmac_bad + 0) = u8x32_msb_mask ((u8x32) (r0));
730           *(u32 *) (dmac_bad + 4) = u8x32_msb_mask ((u8x32) (r1));
731
732           /* next */
733           dmac += 8;
734           dmac_bad += 8;
735           n_left -= 8;
736         }
737 #else
738       while (n_left > 0)
739         {
740           u64 r0, r1, r2, r3;
741           r0 = dmac[0] & mask;
742           r1 = dmac[1] & mask;
743           r2 = dmac[2] & mask;
744           r3 = dmac[3] & mask;
745
746           r0 = (r0 != hwaddr) && ((r0 & igbit) == 0);
747           r1 = (r1 != hwaddr) && ((r1 & igbit) == 0);
748           r2 = (r2 != hwaddr) && ((r2 & igbit) == 0);
749           r3 = (r3 != hwaddr) && ((r3 & igbit) == 0);
750
751           dmac_bad[0] = r0;
752           dmac_bad[1] = r1;
753           dmac_bad[2] = r2;
754           dmac_bad[3] = r3;
755
756           /* next */
757           dmac += 4;
758           dmac_bad += 4;
759           n_left -= 4;
760         }
761 #endif
762     }
763
764   next_ip4 = em->l3_next.input_next_ip4;
765   next_ip6 = em->l3_next.input_next_ip6;
766   next_mpls = em->l3_next.input_next_mpls;
767   next_l2 = em->l2_next;
768
769   if (next_ip4 == ETHERNET_INPUT_NEXT_IP4_INPUT && ip4_cksum_ok)
770     next_ip4 = ETHERNET_INPUT_NEXT_IP4_INPUT_NCS;
771
772 #ifdef CLIB_HAVE_VEC256
773   u16x16 et16_ip4 = u16x16_splat (et_ip4);
774   u16x16 et16_ip6 = u16x16_splat (et_ip6);
775   u16x16 et16_mpls = u16x16_splat (et_mpls);
776   u16x16 et16_vlan = u16x16_splat (et_vlan);
777   u16x16 et16_dot1ad = u16x16_splat (et_dot1ad);
778   u16x16 next16_ip4 = u16x16_splat (next_ip4);
779   u16x16 next16_ip6 = u16x16_splat (next_ip6);
780   u16x16 next16_mpls = u16x16_splat (next_mpls);
781   u16x16 next16_l2 = u16x16_splat (next_l2);
782   u16x16 zero = { 0 };
783   u16x16 stairs = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
784 #endif
785
786   etype = etypes;
787   n_left = n_packets;
788   next = nexts;
789   n_slowpath = 0;
790   i = 0;
791
792   /* fastpath - in l3 mode hadles ip4, ip6 and mpls packets, other packets
793      are considered as slowpath, in l2 mode all untagged packets are
794      considered as fastpath */
795   while (n_left > 0)
796     {
797 #ifdef CLIB_HAVE_VEC256
798       if (n_left >= 16)
799         {
800           u16x16 r = zero;
801           u16x16 e16 = u16x16_load_unaligned (etype);
802           if (main_is_l3)
803             {
804               r += (e16 == et16_ip4) & next16_ip4;
805               r += (e16 == et16_ip6) & next16_ip6;
806               r += (e16 == et16_mpls) & next16_mpls;
807             }
808           else
809             r = ((e16 != et16_vlan) & (e16 != et16_dot1ad)) & next16_l2;
810           u16x16_store_unaligned (r, next);
811
812           if (!u16x16_is_all_zero (r == zero))
813             {
814               if (u16x16_is_all_zero (r))
815                 {
816                   u16x16_store_unaligned (u16x16_splat (i) + stairs,
817                                           slowpath_indices + n_slowpath);
818                   n_slowpath += 16;
819                 }
820               else
821                 {
822                   for (int j = 0; j < 16; j++)
823                     if (next[j] == 0)
824                       slowpath_indices[n_slowpath++] = i + j;
825                 }
826             }
827
828           etype += 16;
829           next += 16;
830           n_left -= 16;
831           i += 16;
832           continue;
833         }
834 #endif
835       if (main_is_l3 && etype[0] == et_ip4)
836         next[0] = next_ip4;
837       else if (main_is_l3 && etype[0] == et_ip6)
838         next[0] = next_ip6;
839       else if (main_is_l3 && etype[0] == et_mpls)
840         next[0] = next_mpls;
841       else if (main_is_l3 == 0 &&
842                etype[0] != et_vlan && etype[0] != et_dot1ad)
843         next[0] = next_l2;
844       else
845         {
846           next[0] = 0;
847           slowpath_indices[n_slowpath++] = i;
848         }
849
850       etype += 1;
851       next += 1;
852       n_left -= 1;
853       i += 1;
854     }
855
856   if (n_slowpath)
857     {
858       vnet_main_t *vnm = vnet_get_main ();
859       n_left = n_slowpath;
860       u16 *si = slowpath_indices;
861       u32 last_unknown_etype = ~0;
862       u32 last_unknown_next = ~0;
863       eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
864         .mask = -1LL,
865         .tag = tags[si[0]] ^ -1LL,
866         .sw_if_index = ~0
867       };
868
869       clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
870
871       while (n_left)
872         {
873           i = si[0];
874           u16 etype = etypes[i];
875
876           if (etype == et_vlan)
877             {
878               vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
879               eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
880                                     &dot1q_lookup, dmacs_bad[i], 0,
881                                     main_is_l3, dmac_check);
882
883             }
884           else if (etype == et_dot1ad)
885             {
886               vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
887               eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
888                                     &dot1ad_lookup, dmacs_bad[i], 1,
889                                     main_is_l3, dmac_check);
890             }
891           else
892             {
893               /* untagged packet with not well known etyertype */
894               if (last_unknown_etype != etype)
895                 {
896                   last_unknown_etype = etype;
897                   etype = clib_host_to_net_u16 (etype);
898                   last_unknown_next = eth_input_next_by_type (etype);
899                 }
900               if (dmac_check && main_is_l3 && dmacs_bad[i])
901                 {
902                   vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
903                   b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
904                   nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
905                 }
906               else
907                 nexts[i] = last_unknown_next;
908             }
909
910           /* next */
911           n_left--;
912           si++;
913         }
914
915       eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
916       eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
917     }
918
919   vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
920 }
921
922 static_always_inline void
923 eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node,
924                       vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
925                       int ip4_cksum_ok)
926 {
927   ethernet_main_t *em = &ethernet_main;
928   ethernet_interface_t *ei;
929   ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
930   main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
931   subint_config_t *subint0 = &intf0->untagged_subint;
932
933   int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
934   int promisc = (ei->flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL) != 0;
935
936   if (main_is_l3)
937     {
938       /* main interface is L3, we dont expect tagged packets and interface
939          is not in promisc node, so we dont't need to check DMAC */
940       int is_l3 = 1;
941
942       if (promisc == 0)
943         eth_input_process_frame (vm, node, hi, from, n_pkts, is_l3,
944                                  ip4_cksum_ok, 0);
945       else
946         /* subinterfaces and promisc mode so DMAC check is needed */
947         eth_input_process_frame (vm, node, hi, from, n_pkts, is_l3,
948                                  ip4_cksum_ok, 1);
949       return;
950     }
951   else
952     {
953       /* untagged packets are treated as L2 */
954       int is_l3 = 0;
955       eth_input_process_frame (vm, node, hi, from, n_pkts, is_l3,
956                                ip4_cksum_ok, 1);
957       return;
958     }
959 }
960
961 static_always_inline void
962 ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
963                       vlib_frame_t * from_frame)
964 {
965   u32 *from, n_left;
966   if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
967     {
968       from = vlib_frame_vector_args (from_frame);
969       n_left = from_frame->n_vectors;
970
971       while (n_left)
972         {
973           ethernet_input_trace_t *t0;
974           vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
975
976           if (b0->flags & VLIB_BUFFER_IS_TRACED)
977             {
978               t0 = vlib_add_trace (vm, node, b0,
979                                    sizeof (ethernet_input_trace_t));
980               clib_memcpy_fast (t0->packet_data, b0->data + b0->current_data,
981                                 sizeof (t0->packet_data));
982               t0->frame_flags = from_frame->flags;
983               clib_memcpy_fast (&t0->frame_data,
984                                 vlib_frame_scalar_args (from_frame),
985                                 sizeof (ethernet_input_frame_t));
986             }
987           from += 1;
988           n_left -= 1;
989         }
990     }
991
992   /* rx pcap capture if enabled */
993   if (PREDICT_FALSE (vlib_global_main.pcap[VLIB_RX].pcap_enable))
994     {
995       u32 bi0;
996
997       from = vlib_frame_vector_args (from_frame);
998       n_left = from_frame->n_vectors;
999       while (n_left > 0)
1000         {
1001           vlib_buffer_t *b0;
1002           bi0 = from[0];
1003           from++;
1004           b0 = vlib_get_buffer (vm, bi0);
1005
1006           if (vlib_global_main.pcap[VLIB_RX].pcap_sw_if_index == 0 ||
1007               vlib_global_main.pcap[VLIB_RX].pcap_sw_if_index
1008               == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1009             {
1010               pcap_add_buffer (&vlib_global_main.pcap[VLIB_RX].pcap_main, vm,
1011                                bi0, 512);
1012             }
1013           n_left--;
1014         }
1015     }
1016 }
1017
1018 static_always_inline void
1019 ethernet_input_inline (vlib_main_t * vm,
1020                        vlib_node_runtime_t * node,
1021                        u32 * from, u32 n_packets,
1022                        ethernet_input_variant_t variant)
1023 {
1024   vnet_main_t *vnm = vnet_get_main ();
1025   ethernet_main_t *em = &ethernet_main;
1026   vlib_node_runtime_t *error_node;
1027   u32 n_left_from, next_index, *to_next;
1028   u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1029   u32 thread_index = vm->thread_index;
1030   u32 cached_sw_if_index = ~0;
1031   u32 cached_is_l2 = 0;         /* shut up gcc */
1032   vnet_hw_interface_t *hi = NULL;       /* used for main interface only */
1033   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
1034   vlib_buffer_t **b = bufs;
1035
1036   if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1037     error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1038   else
1039     error_node = node;
1040
1041   n_left_from = n_packets;
1042
1043   next_index = node->cached_next_index;
1044   stats_sw_if_index = node->runtime_data[0];
1045   stats_n_packets = stats_n_bytes = 0;
1046   vlib_get_buffers (vm, from, bufs, n_left_from);
1047
1048   while (n_left_from > 0)
1049     {
1050       u32 n_left_to_next;
1051
1052       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1053
1054       while (n_left_from >= 4 && n_left_to_next >= 2)
1055         {
1056           u32 bi0, bi1;
1057           vlib_buffer_t *b0, *b1;
1058           u8 next0, next1, error0, error1;
1059           u16 type0, orig_type0, type1, orig_type1;
1060           u16 outer_id0, inner_id0, outer_id1, inner_id1;
1061           u32 match_flags0, match_flags1;
1062           u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1063             new_sw_if_index1, len1;
1064           vnet_hw_interface_t *hi0, *hi1;
1065           main_intf_t *main_intf0, *main_intf1;
1066           vlan_intf_t *vlan_intf0, *vlan_intf1;
1067           qinq_intf_t *qinq_intf0, *qinq_intf1;
1068           u32 is_l20, is_l21;
1069           ethernet_header_t *e0, *e1;
1070
1071           /* Prefetch next iteration. */
1072           {
1073             vlib_prefetch_buffer_header (b[2], STORE);
1074             vlib_prefetch_buffer_header (b[3], STORE);
1075
1076             CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1077             CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1078           }
1079
1080           bi0 = from[0];
1081           bi1 = from[1];
1082           to_next[0] = bi0;
1083           to_next[1] = bi1;
1084           from += 2;
1085           to_next += 2;
1086           n_left_to_next -= 2;
1087           n_left_from -= 2;
1088
1089           b0 = b[0];
1090           b1 = b[1];
1091           b += 2;
1092
1093           error0 = error1 = ETHERNET_ERROR_NONE;
1094           e0 = vlib_buffer_get_current (b0);
1095           type0 = clib_net_to_host_u16 (e0->type);
1096           e1 = vlib_buffer_get_current (b1);
1097           type1 = clib_net_to_host_u16 (e1->type);
1098
1099           /* Set the L2 header offset for all packets */
1100           vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1101           vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1102           b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1103           b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1104
1105           /* Speed-path for the untagged case */
1106           if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1107                             && !ethernet_frame_is_any_tagged_x2 (type0,
1108                                                                  type1)))
1109             {
1110               main_intf_t *intf0;
1111               subint_config_t *subint0;
1112               u32 sw_if_index0, sw_if_index1;
1113
1114               sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1115               sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1116               is_l20 = cached_is_l2;
1117
1118               /* This is probably wholly unnecessary */
1119               if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1120                 goto slowpath;
1121
1122               /* Now sw_if_index0 == sw_if_index1  */
1123               if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1124                 {
1125                   cached_sw_if_index = sw_if_index0;
1126                   hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1127                   intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1128                   subint0 = &intf0->untagged_subint;
1129                   cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1130                 }
1131
1132               if (PREDICT_TRUE (is_l20 != 0))
1133                 {
1134                   vnet_buffer (b0)->l3_hdr_offset =
1135                     vnet_buffer (b0)->l2_hdr_offset +
1136                     sizeof (ethernet_header_t);
1137                   vnet_buffer (b1)->l3_hdr_offset =
1138                     vnet_buffer (b1)->l2_hdr_offset +
1139                     sizeof (ethernet_header_t);
1140                   b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1141                   b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1142                   next0 = em->l2_next;
1143                   vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1144                   next1 = em->l2_next;
1145                   vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1146                 }
1147               else
1148                 {
1149                   if (!ethernet_address_cast (e0->dst_address) &&
1150                       (hi->hw_address != 0) &&
1151                       !ethernet_mac_address_equal ((u8 *) e0, hi->hw_address))
1152                     error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1153                   if (!ethernet_address_cast (e1->dst_address) &&
1154                       (hi->hw_address != 0) &&
1155                       !ethernet_mac_address_equal ((u8 *) e1, hi->hw_address))
1156                     error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1157                   vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1158                   determine_next_node (em, variant, 0, type0, b0,
1159                                        &error0, &next0);
1160                   vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1161                   determine_next_node (em, variant, 0, type1, b1,
1162                                        &error1, &next1);
1163                 }
1164               goto ship_it01;
1165             }
1166
1167           /* Slow-path for the tagged case */
1168         slowpath:
1169           parse_header (variant,
1170                         b0,
1171                         &type0,
1172                         &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1173
1174           parse_header (variant,
1175                         b1,
1176                         &type1,
1177                         &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1178
1179           old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1180           old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1181
1182           eth_vlan_table_lookups (em,
1183                                   vnm,
1184                                   old_sw_if_index0,
1185                                   orig_type0,
1186                                   outer_id0,
1187                                   inner_id0,
1188                                   &hi0,
1189                                   &main_intf0, &vlan_intf0, &qinq_intf0);
1190
1191           eth_vlan_table_lookups (em,
1192                                   vnm,
1193                                   old_sw_if_index1,
1194                                   orig_type1,
1195                                   outer_id1,
1196                                   inner_id1,
1197                                   &hi1,
1198                                   &main_intf1, &vlan_intf1, &qinq_intf1);
1199
1200           identify_subint (hi0,
1201                            b0,
1202                            match_flags0,
1203                            main_intf0,
1204                            vlan_intf0,
1205                            qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1206
1207           identify_subint (hi1,
1208                            b1,
1209                            match_flags1,
1210                            main_intf1,
1211                            vlan_intf1,
1212                            qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1213
1214           // Save RX sw_if_index for later nodes
1215           vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1216             error0 !=
1217             ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1218           vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1219             error1 !=
1220             ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1221
1222           // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1223           if (((new_sw_if_index0 != ~0)
1224                && (new_sw_if_index0 != old_sw_if_index0))
1225               || ((new_sw_if_index1 != ~0)
1226                   && (new_sw_if_index1 != old_sw_if_index1)))
1227             {
1228
1229               len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1230                 - vnet_buffer (b0)->l2_hdr_offset;
1231               len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1232                 - vnet_buffer (b1)->l2_hdr_offset;
1233
1234               stats_n_packets += 2;
1235               stats_n_bytes += len0 + len1;
1236
1237               if (PREDICT_FALSE
1238                   (!(new_sw_if_index0 == stats_sw_if_index
1239                      && new_sw_if_index1 == stats_sw_if_index)))
1240                 {
1241                   stats_n_packets -= 2;
1242                   stats_n_bytes -= len0 + len1;
1243
1244                   if (new_sw_if_index0 != old_sw_if_index0
1245                       && new_sw_if_index0 != ~0)
1246                     vlib_increment_combined_counter (vnm->
1247                                                      interface_main.combined_sw_if_counters
1248                                                      +
1249                                                      VNET_INTERFACE_COUNTER_RX,
1250                                                      thread_index,
1251                                                      new_sw_if_index0, 1,
1252                                                      len0);
1253                   if (new_sw_if_index1 != old_sw_if_index1
1254                       && new_sw_if_index1 != ~0)
1255                     vlib_increment_combined_counter (vnm->
1256                                                      interface_main.combined_sw_if_counters
1257                                                      +
1258                                                      VNET_INTERFACE_COUNTER_RX,
1259                                                      thread_index,
1260                                                      new_sw_if_index1, 1,
1261                                                      len1);
1262
1263                   if (new_sw_if_index0 == new_sw_if_index1)
1264                     {
1265                       if (stats_n_packets > 0)
1266                         {
1267                           vlib_increment_combined_counter
1268                             (vnm->interface_main.combined_sw_if_counters
1269                              + VNET_INTERFACE_COUNTER_RX,
1270                              thread_index,
1271                              stats_sw_if_index,
1272                              stats_n_packets, stats_n_bytes);
1273                           stats_n_packets = stats_n_bytes = 0;
1274                         }
1275                       stats_sw_if_index = new_sw_if_index0;
1276                     }
1277                 }
1278             }
1279
1280           if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1281             is_l20 = is_l21 = 0;
1282
1283           determine_next_node (em, variant, is_l20, type0, b0, &error0,
1284                                &next0);
1285           determine_next_node (em, variant, is_l21, type1, b1, &error1,
1286                                &next1);
1287
1288         ship_it01:
1289           b0->error = error_node->errors[error0];
1290           b1->error = error_node->errors[error1];
1291
1292           // verify speculative enqueue
1293           vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1294                                            n_left_to_next, bi0, bi1, next0,
1295                                            next1);
1296         }
1297
1298       while (n_left_from > 0 && n_left_to_next > 0)
1299         {
1300           u32 bi0;
1301           vlib_buffer_t *b0;
1302           u8 error0, next0;
1303           u16 type0, orig_type0;
1304           u16 outer_id0, inner_id0;
1305           u32 match_flags0;
1306           u32 old_sw_if_index0, new_sw_if_index0, len0;
1307           vnet_hw_interface_t *hi0;
1308           main_intf_t *main_intf0;
1309           vlan_intf_t *vlan_intf0;
1310           qinq_intf_t *qinq_intf0;
1311           ethernet_header_t *e0;
1312           u32 is_l20;
1313
1314           // Prefetch next iteration
1315           if (n_left_from > 1)
1316             {
1317               vlib_prefetch_buffer_header (b[1], STORE);
1318               CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1319             }
1320
1321           bi0 = from[0];
1322           to_next[0] = bi0;
1323           from += 1;
1324           to_next += 1;
1325           n_left_from -= 1;
1326           n_left_to_next -= 1;
1327
1328           b0 = b[0];
1329           b += 1;
1330
1331           error0 = ETHERNET_ERROR_NONE;
1332           e0 = vlib_buffer_get_current (b0);
1333           type0 = clib_net_to_host_u16 (e0->type);
1334
1335           /* Set the L2 header offset for all packets */
1336           vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1337           b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1338
1339           /* Speed-path for the untagged case */
1340           if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1341                             && !ethernet_frame_is_tagged (type0)))
1342             {
1343               main_intf_t *intf0;
1344               subint_config_t *subint0;
1345               u32 sw_if_index0;
1346
1347               sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1348               is_l20 = cached_is_l2;
1349
1350               if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1351                 {
1352                   cached_sw_if_index = sw_if_index0;
1353                   hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1354                   intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1355                   subint0 = &intf0->untagged_subint;
1356                   cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1357                 }
1358
1359
1360               if (PREDICT_TRUE (is_l20 != 0))
1361                 {
1362                   vnet_buffer (b0)->l3_hdr_offset =
1363                     vnet_buffer (b0)->l2_hdr_offset +
1364                     sizeof (ethernet_header_t);
1365                   b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1366                   next0 = em->l2_next;
1367                   vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1368                 }
1369               else
1370                 {
1371                   if (!ethernet_address_cast (e0->dst_address) &&
1372                       (hi->hw_address != 0) &&
1373                       !ethernet_mac_address_equal ((u8 *) e0, hi->hw_address))
1374                     error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1375                   vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1376                   determine_next_node (em, variant, 0, type0, b0,
1377                                        &error0, &next0);
1378                 }
1379               goto ship_it0;
1380             }
1381
1382           /* Slow-path for the tagged case */
1383           parse_header (variant,
1384                         b0,
1385                         &type0,
1386                         &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1387
1388           old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1389
1390           eth_vlan_table_lookups (em,
1391                                   vnm,
1392                                   old_sw_if_index0,
1393                                   orig_type0,
1394                                   outer_id0,
1395                                   inner_id0,
1396                                   &hi0,
1397                                   &main_intf0, &vlan_intf0, &qinq_intf0);
1398
1399           identify_subint (hi0,
1400                            b0,
1401                            match_flags0,
1402                            main_intf0,
1403                            vlan_intf0,
1404                            qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1405
1406           // Save RX sw_if_index for later nodes
1407           vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1408             error0 !=
1409             ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1410
1411           // Increment subinterface stats
1412           // Note that interface-level counters have already been incremented
1413           // prior to calling this function. Thus only subinterface counters
1414           // are incremented here.
1415           //
1416           // Interface level counters include packets received on the main
1417           // interface and all subinterfaces. Subinterface level counters
1418           // include only those packets received on that subinterface
1419           // Increment stats if the subint is valid and it is not the main intf
1420           if ((new_sw_if_index0 != ~0)
1421               && (new_sw_if_index0 != old_sw_if_index0))
1422             {
1423
1424               len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1425                 - vnet_buffer (b0)->l2_hdr_offset;
1426
1427               stats_n_packets += 1;
1428               stats_n_bytes += len0;
1429
1430               // Batch stat increments from the same subinterface so counters
1431               // don't need to be incremented for every packet.
1432               if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1433                 {
1434                   stats_n_packets -= 1;
1435                   stats_n_bytes -= len0;
1436
1437                   if (new_sw_if_index0 != ~0)
1438                     vlib_increment_combined_counter
1439                       (vnm->interface_main.combined_sw_if_counters
1440                        + VNET_INTERFACE_COUNTER_RX,
1441                        thread_index, new_sw_if_index0, 1, len0);
1442                   if (stats_n_packets > 0)
1443                     {
1444                       vlib_increment_combined_counter
1445                         (vnm->interface_main.combined_sw_if_counters
1446                          + VNET_INTERFACE_COUNTER_RX,
1447                          thread_index,
1448                          stats_sw_if_index, stats_n_packets, stats_n_bytes);
1449                       stats_n_packets = stats_n_bytes = 0;
1450                     }
1451                   stats_sw_if_index = new_sw_if_index0;
1452                 }
1453             }
1454
1455           if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1456             is_l20 = 0;
1457
1458           determine_next_node (em, variant, is_l20, type0, b0, &error0,
1459                                &next0);
1460
1461         ship_it0:
1462           b0->error = error_node->errors[error0];
1463
1464           // verify speculative enqueue
1465           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1466                                            to_next, n_left_to_next,
1467                                            bi0, next0);
1468         }
1469
1470       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1471     }
1472
1473   // Increment any remaining batched stats
1474   if (stats_n_packets > 0)
1475     {
1476       vlib_increment_combined_counter
1477         (vnm->interface_main.combined_sw_if_counters
1478          + VNET_INTERFACE_COUNTER_RX,
1479          thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1480       node->runtime_data[0] = stats_sw_if_index;
1481     }
1482 }
1483
1484 VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
1485                                     vlib_node_runtime_t * node,
1486                                     vlib_frame_t * frame)
1487 {
1488   vnet_main_t *vnm = vnet_get_main ();
1489   u32 *from = vlib_frame_vector_args (frame);
1490   u32 n_packets = frame->n_vectors;
1491
1492   ethernet_input_trace (vm, node, frame);
1493
1494   if (frame->flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
1495     {
1496       ethernet_input_frame_t *ef = vlib_frame_scalar_args (frame);
1497       int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1498       vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ef->hw_if_index);
1499       eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1500     }
1501   else
1502     ethernet_input_inline (vm, node, from, n_packets,
1503                            ETHERNET_INPUT_VARIANT_ETHERNET);
1504   return n_packets;
1505 }
1506
1507 VLIB_NODE_FN (ethernet_input_type_node) (vlib_main_t * vm,
1508                                          vlib_node_runtime_t * node,
1509                                          vlib_frame_t * from_frame)
1510 {
1511   u32 *from = vlib_frame_vector_args (from_frame);
1512   u32 n_packets = from_frame->n_vectors;
1513   ethernet_input_trace (vm, node, from_frame);
1514   ethernet_input_inline (vm, node, from, n_packets,
1515                          ETHERNET_INPUT_VARIANT_ETHERNET_TYPE);
1516   return n_packets;
1517 }
1518
1519 VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
1520                                            vlib_node_runtime_t * node,
1521                                            vlib_frame_t * from_frame)
1522 {
1523   u32 *from = vlib_frame_vector_args (from_frame);
1524   u32 n_packets = from_frame->n_vectors;
1525   ethernet_input_trace (vm, node, from_frame);
1526   ethernet_input_inline (vm, node, from, n_packets,
1527                          ETHERNET_INPUT_VARIANT_NOT_L2);
1528   return n_packets;
1529 }
1530
1531
1532 // Return the subinterface config struct for the given sw_if_index
1533 // Also return via parameter the appropriate match flags for the
1534 // configured number of tags.
1535 // On error (unsupported or not ethernet) return 0.
1536 static subint_config_t *
1537 ethernet_sw_interface_get_config (vnet_main_t * vnm,
1538                                   u32 sw_if_index,
1539                                   u32 * flags, u32 * unsupported)
1540 {
1541   ethernet_main_t *em = &ethernet_main;
1542   vnet_hw_interface_t *hi;
1543   vnet_sw_interface_t *si;
1544   main_intf_t *main_intf;
1545   vlan_table_t *vlan_table;
1546   qinq_table_t *qinq_table;
1547   subint_config_t *subint = 0;
1548
1549   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1550
1551   if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1552     {
1553       *unsupported = 0;
1554       goto done;                // non-ethernet interface
1555     }
1556
1557   // ensure there's an entry for the main intf (shouldn't really be necessary)
1558   vec_validate (em->main_intfs, hi->hw_if_index);
1559   main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1560
1561   // Locate the subint for the given ethernet config
1562   si = vnet_get_sw_interface (vnm, sw_if_index);
1563
1564   if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1565     {
1566       p2p_ethernet_main_t *p2pm = &p2p_main;
1567       u32 p2pe_sw_if_index =
1568         p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
1569       if (p2pe_sw_if_index == ~0)
1570         {
1571           pool_get (p2pm->p2p_subif_pool, subint);
1572           si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1573         }
1574       else
1575         subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1576       *flags = SUBINT_CONFIG_P2P;
1577     }
1578   else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1579     {
1580       pipe_t *pipe;
1581
1582       pipe = pipe_get (sw_if_index);
1583       subint = &pipe->subint;
1584       *flags = SUBINT_CONFIG_P2P;
1585     }
1586   else if (si->sub.eth.flags.default_sub)
1587     {
1588       subint = &main_intf->default_subint;
1589       *flags = SUBINT_CONFIG_MATCH_1_TAG |
1590         SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1591     }
1592   else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1593     {
1594       // if no flags are set then this is a main interface
1595       // so treat as untagged
1596       subint = &main_intf->untagged_subint;
1597       *flags = SUBINT_CONFIG_MATCH_0_TAG;
1598     }
1599   else
1600     {
1601       // one or two tags
1602       // first get the vlan table
1603       if (si->sub.eth.flags.dot1ad)
1604         {
1605           if (main_intf->dot1ad_vlans == 0)
1606             {
1607               // Allocate a vlan table from the pool
1608               pool_get (em->vlan_pool, vlan_table);
1609               main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1610             }
1611           else
1612             {
1613               // Get ptr to existing vlan table
1614               vlan_table =
1615                 vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1616             }
1617         }
1618       else
1619         {                       // dot1q
1620           if (main_intf->dot1q_vlans == 0)
1621             {
1622               // Allocate a vlan table from the pool
1623               pool_get (em->vlan_pool, vlan_table);
1624               main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1625             }
1626           else
1627             {
1628               // Get ptr to existing vlan table
1629               vlan_table =
1630                 vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1631             }
1632         }
1633
1634       if (si->sub.eth.flags.one_tag)
1635         {
1636           *flags = si->sub.eth.flags.exact_match ?
1637             SUBINT_CONFIG_MATCH_1_TAG :
1638             (SUBINT_CONFIG_MATCH_1_TAG |
1639              SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1640
1641           if (si->sub.eth.flags.outer_vlan_id_any)
1642             {
1643               // not implemented yet
1644               *unsupported = 1;
1645               goto done;
1646             }
1647           else
1648             {
1649               // a single vlan, a common case
1650               subint =
1651                 &vlan_table->vlans[si->sub.eth.
1652                                    outer_vlan_id].single_tag_subint;
1653             }
1654
1655         }
1656       else
1657         {
1658           // Two tags
1659           *flags = si->sub.eth.flags.exact_match ?
1660             SUBINT_CONFIG_MATCH_2_TAG :
1661             (SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1662
1663           if (si->sub.eth.flags.outer_vlan_id_any
1664               && si->sub.eth.flags.inner_vlan_id_any)
1665             {
1666               // not implemented yet
1667               *unsupported = 1;
1668               goto done;
1669             }
1670
1671           if (si->sub.eth.flags.inner_vlan_id_any)
1672             {
1673               // a specific outer and "any" inner
1674               // don't need a qinq table for this
1675               subint =
1676                 &vlan_table->vlans[si->sub.eth.
1677                                    outer_vlan_id].inner_any_subint;
1678               if (si->sub.eth.flags.exact_match)
1679                 {
1680                   *flags = SUBINT_CONFIG_MATCH_2_TAG;
1681                 }
1682               else
1683                 {
1684                   *flags = SUBINT_CONFIG_MATCH_2_TAG |
1685                     SUBINT_CONFIG_MATCH_3_TAG;
1686                 }
1687             }
1688           else
1689             {
1690               // a specific outer + specifc innner vlan id, a common case
1691
1692               // get the qinq table
1693               if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1694                 {
1695                   // Allocate a qinq table from the pool
1696                   pool_get (em->qinq_pool, qinq_table);
1697                   vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1698                     qinq_table - em->qinq_pool;
1699                 }
1700               else
1701                 {
1702                   // Get ptr to existing qinq table
1703                   qinq_table =
1704                     vec_elt_at_index (em->qinq_pool,
1705                                       vlan_table->vlans[si->sub.
1706                                                         eth.outer_vlan_id].
1707                                       qinqs);
1708                 }
1709               subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1710             }
1711         }
1712     }
1713
1714 done:
1715   return subint;
1716 }
1717
1718 static clib_error_t *
1719 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
1720 {
1721   subint_config_t *subint;
1722   u32 dummy_flags;
1723   u32 dummy_unsup;
1724   clib_error_t *error = 0;
1725
1726   // Find the config for this subinterface
1727   subint =
1728     ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags,
1729                                       &dummy_unsup);
1730
1731   if (subint == 0)
1732     {
1733       // not implemented yet or not ethernet
1734       goto done;
1735     }
1736
1737   subint->sw_if_index =
1738     ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1739
1740 done:
1741   return error;
1742 }
1743
1744 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
1745
1746
1747 #ifndef CLIB_MARCH_VARIANT
1748 // Set the L2/L3 mode for the subinterface
1749 void
1750 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
1751 {
1752   subint_config_t *subint;
1753   u32 dummy_flags;
1754   u32 dummy_unsup;
1755   int is_port;
1756   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1757
1758   is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1759
1760   // Find the config for this subinterface
1761   subint =
1762     ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags,
1763                                       &dummy_unsup);
1764
1765   if (subint == 0)
1766     {
1767       // unimplemented or not ethernet
1768       goto done;
1769     }
1770
1771   // Double check that the config we found is for our interface (or the interface is down)
1772   ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
1773
1774   if (l2)
1775     {
1776       subint->flags |= SUBINT_CONFIG_L2;
1777       if (is_port)
1778         subint->flags |=
1779           SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
1780           | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1781     }
1782   else
1783     {
1784       subint->flags &= ~SUBINT_CONFIG_L2;
1785       if (is_port)
1786         subint->flags &=
1787           ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
1788             | SUBINT_CONFIG_MATCH_3_TAG);
1789     }
1790
1791 done:
1792   return;
1793 }
1794
1795 /*
1796  * Set the L2/L3 mode for the subinterface regardless of port
1797  */
1798 void
1799 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
1800                                           u32 sw_if_index, u32 l2)
1801 {
1802   subint_config_t *subint;
1803   u32 dummy_flags;
1804   u32 dummy_unsup;
1805
1806   /* Find the config for this subinterface */
1807   subint =
1808     ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags,
1809                                       &dummy_unsup);
1810
1811   if (subint == 0)
1812     {
1813       /* unimplemented or not ethernet */
1814       goto done;
1815     }
1816
1817   /*
1818    * Double check that the config we found is for our interface (or the
1819    * interface is down)
1820    */
1821   ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
1822
1823   if (l2)
1824     {
1825       subint->flags |= SUBINT_CONFIG_L2;
1826     }
1827   else
1828     {
1829       subint->flags &= ~SUBINT_CONFIG_L2;
1830     }
1831
1832 done:
1833   return;
1834 }
1835 #endif
1836
1837 static clib_error_t *
1838 ethernet_sw_interface_add_del (vnet_main_t * vnm,
1839                                u32 sw_if_index, u32 is_create)
1840 {
1841   clib_error_t *error = 0;
1842   subint_config_t *subint;
1843   u32 match_flags;
1844   u32 unsupported = 0;
1845
1846   // Find the config for this subinterface
1847   subint =
1848     ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
1849                                       &unsupported);
1850
1851   if (subint == 0)
1852     {
1853       // not implemented yet or not ethernet
1854       if (unsupported)
1855         {
1856           // this is the NYI case
1857           error = clib_error_return (0, "not implemented yet");
1858         }
1859       goto done;
1860     }
1861
1862   if (!is_create)
1863     {
1864       subint->flags = 0;
1865       return error;
1866     }
1867
1868   // Initialize the subint
1869   if (subint->flags & SUBINT_CONFIG_VALID)
1870     {
1871       // Error vlan already in use
1872       error = clib_error_return (0, "vlan is already in use");
1873     }
1874   else
1875     {
1876       // Note that config is L3 by default
1877       subint->flags = SUBINT_CONFIG_VALID | match_flags;
1878       subint->sw_if_index = ~0; // because interfaces are initially down
1879     }
1880
1881 done:
1882   return error;
1883 }
1884
1885 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
1886
1887 static char *ethernet_error_strings[] = {
1888 #define ethernet_error(n,c,s) s,
1889 #include "error.def"
1890 #undef ethernet_error
1891 };
1892
1893 /* *INDENT-OFF* */
1894 VLIB_REGISTER_NODE (ethernet_input_node) = {
1895   .name = "ethernet-input",
1896   /* Takes a vector of packets. */
1897   .vector_size = sizeof (u32),
1898   .scalar_size = sizeof (ethernet_input_frame_t),
1899   .n_errors = ETHERNET_N_ERROR,
1900   .error_strings = ethernet_error_strings,
1901   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
1902   .next_nodes = {
1903 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
1904     foreach_ethernet_input_next
1905 #undef _
1906   },
1907   .format_buffer = format_ethernet_header_with_length,
1908   .format_trace = format_ethernet_input_trace,
1909   .unformat_buffer = unformat_ethernet_header,
1910 };
1911
1912 VLIB_REGISTER_NODE (ethernet_input_type_node) = {
1913   .name = "ethernet-input-type",
1914   /* Takes a vector of packets. */
1915   .vector_size = sizeof (u32),
1916   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
1917   .next_nodes = {
1918 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
1919     foreach_ethernet_input_next
1920 #undef _
1921   },
1922 };
1923
1924 VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
1925   .name = "ethernet-input-not-l2",
1926   /* Takes a vector of packets. */
1927   .vector_size = sizeof (u32),
1928   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
1929   .next_nodes = {
1930 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
1931     foreach_ethernet_input_next
1932 #undef _
1933   },
1934 };
1935 /* *INDENT-ON* */
1936
1937 #ifndef CLIB_MARCH_VARIANT
1938 void
1939 ethernet_set_rx_redirect (vnet_main_t * vnm,
1940                           vnet_hw_interface_t * hi, u32 enable)
1941 {
1942   // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
1943   // don't go directly to ip4-input)
1944   vnet_hw_interface_rx_redirect_to_node
1945     (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
1946 }
1947
1948
1949 /*
1950  * Initialization and registration for the next_by_ethernet structure
1951  */
1952
1953 clib_error_t *
1954 next_by_ethertype_init (next_by_ethertype_t * l3_next)
1955 {
1956   l3_next->input_next_by_type = sparse_vec_new
1957     ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
1958      /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
1959
1960   vec_validate (l3_next->sparse_index_by_input_next_index,
1961                 ETHERNET_INPUT_NEXT_DROP);
1962   vec_validate (l3_next->sparse_index_by_input_next_index,
1963                 ETHERNET_INPUT_NEXT_PUNT);
1964   l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
1965     SPARSE_VEC_INVALID_INDEX;
1966   l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
1967     SPARSE_VEC_INVALID_INDEX;
1968
1969   /*
1970    * Make sure we don't wipe out an ethernet registration by mistake
1971    * Can happen if init function ordering constraints are missing.
1972    */
1973   if (CLIB_DEBUG > 0)
1974     {
1975       ethernet_main_t *em = &ethernet_main;
1976       ASSERT (em->next_by_ethertype_register_called == 0);
1977     }
1978
1979   return 0;
1980 }
1981
1982 // Add an ethertype -> next index mapping to the structure
1983 clib_error_t *
1984 next_by_ethertype_register (next_by_ethertype_t * l3_next,
1985                             u32 ethertype, u32 next_index)
1986 {
1987   u32 i;
1988   u16 *n;
1989   ethernet_main_t *em = &ethernet_main;
1990
1991   if (CLIB_DEBUG > 0)
1992     {
1993       ethernet_main_t *em = &ethernet_main;
1994       em->next_by_ethertype_register_called = 1;
1995     }
1996
1997   /* Setup ethernet type -> next index sparse vector mapping. */
1998   n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
1999   n[0] = next_index;
2000
2001   /* Rebuild next index -> sparse index inverse mapping when sparse vector
2002      is updated. */
2003   vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2004   for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2005     l3_next->
2006       sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2007
2008   // do not allow the cached next index's to be updated if L3
2009   // redirect is enabled, as it will have overwritten them
2010   if (!em->redirect_l3)
2011     {
2012       // Cache common ethertypes directly
2013       if (ethertype == ETHERNET_TYPE_IP4)
2014         {
2015           l3_next->input_next_ip4 = next_index;
2016         }
2017       else if (ethertype == ETHERNET_TYPE_IP6)
2018         {
2019           l3_next->input_next_ip6 = next_index;
2020         }
2021       else if (ethertype == ETHERNET_TYPE_MPLS)
2022         {
2023           l3_next->input_next_mpls = next_index;
2024         }
2025     }
2026   return 0;
2027 }
2028
2029 void
2030 ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
2031 {
2032   __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2033   __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2034
2035   ethernet_setup_node (vm, ethernet_input_node.index);
2036   ethernet_setup_node (vm, ethernet_input_type_node.index);
2037   ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
2038
2039   next_by_ethertype_init (&em->l3_next);
2040
2041   // Initialize pools and vector for vlan parsing
2042   vec_validate (em->main_intfs, 10);    // 10 main interfaces
2043   pool_alloc (em->vlan_pool, 10);
2044   pool_alloc (em->qinq_pool, 1);
2045
2046   // The first vlan pool will always be reserved for an invalid table
2047   pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2048   // The first qinq pool will always be reserved for an invalid table
2049   pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2050 }
2051
2052 void
2053 ethernet_register_input_type (vlib_main_t * vm,
2054                               ethernet_type_t type, u32 node_index)
2055 {
2056   ethernet_main_t *em = &ethernet_main;
2057   ethernet_type_info_t *ti;
2058   u32 i;
2059
2060   {
2061     clib_error_t *error = vlib_call_init_function (vm, ethernet_init);
2062     if (error)
2063       clib_error_report (error);
2064   }
2065
2066   ti = ethernet_get_type_info (em, type);
2067   if (ti == 0)
2068     {
2069       clib_warning ("type_info NULL for type %d", type);
2070       return;
2071     }
2072   ti->node_index = node_index;
2073   ti->next_index = vlib_node_add_next (vm,
2074                                        ethernet_input_node.index, node_index);
2075   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2076   ASSERT (i == ti->next_index);
2077
2078   i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2079   ASSERT (i == ti->next_index);
2080
2081   // Add the L3 node for this ethertype to the next nodes structure
2082   next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2083
2084   // Call the registration functions for other nodes that want a mapping
2085   l2bvi_register_input_type (vm, type, node_index);
2086 }
2087
2088 void
2089 ethernet_register_l2_input (vlib_main_t * vm, u32 node_index)
2090 {
2091   ethernet_main_t *em = &ethernet_main;
2092   u32 i;
2093
2094   em->l2_next =
2095     vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2096
2097   /*
2098    * Even if we never use these arcs, we have to align the next indices...
2099    */
2100   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2101
2102   ASSERT (i == em->l2_next);
2103
2104   i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2105   ASSERT (i == em->l2_next);
2106 }
2107
2108 // Register a next node for L3 redirect, and enable L3 redirect
2109 void
2110 ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
2111 {
2112   ethernet_main_t *em = &ethernet_main;
2113   u32 i;
2114
2115   em->redirect_l3 = 1;
2116   em->redirect_l3_next = vlib_node_add_next (vm,
2117                                              ethernet_input_node.index,
2118                                              node_index);
2119   /*
2120    * Change the cached next nodes to the redirect node
2121    */
2122   em->l3_next.input_next_ip4 = em->redirect_l3_next;
2123   em->l3_next.input_next_ip6 = em->redirect_l3_next;
2124   em->l3_next.input_next_mpls = em->redirect_l3_next;
2125
2126   /*
2127    * Even if we never use these arcs, we have to align the next indices...
2128    */
2129   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2130
2131   ASSERT (i == em->redirect_l3_next);
2132
2133   i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2134
2135   ASSERT (i == em->redirect_l3_next);
2136 }
2137 #endif
2138
2139 /*
2140  * fd.io coding-style-patch-verification: ON
2141  *
2142  * Local Variables:
2143  * eval: (c-set-style "gnu")
2144  * End:
2145  */