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