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