http: fix client parse error handling
[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                     {
986                       if (next[j] == 0)
987                         slowpath_indices[n_slowpath++] = i + j;
988                       else if (dmac_check && main_is_l3 && dmacs_bad[i + j])
989                         {
990                           next[j] = 0;
991                           slowpath_indices[n_slowpath++] = i + j;
992                         }
993                     }
994                 }
995             }
996           else
997             {
998               if (dmac_check && main_is_l3)
999                 {
1000                   u8x16 dmac_bad = u8x16_load_unaligned (&dmacs_bad[i]);
1001                   if (!u8x16_is_all_zero (dmac_bad))
1002                     {
1003                       for (int j = 0; j < 16; j++)
1004                         if (dmacs_bad[i + j])
1005                           {
1006                             next[j] = 0;
1007                             slowpath_indices[n_slowpath++] = i + j;
1008                           }
1009                     }
1010                 }
1011             }
1012
1013           etype += 16;
1014           next += 16;
1015           n_left -= 16;
1016           i += 16;
1017           continue;
1018         }
1019 #endif
1020       if (dmac_check && main_is_l3 && dmacs_bad[i])
1021         {
1022           next[0] = 0;
1023           slowpath_indices[n_slowpath++] = i;
1024         }
1025       else if (main_is_l3 && etype[0] == et_ip4)
1026         next[0] = next_ip4;
1027       else if (main_is_l3 && etype[0] == et_ip6)
1028         next[0] = next_ip6;
1029       else if (main_is_l3 && etype[0] == et_mpls)
1030         next[0] = next_mpls;
1031       else if (main_is_l3 == 0 &&
1032                etype[0] != et_vlan && etype[0] != et_dot1ad)
1033         next[0] = next_l2;
1034       else
1035         {
1036           next[0] = 0;
1037           slowpath_indices[n_slowpath++] = i;
1038         }
1039
1040       etype += 1;
1041       next += 1;
1042       n_left -= 1;
1043       i += 1;
1044     }
1045
1046   if (n_slowpath)
1047     {
1048       vnet_main_t *vnm = vnet_get_main ();
1049       n_left = n_slowpath;
1050       u16 *si = slowpath_indices;
1051       u32 last_unknown_etype = ~0;
1052       u32 last_unknown_next = ~0;
1053       eth_input_tag_lookup_t dot1ad_lookup, dot1q_lookup = {
1054         .mask = -1LL,
1055         .tag = tags[si[0]] ^ -1LL,
1056         .sw_if_index = ~0
1057       };
1058
1059       clib_memcpy_fast (&dot1ad_lookup, &dot1q_lookup, sizeof (dot1q_lookup));
1060
1061       while (n_left)
1062         {
1063           i = si[0];
1064           u16 etype = etypes[i];
1065
1066           if (etype == et_vlan)
1067             {
1068               vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1069               eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1070                                     &dot1q_lookup, dmacs_bad[i], 0,
1071                                     main_is_l3, dmac_check);
1072
1073             }
1074           else if (etype == et_dot1ad)
1075             {
1076               vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1077               eth_input_tag_lookup (vm, vnm, node, hi, tags[i], nexts + i, b,
1078                                     &dot1ad_lookup, dmacs_bad[i], 1,
1079                                     main_is_l3, dmac_check);
1080             }
1081           else
1082             {
1083               /* untagged packet with not well known ethertype */
1084               if (last_unknown_etype != etype)
1085                 {
1086                   last_unknown_etype = etype;
1087                   etype = clib_host_to_net_u16 (etype);
1088                   last_unknown_next = eth_input_next_by_type (etype);
1089                 }
1090               if (dmac_check && main_is_l3 && dmacs_bad[i])
1091                 {
1092                   vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
1093                   b->error = node->errors[ETHERNET_ERROR_L3_MAC_MISMATCH];
1094                   nexts[i] = ETHERNET_INPUT_NEXT_PUNT;
1095                 }
1096               else
1097                 nexts[i] = last_unknown_next;
1098             }
1099
1100           /* next */
1101           n_left--;
1102           si++;
1103         }
1104
1105       eth_input_update_if_counters (vm, vnm, &dot1q_lookup);
1106       eth_input_update_if_counters (vm, vnm, &dot1ad_lookup);
1107     }
1108
1109   vlib_buffer_enqueue_to_next (vm, node, buffer_indices, nexts, n_packets);
1110 }
1111
1112 static_always_inline void
1113 eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node,
1114                       vnet_hw_interface_t * hi, u32 * from, u32 n_pkts,
1115                       int ip4_cksum_ok)
1116 {
1117   ethernet_main_t *em = &ethernet_main;
1118   ethernet_interface_t *ei;
1119   ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
1120   main_intf_t *intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1121   subint_config_t *subint0 = &intf0->untagged_subint;
1122
1123   int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0;
1124   int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3;
1125
1126   if (main_is_l3)
1127     {
1128       if (int_is_l3 ||          /* DMAC filter already done by NIC */
1129           ((hi->l2_if_count != 0) && (hi->l3_if_count == 0)))
1130         {                       /* All L2 usage - DMAC check not needed */
1131           eth_input_process_frame (vm, node, hi, from, n_pkts,
1132                                    /*is_l3 */ 1, ip4_cksum_ok, 0);
1133         }
1134       else
1135         {                       /* DMAC check needed for L3 */
1136           eth_input_process_frame (vm, node, hi, from, n_pkts,
1137                                    /*is_l3 */ 1, ip4_cksum_ok, 1);
1138         }
1139       return;
1140     }
1141   else
1142     {
1143       if (hi->l3_if_count == 0)
1144         {                       /* All L2 usage - DMAC check not needed */
1145           eth_input_process_frame (vm, node, hi, from, n_pkts,
1146                                    /*is_l3 */ 0, ip4_cksum_ok, 0);
1147         }
1148       else
1149         {                       /* DMAC check needed for L3 */
1150           eth_input_process_frame (vm, node, hi, from, n_pkts,
1151                                    /*is_l3 */ 0, ip4_cksum_ok, 1);
1152         }
1153       return;
1154     }
1155 }
1156
1157 static_always_inline void
1158 ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
1159                       vlib_frame_t * from_frame)
1160 {
1161   vnet_main_t *vnm = vnet_get_main ();
1162   u32 *from, n_left;
1163   if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1164     {
1165       from = vlib_frame_vector_args (from_frame);
1166       n_left = from_frame->n_vectors;
1167
1168       while (n_left)
1169         {
1170           ethernet_input_trace_t *t0;
1171           vlib_buffer_t *b0 = vlib_get_buffer (vm, from[0]);
1172
1173           if (b0->flags & VLIB_BUFFER_IS_TRACED)
1174             {
1175               t0 = vlib_add_trace (vm, node, b0,
1176                                    sizeof (ethernet_input_trace_t));
1177               clib_memcpy_fast (t0->packet_data, b0->data + b0->current_data,
1178                                 sizeof (t0->packet_data));
1179               t0->frame_flags = from_frame->flags;
1180               clib_memcpy_fast (&t0->frame_data,
1181                                 vlib_frame_scalar_args (from_frame),
1182                                 sizeof (ethernet_input_frame_t));
1183             }
1184           from += 1;
1185           n_left -= 1;
1186         }
1187     }
1188
1189   /* rx pcap capture if enabled */
1190   if (PREDICT_FALSE (vnm->pcap.pcap_rx_enable))
1191     {
1192       u32 bi0;
1193       vnet_pcap_t *pp = &vnm->pcap;
1194
1195       from = vlib_frame_vector_args (from_frame);
1196       n_left = from_frame->n_vectors;
1197       while (n_left > 0)
1198         {
1199           vlib_buffer_t *b0;
1200           bi0 = from[0];
1201           from++;
1202           n_left--;
1203           b0 = vlib_get_buffer (vm, bi0);
1204           if (vnet_is_packet_pcaped (pp, b0, ~0))
1205             pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
1206         }
1207     }
1208 }
1209
1210 static_always_inline void
1211 ethernet_input_inline (vlib_main_t * vm,
1212                        vlib_node_runtime_t * node,
1213                        u32 * from, u32 n_packets,
1214                        ethernet_input_variant_t variant)
1215 {
1216   vnet_main_t *vnm = vnet_get_main ();
1217   ethernet_main_t *em = &ethernet_main;
1218   vlib_node_runtime_t *error_node;
1219   u32 n_left_from, next_index, *to_next;
1220   u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
1221   u32 thread_index = vm->thread_index;
1222   u32 cached_sw_if_index = ~0;
1223   u32 cached_is_l2 = 0;         /* shut up gcc */
1224   vnet_hw_interface_t *hi = NULL;       /* used for main interface only */
1225   ethernet_interface_t *ei = NULL;
1226   vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
1227   vlib_buffer_t **b = bufs;
1228
1229   if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
1230     error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
1231   else
1232     error_node = node;
1233
1234   n_left_from = n_packets;
1235
1236   next_index = node->cached_next_index;
1237   stats_sw_if_index = node->runtime_data[0];
1238   stats_n_packets = stats_n_bytes = 0;
1239   vlib_get_buffers (vm, from, bufs, n_left_from);
1240
1241   while (n_left_from > 0)
1242     {
1243       u32 n_left_to_next;
1244
1245       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1246
1247       while (n_left_from >= 4 && n_left_to_next >= 2)
1248         {
1249           u32 bi0, bi1;
1250           vlib_buffer_t *b0, *b1;
1251           u8 next0, next1, error0, error1;
1252           u16 type0, orig_type0, type1, orig_type1;
1253           u16 outer_id0, inner_id0, outer_id1, inner_id1;
1254           u32 match_flags0, match_flags1;
1255           u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1,
1256             new_sw_if_index1, len1;
1257           vnet_hw_interface_t *hi0, *hi1;
1258           main_intf_t *main_intf0, *main_intf1;
1259           vlan_intf_t *vlan_intf0, *vlan_intf1;
1260           qinq_intf_t *qinq_intf0, *qinq_intf1;
1261           u32 is_l20, is_l21;
1262           ethernet_header_t *e0, *e1;
1263           u64 dmacs[2];
1264           u8 dmacs_bad[2];
1265
1266           /* Prefetch next iteration. */
1267           {
1268             vlib_prefetch_buffer_header (b[2], STORE);
1269             vlib_prefetch_buffer_header (b[3], STORE);
1270
1271             CLIB_PREFETCH (b[2]->data, sizeof (ethernet_header_t), LOAD);
1272             CLIB_PREFETCH (b[3]->data, sizeof (ethernet_header_t), LOAD);
1273           }
1274
1275           bi0 = from[0];
1276           bi1 = from[1];
1277           to_next[0] = bi0;
1278           to_next[1] = bi1;
1279           from += 2;
1280           to_next += 2;
1281           n_left_to_next -= 2;
1282           n_left_from -= 2;
1283
1284           b0 = b[0];
1285           b1 = b[1];
1286           b += 2;
1287
1288           error0 = error1 = ETHERNET_ERROR_NONE;
1289           e0 = vlib_buffer_get_current (b0);
1290           type0 = clib_net_to_host_u16 (e0->type);
1291           e1 = vlib_buffer_get_current (b1);
1292           type1 = clib_net_to_host_u16 (e1->type);
1293
1294           /* Set the L2 header offset for all packets */
1295           vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1296           vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
1297           b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1298           b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1299
1300           /* Speed-path for the untagged case */
1301           if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1302                             && !ethernet_frame_is_any_tagged_x2 (type0,
1303                                                                  type1)))
1304             {
1305               main_intf_t *intf0;
1306               subint_config_t *subint0;
1307               u32 sw_if_index0, sw_if_index1;
1308
1309               sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1310               sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1311               is_l20 = cached_is_l2;
1312
1313               /* This is probably wholly unnecessary */
1314               if (PREDICT_FALSE (sw_if_index0 != sw_if_index1))
1315                 goto slowpath;
1316
1317               /* Now sw_if_index0 == sw_if_index1  */
1318               if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1319                 {
1320                   cached_sw_if_index = sw_if_index0;
1321                   hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1322                   ei = ethernet_get_interface (em, hi->hw_if_index);
1323                   intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1324                   subint0 = &intf0->untagged_subint;
1325                   cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1326                 }
1327
1328               if (PREDICT_TRUE (is_l20 != 0))
1329                 {
1330                   vnet_buffer (b0)->l3_hdr_offset =
1331                     vnet_buffer (b0)->l2_hdr_offset +
1332                     sizeof (ethernet_header_t);
1333                   vnet_buffer (b1)->l3_hdr_offset =
1334                     vnet_buffer (b1)->l2_hdr_offset +
1335                     sizeof (ethernet_header_t);
1336                   b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1337                   b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1338                   next0 = em->l2_next;
1339                   vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1340                   next1 = em->l2_next;
1341                   vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
1342                 }
1343               else
1344                 {
1345                   if (ei && (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3))
1346                     goto skip_dmac_check01;
1347
1348                   dmacs[0] = *(u64 *) e0;
1349                   dmacs[1] = *(u64 *) e1;
1350
1351                   if (ei && vec_len (ei->secondary_addrs))
1352                     ethernet_input_inline_dmac_check (hi, dmacs,
1353                                                       dmacs_bad,
1354                                                       2 /* n_packets */ ,
1355                                                       ei,
1356                                                       1 /* have_sec_dmac */ );
1357                   else
1358                     ethernet_input_inline_dmac_check (hi, dmacs,
1359                                                       dmacs_bad,
1360                                                       2 /* n_packets */ ,
1361                                                       ei,
1362                                                       0 /* have_sec_dmac */ );
1363
1364                   if (dmacs_bad[0])
1365                     error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1366                   if (dmacs_bad[1])
1367                     error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1368
1369                 skip_dmac_check01:
1370                   vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1371                   determine_next_node (em, variant, 0, type0, b0,
1372                                        &error0, &next0);
1373                   vlib_buffer_advance (b1, sizeof (ethernet_header_t));
1374                   determine_next_node (em, variant, 0, type1, b1,
1375                                        &error1, &next1);
1376                 }
1377               goto ship_it01;
1378             }
1379
1380           /* Slow-path for the tagged case */
1381         slowpath:
1382           parse_header (variant,
1383                         b0,
1384                         &type0,
1385                         &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1386
1387           parse_header (variant,
1388                         b1,
1389                         &type1,
1390                         &orig_type1, &outer_id1, &inner_id1, &match_flags1);
1391
1392           old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1393           old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1394
1395           eth_vlan_table_lookups (em,
1396                                   vnm,
1397                                   old_sw_if_index0,
1398                                   orig_type0,
1399                                   outer_id0,
1400                                   inner_id0,
1401                                   &hi0,
1402                                   &main_intf0, &vlan_intf0, &qinq_intf0);
1403
1404           eth_vlan_table_lookups (em,
1405                                   vnm,
1406                                   old_sw_if_index1,
1407                                   orig_type1,
1408                                   outer_id1,
1409                                   inner_id1,
1410                                   &hi1,
1411                                   &main_intf1, &vlan_intf1, &qinq_intf1);
1412
1413           identify_subint (em,
1414                            hi0,
1415                            b0,
1416                            match_flags0,
1417                            main_intf0,
1418                            vlan_intf0,
1419                            qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1420
1421           identify_subint (em,
1422                            hi1,
1423                            b1,
1424                            match_flags1,
1425                            main_intf1,
1426                            vlan_intf1,
1427                            qinq_intf1, &new_sw_if_index1, &error1, &is_l21);
1428
1429           // Save RX sw_if_index for later nodes
1430           vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1431             error0 !=
1432             ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1433           vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1434             error1 !=
1435             ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
1436
1437           // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
1438           if (((new_sw_if_index0 != ~0)
1439                && (new_sw_if_index0 != old_sw_if_index0))
1440               || ((new_sw_if_index1 != ~0)
1441                   && (new_sw_if_index1 != old_sw_if_index1)))
1442             {
1443
1444               len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1445                 - vnet_buffer (b0)->l2_hdr_offset;
1446               len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
1447                 - vnet_buffer (b1)->l2_hdr_offset;
1448
1449               stats_n_packets += 2;
1450               stats_n_bytes += len0 + len1;
1451
1452               if (PREDICT_FALSE
1453                   (!(new_sw_if_index0 == stats_sw_if_index
1454                      && new_sw_if_index1 == stats_sw_if_index)))
1455                 {
1456                   stats_n_packets -= 2;
1457                   stats_n_bytes -= len0 + len1;
1458
1459                   if (new_sw_if_index0 != old_sw_if_index0
1460                       && new_sw_if_index0 != ~0)
1461                     vlib_increment_combined_counter (vnm->
1462                                                      interface_main.combined_sw_if_counters
1463                                                      +
1464                                                      VNET_INTERFACE_COUNTER_RX,
1465                                                      thread_index,
1466                                                      new_sw_if_index0, 1,
1467                                                      len0);
1468                   if (new_sw_if_index1 != old_sw_if_index1
1469                       && new_sw_if_index1 != ~0)
1470                     vlib_increment_combined_counter (vnm->
1471                                                      interface_main.combined_sw_if_counters
1472                                                      +
1473                                                      VNET_INTERFACE_COUNTER_RX,
1474                                                      thread_index,
1475                                                      new_sw_if_index1, 1,
1476                                                      len1);
1477
1478                   if (new_sw_if_index0 == new_sw_if_index1)
1479                     {
1480                       if (stats_n_packets > 0)
1481                         {
1482                           vlib_increment_combined_counter
1483                             (vnm->interface_main.combined_sw_if_counters
1484                              + VNET_INTERFACE_COUNTER_RX,
1485                              thread_index,
1486                              stats_sw_if_index,
1487                              stats_n_packets, stats_n_bytes);
1488                           stats_n_packets = stats_n_bytes = 0;
1489                         }
1490                       stats_sw_if_index = new_sw_if_index0;
1491                     }
1492                 }
1493             }
1494
1495           if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1496             is_l20 = is_l21 = 0;
1497
1498           determine_next_node (em, variant, is_l20, type0, b0, &error0,
1499                                &next0);
1500           determine_next_node (em, variant, is_l21, type1, b1, &error1,
1501                                &next1);
1502
1503         ship_it01:
1504           b0->error = error_node->errors[error0];
1505           b1->error = error_node->errors[error1];
1506
1507           // verify speculative enqueue
1508           vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1509                                            n_left_to_next, bi0, bi1, next0,
1510                                            next1);
1511         }
1512
1513       while (n_left_from > 0 && n_left_to_next > 0)
1514         {
1515           u32 bi0;
1516           vlib_buffer_t *b0;
1517           u8 error0, next0;
1518           u16 type0, orig_type0;
1519           u16 outer_id0, inner_id0;
1520           u32 match_flags0;
1521           u32 old_sw_if_index0, new_sw_if_index0, len0;
1522           vnet_hw_interface_t *hi0;
1523           main_intf_t *main_intf0;
1524           vlan_intf_t *vlan_intf0;
1525           qinq_intf_t *qinq_intf0;
1526           ethernet_header_t *e0;
1527           u32 is_l20;
1528           u64 dmacs[2];
1529           u8 dmacs_bad[2];
1530
1531           // Prefetch next iteration
1532           if (n_left_from > 1)
1533             {
1534               vlib_prefetch_buffer_header (b[1], STORE);
1535               clib_prefetch_load (b[1]->data);
1536             }
1537
1538           bi0 = from[0];
1539           to_next[0] = bi0;
1540           from += 1;
1541           to_next += 1;
1542           n_left_from -= 1;
1543           n_left_to_next -= 1;
1544
1545           b0 = b[0];
1546           b += 1;
1547
1548           error0 = ETHERNET_ERROR_NONE;
1549           e0 = vlib_buffer_get_current (b0);
1550           type0 = clib_net_to_host_u16 (e0->type);
1551
1552           /* Set the L2 header offset for all packets */
1553           vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
1554           b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
1555
1556           /* Speed-path for the untagged case */
1557           if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
1558                             && !ethernet_frame_is_tagged (type0)))
1559             {
1560               main_intf_t *intf0;
1561               subint_config_t *subint0;
1562               u32 sw_if_index0;
1563
1564               sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1565               is_l20 = cached_is_l2;
1566
1567               if (PREDICT_FALSE (cached_sw_if_index != sw_if_index0))
1568                 {
1569                   cached_sw_if_index = sw_if_index0;
1570                   hi = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1571                   ei = ethernet_get_interface (em, hi->hw_if_index);
1572                   intf0 = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1573                   subint0 = &intf0->untagged_subint;
1574                   cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
1575                 }
1576
1577
1578               if (PREDICT_TRUE (is_l20 != 0))
1579                 {
1580                   vnet_buffer (b0)->l3_hdr_offset =
1581                     vnet_buffer (b0)->l2_hdr_offset +
1582                     sizeof (ethernet_header_t);
1583                   b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
1584                   next0 = em->l2_next;
1585                   vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
1586                 }
1587               else
1588                 {
1589                   if (ei && ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)
1590                     goto skip_dmac_check0;
1591
1592                   dmacs[0] = *(u64 *) e0;
1593
1594                   if (ei)
1595                     {
1596                       if (vec_len (ei->secondary_addrs))
1597                         ethernet_input_inline_dmac_check (
1598                           hi, dmacs, dmacs_bad, 1 /* n_packets */, ei,
1599                           1 /* have_sec_dmac */);
1600                       else
1601                         ethernet_input_inline_dmac_check (
1602                           hi, dmacs, dmacs_bad, 1 /* n_packets */, ei,
1603                           0 /* have_sec_dmac */);
1604
1605                       if (dmacs_bad[0])
1606                         error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
1607                     }
1608
1609                 skip_dmac_check0:
1610                   vlib_buffer_advance (b0, sizeof (ethernet_header_t));
1611                   determine_next_node (em, variant, 0, type0, b0,
1612                                        &error0, &next0);
1613                 }
1614               goto ship_it0;
1615             }
1616
1617           /* Slow-path for the tagged case */
1618           parse_header (variant,
1619                         b0,
1620                         &type0,
1621                         &orig_type0, &outer_id0, &inner_id0, &match_flags0);
1622
1623           old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1624
1625           eth_vlan_table_lookups (em,
1626                                   vnm,
1627                                   old_sw_if_index0,
1628                                   orig_type0,
1629                                   outer_id0,
1630                                   inner_id0,
1631                                   &hi0,
1632                                   &main_intf0, &vlan_intf0, &qinq_intf0);
1633
1634           identify_subint (em,
1635                            hi0,
1636                            b0,
1637                            match_flags0,
1638                            main_intf0,
1639                            vlan_intf0,
1640                            qinq_intf0, &new_sw_if_index0, &error0, &is_l20);
1641
1642           // Save RX sw_if_index for later nodes
1643           vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1644             error0 !=
1645             ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
1646
1647           // Increment subinterface stats
1648           // Note that interface-level counters have already been incremented
1649           // prior to calling this function. Thus only subinterface counters
1650           // are incremented here.
1651           //
1652           // Interface level counters include packets received on the main
1653           // interface and all subinterfaces. Subinterface level counters
1654           // include only those packets received on that subinterface
1655           // Increment stats if the subint is valid and it is not the main intf
1656           if ((new_sw_if_index0 != ~0)
1657               && (new_sw_if_index0 != old_sw_if_index0))
1658             {
1659
1660               len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
1661                 - vnet_buffer (b0)->l2_hdr_offset;
1662
1663               stats_n_packets += 1;
1664               stats_n_bytes += len0;
1665
1666               // Batch stat increments from the same subinterface so counters
1667               // don't need to be incremented for every packet.
1668               if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index))
1669                 {
1670                   stats_n_packets -= 1;
1671                   stats_n_bytes -= len0;
1672
1673                   if (new_sw_if_index0 != ~0)
1674                     vlib_increment_combined_counter
1675                       (vnm->interface_main.combined_sw_if_counters
1676                        + VNET_INTERFACE_COUNTER_RX,
1677                        thread_index, new_sw_if_index0, 1, len0);
1678                   if (stats_n_packets > 0)
1679                     {
1680                       vlib_increment_combined_counter
1681                         (vnm->interface_main.combined_sw_if_counters
1682                          + VNET_INTERFACE_COUNTER_RX,
1683                          thread_index,
1684                          stats_sw_if_index, stats_n_packets, stats_n_bytes);
1685                       stats_n_packets = stats_n_bytes = 0;
1686                     }
1687                   stats_sw_if_index = new_sw_if_index0;
1688                 }
1689             }
1690
1691           if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
1692             is_l20 = 0;
1693
1694           determine_next_node (em, variant, is_l20, type0, b0, &error0,
1695                                &next0);
1696
1697         ship_it0:
1698           b0->error = error_node->errors[error0];
1699
1700           // verify speculative enqueue
1701           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1702                                            to_next, n_left_to_next,
1703                                            bi0, next0);
1704         }
1705
1706       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1707     }
1708
1709   // Increment any remaining batched stats
1710   if (stats_n_packets > 0)
1711     {
1712       vlib_increment_combined_counter
1713         (vnm->interface_main.combined_sw_if_counters
1714          + VNET_INTERFACE_COUNTER_RX,
1715          thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
1716       node->runtime_data[0] = stats_sw_if_index;
1717     }
1718 }
1719
1720 VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
1721                                     vlib_node_runtime_t * node,
1722                                     vlib_frame_t * frame)
1723 {
1724   vnet_main_t *vnm = vnet_get_main ();
1725   u32 *from = vlib_frame_vector_args (frame);
1726   u32 n_packets = frame->n_vectors;
1727
1728   ethernet_input_trace (vm, node, frame);
1729
1730   if (frame->flags & ETH_INPUT_FRAME_F_SINGLE_SW_IF_IDX)
1731     {
1732       ethernet_input_frame_t *ef = vlib_frame_scalar_args (frame);
1733       int ip4_cksum_ok = (frame->flags & ETH_INPUT_FRAME_F_IP4_CKSUM_OK) != 0;
1734       vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, ef->hw_if_index);
1735       eth_input_single_int (vm, node, hi, from, n_packets, ip4_cksum_ok);
1736     }
1737   else
1738     ethernet_input_inline (vm, node, from, n_packets,
1739                            ETHERNET_INPUT_VARIANT_ETHERNET);
1740   return n_packets;
1741 }
1742
1743 VLIB_NODE_FN (ethernet_input_type_node) (vlib_main_t * vm,
1744                                          vlib_node_runtime_t * node,
1745                                          vlib_frame_t * from_frame)
1746 {
1747   u32 *from = vlib_frame_vector_args (from_frame);
1748   u32 n_packets = from_frame->n_vectors;
1749   ethernet_input_trace (vm, node, from_frame);
1750   ethernet_input_inline (vm, node, from, n_packets,
1751                          ETHERNET_INPUT_VARIANT_ETHERNET_TYPE);
1752   return n_packets;
1753 }
1754
1755 VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
1756                                            vlib_node_runtime_t * node,
1757                                            vlib_frame_t * from_frame)
1758 {
1759   u32 *from = vlib_frame_vector_args (from_frame);
1760   u32 n_packets = from_frame->n_vectors;
1761   ethernet_input_trace (vm, node, from_frame);
1762   ethernet_input_inline (vm, node, from, n_packets,
1763                          ETHERNET_INPUT_VARIANT_NOT_L2);
1764   return n_packets;
1765 }
1766
1767
1768 // Return the subinterface config struct for the given sw_if_index
1769 // Also return via parameter the appropriate match flags for the
1770 // configured number of tags.
1771 // On error (unsupported or not ethernet) return 0.
1772 static subint_config_t *
1773 ethernet_sw_interface_get_config (vnet_main_t * vnm,
1774                                   u32 sw_if_index,
1775                                   u32 * flags, u32 * unsupported)
1776 {
1777   ethernet_main_t *em = &ethernet_main;
1778   vnet_hw_interface_t *hi;
1779   vnet_sw_interface_t *si;
1780   main_intf_t *main_intf;
1781   vlan_table_t *vlan_table;
1782   qinq_table_t *qinq_table;
1783   subint_config_t *subint = 0;
1784
1785   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1786
1787   if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index))
1788     {
1789       *unsupported = 0;
1790       goto done;                // non-ethernet interface
1791     }
1792
1793   // ensure there's an entry for the main intf (shouldn't really be necessary)
1794   vec_validate (em->main_intfs, hi->hw_if_index);
1795   main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
1796
1797   // Locate the subint for the given ethernet config
1798   si = vnet_get_sw_interface (vnm, sw_if_index);
1799
1800   if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
1801     {
1802       p2p_ethernet_main_t *p2pm = &p2p_main;
1803       u32 p2pe_sw_if_index =
1804         p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
1805       if (p2pe_sw_if_index == ~0)
1806         {
1807           pool_get (p2pm->p2p_subif_pool, subint);
1808           si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
1809         }
1810       else
1811         subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
1812       *flags = SUBINT_CONFIG_P2P;
1813     }
1814   else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
1815     {
1816       pipe_t *pipe;
1817
1818       pipe = pipe_get (sw_if_index);
1819       subint = &pipe->subint;
1820       *flags = SUBINT_CONFIG_P2P;
1821     }
1822   else if (si->sub.eth.flags.default_sub)
1823     {
1824       subint = &main_intf->default_subint;
1825       *flags = SUBINT_CONFIG_MATCH_1_TAG |
1826         SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
1827     }
1828   else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
1829     {
1830       // if no flags are set then this is a main interface
1831       // so treat as untagged
1832       subint = &main_intf->untagged_subint;
1833       *flags = SUBINT_CONFIG_MATCH_0_TAG;
1834     }
1835   else
1836     {
1837       // one or two tags
1838       // first get the vlan table
1839       if (si->sub.eth.flags.dot1ad)
1840         {
1841           if (main_intf->dot1ad_vlans == 0)
1842             {
1843               // Allocate a vlan table from the pool
1844               pool_get (em->vlan_pool, vlan_table);
1845               main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
1846             }
1847           else
1848             {
1849               // Get ptr to existing vlan table
1850               vlan_table =
1851                 vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
1852             }
1853         }
1854       else
1855         {                       // dot1q
1856           if (main_intf->dot1q_vlans == 0)
1857             {
1858               // Allocate a vlan table from the pool
1859               pool_get (em->vlan_pool, vlan_table);
1860               main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
1861             }
1862           else
1863             {
1864               // Get ptr to existing vlan table
1865               vlan_table =
1866                 vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
1867             }
1868         }
1869
1870       if (si->sub.eth.flags.one_tag)
1871         {
1872           *flags = si->sub.eth.flags.exact_match ?
1873             SUBINT_CONFIG_MATCH_1_TAG :
1874             (SUBINT_CONFIG_MATCH_1_TAG |
1875              SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1876
1877           if (si->sub.eth.flags.outer_vlan_id_any)
1878             {
1879               // not implemented yet
1880               *unsupported = 1;
1881               goto done;
1882             }
1883           else
1884             {
1885               // a single vlan, a common case
1886               subint =
1887                 &vlan_table->vlans[si->sub.eth.
1888                                    outer_vlan_id].single_tag_subint;
1889             }
1890
1891         }
1892       else
1893         {
1894           // Two tags
1895           *flags = si->sub.eth.flags.exact_match ?
1896             SUBINT_CONFIG_MATCH_2_TAG :
1897             (SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG);
1898
1899           if (si->sub.eth.flags.outer_vlan_id_any
1900               && si->sub.eth.flags.inner_vlan_id_any)
1901             {
1902               // not implemented yet
1903               *unsupported = 1;
1904               goto done;
1905             }
1906
1907           if (si->sub.eth.flags.inner_vlan_id_any)
1908             {
1909               // a specific outer and "any" inner
1910               // don't need a qinq table for this
1911               subint =
1912                 &vlan_table->vlans[si->sub.eth.
1913                                    outer_vlan_id].inner_any_subint;
1914               if (si->sub.eth.flags.exact_match)
1915                 {
1916                   *flags = SUBINT_CONFIG_MATCH_2_TAG;
1917                 }
1918               else
1919                 {
1920                   *flags = SUBINT_CONFIG_MATCH_2_TAG |
1921                     SUBINT_CONFIG_MATCH_3_TAG;
1922                 }
1923             }
1924           else
1925             {
1926               // a specific outer + specific innner vlan id, a common case
1927
1928               // get the qinq table
1929               if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0)
1930                 {
1931                   // Allocate a qinq table from the pool
1932                   pool_get (em->qinq_pool, qinq_table);
1933                   vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs =
1934                     qinq_table - em->qinq_pool;
1935                 }
1936               else
1937                 {
1938                   // Get ptr to existing qinq table
1939                   qinq_table =
1940                     vec_elt_at_index (em->qinq_pool,
1941                                       vlan_table->vlans[si->sub.
1942                                                         eth.outer_vlan_id].
1943                                       qinqs);
1944                 }
1945               subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
1946             }
1947         }
1948     }
1949
1950 done:
1951   return subint;
1952 }
1953
1954 static clib_error_t *
1955 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
1956 {
1957   subint_config_t *subint;
1958   u32 placeholder_flags;
1959   u32 placeholder_unsup;
1960   clib_error_t *error = 0;
1961
1962   // Find the config for this subinterface
1963   subint =
1964     ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1965                                       &placeholder_unsup);
1966
1967   if (subint == 0)
1968     {
1969       // not implemented yet or not ethernet
1970       goto done;
1971     }
1972
1973   subint->sw_if_index =
1974     ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
1975
1976 done:
1977   return error;
1978 }
1979
1980 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
1981
1982
1983 #ifndef CLIB_MARCH_VARIANT
1984 // Set the L2/L3 mode for the subinterface
1985 void
1986 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
1987 {
1988   subint_config_t *subint;
1989   u32 placeholder_flags;
1990   u32 placeholder_unsup;
1991   int is_port;
1992   vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
1993
1994   is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
1995
1996   // Find the config for this subinterface
1997   subint =
1998     ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
1999                                       &placeholder_unsup);
2000
2001   if (subint == 0)
2002     {
2003       // unimplemented or not ethernet
2004       goto done;
2005     }
2006
2007   // Double check that the config we found is for our interface (or the interface is down)
2008   ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2009
2010   if (l2)
2011     {
2012       subint->flags |= SUBINT_CONFIG_L2;
2013       if (is_port)
2014         subint->flags |=
2015           SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
2016           | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
2017     }
2018   else
2019     {
2020       subint->flags &= ~SUBINT_CONFIG_L2;
2021       if (is_port)
2022         subint->flags &=
2023           ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
2024             | SUBINT_CONFIG_MATCH_3_TAG);
2025     }
2026
2027 done:
2028   return;
2029 }
2030
2031 /*
2032  * Set the L2/L3 mode for the subinterface regardless of port
2033  */
2034 void
2035 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
2036                                           u32 sw_if_index, u32 l2)
2037 {
2038   subint_config_t *subint;
2039   u32 placeholder_flags;
2040   u32 placeholder_unsup;
2041
2042   /* Find the config for this subinterface */
2043   subint =
2044     ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags,
2045                                       &placeholder_unsup);
2046
2047   if (subint == 0)
2048     {
2049       /* unimplemented or not ethernet */
2050       goto done;
2051     }
2052
2053   /*
2054    * Double check that the config we found is for our interface (or the
2055    * interface is down)
2056    */
2057   ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
2058
2059   if (l2)
2060     {
2061       subint->flags |= SUBINT_CONFIG_L2;
2062     }
2063   else
2064     {
2065       subint->flags &= ~SUBINT_CONFIG_L2;
2066     }
2067
2068 done:
2069   return;
2070 }
2071 #endif
2072
2073 static clib_error_t *
2074 ethernet_sw_interface_add_del (vnet_main_t * vnm,
2075                                u32 sw_if_index, u32 is_create)
2076 {
2077   clib_error_t *error = 0;
2078   subint_config_t *subint;
2079   u32 match_flags;
2080   u32 unsupported = 0;
2081
2082   // Find the config for this subinterface
2083   subint =
2084     ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags,
2085                                       &unsupported);
2086
2087   if (subint == 0)
2088     {
2089       // not implemented yet or not ethernet
2090       if (unsupported)
2091         {
2092           // this is the NYI case
2093           error = clib_error_return (0, "not implemented yet");
2094         }
2095       goto done;
2096     }
2097
2098   if (!is_create)
2099     {
2100       subint->flags = 0;
2101       return error;
2102     }
2103
2104   // Initialize the subint
2105   if (subint->flags & SUBINT_CONFIG_VALID)
2106     {
2107       // Error vlan already in use
2108       error = clib_error_return (0, "vlan is already in use");
2109     }
2110   else
2111     {
2112       // Note that config is L3 by default
2113       subint->flags = SUBINT_CONFIG_VALID | match_flags;
2114       subint->sw_if_index = ~0; // because interfaces are initially down
2115     }
2116
2117 done:
2118   return error;
2119 }
2120
2121 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
2122
2123 static char *ethernet_error_strings[] = {
2124 #define ethernet_error(n,c,s) s,
2125 #include "error.def"
2126 #undef ethernet_error
2127 };
2128
2129 VLIB_REGISTER_NODE (ethernet_input_node) = {
2130   .name = "ethernet-input",
2131   /* Takes a vector of packets. */
2132   .vector_size = sizeof (u32),
2133   .scalar_size = sizeof (ethernet_input_frame_t),
2134   .n_errors = ETHERNET_N_ERROR,
2135   .error_strings = ethernet_error_strings,
2136   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2137   .next_nodes = {
2138 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2139     foreach_ethernet_input_next
2140 #undef _
2141   },
2142   .format_buffer = format_ethernet_header_with_length,
2143   .format_trace = format_ethernet_input_trace,
2144   .unformat_buffer = unformat_ethernet_header,
2145 };
2146
2147 VLIB_REGISTER_NODE (ethernet_input_type_node) = {
2148   .name = "ethernet-input-type",
2149   /* Takes a vector of packets. */
2150   .vector_size = sizeof (u32),
2151   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2152   .next_nodes = {
2153 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2154     foreach_ethernet_input_next
2155 #undef _
2156   },
2157 };
2158
2159 VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
2160   .name = "ethernet-input-not-l2",
2161   /* Takes a vector of packets. */
2162   .vector_size = sizeof (u32),
2163   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
2164   .next_nodes = {
2165 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
2166     foreach_ethernet_input_next
2167 #undef _
2168   },
2169 };
2170
2171 #ifndef CLIB_MARCH_VARIANT
2172 void
2173 ethernet_set_rx_redirect (vnet_main_t * vnm,
2174                           vnet_hw_interface_t * hi, u32 enable)
2175 {
2176   // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
2177   // don't go directly to ip4-input)
2178   vnet_hw_interface_rx_redirect_to_node
2179     (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
2180 }
2181
2182
2183 /*
2184  * Initialization and registration for the next_by_ethernet structure
2185  */
2186
2187 clib_error_t *
2188 next_by_ethertype_init (next_by_ethertype_t * l3_next)
2189 {
2190   l3_next->input_next_by_type = sparse_vec_new
2191     ( /* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
2192      /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
2193
2194   vec_validate (l3_next->sparse_index_by_input_next_index,
2195                 ETHERNET_INPUT_NEXT_DROP);
2196   vec_validate (l3_next->sparse_index_by_input_next_index,
2197                 ETHERNET_INPUT_NEXT_PUNT);
2198   l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP] =
2199     SPARSE_VEC_INVALID_INDEX;
2200   l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT] =
2201     SPARSE_VEC_INVALID_INDEX;
2202
2203   /*
2204    * Make sure we don't wipe out an ethernet registration by mistake
2205    * Can happen if init function ordering constraints are missing.
2206    */
2207   if (CLIB_DEBUG > 0)
2208     {
2209       ethernet_main_t *em = &ethernet_main;
2210       ASSERT (em->next_by_ethertype_register_called == 0);
2211     }
2212
2213   return 0;
2214 }
2215
2216 // Add an ethertype -> next index mapping to the structure
2217 clib_error_t *
2218 next_by_ethertype_register (next_by_ethertype_t * l3_next,
2219                             u32 ethertype, u32 next_index)
2220 {
2221   u32 i;
2222   u16 *n;
2223   ethernet_main_t *em = &ethernet_main;
2224
2225   if (CLIB_DEBUG > 0)
2226     {
2227       ethernet_main_t *em = &ethernet_main;
2228       em->next_by_ethertype_register_called = 1;
2229     }
2230
2231   /* Setup ethernet type -> next index sparse vector mapping. */
2232   n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
2233   n[0] = next_index;
2234
2235   /* Rebuild next index -> sparse index inverse mapping when sparse vector
2236      is updated. */
2237   vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
2238   for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
2239     l3_next->
2240       sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
2241
2242   // do not allow the cached next index's to be updated if L3
2243   // redirect is enabled, as it will have overwritten them
2244   if (!em->redirect_l3)
2245     {
2246       // Cache common ethertypes directly
2247       if (ethertype == ETHERNET_TYPE_IP4)
2248         {
2249           l3_next->input_next_ip4 = next_index;
2250         }
2251       else if (ethertype == ETHERNET_TYPE_IP6)
2252         {
2253           l3_next->input_next_ip6 = next_index;
2254         }
2255       else if (ethertype == ETHERNET_TYPE_MPLS)
2256         {
2257           l3_next->input_next_mpls = next_index;
2258         }
2259     }
2260   return 0;
2261 }
2262
2263 void
2264 ethernet_setup_node (vlib_main_t *vm, u32 node_index)
2265 {
2266   vlib_node_t *n = vlib_get_node (vm, node_index);
2267   pg_node_t *pn = pg_get_node (node_index);
2268
2269   n->format_buffer = format_ethernet_header_with_length;
2270   n->unformat_buffer = unformat_ethernet_header;
2271   pn->unformat_edit = unformat_pg_ethernet_header;
2272 }
2273
2274 void
2275 ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
2276 {
2277   __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
2278   __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
2279
2280   ethernet_setup_node (vm, ethernet_input_node.index);
2281   ethernet_setup_node (vm, ethernet_input_type_node.index);
2282   ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
2283
2284   next_by_ethertype_init (&em->l3_next);
2285
2286   // Initialize pools and vector for vlan parsing
2287   vec_validate (em->main_intfs, 10);    // 10 main interfaces
2288   pool_alloc (em->vlan_pool, 10);
2289   pool_alloc (em->qinq_pool, 1);
2290
2291   // The first vlan pool will always be reserved for an invalid table
2292   pool_get (em->vlan_pool, invalid_vlan_table); // first id = 0
2293   // The first qinq pool will always be reserved for an invalid table
2294   pool_get (em->qinq_pool, invalid_qinq_table); // first id = 0
2295 }
2296
2297 void
2298 ethernet_register_input_type (vlib_main_t * vm,
2299                               ethernet_type_t type, u32 node_index)
2300 {
2301   ethernet_main_t *em = &ethernet_main;
2302   ethernet_type_info_t *ti;
2303   u32 i;
2304
2305   {
2306     clib_error_t *error = vlib_call_init_function (vm, ethernet_init);
2307     if (error)
2308       clib_error_report (error);
2309   }
2310
2311   ti = ethernet_get_type_info (em, type);
2312   if (ti == 0)
2313     {
2314       clib_warning ("type_info NULL for type %d", type);
2315       return;
2316     }
2317   ti->node_index = node_index;
2318   ti->next_index = vlib_node_add_next (vm,
2319                                        ethernet_input_node.index, node_index);
2320   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2321   ASSERT (i == ti->next_index);
2322
2323   i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2324   ASSERT (i == ti->next_index);
2325
2326   // Add the L3 node for this ethertype to the next nodes structure
2327   next_by_ethertype_register (&em->l3_next, type, ti->next_index);
2328
2329   // Call the registration functions for other nodes that want a mapping
2330   l2bvi_register_input_type (vm, type, node_index);
2331 }
2332
2333 void
2334 ethernet_register_l2_input (vlib_main_t * vm, u32 node_index)
2335 {
2336   ethernet_main_t *em = &ethernet_main;
2337   u32 i;
2338
2339   em->l2_next =
2340     vlib_node_add_next (vm, ethernet_input_node.index, node_index);
2341
2342   /*
2343    * Even if we never use these arcs, we have to align the next indices...
2344    */
2345   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2346
2347   ASSERT (i == em->l2_next);
2348
2349   i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2350   ASSERT (i == em->l2_next);
2351 }
2352
2353 // Register a next node for L3 redirect, and enable L3 redirect
2354 void
2355 ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
2356 {
2357   ethernet_main_t *em = &ethernet_main;
2358   u32 i;
2359
2360   em->redirect_l3 = 1;
2361   em->redirect_l3_next = vlib_node_add_next (vm,
2362                                              ethernet_input_node.index,
2363                                              node_index);
2364   /*
2365    * Change the cached next nodes to the redirect node
2366    */
2367   em->l3_next.input_next_ip4 = em->redirect_l3_next;
2368   em->l3_next.input_next_ip6 = em->redirect_l3_next;
2369   em->l3_next.input_next_mpls = em->redirect_l3_next;
2370
2371   /*
2372    * Even if we never use these arcs, we have to align the next indices...
2373    */
2374   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
2375
2376   ASSERT (i == em->redirect_l3_next);
2377
2378   i = vlib_node_add_next (vm, ethernet_input_not_l2_node.index, node_index);
2379
2380   ASSERT (i == em->redirect_l3_next);
2381 }
2382 #endif
2383
2384 /*
2385  * fd.io coding-style-patch-verification: ON
2386  *
2387  * Local Variables:
2388  * eval: (c-set-style "gnu")
2389  * End:
2390  */