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