57a699594fc1a40080967ffee1f8441e2d19914f
[vpp.git] / vnet / vnet / ethernet / node.c
1 /*
2  * Copyright (c) 2015 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 <vppinfra/sparse_vec.h>
44 #include <vnet/l2/l2_bvi.h>
45
46
47 #define foreach_ethernet_input_next             \
48   _ (PUNT, "error-punt")                        \
49   _ (DROP, "error-drop")                        \
50   _ (LLC, "llc-input")                          
51
52 typedef enum {
53 #define _(s,n) ETHERNET_INPUT_NEXT_##s,
54   foreach_ethernet_input_next
55 #undef _
56   ETHERNET_INPUT_N_NEXT,
57 } ethernet_input_next_t;
58
59 typedef struct {
60   u8 packet_data[32];
61 } ethernet_input_trace_t;
62
63 static u8 * format_ethernet_input_trace (u8 * s, va_list * va)
64 {
65   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
66   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
67   ethernet_input_trace_t * t = va_arg (*va, ethernet_input_trace_t *);
68
69   s = format (s, "%U", format_ethernet_header, t->packet_data);
70
71   return s;
72 }
73
74 vlib_node_registration_t ethernet_input_node;
75
76 typedef enum {
77   ETHERNET_INPUT_VARIANT_ETHERNET,
78   ETHERNET_INPUT_VARIANT_ETHERNET_TYPE,
79   ETHERNET_INPUT_VARIANT_VLAN,
80   ETHERNET_INPUT_VARIANT_NOT_L2,
81 } ethernet_input_variant_t;
82
83
84 // Parse the ethernet header to extract vlan tags and innermost ethertype
85 static_always_inline void
86 parse_header (ethernet_input_variant_t variant,
87               vlib_buffer_t * b0,
88               u16 * type, 
89               u16 * orig_type, 
90               u16 * outer_id,
91               u16 * inner_id,
92               u32 * match_flags) {
93   u8 vlan_count;
94
95   if (variant == ETHERNET_INPUT_VARIANT_ETHERNET 
96       || variant == ETHERNET_INPUT_VARIANT_NOT_L2) {
97     ethernet_header_t * e0;
98
99     e0 = (void *) (b0->data + b0->current_data);
100
101     vnet_buffer (b0)->ethernet.start_of_ethernet_header = b0->current_data;
102
103     vlib_buffer_advance (b0, sizeof (e0[0]));
104
105     *type = clib_net_to_host_u16(e0->type);
106   } else if (variant == ETHERNET_INPUT_VARIANT_ETHERNET_TYPE) {
107     // here when prior node was LLC/SNAP processing
108     u16 * e0;
109
110     e0 = (void *) (b0->data + b0->current_data);
111
112     vlib_buffer_advance (b0, sizeof (e0[0]));
113
114     *type = clib_net_to_host_u16(e0[0]);
115   }
116
117   // save for distinguishing between dot1q and dot1ad later
118   *orig_type = *type;
119
120   // default the tags to 0 (used if there is no corresponding tag)
121   *outer_id = 0;
122   *inner_id = 0;
123
124   *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_0_TAG;
125   vlan_count = 0;
126
127   // check for vlan encaps
128   if ((*type == ETHERNET_TYPE_VLAN) ||
129       (*type == ETHERNET_TYPE_DOT1AD) ||
130       (*type == ETHERNET_TYPE_VLAN_9100) ||
131       (*type == ETHERNET_TYPE_VLAN_9200))
132   {
133     ethernet_vlan_header_t * h0;
134     u16 tag;
135  
136     *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_1_TAG;
137
138     h0 = (void *) (b0->data + b0->current_data);
139
140     tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
141
142     *outer_id = tag & 0xfff;
143
144     *type = clib_net_to_host_u16(h0->type);
145
146     vlib_buffer_advance (b0, sizeof (h0[0]));
147     vlan_count = 1;
148
149     if (*type == ETHERNET_TYPE_VLAN) {
150       // Double tagged packet
151       *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_2_TAG;
152
153       h0 = (void *) (b0->data + b0->current_data);
154
155       tag = clib_net_to_host_u16 (h0->priority_cfi_and_id);
156
157       *inner_id = tag & 0xfff;
158
159       *type = clib_net_to_host_u16(h0->type);
160
161       vlib_buffer_advance (b0, sizeof (h0[0]));
162       vlan_count = 2;
163
164       if (*type == ETHERNET_TYPE_VLAN) {
165         // More than double tagged packet
166         *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_3_TAG;
167         vlan_count = 3; // "unknown" number, aka, 3-or-more
168       }
169     }
170   }
171   ethernet_buffer_set_vlan_count(b0, vlan_count);
172 }
173
174 // Determine the subinterface for this packet, given the result of the
175 // vlan table lookups and vlan header parsing. Check the most specific
176 // matches first.
177 static_always_inline void
178 identify_subint (vnet_hw_interface_t * hi,
179                  vlib_buffer_t * b0,
180                  u32 match_flags, 
181                  main_intf_t * main_intf, 
182                  vlan_intf_t * vlan_intf, 
183                  qinq_intf_t * qinq_intf, 
184                  u32 * new_sw_if_index, 
185                  u8 * error0, 
186                  u32 * is_l2) 
187 {
188   u32 matched;
189
190   matched = eth_identify_subint (hi, b0, match_flags, 
191                                  main_intf, vlan_intf, qinq_intf,
192                                  new_sw_if_index, error0, is_l2);
193
194   if (matched) {
195
196     // Perform L3 my-mac filter
197     // A unicast packet arriving on an L3 interface must have a dmac matching the interface mac.
198     // This is required for promiscuous mode, else we will forward packets we aren't supposed to.
199     if (!(*is_l2)) {
200       ethernet_header_t * e0;
201       e0 = (void *) (b0->data + vnet_buffer (b0)->ethernet.start_of_ethernet_header);
202
203       if (!(ethernet_address_cast(e0->dst_address))) {
204         if (!eth_mac_equal((u8 *)e0, hi->hw_address)) {
205           *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
206         }
207       }
208     }
209
210     // Check for down subinterface
211     *error0 = (*new_sw_if_index) != ~0 ? (*error0) : ETHERNET_ERROR_DOWN;
212   }
213 }
214
215 static_always_inline void
216 determine_next_node (ethernet_main_t * em,
217                      ethernet_input_variant_t variant,
218                      u32 is_l20, 
219                      u32 type0, 
220                      vlib_buffer_t * b0,
221                      u8 * error0,
222                      u8 * next0)
223 {
224   if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE)) {
225     // some error occurred
226     *next0 = ETHERNET_INPUT_NEXT_DROP;
227   } else if (is_l20) {
228     *next0 = em->l2_next;
229     // record the L2 len and reset the buffer so the L2 header is preserved
230     vnet_buffer(b0)->l2.l2_len = b0->current_data;
231     vlib_buffer_advance(b0, - ethernet_buffer_header_size(b0));
232
233   // check for common IP/MPLS ethertypes
234   } else if (type0 == ETHERNET_TYPE_IP4) {
235     *next0 = em->l3_next.input_next_ip4;
236   } else if (type0 == ETHERNET_TYPE_IP6) {
237     *next0 = em->l3_next.input_next_ip6;
238   } else if (type0 == ETHERNET_TYPE_MPLS_UNICAST) {
239     *next0 = em->l3_next.input_next_mpls;
240
241   } else if (em->redirect_l3) {
242     // L3 Redirect is on, the cached common next nodes will be
243     // pointing to the redirect node, catch the uncommon types here
244     *next0 = em->redirect_l3_next;
245   } else {
246     // uncommon ethertype, check table
247     u32 i0;
248     i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
249     *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
250     *error0 = i0 == SPARSE_VEC_INVALID_INDEX ? ETHERNET_ERROR_UNKNOWN_TYPE : *error0;
251
252     // The table is not populated with LLC values, so check that now.
253     // If variant is variant_ethernet then we came from LLC processing. Don't 
254     // go back there; drop instead using by keeping the drop/bad table result.
255     if ((type0 < 0x600) && (variant == ETHERNET_INPUT_VARIANT_ETHERNET)) {
256       *next0 = ETHERNET_INPUT_NEXT_LLC;
257     }
258   }
259 }
260
261 static_always_inline uword
262 ethernet_input_inline (vlib_main_t * vm,
263                        vlib_node_runtime_t * node,
264                        vlib_frame_t * from_frame,
265                        ethernet_input_variant_t variant)
266 {
267   vnet_main_t * vnm = vnet_get_main();
268   ethernet_main_t * em = &ethernet_main;
269   vlib_node_runtime_t * error_node;
270   u32 n_left_from, next_index, * from, * to_next;
271   u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
272   u32 cpu_index = os_get_cpu_number();
273
274   if (variant != ETHERNET_INPUT_VARIANT_ETHERNET)
275     error_node = vlib_node_get_runtime (vm, ethernet_input_node.index);
276   else
277     error_node = node;
278
279   from = vlib_frame_vector_args (from_frame);
280   n_left_from = from_frame->n_vectors;
281
282   if (node->flags & VLIB_NODE_FLAG_TRACE)
283     vlib_trace_frame_buffers_only (vm, node,
284                                    from,
285                                    n_left_from,
286                                    sizeof (from[0]),
287                                    sizeof (ethernet_input_trace_t));
288
289   next_index = node->cached_next_index;
290   stats_sw_if_index = node->runtime_data[0];
291   stats_n_packets = stats_n_bytes = 0;
292
293   while (n_left_from > 0)
294     {
295       u32 n_left_to_next;
296
297       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
298
299       while (n_left_from >= 4 && n_left_to_next >= 2)
300         {
301           u32 bi0, bi1;
302           vlib_buffer_t * b0, * b1;
303           u8 next0, next1, error0, error1;
304           u16 type0, orig_type0, type1, orig_type1;
305           u16 outer_id0, inner_id0, outer_id1, inner_id1;
306           u32 match_flags0, match_flags1;
307           u32 old_sw_if_index0, new_sw_if_index0, len0, old_sw_if_index1, new_sw_if_index1, len1;
308           vnet_hw_interface_t * hi0, * hi1;
309           main_intf_t * main_intf0, * main_intf1;
310           vlan_intf_t * vlan_intf0, * vlan_intf1;
311           qinq_intf_t * qinq_intf0, * qinq_intf1;
312           u32 is_l20, is_l21;
313
314           /* Prefetch next iteration. */
315           {
316             vlib_buffer_t * b2, * b3;
317
318             b2 = vlib_get_buffer (vm, from[2]);
319             b3 = vlib_get_buffer (vm, from[3]);
320
321             vlib_prefetch_buffer_header (b2, STORE);
322             vlib_prefetch_buffer_header (b3, STORE);
323
324             CLIB_PREFETCH (b2->data, sizeof (ethernet_header_t), LOAD);
325             CLIB_PREFETCH (b3->data, sizeof (ethernet_header_t), LOAD);
326           }
327
328           bi0 = from[0];
329           bi1 = from[1];
330           to_next[0] = bi0;
331           to_next[1] = bi1;
332           from += 2;
333           to_next += 2;
334           n_left_to_next -= 2;
335           n_left_from -= 2;
336
337           b0 = vlib_get_buffer (vm, bi0);
338           b1 = vlib_get_buffer (vm, bi1);
339
340           error0 = error1 = ETHERNET_ERROR_NONE;
341
342           parse_header (variant, 
343                         b0,
344                         &type0, 
345                         &orig_type0, 
346                         &outer_id0,
347                         &inner_id0,
348                         &match_flags0);
349
350           parse_header (variant, 
351                         b1,
352                         &type1, 
353                         &orig_type1, 
354                         &outer_id1,
355                         &inner_id1,
356                         &match_flags1);
357
358           old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
359           old_sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
360
361           eth_vlan_table_lookups (em, 
362                               vnm, 
363                               old_sw_if_index0, 
364                               orig_type0, 
365                               outer_id0,
366                               inner_id0,
367                               &hi0,
368                               &main_intf0,  
369                               &vlan_intf0, 
370                               &qinq_intf0);
371
372           eth_vlan_table_lookups (em, 
373                               vnm, 
374                               old_sw_if_index1, 
375                               orig_type1, 
376                               outer_id1,
377                               inner_id1,
378                               &hi1,
379                               &main_intf1,  
380                               &vlan_intf1, 
381                               &qinq_intf1);
382
383           identify_subint (hi0,
384                            b0,
385                            match_flags0, 
386                            main_intf0, 
387                            vlan_intf0, 
388                            qinq_intf0, 
389                            &new_sw_if_index0, 
390                            &error0, 
391                            &is_l20);
392
393           identify_subint (hi1,
394                            b1,
395                            match_flags1, 
396                            main_intf1, 
397                            vlan_intf1, 
398                            qinq_intf1, 
399                            &new_sw_if_index1, 
400                            &error1, 
401                            &is_l21);
402
403           // Save RX sw_if_index for later nodes
404           vnet_buffer (b0)->sw_if_index[VLIB_RX] = error0 != ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
405           vnet_buffer (b1)->sw_if_index[VLIB_RX] = error1 != ETHERNET_ERROR_NONE ? old_sw_if_index1 : new_sw_if_index1;
406
407           // Check if there is a stat to take (valid and non-main sw_if_index for pkt 0 or pkt 1)
408           if (((new_sw_if_index0 != ~0) && (new_sw_if_index0 != old_sw_if_index0)) ||
409               ((new_sw_if_index1 != ~0) && (new_sw_if_index1 != old_sw_if_index1))) {
410
411             len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
412                    - vnet_buffer (b0)->ethernet.start_of_ethernet_header;
413             len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
414                    - vnet_buffer (b1)->ethernet.start_of_ethernet_header;
415
416             stats_n_packets += 2;
417             stats_n_bytes += len0 + len1;
418
419               if (PREDICT_FALSE (! (new_sw_if_index0 == stats_sw_if_index && new_sw_if_index1 == stats_sw_if_index)))
420                 {
421                   stats_n_packets -= 2;
422                   stats_n_bytes -= len0 + len1;
423
424                   if (new_sw_if_index0 != old_sw_if_index0 && new_sw_if_index0 != ~0)
425                     vlib_increment_combined_counter 
426                         (vnm->interface_main.combined_sw_if_counters
427                          + VNET_INTERFACE_COUNTER_RX,
428                          cpu_index, 
429                          new_sw_if_index0,
430                          1,
431                          len0);
432                   if (new_sw_if_index1 != old_sw_if_index1 && new_sw_if_index1 != ~0)
433                     vlib_increment_combined_counter 
434                         (vnm->interface_main.combined_sw_if_counters
435                          + VNET_INTERFACE_COUNTER_RX,
436                          cpu_index, 
437                          new_sw_if_index1,
438                          1,
439                          len1);
440
441                   if (new_sw_if_index0 == new_sw_if_index1)
442                     {
443                       if (stats_n_packets > 0)
444                         {
445                           vlib_increment_combined_counter 
446                               (vnm->interface_main.combined_sw_if_counters
447                                + VNET_INTERFACE_COUNTER_RX,
448                                cpu_index, 
449                                stats_sw_if_index,
450                                stats_n_packets,
451                                stats_n_bytes);
452                           stats_n_packets = stats_n_bytes = 0;
453                         }
454                       stats_sw_if_index = new_sw_if_index0;
455                     }
456                 }
457             }
458
459           if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
460               is_l20 = is_l21 = 0;
461
462           determine_next_node(em, variant, is_l20, type0, b0, &error0, &next0);
463           determine_next_node(em, variant, is_l21, type1, b1, &error1, &next1);
464           
465           b0->error = error_node->errors[error0];
466           b1->error = error_node->errors[error1];
467
468           // verify speculative enqueue
469           vlib_validate_buffer_enqueue_x2(vm,node,next_index,to_next,n_left_to_next,bi0,bi1,next0,next1);
470         }
471
472       while (n_left_from > 0 && n_left_to_next > 0)
473         {
474           u32 bi0;
475           vlib_buffer_t * b0;
476           u8 error0, next0;
477           u16 type0, orig_type0;
478           u16 outer_id0, inner_id0;
479           u32 match_flags0;
480           u32 old_sw_if_index0, new_sw_if_index0, len0;
481           vnet_hw_interface_t * hi0;
482           main_intf_t * main_intf0;
483           vlan_intf_t * vlan_intf0;
484           qinq_intf_t * qinq_intf0;
485           u32 is_l20;
486
487           // Prefetch next iteration
488           if (n_left_from > 1) {
489             vlib_buffer_t * p2;
490             
491             p2 = vlib_get_buffer (vm, from[1]);
492             vlib_prefetch_buffer_header (p2, STORE);
493             CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, LOAD);
494           }
495
496           bi0 = from[0];
497           to_next[0] = bi0;
498           from += 1;
499           to_next += 1;
500           n_left_from -= 1;
501           n_left_to_next -= 1;
502
503           b0 = vlib_get_buffer (vm, bi0);
504
505           error0 = ETHERNET_ERROR_NONE;
506
507           parse_header (variant, 
508                         b0,
509                         &type0, 
510                         &orig_type0, 
511                         &outer_id0,
512                         &inner_id0,
513                         &match_flags0);
514
515           old_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
516
517           eth_vlan_table_lookups (em, 
518                               vnm, 
519                               old_sw_if_index0, 
520                               orig_type0, 
521                               outer_id0,
522                               inner_id0,
523                               &hi0,
524                               &main_intf0,  
525                               &vlan_intf0, 
526                               &qinq_intf0);
527
528           identify_subint (hi0,
529                            b0,
530                            match_flags0, 
531                            main_intf0, 
532                            vlan_intf0, 
533                            qinq_intf0, 
534                            &new_sw_if_index0, 
535                            &error0, 
536                            &is_l20);
537
538           // Save RX sw_if_index for later nodes
539           vnet_buffer (b0)->sw_if_index[VLIB_RX] = error0 != ETHERNET_ERROR_NONE ? old_sw_if_index0 : new_sw_if_index0;
540
541           // Increment subinterface stats
542           // Note that interface-level counters have already been incremented
543           // prior to calling this function. Thus only subinterface counters
544           // are incremented here.
545           //
546           // Interface level counters include packets received on the main 
547           // interface and all subinterfaces. Subinterface level counters
548           // include only those packets received on that subinterface
549           // Increment stats if the subint is valid and it is not the main intf
550           if ((new_sw_if_index0 != ~0) && (new_sw_if_index0 != old_sw_if_index0)) {
551
552             len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
553                 - vnet_buffer (b0)->ethernet.start_of_ethernet_header;
554
555             stats_n_packets += 1;
556             stats_n_bytes += len0;
557
558             // Batch stat increments from the same subinterface so counters
559             // don't need to be incremented for every packet. 
560             if (PREDICT_FALSE (new_sw_if_index0 != stats_sw_if_index)) {
561               stats_n_packets -= 1;
562               stats_n_bytes -= len0;
563
564               if (new_sw_if_index0 != ~0)
565                 vlib_increment_combined_counter 
566                     (vnm->interface_main.combined_sw_if_counters
567                      + VNET_INTERFACE_COUNTER_RX,
568                      cpu_index, 
569                      new_sw_if_index0,
570                      1,
571                      len0);
572               if (stats_n_packets > 0) {
573                 vlib_increment_combined_counter 
574                     (vnm->interface_main.combined_sw_if_counters
575                      + VNET_INTERFACE_COUNTER_RX,
576                      cpu_index, 
577                      stats_sw_if_index,
578                      stats_n_packets,
579                      stats_n_bytes);
580                 stats_n_packets = stats_n_bytes = 0;
581               }
582               stats_sw_if_index = new_sw_if_index0;
583             }
584           }
585
586           if (variant == ETHERNET_INPUT_VARIANT_NOT_L2)
587               is_l20 = 0;
588
589           determine_next_node(em, variant, is_l20, type0, b0, &error0, &next0);
590
591           b0->error = error_node->errors[error0];
592           
593           // verify speculative enqueue
594           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
595                                            to_next, n_left_to_next,
596                                            bi0, next0);
597         }
598
599       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
600     }
601
602     // Increment any remaining batched stats
603     if (stats_n_packets > 0)
604     {
605       vlib_increment_combined_counter 
606           (vnm->interface_main.combined_sw_if_counters
607            + VNET_INTERFACE_COUNTER_RX,
608            cpu_index, 
609            stats_sw_if_index,
610            stats_n_packets,
611            stats_n_bytes);
612       node->runtime_data[0] = stats_sw_if_index;
613     }
614
615   return from_frame->n_vectors;
616 }
617
618 static uword
619 ethernet_input (vlib_main_t * vm,
620                 vlib_node_runtime_t * node,
621                 vlib_frame_t * from_frame)
622 { return ethernet_input_inline (vm, node, from_frame, ETHERNET_INPUT_VARIANT_ETHERNET); }
623
624 static uword
625 ethernet_input_type (vlib_main_t * vm,
626                      vlib_node_runtime_t * node,
627                      vlib_frame_t * from_frame)
628 { return ethernet_input_inline (vm, node, from_frame, ETHERNET_INPUT_VARIANT_ETHERNET_TYPE); }
629
630 static uword
631 ethernet_input_not_l2 (vlib_main_t * vm,
632                        vlib_node_runtime_t * node,
633                      vlib_frame_t * from_frame)
634 { return ethernet_input_inline (vm, node, from_frame, ETHERNET_INPUT_VARIANT_NOT_L2); }
635
636
637 // Return the subinterface config struct for the given sw_if_index
638 // Also return via parameter the appropriate match flags for the
639 // configured number of tags.
640 // On error (unsupported or not ethernet) return 0.
641 static subint_config_t *
642 ethernet_sw_interface_get_config (vnet_main_t * vnm,
643                                   u32 sw_if_index,
644                                   u32 * flags,
645                                   u32 * unsupported) {
646   ethernet_main_t * em = &ethernet_main;
647   vnet_hw_interface_t * hi;
648   vnet_sw_interface_t * si;
649   main_intf_t * main_intf;
650   vlan_table_t * vlan_table;
651   qinq_table_t * qinq_table;
652   subint_config_t * subint = 0;
653   
654   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
655
656   if (!hi || (hi->hw_class_index != ethernet_hw_interface_class.index)) {
657     *unsupported = 0;
658     goto done;  // non-ethernet interface
659   }
660
661   // ensure there's an entry for the main intf (shouldn't really be necessary)
662   vec_validate (em->main_intfs, hi->hw_if_index);
663   main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
664
665   // Locate the subint for the given ethernet config
666   si = vnet_get_sw_interface (vnm, sw_if_index);
667
668   if (si->sub.eth.flags.default_sub) {
669     subint = &main_intf->default_subint;
670     *flags = SUBINT_CONFIG_MATCH_0_TAG |
671              SUBINT_CONFIG_MATCH_1_TAG |
672              SUBINT_CONFIG_MATCH_2_TAG |
673              SUBINT_CONFIG_MATCH_3_TAG;
674   } else if ((si->sub.eth.flags.no_tags) ||
675              (si->sub.eth.raw_flags == 0)) {
676     // if no flags are set then this is a main interface
677     // so treat as untagged
678     subint = &main_intf->untagged_subint;
679     *flags = SUBINT_CONFIG_MATCH_0_TAG;
680   } else {
681     // one or two tags
682     // first get the vlan table
683     if (si->sub.eth.flags.dot1ad) {
684       if (main_intf->dot1ad_vlans == 0) {
685         // Allocate a vlan table from the pool
686         pool_get(em->vlan_pool, vlan_table); 
687         main_intf->dot1ad_vlans = vlan_table - em->vlan_pool;
688       } else {
689         // Get ptr to existing vlan table
690         vlan_table = vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
691       }
692     } else { // dot1q
693       if (main_intf->dot1q_vlans == 0) {
694         // Allocate a vlan table from the pool
695         pool_get(em->vlan_pool, vlan_table); 
696         main_intf->dot1q_vlans = vlan_table - em->vlan_pool;
697       } else {
698         // Get ptr to existing vlan table
699         vlan_table = vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
700       }
701     }
702
703     if (si->sub.eth.flags.one_tag) {
704       *flags = si->sub.eth.flags.exact_match ?
705         SUBINT_CONFIG_MATCH_1_TAG :
706         (SUBINT_CONFIG_MATCH_1_TAG |
707          SUBINT_CONFIG_MATCH_2_TAG |
708          SUBINT_CONFIG_MATCH_3_TAG);
709
710       if (si->sub.eth.flags.outer_vlan_id_any) {
711         // not implemented yet
712         *unsupported =1;
713         goto done;
714       } else {
715         // a single vlan, a common case
716         subint = &vlan_table->vlans[si->sub.eth.outer_vlan_id].single_tag_subint;
717       }
718
719     } else {
720       // Two tags
721       *flags = si->sub.eth.flags.exact_match ?
722         SUBINT_CONFIG_MATCH_2_TAG :
723         (SUBINT_CONFIG_MATCH_2_TAG |
724          SUBINT_CONFIG_MATCH_3_TAG);
725
726       if (si->sub.eth.flags.outer_vlan_id_any && si->sub.eth.flags.inner_vlan_id_any) {
727         // not implemented yet
728         *unsupported = 1;
729         goto done;
730       }
731
732       if (si->sub.eth.flags.inner_vlan_id_any) {
733         // a specific outer and "any" inner
734         // don't need a qinq table for this
735         subint = &vlan_table->vlans[si->sub.eth.outer_vlan_id].inner_any_subint;
736         if (si->sub.eth.flags.exact_match) {
737           *flags = SUBINT_CONFIG_MATCH_2_TAG;
738         } else {
739           *flags = SUBINT_CONFIG_MATCH_2_TAG |
740                    SUBINT_CONFIG_MATCH_3_TAG;
741         }
742       } else {
743         // a specific outer + specifc innner vlan id, a common case
744
745         // get the qinq table
746         if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0) {
747           // Allocate a qinq table from the pool
748           pool_get(em->qinq_pool, qinq_table); 
749           vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs = qinq_table - em->qinq_pool;
750         } else {
751           // Get ptr to existing qinq table
752           qinq_table = vec_elt_at_index (em->qinq_pool, vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs);
753         }
754         subint = &qinq_table->vlans[si->sub.eth.inner_vlan_id].subint;
755       }
756     }
757   }
758
759  done:
760   return subint;
761 }
762
763 clib_error_t *
764 ethernet_sw_interface_up_down (vnet_main_t * vnm,
765                                u32 sw_if_index,
766                                u32 flags)
767 {
768   subint_config_t * subint;
769   u32 dummy_flags;
770   u32 dummy_unsup;
771   clib_error_t * error = 0;
772
773   // Find the config for this subinterface
774   subint = ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags, &dummy_unsup);
775
776   if (subint == 0) {
777     // not implemented yet or not ethernet
778     goto done;
779   }
780
781   subint->sw_if_index =
782     ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? sw_if_index : ~0);
783
784  done:
785   return error;
786 }
787
788 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
789
790
791 // Set the L2/L3 mode for the subinterface
792 void
793 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm,
794                                    u32 sw_if_index,
795                                    u32 l2)
796 {
797   subint_config_t *subint;
798   u32 dummy_flags;
799   u32 dummy_unsup;
800   int is_port;
801   vnet_sw_interface_t * sw = vnet_get_sw_interface (vnm, sw_if_index);
802
803   is_port = !(sw->type == VNET_SW_INTERFACE_TYPE_SUB);
804
805   // Find the config for this subinterface
806   subint = ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags, &dummy_unsup);
807
808   if (subint == 0) {
809     // unimplemented or not ethernet
810     goto done;
811   }
812
813   // Double check that the config we found is for our interface (or the interface is down)
814   ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
815
816   if (l2) {
817     subint->flags |= SUBINT_CONFIG_L2;
818     if (is_port) 
819         subint->flags |= 
820             SUBINT_CONFIG_MATCH_0_TAG | SUBINT_CONFIG_MATCH_1_TAG
821             | SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
822   } else {
823     subint->flags &= ~SUBINT_CONFIG_L2;
824     if (is_port) 
825         subint->flags &= 
826             ~(SUBINT_CONFIG_MATCH_1_TAG | SUBINT_CONFIG_MATCH_2_TAG
827                     | SUBINT_CONFIG_MATCH_3_TAG);
828   }
829
830  done:
831   return;
832 }
833
834 /*
835  * Set the L2/L3 mode for the subinterface regardless of port
836  */
837 void
838 ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
839                                           u32 sw_if_index,
840                                           u32 l2)
841 {
842   subint_config_t *subint;
843   u32 dummy_flags;
844   u32 dummy_unsup;
845
846   /* Find the config for this subinterface */
847   subint = ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags, &dummy_unsup);
848
849   if (subint == 0) {
850     /* unimplemented or not ethernet */
851     goto done;
852   }
853
854   /*
855    * Double check that the config we found is for our interface (or the
856    * interface is down)
857    */
858   ASSERT ((subint->sw_if_index == sw_if_index) | (subint->sw_if_index == ~0));
859
860   if (l2) {
861     subint->flags |= SUBINT_CONFIG_L2;
862   } else {
863     subint->flags &= ~SUBINT_CONFIG_L2;
864   }
865
866  done:
867   return;
868 }
869
870 static clib_error_t *
871 ethernet_sw_interface_add_del (vnet_main_t * vnm,
872                                u32 sw_if_index,
873                                u32 is_create)
874 {
875   clib_error_t * error = 0;
876   subint_config_t *subint;
877   u32 match_flags;
878   u32 unsupported=0;
879
880   // Find the config for this subinterface
881   subint = ethernet_sw_interface_get_config (vnm, sw_if_index, &match_flags, &unsupported);
882
883   if (subint == 0) {
884     // not implemented yet or not ethernet
885     if (unsupported) {
886       // this is the NYI case 
887       error = clib_error_return (0, "not implemented yet");
888     }
889     goto done;
890   }
891
892  if (!is_create) {
893    subint->flags = 0;
894    return error;
895  }
896
897   // Initialize the subint
898   if (subint->flags & SUBINT_CONFIG_VALID) {
899     // Error vlan already in use
900     error = clib_error_return (0, "vlan is already in use");
901   } else {
902     // Note that config is L3 by defaulty
903     subint->flags = SUBINT_CONFIG_VALID | match_flags;
904     subint->sw_if_index = ~0;  // because interfaces are initially down
905   }
906
907  done:
908   return error;
909 }
910
911 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ethernet_sw_interface_add_del);
912
913 static char * ethernet_error_strings[] = {
914 #define ethernet_error(n,c,s) s,
915 #include "error.def"
916 #undef ethernet_error
917 };
918
919 VLIB_REGISTER_NODE (ethernet_input_node) = {
920   .function = ethernet_input,
921   .name = "ethernet-input",
922   /* Takes a vector of packets. */
923   .vector_size = sizeof (u32),
924
925   .n_errors = ETHERNET_N_ERROR,
926   .error_strings = ethernet_error_strings,
927
928   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
929   .next_nodes = {
930 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
931     foreach_ethernet_input_next
932 #undef _
933   },
934
935   .format_buffer = format_ethernet_header_with_length,
936   .format_trace = format_ethernet_input_trace,
937   .unformat_buffer = unformat_ethernet_header,
938 };
939
940 VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_node, ethernet_input)
941
942 VLIB_REGISTER_NODE (ethernet_input_type_node,static) = {
943   .function = ethernet_input_type,
944   .name = "ethernet-input-type",
945   /* Takes a vector of packets. */
946   .vector_size = sizeof (u32),
947
948   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
949   .next_nodes = {
950 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
951     foreach_ethernet_input_next
952 #undef _
953   },
954 };
955
956 VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_type_node, ethernet_input_type)
957
958 VLIB_REGISTER_NODE (ethernet_input_not_l2_node,static) = {
959   .function = ethernet_input_not_l2,
960   .name = "ethernet-input-not-l2",
961   /* Takes a vector of packets. */
962   .vector_size = sizeof (u32),
963
964   .n_next_nodes = ETHERNET_INPUT_N_NEXT,
965   .next_nodes = {
966 #define _(s,n) [ETHERNET_INPUT_NEXT_##s] = n,
967     foreach_ethernet_input_next
968 #undef _
969   },
970 };
971
972 VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_not_l2_node, ethernet_input_not_l2)
973
974 void ethernet_set_rx_redirect (vnet_main_t * vnm, 
975                                vnet_hw_interface_t * hi, 
976                                u32 enable)
977 {
978   // Insure all packets go to ethernet-input (i.e. untagged ipv4 packets
979   // don't go directly to ip4-input)
980   vnet_hw_interface_rx_redirect_to_node 
981       (vnm, hi->hw_if_index, enable ? ethernet_input_node.index : ~0);
982 }
983
984
985 /*
986  * Initialization and registration for the next_by_ethernet structure
987  */
988
989 clib_error_t * next_by_ethertype_init (next_by_ethertype_t * l3_next)
990 {
991   l3_next->input_next_by_type = sparse_vec_new
992     (/* elt bytes */ sizeof (l3_next->input_next_by_type[0]),
993      /* bits in index */ BITS (((ethernet_header_t *) 0)->type));
994
995   vec_validate (l3_next->sparse_index_by_input_next_index, ETHERNET_INPUT_NEXT_DROP);
996   vec_validate (l3_next->sparse_index_by_input_next_index, ETHERNET_INPUT_NEXT_PUNT);
997   l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_DROP]
998     = SPARSE_VEC_INVALID_INDEX;
999   l3_next->sparse_index_by_input_next_index[ETHERNET_INPUT_NEXT_PUNT]
1000     = SPARSE_VEC_INVALID_INDEX;
1001  
1002   /* 
1003    * Make sure we don't wipe out an ethernet registration by mistake 
1004    * Can happen if init function ordering constraints are missing.
1005    */
1006   if (CLIB_DEBUG > 0)
1007     {
1008       ethernet_main_t * em = &ethernet_main;
1009       ASSERT(em->next_by_ethertype_register_called == 0);
1010     }
1011
1012   return 0;
1013 }
1014
1015 // Add an ethertype -> next index mapping to the structure
1016 clib_error_t * next_by_ethertype_register (next_by_ethertype_t * l3_next,
1017                                            u32                   ethertype,
1018                                            u32                   next_index)
1019 {
1020   u32 i;
1021   u16 * n;
1022   ethernet_main_t * em = &ethernet_main;
1023
1024   if (CLIB_DEBUG > 0)
1025     {
1026       ethernet_main_t * em = &ethernet_main;
1027       em->next_by_ethertype_register_called = 1;
1028     }
1029
1030   /* Setup ethernet type -> next index sparse vector mapping. */
1031   n = sparse_vec_validate (l3_next->input_next_by_type, ethertype);
1032   n[0] = next_index;
1033
1034   /* Rebuild next index -> sparse index inverse mapping when sparse vector
1035      is updated. */
1036   vec_validate (l3_next->sparse_index_by_input_next_index, next_index);
1037   for (i = 1; i < vec_len (l3_next->input_next_by_type); i++)
1038     l3_next->sparse_index_by_input_next_index[l3_next->input_next_by_type[i]] = i;
1039
1040   // do not allow the cached next index's to be updated if L3
1041   // redirect is enabled, as it will have overwritten them
1042   if (!em->redirect_l3) {
1043     // Cache common ethertypes directly
1044     if (ethertype == ETHERNET_TYPE_IP4) {
1045       l3_next->input_next_ip4 = next_index;
1046     } else if (ethertype == ETHERNET_TYPE_IP6) {
1047       l3_next->input_next_ip6 = next_index;
1048     } else if (ethertype == ETHERNET_TYPE_MPLS_UNICAST) {
1049       l3_next->input_next_mpls = next_index;
1050     }
1051   }
1052   return 0;
1053 }
1054
1055
1056 static clib_error_t * ethernet_input_init (vlib_main_t * vm)
1057 {
1058   ethernet_main_t * em = &ethernet_main;
1059   __attribute__((unused)) vlan_table_t * invalid_vlan_table;
1060   __attribute__((unused)) qinq_table_t * invalid_qinq_table;
1061
1062   ethernet_setup_node (vm, ethernet_input_node.index);
1063   ethernet_setup_node (vm, ethernet_input_type_node.index);
1064   ethernet_setup_node (vm, ethernet_input_not_l2_node.index);
1065
1066   next_by_ethertype_init (&em->l3_next);
1067  
1068   // Initialize pools and vector for vlan parsing
1069   vec_validate (em->main_intfs, 10);  // 10 main interfaces
1070   pool_alloc(em->vlan_pool, 10);
1071   pool_alloc(em->qinq_pool, 1);
1072
1073   // The first vlan pool will always be reserved for an invalid table
1074   pool_get(em->vlan_pool, invalid_vlan_table); // first id = 0
1075   // The first qinq pool will always be reserved for an invalid table
1076   pool_get(em->qinq_pool, invalid_qinq_table); // first id = 0
1077
1078   return 0;
1079 }
1080
1081 VLIB_INIT_FUNCTION (ethernet_input_init);
1082
1083 void
1084 ethernet_register_input_type (vlib_main_t * vm,
1085                               ethernet_type_t type,
1086                               u32 node_index)
1087 {
1088   ethernet_main_t * em = &ethernet_main;
1089   ethernet_type_info_t * ti;
1090   u32 i;
1091
1092   {
1093     clib_error_t * error = vlib_call_init_function (vm, ethernet_init);
1094     if (error)
1095       clib_error_report (error);
1096   }
1097
1098   ti = ethernet_get_type_info (em, type);
1099   ti->node_index = node_index;
1100   ti->next_index = vlib_node_add_next (vm, 
1101                                        ethernet_input_node.index,
1102                                        node_index);
1103   i = vlib_node_add_next (vm, 
1104                           ethernet_input_type_node.index,
1105                           node_index);
1106   ASSERT (i == ti->next_index);
1107
1108   i = vlib_node_add_next (vm, 
1109                           ethernet_input_not_l2_node.index,
1110                           node_index);
1111   ASSERT (i == ti->next_index);
1112
1113   // Add the L3 node for this ethertype to the next nodes structure
1114   next_by_ethertype_register (&em->l3_next, type, ti->next_index);
1115
1116   // Call the registration functions for other nodes that want a mapping
1117   l2bvi_register_input_type (vm, type, node_index);
1118 }
1119
1120 void
1121 ethernet_register_l2_input (vlib_main_t * vm,
1122                             u32 node_index)
1123 {
1124   ethernet_main_t * em = &ethernet_main;
1125   u32 i;
1126
1127   em->l2_next = vlib_node_add_next (vm, ethernet_input_node.index, node_index);
1128
1129   /* 
1130    * Even if we never use these arcs, we have to align the next indices...
1131    */
1132   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
1133
1134   ASSERT (i == em->l2_next);
1135
1136   i = vlib_node_add_next (vm, 
1137                           ethernet_input_not_l2_node.index,
1138                           node_index);
1139   ASSERT (i == em->l2_next);
1140 }
1141
1142 // Register a next node for L3 redirect, and enable L3 redirect
1143 void
1144 ethernet_register_l3_redirect (vlib_main_t * vm,
1145                                u32 node_index)
1146 {
1147   ethernet_main_t * em = &ethernet_main;
1148   u32 i;
1149
1150   em->redirect_l3 = 1;
1151   em->redirect_l3_next = vlib_node_add_next(vm,
1152                                             ethernet_input_node.index,
1153                                             node_index);
1154   /*
1155    * Change the cached next nodes to the redirect node
1156    */
1157   em->l3_next.input_next_ip4 = em->redirect_l3_next;
1158   em->l3_next.input_next_ip6 = em->redirect_l3_next;
1159   em->l3_next.input_next_mpls = em->redirect_l3_next;
1160
1161   /*
1162    * Even if we never use these arcs, we have to align the next indices...
1163    */
1164   i = vlib_node_add_next (vm, ethernet_input_type_node.index, node_index);
1165
1166   ASSERT (i == em->redirect_l3_next);
1167 }