vxlan:decap.c conform coding style
[vpp.git] / src / vnet / vxlan / decap.c
1 /*
2  * decap.c: vxlan tunnel decap packet processing
3  *
4  * Copyright (c) 2013 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vlib/vlib.h>
19 #include <vnet/pg/pg.h>
20 #include <vnet/vxlan/vxlan.h>
21
22 vlib_node_registration_t vxlan4_input_node;
23 vlib_node_registration_t vxlan6_input_node;
24
25 typedef struct
26 {
27   u32 next_index;
28   u32 tunnel_index;
29   u32 error;
30   u32 vni;
31 } vxlan_rx_trace_t;
32
33 static u8 *
34 format_vxlan_rx_trace (u8 * s, va_list * args)
35 {
36   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
37   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
38   vxlan_rx_trace_t *t = va_arg (*args, vxlan_rx_trace_t *);
39
40   if (t->tunnel_index == ~0)
41     return format (s, "VXLAN decap error - tunnel for vni %d does not exist",
42                    t->vni);
43   return format (s, "VXLAN decap from vxlan_tunnel%d vni %d next %d error %d",
44                  t->tunnel_index, t->vni, t->next_index, t->error);
45 }
46
47 always_inline u32
48 buf_fib_index (vlib_buffer_t * b, u32 is_ip4)
49 {
50   u32 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
51   if (sw_if_index != (u32) ~ 0)
52     return sw_if_index;
53
54   u32 *fib_index_by_sw_if_index = is_ip4 ?
55     ip4_main.fib_index_by_sw_if_index : ip6_main.fib_index_by_sw_if_index;
56   sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
57
58   return vec_elt (fib_index_by_sw_if_index, sw_if_index);
59 }
60
61 typedef vxlan4_tunnel_key_t last_tunnel_cache4;
62
63 always_inline vxlan_tunnel_t *
64 vxlan4_find_tunnel (vxlan_main_t * vxm, last_tunnel_cache4 * cache,
65                     u32 fib_index, ip4_header_t * ip4_0,
66                     vxlan_header_t * vxlan0, vxlan_tunnel_t ** stats_t0)
67 {
68   /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
69   vxlan4_tunnel_key_t key4 = {
70     .key = {
71             [0] = ip4_0->src_address.as_u32,
72             [1] = (((u64) fib_index) << 32) | vxlan0->vni_reserved,
73             }
74   };
75
76   if (PREDICT_FALSE
77       (clib_bihash_key_compare_16_8 (key4.key, cache->key) == 0))
78     {
79       int rv =
80         clib_bihash_search_inline_16_8 (&vxm->vxlan4_tunnel_by_key, &key4);
81       if (PREDICT_FALSE (rv != 0))
82         return 0;
83
84       *cache = key4;
85     }
86   vxlan_tunnel_t *t0 = pool_elt_at_index (vxm->tunnels, cache->value);
87
88   /* Validate VXLAN tunnel SIP against packet DIP */
89   if (PREDICT_TRUE (ip4_0->dst_address.as_u32 == t0->src.ip4.as_u32))
90     *stats_t0 = t0;
91   else
92     {
93       /* try multicast */
94       if (PREDICT_TRUE (!ip4_address_is_multicast (&ip4_0->dst_address)))
95         return 0;
96
97       key4.key[0] = ip4_0->dst_address.as_u32;
98       /* Make sure mcast VXLAN tunnel exist by packet DIP and VNI */
99       int rv =
100         clib_bihash_search_inline_16_8 (&vxm->vxlan4_tunnel_by_key, &key4);
101       if (PREDICT_FALSE (rv != 0))
102         return 0;
103
104       *stats_t0 = pool_elt_at_index (vxm->tunnels, key4.value);
105     }
106
107   return t0;
108 }
109
110 typedef vxlan6_tunnel_key_t last_tunnel_cache6;
111
112 always_inline vxlan_tunnel_t *
113 vxlan6_find_tunnel (vxlan_main_t * vxm, last_tunnel_cache6 * cache,
114                     u32 fib_index, ip6_header_t * ip6_0,
115                     vxlan_header_t * vxlan0, vxlan_tunnel_t ** stats_t0)
116 {
117   /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
118
119   vxlan6_tunnel_key_t key6 = {
120     .key = {
121             [0] = ip6_0->src_address.as_u64[0],
122             [1] = ip6_0->src_address.as_u64[1],
123             [2] = (((u64) fib_index) << 32) | vxlan0->vni_reserved,
124             }
125   };
126
127   if (PREDICT_FALSE
128       (clib_bihash_key_compare_24_8 (key6.key, cache->key) == 0))
129     {
130       int rv =
131         clib_bihash_search_inline_24_8 (&vxm->vxlan6_tunnel_by_key, &key6);
132       if (PREDICT_FALSE (rv != 0))
133         return 0;
134
135       *cache = key6;
136     }
137   vxlan_tunnel_t *t0 = pool_elt_at_index (vxm->tunnels, cache->value);
138
139   /* Validate VXLAN tunnel SIP against packet DIP */
140   if (PREDICT_TRUE (ip6_address_is_equal (&ip6_0->dst_address, &t0->src.ip6)))
141     *stats_t0 = t0;
142   else
143     {
144       /* try multicast */
145       if (PREDICT_TRUE (!ip6_address_is_multicast (&ip6_0->dst_address)))
146         return 0;
147
148       /* Make sure mcast VXLAN tunnel exist by packet DIP and VNI */
149       key6.key[0] = ip6_0->dst_address.as_u64[0];
150       key6.key[1] = ip6_0->dst_address.as_u64[1];
151       int rv =
152         clib_bihash_search_inline_24_8 (&vxm->vxlan6_tunnel_by_key, &key6);
153       if (PREDICT_FALSE (rv != 0))
154         return 0;
155
156       *stats_t0 = pool_elt_at_index (vxm->tunnels, key6.value);
157     }
158
159   return t0;
160 }
161
162 always_inline uword
163 vxlan_input (vlib_main_t * vm,
164              vlib_node_runtime_t * node,
165              vlib_frame_t * from_frame, u32 is_ip4)
166 {
167   vxlan_main_t *vxm = &vxlan_main;
168   vnet_main_t *vnm = vxm->vnet_main;
169   vnet_interface_main_t *im = &vnm->interface_main;
170   vlib_combined_counter_main_t *rx_counter =
171     im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX;
172   vlib_combined_counter_main_t *drop_counter =
173     im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_DROP;
174   last_tunnel_cache4 last4;
175   last_tunnel_cache6 last6;
176   u32 pkts_decapsulated = 0;
177   u32 thread_index = vlib_get_thread_index ();
178
179   if (is_ip4)
180     memset (&last4, 0xff, sizeof last4);
181   else
182     memset (&last6, 0xff, sizeof last6);
183
184   u32 next_index = node->cached_next_index;
185
186   u32 *from = vlib_frame_vector_args (from_frame);
187   u32 n_left_from = from_frame->n_vectors;
188
189   while (n_left_from > 0)
190     {
191       u32 *to_next, n_left_to_next;
192       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
193
194       while (n_left_from >= 4 && n_left_to_next >= 2)
195         {
196           /* Prefetch next iteration. */
197           {
198             vlib_buffer_t *p2, *p3;
199
200             p2 = vlib_get_buffer (vm, from[2]);
201             p3 = vlib_get_buffer (vm, from[3]);
202
203             vlib_prefetch_buffer_header (p2, LOAD);
204             vlib_prefetch_buffer_header (p3, LOAD);
205
206             CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
207             CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
208           }
209
210           u32 bi0 = to_next[0] = from[0];
211           u32 bi1 = to_next[1] = from[1];
212           from += 2;
213           to_next += 2;
214           n_left_to_next -= 2;
215           n_left_from -= 2;
216
217           vlib_buffer_t *b0, *b1;
218           b0 = vlib_get_buffer (vm, bi0);
219           b1 = vlib_get_buffer (vm, bi1);
220
221           /* udp leaves current_data pointing at the vxlan header */
222           void *cur0 = vlib_buffer_get_current (b0);
223           void *cur1 = vlib_buffer_get_current (b1);
224           vxlan_header_t *vxlan0 = cur0;
225           vxlan_header_t *vxlan1 = cur1;
226
227           ip4_header_t *ip4_0, *ip4_1;
228           ip6_header_t *ip6_0, *ip6_1;
229           if (is_ip4)
230             {
231               ip4_0 = cur0 - sizeof (udp_header_t) - sizeof (ip4_header_t);
232               ip4_1 = cur1 - sizeof (udp_header_t) - sizeof (ip4_header_t);
233             }
234           else
235             {
236               ip6_0 = cur0 - sizeof (udp_header_t) - sizeof (ip6_header_t);
237               ip6_1 = cur1 - sizeof (udp_header_t) - sizeof (ip6_header_t);
238             }
239
240           /* pop vxlan */
241           vlib_buffer_advance (b0, sizeof *vxlan0);
242           vlib_buffer_advance (b1, sizeof *vxlan1);
243
244           u32 fi0 = buf_fib_index (b0, is_ip4);
245           u32 fi1 = buf_fib_index (b1, is_ip4);
246
247           vxlan_tunnel_t *t0, *stats_t0;
248           vxlan_tunnel_t *t1, *stats_t1;
249           if (is_ip4)
250             {
251               t0 =
252                 vxlan4_find_tunnel (vxm, &last4, fi0, ip4_0, vxlan0,
253                                     &stats_t0);
254               t1 =
255                 vxlan4_find_tunnel (vxm, &last4, fi1, ip4_1, vxlan1,
256                                     &stats_t1);
257             }
258           else
259             {
260               t0 =
261                 vxlan6_find_tunnel (vxm, &last6, fi0, ip6_0, vxlan0,
262                                     &stats_t0);
263               t1 =
264                 vxlan6_find_tunnel (vxm, &last6, fi1, ip6_1, vxlan1,
265                                     &stats_t1);
266             }
267
268           u32 len0 = vlib_buffer_length_in_chain (vm, b0);
269           u32 len1 = vlib_buffer_length_in_chain (vm, b1);
270
271           u32 next0, next1;
272           u8 error0 = 0, error1 = 0;
273           /* Validate VXLAN tunnel encap-fib index agaist packet */
274           if (PREDICT_FALSE (t0 == 0 || vxlan0->flags != VXLAN_FLAGS_I))
275             {
276               next0 = VXLAN_INPUT_NEXT_DROP;
277
278               if (t0 != 0 && vxlan0->flags != VXLAN_FLAGS_I)
279                 {
280                   error0 = VXLAN_ERROR_BAD_FLAGS;
281                   vlib_increment_combined_counter
282                     (drop_counter, thread_index, stats_t0->sw_if_index, 1,
283                      len0);
284                 }
285               else
286                 error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
287               b0->error = node->errors[error0];
288             }
289           else
290             {
291               next0 = t0->decap_next_index;
292
293               /* Required to make the l2 tag push / pop code work on l2 subifs */
294               if (PREDICT_TRUE (next0 == VXLAN_INPUT_NEXT_L2_INPUT))
295                 vnet_update_l2_len (b0);
296
297               /* Set packet input sw_if_index to unicast VXLAN tunnel for learning */
298               vnet_buffer (b0)->sw_if_index[VLIB_RX] = t0->sw_if_index;
299               vlib_increment_combined_counter
300                 (rx_counter, thread_index, stats_t0->sw_if_index, 1, len0);
301               pkts_decapsulated++;
302             }
303
304           /* Validate VXLAN tunnel encap-fib index agaist packet */
305           if (PREDICT_FALSE (t1 == 0 || vxlan1->flags != VXLAN_FLAGS_I))
306             {
307               next1 = VXLAN_INPUT_NEXT_DROP;
308
309               if (t1 != 0 && vxlan1->flags != VXLAN_FLAGS_I)
310                 {
311                   error1 = VXLAN_ERROR_BAD_FLAGS;
312                   vlib_increment_combined_counter
313                     (drop_counter, thread_index, stats_t1->sw_if_index, 1,
314                      len1);
315                 }
316               else
317                 error1 = VXLAN_ERROR_NO_SUCH_TUNNEL;
318               b1->error = node->errors[error1];
319             }
320           else
321             {
322               next1 = t1->decap_next_index;
323
324               /* Required to make the l2 tag push / pop code work on l2 subifs */
325               if (PREDICT_TRUE (next1 == VXLAN_INPUT_NEXT_L2_INPUT))
326                 vnet_update_l2_len (b1);
327
328               /* Set packet input sw_if_index to unicast VXLAN tunnel for learning */
329               vnet_buffer (b1)->sw_if_index[VLIB_RX] = t1->sw_if_index;
330               pkts_decapsulated++;
331
332               vlib_increment_combined_counter
333                 (rx_counter, thread_index, stats_t1->sw_if_index, 1, len1);
334             }
335
336           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
337             {
338               vxlan_rx_trace_t *tr =
339                 vlib_add_trace (vm, node, b0, sizeof (*tr));
340               tr->next_index = next0;
341               tr->error = error0;
342               tr->tunnel_index = t0 == 0 ? ~0 : t0 - vxm->tunnels;
343               tr->vni = vnet_get_vni (vxlan0);
344             }
345           if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
346             {
347               vxlan_rx_trace_t *tr =
348                 vlib_add_trace (vm, node, b1, sizeof (*tr));
349               tr->next_index = next1;
350               tr->error = error1;
351               tr->tunnel_index = t1 == 0 ? ~0 : t1 - vxm->tunnels;
352               tr->vni = vnet_get_vni (vxlan1);
353             }
354
355           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
356                                            to_next, n_left_to_next,
357                                            bi0, bi1, next0, next1);
358         }
359
360       while (n_left_from > 0 && n_left_to_next > 0)
361         {
362           u32 bi0 = to_next[0] = from[0];
363           from += 1;
364           to_next += 1;
365           n_left_from -= 1;
366           n_left_to_next -= 1;
367
368           vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
369
370           /* udp leaves current_data pointing at the vxlan header */
371           void *cur0 = vlib_buffer_get_current (b0);
372           vxlan_header_t *vxlan0 = cur0;
373           ip4_header_t *ip4_0;
374           ip6_header_t *ip6_0;
375           if (is_ip4)
376             ip4_0 = cur0 - sizeof (udp_header_t) - sizeof (ip4_header_t);
377           else
378             ip6_0 = cur0 - sizeof (udp_header_t) - sizeof (ip6_header_t);
379
380           /* pop (ip, udp, vxlan) */
381           vlib_buffer_advance (b0, sizeof (*vxlan0));
382
383           u32 fi0 = buf_fib_index (b0, is_ip4);
384
385           vxlan_tunnel_t *t0, *stats_t0;
386           if (is_ip4)
387             t0 =
388               vxlan4_find_tunnel (vxm, &last4, fi0, ip4_0, vxlan0, &stats_t0);
389           else
390             t0 =
391               vxlan6_find_tunnel (vxm, &last6, fi0, ip6_0, vxlan0, &stats_t0);
392
393           uword len0 = vlib_buffer_length_in_chain (vm, b0);
394
395           u32 next0;
396           u8 error0 = 0;
397           /* Validate VXLAN tunnel encap-fib index agaist packet */
398           if (PREDICT_FALSE (t0 == 0 || vxlan0->flags != VXLAN_FLAGS_I))
399             {
400               next0 = VXLAN_INPUT_NEXT_DROP;
401
402               if (t0 != 0 && vxlan0->flags != VXLAN_FLAGS_I)
403                 {
404                   error0 = VXLAN_ERROR_BAD_FLAGS;
405                   vlib_increment_combined_counter
406                     (drop_counter, thread_index, stats_t0->sw_if_index, 1,
407                      len0);
408                 }
409               else
410                 error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
411               b0->error = node->errors[error0];
412             }
413           else
414             {
415               next0 = t0->decap_next_index;
416
417               /* Required to make the l2 tag push / pop code work on l2 subifs */
418               if (PREDICT_TRUE (next0 == VXLAN_INPUT_NEXT_L2_INPUT))
419                 vnet_update_l2_len (b0);
420
421               /* Set packet input sw_if_index to unicast VXLAN tunnel for learning */
422               vnet_buffer (b0)->sw_if_index[VLIB_RX] = t0->sw_if_index;
423               pkts_decapsulated++;
424
425               vlib_increment_combined_counter
426                 (rx_counter, thread_index, stats_t0->sw_if_index, 1, len0);
427             }
428
429           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
430             {
431               vxlan_rx_trace_t *tr
432                 = vlib_add_trace (vm, node, b0, sizeof (*tr));
433               tr->next_index = next0;
434               tr->error = error0;
435               tr->tunnel_index = t0 == 0 ? ~0 : t0 - vxm->tunnels;
436               tr->vni = vnet_get_vni (vxlan0);
437             }
438           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
439                                            to_next, n_left_to_next,
440                                            bi0, next0);
441         }
442
443       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
444     }
445   /* Do we still need this now that tunnel tx stats is kept? */
446   u32 node_idx = is_ip4 ? vxlan4_input_node.index : vxlan6_input_node.index;
447   vlib_node_increment_counter (vm, node_idx, VXLAN_ERROR_DECAPSULATED,
448                                pkts_decapsulated);
449
450   return from_frame->n_vectors;
451 }
452
453 static uword
454 vxlan4_input (vlib_main_t * vm,
455               vlib_node_runtime_t * node, vlib_frame_t * from_frame)
456 {
457   return vxlan_input (vm, node, from_frame, /* is_ip4 */ 1);
458 }
459
460 static uword
461 vxlan6_input (vlib_main_t * vm,
462               vlib_node_runtime_t * node, vlib_frame_t * from_frame)
463 {
464   return vxlan_input (vm, node, from_frame, /* is_ip4 */ 0);
465 }
466
467 static char *vxlan_error_strings[] = {
468 #define vxlan_error(n,s) s,
469 #include <vnet/vxlan/vxlan_error.def>
470 #undef vxlan_error
471 #undef _
472 };
473
474 /* *INDENT-OFF* */
475 VLIB_REGISTER_NODE (vxlan4_input_node) =
476 {
477   .function = vxlan4_input,
478   .name = "vxlan4-input",
479   .vector_size = sizeof (u32),
480   .n_errors = VXLAN_N_ERROR,
481   .error_strings = vxlan_error_strings,
482   .n_next_nodes = VXLAN_INPUT_N_NEXT,
483   .format_trace = format_vxlan_rx_trace,
484   .next_nodes = {
485 #define _(s,n) [VXLAN_INPUT_NEXT_##s] = n,
486     foreach_vxlan_input_next
487 #undef _
488   },
489 };
490 VLIB_NODE_FUNCTION_MULTIARCH (vxlan4_input_node, vxlan4_input)
491
492 VLIB_REGISTER_NODE (vxlan6_input_node) =
493 {
494   .function = vxlan6_input,
495   .name = "vxlan6-input",
496   .vector_size = sizeof (u32),
497   .n_errors = VXLAN_N_ERROR,
498   .error_strings = vxlan_error_strings,
499   .n_next_nodes = VXLAN_INPUT_N_NEXT,
500   .next_nodes = {
501 #define _(s,n) [VXLAN_INPUT_NEXT_##s] = n,
502     foreach_vxlan_input_next
503 #undef _
504   },
505   .format_trace = format_vxlan_rx_trace,
506 };
507 VLIB_NODE_FUNCTION_MULTIARCH (vxlan6_input_node, vxlan6_input)
508 /* *INDENT-ON* */
509
510 typedef enum
511 {
512   IP_VXLAN_BYPASS_NEXT_DROP,
513   IP_VXLAN_BYPASS_NEXT_VXLAN,
514   IP_VXLAN_BYPASS_N_NEXT,
515 } ip_vxan_bypass_next_t;
516
517 always_inline uword
518 ip_vxlan_bypass_inline (vlib_main_t * vm,
519                         vlib_node_runtime_t * node,
520                         vlib_frame_t * frame, u32 is_ip4)
521 {
522   vxlan_main_t *vxm = &vxlan_main;
523   u32 *from, *to_next, n_left_from, n_left_to_next, next_index;
524   vlib_node_runtime_t *error_node =
525     vlib_node_get_runtime (vm, ip4_input_node.index);
526   ip4_address_t addr4;          /* last IPv4 address matching a local VTEP address */
527   ip6_address_t addr6;          /* last IPv6 address matching a local VTEP address */
528
529   from = vlib_frame_vector_args (frame);
530   n_left_from = frame->n_vectors;
531   next_index = node->cached_next_index;
532
533   if (node->flags & VLIB_NODE_FLAG_TRACE)
534     ip4_forward_next_trace (vm, node, frame, VLIB_TX);
535
536   if (is_ip4)
537     addr4.data_u32 = ~0;
538   else
539     ip6_address_set_zero (&addr6);
540
541   while (n_left_from > 0)
542     {
543       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
544
545       while (n_left_from >= 4 && n_left_to_next >= 2)
546         {
547           vlib_buffer_t *b0, *b1;
548           ip4_header_t *ip40, *ip41;
549           ip6_header_t *ip60, *ip61;
550           udp_header_t *udp0, *udp1;
551           u32 bi0, ip_len0, udp_len0, flags0, next0;
552           u32 bi1, ip_len1, udp_len1, flags1, next1;
553           i32 len_diff0, len_diff1;
554           u8 error0, good_udp0, proto0;
555           u8 error1, good_udp1, proto1;
556
557           /* Prefetch next iteration. */
558           {
559             vlib_buffer_t *p2, *p3;
560
561             p2 = vlib_get_buffer (vm, from[2]);
562             p3 = vlib_get_buffer (vm, from[3]);
563
564             vlib_prefetch_buffer_header (p2, LOAD);
565             vlib_prefetch_buffer_header (p3, LOAD);
566
567             CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
568             CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
569           }
570
571           bi0 = to_next[0] = from[0];
572           bi1 = to_next[1] = from[1];
573           from += 2;
574           n_left_from -= 2;
575           to_next += 2;
576           n_left_to_next -= 2;
577
578           b0 = vlib_get_buffer (vm, bi0);
579           b1 = vlib_get_buffer (vm, bi1);
580           if (is_ip4)
581             {
582               ip40 = vlib_buffer_get_current (b0);
583               ip41 = vlib_buffer_get_current (b1);
584             }
585           else
586             {
587               ip60 = vlib_buffer_get_current (b0);
588               ip61 = vlib_buffer_get_current (b1);
589             }
590
591           /* Setup packet for next IP feature */
592           vnet_feature_next (&next0, b0);
593           vnet_feature_next (&next1, b1);
594
595           if (is_ip4)
596             {
597               /* Treat IP frag packets as "experimental" protocol for now
598                  until support of IP frag reassembly is implemented */
599               proto0 = ip4_is_fragment (ip40) ? 0xfe : ip40->protocol;
600               proto1 = ip4_is_fragment (ip41) ? 0xfe : ip41->protocol;
601             }
602           else
603             {
604               proto0 = ip60->protocol;
605               proto1 = ip61->protocol;
606             }
607
608           /* Process packet 0 */
609           if (proto0 != IP_PROTOCOL_UDP)
610             goto exit0;         /* not UDP packet */
611
612           if (is_ip4)
613             udp0 = ip4_next_header (ip40);
614           else
615             udp0 = ip6_next_header (ip60);
616
617           if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
618             goto exit0;         /* not VXLAN packet */
619
620           /* Validate DIP against VTEPs */
621           if (is_ip4)
622             {
623               if (addr4.as_u32 != ip40->dst_address.as_u32)
624                 {
625                   if (!hash_get (vxm->vtep4, ip40->dst_address.as_u32))
626                     goto exit0; /* no local VTEP for VXLAN packet */
627                   addr4 = ip40->dst_address;
628                 }
629             }
630           else
631             {
632               if (!ip6_address_is_equal (&addr6, &ip60->dst_address))
633                 {
634                   if (!hash_get_mem (vxm->vtep6, &ip60->dst_address))
635                     goto exit0; /* no local VTEP for VXLAN packet */
636                   addr6 = ip60->dst_address;
637                 }
638             }
639
640           flags0 = b0->flags;
641           good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
642
643           /* Don't verify UDP checksum for packets with explicit zero checksum. */
644           good_udp0 |= udp0->checksum == 0;
645
646           /* Verify UDP length */
647           if (is_ip4)
648             ip_len0 = clib_net_to_host_u16 (ip40->length);
649           else
650             ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
651           udp_len0 = clib_net_to_host_u16 (udp0->length);
652           len_diff0 = ip_len0 - udp_len0;
653
654           /* Verify UDP checksum */
655           if (PREDICT_FALSE (!good_udp0))
656             {
657               if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
658                 {
659                   if (is_ip4)
660                     flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
661                   else
662                     flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
663                   good_udp0 =
664                     (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
665                 }
666             }
667
668           if (is_ip4)
669             {
670               error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
671               error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
672             }
673           else
674             {
675               error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
676               error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
677             }
678
679           next0 = error0 ?
680             IP_VXLAN_BYPASS_NEXT_DROP : IP_VXLAN_BYPASS_NEXT_VXLAN;
681           b0->error = error0 ? error_node->errors[error0] : 0;
682
683           /* vxlan-input node expect current at VXLAN header */
684           if (is_ip4)
685             vlib_buffer_advance (b0,
686                                  sizeof (ip4_header_t) +
687                                  sizeof (udp_header_t));
688           else
689             vlib_buffer_advance (b0,
690                                  sizeof (ip6_header_t) +
691                                  sizeof (udp_header_t));
692
693         exit0:
694           /* Process packet 1 */
695           if (proto1 != IP_PROTOCOL_UDP)
696             goto exit1;         /* not UDP packet */
697
698           if (is_ip4)
699             udp1 = ip4_next_header (ip41);
700           else
701             udp1 = ip6_next_header (ip61);
702
703           if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
704             goto exit1;         /* not VXLAN packet */
705
706           /* Validate DIP against VTEPs */
707           if (is_ip4)
708             {
709               if (addr4.as_u32 != ip41->dst_address.as_u32)
710                 {
711                   if (!hash_get (vxm->vtep4, ip41->dst_address.as_u32))
712                     goto exit1; /* no local VTEP for VXLAN packet */
713                   addr4 = ip41->dst_address;
714                 }
715             }
716           else
717             {
718               if (!ip6_address_is_equal (&addr6, &ip61->dst_address))
719                 {
720                   if (!hash_get_mem (vxm->vtep6, &ip61->dst_address))
721                     goto exit1; /* no local VTEP for VXLAN packet */
722                   addr6 = ip61->dst_address;
723                 }
724             }
725
726           flags1 = b1->flags;
727           good_udp1 = (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
728
729           /* Don't verify UDP checksum for packets with explicit zero checksum. */
730           good_udp1 |= udp1->checksum == 0;
731
732           /* Verify UDP length */
733           if (is_ip4)
734             ip_len1 = clib_net_to_host_u16 (ip41->length);
735           else
736             ip_len1 = clib_net_to_host_u16 (ip61->payload_length);
737           udp_len1 = clib_net_to_host_u16 (udp1->length);
738           len_diff1 = ip_len1 - udp_len1;
739
740           /* Verify UDP checksum */
741           if (PREDICT_FALSE (!good_udp1))
742             {
743               if ((flags1 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
744                 {
745                   if (is_ip4)
746                     flags1 = ip4_tcp_udp_validate_checksum (vm, b1);
747                   else
748                     flags1 = ip6_tcp_udp_icmp_validate_checksum (vm, b1);
749                   good_udp1 =
750                     (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
751                 }
752             }
753
754           if (is_ip4)
755             {
756               error1 = good_udp1 ? 0 : IP4_ERROR_UDP_CHECKSUM;
757               error1 = (len_diff1 >= 0) ? error1 : IP4_ERROR_UDP_LENGTH;
758             }
759           else
760             {
761               error1 = good_udp1 ? 0 : IP6_ERROR_UDP_CHECKSUM;
762               error1 = (len_diff1 >= 0) ? error1 : IP6_ERROR_UDP_LENGTH;
763             }
764
765           next1 = error1 ?
766             IP_VXLAN_BYPASS_NEXT_DROP : IP_VXLAN_BYPASS_NEXT_VXLAN;
767           b1->error = error1 ? error_node->errors[error1] : 0;
768
769           /* vxlan-input node expect current at VXLAN header */
770           if (is_ip4)
771             vlib_buffer_advance (b1,
772                                  sizeof (ip4_header_t) +
773                                  sizeof (udp_header_t));
774           else
775             vlib_buffer_advance (b1,
776                                  sizeof (ip6_header_t) +
777                                  sizeof (udp_header_t));
778
779         exit1:
780           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
781                                            to_next, n_left_to_next,
782                                            bi0, bi1, next0, next1);
783         }
784
785       while (n_left_from > 0 && n_left_to_next > 0)
786         {
787           vlib_buffer_t *b0;
788           ip4_header_t *ip40;
789           ip6_header_t *ip60;
790           udp_header_t *udp0;
791           u32 bi0, ip_len0, udp_len0, flags0, next0;
792           i32 len_diff0;
793           u8 error0, good_udp0, proto0;
794
795           bi0 = to_next[0] = from[0];
796           from += 1;
797           n_left_from -= 1;
798           to_next += 1;
799           n_left_to_next -= 1;
800
801           b0 = vlib_get_buffer (vm, bi0);
802           if (is_ip4)
803             ip40 = vlib_buffer_get_current (b0);
804           else
805             ip60 = vlib_buffer_get_current (b0);
806
807           /* Setup packet for next IP feature */
808           vnet_feature_next (&next0, b0);
809
810           if (is_ip4)
811             /* Treat IP4 frag packets as "experimental" protocol for now
812                until support of IP frag reassembly is implemented */
813             proto0 = ip4_is_fragment (ip40) ? 0xfe : ip40->protocol;
814           else
815             proto0 = ip60->protocol;
816
817           if (proto0 != IP_PROTOCOL_UDP)
818             goto exit;          /* not UDP packet */
819
820           if (is_ip4)
821             udp0 = ip4_next_header (ip40);
822           else
823             udp0 = ip6_next_header (ip60);
824
825           if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
826             goto exit;          /* not VXLAN packet */
827
828           /* Validate DIP against VTEPs */
829           if (is_ip4)
830             {
831               if (addr4.as_u32 != ip40->dst_address.as_u32)
832                 {
833                   if (!hash_get (vxm->vtep4, ip40->dst_address.as_u32))
834                     goto exit;  /* no local VTEP for VXLAN packet */
835                   addr4 = ip40->dst_address;
836                 }
837             }
838           else
839             {
840               if (!ip6_address_is_equal (&addr6, &ip60->dst_address))
841                 {
842                   if (!hash_get_mem (vxm->vtep6, &ip60->dst_address))
843                     goto exit;  /* no local VTEP for VXLAN packet */
844                   addr6 = ip60->dst_address;
845                 }
846             }
847
848           flags0 = b0->flags;
849           good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
850
851           /* Don't verify UDP checksum for packets with explicit zero checksum. */
852           good_udp0 |= udp0->checksum == 0;
853
854           /* Verify UDP length */
855           if (is_ip4)
856             ip_len0 = clib_net_to_host_u16 (ip40->length);
857           else
858             ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
859           udp_len0 = clib_net_to_host_u16 (udp0->length);
860           len_diff0 = ip_len0 - udp_len0;
861
862           /* Verify UDP checksum */
863           if (PREDICT_FALSE (!good_udp0))
864             {
865               if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
866                 {
867                   if (is_ip4)
868                     flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
869                   else
870                     flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
871                   good_udp0 =
872                     (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
873                 }
874             }
875
876           if (is_ip4)
877             {
878               error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
879               error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
880             }
881           else
882             {
883               error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
884               error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
885             }
886
887           next0 = error0 ?
888             IP_VXLAN_BYPASS_NEXT_DROP : IP_VXLAN_BYPASS_NEXT_VXLAN;
889           b0->error = error0 ? error_node->errors[error0] : 0;
890
891           /* vxlan-input node expect current at VXLAN header */
892           if (is_ip4)
893             vlib_buffer_advance (b0,
894                                  sizeof (ip4_header_t) +
895                                  sizeof (udp_header_t));
896           else
897             vlib_buffer_advance (b0,
898                                  sizeof (ip6_header_t) +
899                                  sizeof (udp_header_t));
900
901         exit:
902           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
903                                            to_next, n_left_to_next,
904                                            bi0, next0);
905         }
906
907       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
908     }
909
910   return frame->n_vectors;
911 }
912
913 static uword
914 ip4_vxlan_bypass (vlib_main_t * vm,
915                   vlib_node_runtime_t * node, vlib_frame_t * frame)
916 {
917   return ip_vxlan_bypass_inline (vm, node, frame, /* is_ip4 */ 1);
918 }
919
920 /* *INDENT-OFF* */
921 VLIB_REGISTER_NODE (ip4_vxlan_bypass_node) =
922 {
923   .function = ip4_vxlan_bypass,
924   .name = "ip4-vxlan-bypass",
925   .vector_size = sizeof (u32),
926   .n_next_nodes = IP_VXLAN_BYPASS_N_NEXT,
927   .next_nodes = {
928           [IP_VXLAN_BYPASS_NEXT_DROP] = "error-drop",
929           [IP_VXLAN_BYPASS_NEXT_VXLAN] = "vxlan4-input",
930   },
931   .format_buffer = format_ip4_header,
932   .format_trace = format_ip4_forward_next_trace,
933 };
934
935 VLIB_NODE_FUNCTION_MULTIARCH (ip4_vxlan_bypass_node, ip4_vxlan_bypass)
936 /* *INDENT-ON* */
937
938 /* Dummy init function to get us linked in. */
939 clib_error_t *
940 ip4_vxlan_bypass_init (vlib_main_t * vm)
941 {
942   return 0;
943 }
944
945 VLIB_INIT_FUNCTION (ip4_vxlan_bypass_init);
946
947 static uword
948 ip6_vxlan_bypass (vlib_main_t * vm,
949                   vlib_node_runtime_t * node, vlib_frame_t * frame)
950 {
951   return ip_vxlan_bypass_inline (vm, node, frame, /* is_ip4 */ 0);
952 }
953
954 /* *INDENT-OFF* */
955 VLIB_REGISTER_NODE (ip6_vxlan_bypass_node) =
956 {
957   .function = ip6_vxlan_bypass,
958   .name = "ip6-vxlan-bypass",
959   .vector_size = sizeof (u32),
960   .n_next_nodes = IP_VXLAN_BYPASS_N_NEXT,
961   .next_nodes = {
962     [IP_VXLAN_BYPASS_NEXT_DROP] = "error-drop",
963     [IP_VXLAN_BYPASS_NEXT_VXLAN] = "vxlan6-input",
964   },
965   .format_buffer = format_ip6_header,
966   .format_trace = format_ip6_forward_next_trace,
967 };
968
969 VLIB_NODE_FUNCTION_MULTIARCH (ip6_vxlan_bypass_node, ip6_vxlan_bypass)
970 /* *INDENT-ON* */
971
972 /* Dummy init function to get us linked in. */
973 clib_error_t *
974 ip6_vxlan_bypass_init (vlib_main_t * vm)
975 {
976   return 0;
977 }
978
979 VLIB_INIT_FUNCTION (ip6_vxlan_bypass_init);
980
981 #define foreach_vxlan_flow_input_next        \
982 _(DROP, "error-drop")                           \
983 _(L2_INPUT, "l2-input")
984
985 typedef enum
986 {
987 #define _(s,n) VXLAN_FLOW_NEXT_##s,
988   foreach_vxlan_flow_input_next
989 #undef _
990     VXLAN_FLOW_N_NEXT,
991 } vxlan_flow_input_next_t;
992
993 #define foreach_vxlan_flow_error                                        \
994   _(NONE, "no error")                                                   \
995   _(IP_CHECKSUM_ERROR, "Rx ip checksum errors")                         \
996   _(IP_HEADER_ERROR, "Rx ip header errors")                             \
997   _(UDP_CHECKSUM_ERROR, "Rx udp checksum errors")                               \
998   _(UDP_LENGTH_ERROR, "Rx udp length errors")
999
1000 typedef enum
1001 {
1002 #define _(f,s) VXLAN_FLOW_ERROR_##f,
1003   foreach_vxlan_flow_error
1004 #undef _
1005     VXLAN_FLOW_N_ERROR,
1006 } vxlan_flow_error_t;
1007
1008 static char *vxlan_flow_error_strings[] = {
1009 #define _(n,s) s,
1010   foreach_vxlan_flow_error
1011 #undef _
1012 };
1013
1014
1015 static_always_inline u8
1016 vxlan_validate_udp_csum (vlib_main_t * vm, vlib_buffer_t * b)
1017 {
1018   u32 flags = b->flags;
1019   enum
1020   { offset =
1021       sizeof (ip4_header_t) + sizeof (udp_header_t) + sizeof (vxlan_header_t),
1022   };
1023
1024   /* Verify UDP checksum */
1025   if ((flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1026     {
1027       vlib_buffer_advance (b, -offset);
1028       flags = ip4_tcp_udp_validate_checksum (vm, b);
1029       vlib_buffer_advance (b, offset);
1030     }
1031
1032   return (flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1033 }
1034
1035 static_always_inline u8
1036 vxlan_check_udp_csum (vlib_main_t * vm, vlib_buffer_t * b)
1037 {
1038   ip4_vxlan_header_t *hdr = vlib_buffer_get_current (b) - sizeof *hdr;
1039   udp_header_t *udp = &hdr->udp;
1040   /* Don't verify UDP checksum for packets with explicit zero checksum. */
1041   u8 good_csum = (b->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0 ||
1042     udp->checksum == 0;
1043
1044   return !good_csum;
1045 }
1046
1047 static_always_inline u8
1048 vxlan_check_ip (vlib_buffer_t * b, u16 payload_len)
1049 {
1050   ip4_vxlan_header_t *hdr = vlib_buffer_get_current (b) - sizeof *hdr;
1051   u16 ip_len = clib_net_to_host_u16 (hdr->ip4.length);
1052   u16 expected = payload_len + sizeof *hdr;
1053   return ip_len > expected || hdr->ip4.ttl == 0
1054     || hdr->ip4.ip_version_and_header_length != 0x45;
1055 }
1056
1057 static_always_inline u8
1058 vxlan_check_ip_udp_len (vlib_buffer_t * b)
1059 {
1060   ip4_vxlan_header_t *hdr = vlib_buffer_get_current (b) - sizeof *hdr;
1061   u16 ip_len = clib_net_to_host_u16 (hdr->ip4.length);
1062   u16 udp_len = clib_net_to_host_u16 (hdr->udp.length);
1063   return udp_len > ip_len;
1064 }
1065
1066 static_always_inline u8
1067 vxlan_err_code (u8 ip_err0, u8 udp_err0, u8 csum_err0)
1068 {
1069   u8 error0 = VXLAN_FLOW_ERROR_NONE;
1070   if (ip_err0)
1071     error0 = VXLAN_FLOW_ERROR_IP_HEADER_ERROR;
1072   if (udp_err0)
1073     error0 = VXLAN_FLOW_ERROR_UDP_LENGTH_ERROR;
1074   if (csum_err0)
1075     error0 = VXLAN_FLOW_ERROR_UDP_CHECKSUM_ERROR;
1076   return error0;
1077 }
1078
1079 VLIB_NODE_FN (vxlan4_flow_input_node) (vlib_main_t * vm,
1080                                        vlib_node_runtime_t * node,
1081                                        vlib_frame_t * f)
1082 {
1083   enum
1084   { payload_offset = sizeof (ip4_vxlan_header_t) };
1085
1086   vxlan_main_t *vxm = &vxlan_main;
1087   vnet_interface_main_t *im = &vnet_main.interface_main;
1088   vlib_combined_counter_main_t *rx_counter[VXLAN_FLOW_N_NEXT] = {
1089     [VXLAN_FLOW_NEXT_DROP] =
1090       im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_DROP,
1091     [VXLAN_FLOW_NEXT_L2_INPUT] =
1092       im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
1093   };
1094   u32 thread_index = vlib_get_thread_index ();
1095
1096   u32 *from = vlib_frame_vector_args (f);
1097   u32 n_left_from = f->n_vectors;
1098   u32 next_index = VXLAN_FLOW_NEXT_L2_INPUT;
1099
1100   while (n_left_from > 0)
1101     {
1102       u32 n_left_to_next, *to_next;
1103
1104       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1105
1106       while (n_left_from > 3 && n_left_to_next > 3)
1107         {
1108           u32 bi0 = to_next[0] = from[0];
1109           u32 bi1 = to_next[1] = from[1];
1110           u32 bi2 = to_next[2] = from[2];
1111           u32 bi3 = to_next[3] = from[3];
1112           from += 4;
1113           n_left_from -= 4;
1114           to_next += 4;
1115           n_left_to_next -= 4;
1116
1117           vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
1118           vlib_buffer_t *b1 = vlib_get_buffer (vm, bi1);
1119           vlib_buffer_t *b2 = vlib_get_buffer (vm, bi2);
1120           vlib_buffer_t *b3 = vlib_get_buffer (vm, bi3);
1121
1122           vlib_buffer_advance (b0, payload_offset);
1123           vlib_buffer_advance (b1, payload_offset);
1124           vlib_buffer_advance (b2, payload_offset);
1125           vlib_buffer_advance (b3, payload_offset);
1126
1127           u16 len0 = vlib_buffer_length_in_chain (vm, b0);
1128           u16 len1 = vlib_buffer_length_in_chain (vm, b1);
1129           u16 len2 = vlib_buffer_length_in_chain (vm, b2);
1130           u16 len3 = vlib_buffer_length_in_chain (vm, b3);
1131
1132           u32 next0 = VXLAN_FLOW_NEXT_L2_INPUT, next1 =
1133             VXLAN_FLOW_NEXT_L2_INPUT, next2 =
1134             VXLAN_FLOW_NEXT_L2_INPUT, next3 = VXLAN_FLOW_NEXT_L2_INPUT;
1135
1136           u8 ip_err0 = vxlan_check_ip (b0, len0);
1137           u8 ip_err1 = vxlan_check_ip (b1, len1);
1138           u8 ip_err2 = vxlan_check_ip (b2, len2);
1139           u8 ip_err3 = vxlan_check_ip (b3, len3);
1140           u8 ip_err = ip_err0 | ip_err1 | ip_err2 | ip_err3;
1141
1142           u8 udp_err0 = vxlan_check_ip_udp_len (b0);
1143           u8 udp_err1 = vxlan_check_ip_udp_len (b1);
1144           u8 udp_err2 = vxlan_check_ip_udp_len (b2);
1145           u8 udp_err3 = vxlan_check_ip_udp_len (b3);
1146           u8 udp_err = udp_err0 | udp_err1 | udp_err2 | udp_err3;
1147
1148           u8 csum_err0 = vxlan_check_udp_csum (vm, b0);
1149           u8 csum_err1 = vxlan_check_udp_csum (vm, b1);
1150           u8 csum_err2 = vxlan_check_udp_csum (vm, b2);
1151           u8 csum_err3 = vxlan_check_udp_csum (vm, b3);
1152           u8 csum_err = csum_err0 | csum_err1 | csum_err2 | csum_err3;
1153
1154           if (PREDICT_FALSE (csum_err))
1155             {
1156               if (csum_err0)
1157                 csum_err0 = !vxlan_validate_udp_csum (vm, b0);
1158               if (csum_err1)
1159                 csum_err1 = !vxlan_validate_udp_csum (vm, b1);
1160               if (csum_err2)
1161                 csum_err2 = !vxlan_validate_udp_csum (vm, b2);
1162               if (csum_err3)
1163                 csum_err3 = !vxlan_validate_udp_csum (vm, b3);
1164               csum_err = csum_err0 | csum_err1 | csum_err2 | csum_err3;
1165             }
1166
1167           if (PREDICT_FALSE (ip_err || udp_err || csum_err))
1168             {
1169               if (ip_err0 || udp_err0 || csum_err0)
1170                 {
1171                   next0 = VXLAN_FLOW_NEXT_DROP;
1172                   u8 error0 = vxlan_err_code (ip_err0, udp_err0, csum_err0);
1173                   b0->error = node->errors[error0];
1174                 }
1175               if (ip_err1 || udp_err1 || csum_err1)
1176                 {
1177                   next1 = VXLAN_FLOW_NEXT_DROP;
1178                   u8 error1 = vxlan_err_code (ip_err1, udp_err1, csum_err1);
1179                   b1->error = node->errors[error1];
1180                 }
1181               if (ip_err2 || udp_err2 || csum_err2)
1182                 {
1183                   next2 = VXLAN_FLOW_NEXT_DROP;
1184                   u8 error2 = vxlan_err_code (ip_err2, udp_err2, csum_err2);
1185                   b2->error = node->errors[error2];
1186                 }
1187               if (ip_err3 || udp_err3 || csum_err3)
1188                 {
1189                   next3 = VXLAN_FLOW_NEXT_DROP;
1190                   u8 error3 = vxlan_err_code (ip_err3, udp_err3, csum_err3);
1191                   b3->error = node->errors[error3];
1192                 }
1193             }
1194
1195           vnet_update_l2_len (b0);
1196           vnet_update_l2_len (b1);
1197           vnet_update_l2_len (b2);
1198           vnet_update_l2_len (b3);
1199
1200           ASSERT (b0->flow_id != 0);
1201           ASSERT (b1->flow_id != 0);
1202           ASSERT (b2->flow_id != 0);
1203           ASSERT (b3->flow_id != 0);
1204
1205           u32 t_index0 = b0->flow_id - vxm->flow_id_start;
1206           u32 t_index1 = b1->flow_id - vxm->flow_id_start;
1207           u32 t_index2 = b2->flow_id - vxm->flow_id_start;
1208           u32 t_index3 = b3->flow_id - vxm->flow_id_start;
1209
1210           vxlan_tunnel_t *t0 = &vxm->tunnels[t_index0];
1211           vxlan_tunnel_t *t1 = &vxm->tunnels[t_index1];
1212           vxlan_tunnel_t *t2 = &vxm->tunnels[t_index2];
1213           vxlan_tunnel_t *t3 = &vxm->tunnels[t_index3];
1214
1215           /* flow id consumed */
1216           b0->flow_id = 0;
1217           b1->flow_id = 0;
1218           b2->flow_id = 0;
1219           b3->flow_id = 0;
1220
1221           u32 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1222             t0->sw_if_index;
1223           u32 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX] =
1224             t1->sw_if_index;
1225           u32 sw_if_index2 = vnet_buffer (b2)->sw_if_index[VLIB_RX] =
1226             t2->sw_if_index;
1227           u32 sw_if_index3 = vnet_buffer (b3)->sw_if_index[VLIB_RX] =
1228             t3->sw_if_index;
1229
1230           vlib_increment_combined_counter (rx_counter[next0], thread_index,
1231                                            sw_if_index0, 1, len0);
1232           vlib_increment_combined_counter (rx_counter[next1], thread_index,
1233                                            sw_if_index1, 1, len1);
1234           vlib_increment_combined_counter (rx_counter[next2], thread_index,
1235                                            sw_if_index2, 1, len2);
1236           vlib_increment_combined_counter (rx_counter[next3], thread_index,
1237                                            sw_if_index3, 1, len3);
1238
1239           u32 flags = b0->flags | b1->flags | b2->flags | b3->flags;
1240
1241           if (PREDICT_FALSE (flags & VLIB_BUFFER_IS_TRACED))
1242             {
1243               if (b0->flags & VLIB_BUFFER_IS_TRACED)
1244                 {
1245                   vxlan_rx_trace_t *tr =
1246                     vlib_add_trace (vm, node, b0, sizeof *tr);
1247                   u8 error0 = vxlan_err_code (ip_err0, udp_err0, csum_err0);
1248                   tr->next_index = next0;
1249                   tr->error = error0;
1250                   tr->tunnel_index = t_index0;
1251                   tr->vni = t0->vni;
1252                 }
1253               if (b1->flags & VLIB_BUFFER_IS_TRACED)
1254                 {
1255                   vxlan_rx_trace_t *tr =
1256                     vlib_add_trace (vm, node, b1, sizeof *tr);
1257                   u8 error1 = vxlan_err_code (ip_err1, udp_err1, csum_err1);
1258                   tr->next_index = next1;
1259                   tr->error = error1;
1260                   tr->tunnel_index = t_index1;
1261                   tr->vni = t1->vni;
1262                 }
1263               if (b2->flags & VLIB_BUFFER_IS_TRACED)
1264                 {
1265                   vxlan_rx_trace_t *tr =
1266                     vlib_add_trace (vm, node, b2, sizeof *tr);
1267                   u8 error2 = vxlan_err_code (ip_err2, udp_err2, csum_err2);
1268                   tr->next_index = next2;
1269                   tr->error = error2;
1270                   tr->tunnel_index = t_index2;
1271                   tr->vni = t2->vni;
1272                 }
1273               if (b3->flags & VLIB_BUFFER_IS_TRACED)
1274                 {
1275                   vxlan_rx_trace_t *tr =
1276                     vlib_add_trace (vm, node, b3, sizeof *tr);
1277                   u8 error3 = vxlan_err_code (ip_err3, udp_err3, csum_err3);
1278                   tr->next_index = next3;
1279                   tr->error = error3;
1280                   tr->tunnel_index = t_index3;
1281                   tr->vni = t3->vni;
1282                 }
1283             }
1284           vlib_validate_buffer_enqueue_x4
1285             (vm, node, next_index, to_next, n_left_to_next,
1286              bi0, bi1, bi2, bi3, next0, next1, next2, next3);
1287         }
1288       while (n_left_from > 0 && n_left_to_next > 0)
1289         {
1290           u32 bi0 = to_next[0] = from[0];
1291           from++;
1292           n_left_from--;
1293           to_next++;
1294           n_left_to_next--;
1295
1296           vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
1297           vlib_buffer_advance (b0, payload_offset);
1298
1299           u16 len0 = vlib_buffer_length_in_chain (vm, b0);
1300           u32 next0 = VXLAN_FLOW_NEXT_L2_INPUT;
1301
1302           u8 ip_err0 = vxlan_check_ip (b0, len0);
1303           u8 udp_err0 = vxlan_check_ip_udp_len (b0);
1304           u8 csum_err0 = vxlan_check_udp_csum (vm, b0);
1305
1306           if (csum_err0)
1307             csum_err0 = !vxlan_validate_udp_csum (vm, b0);
1308           if (ip_err0 || udp_err0 || csum_err0)
1309             {
1310               next0 = VXLAN_FLOW_NEXT_DROP;
1311               u8 error0 = vxlan_err_code (ip_err0, udp_err0, csum_err0);
1312               b0->error = node->errors[error0];
1313             }
1314
1315           vnet_update_l2_len (b0);
1316
1317           ASSERT (b0->flow_id != 0);
1318           u32 t_index0 = b0->flow_id - vxm->flow_id_start;
1319           vxlan_tunnel_t *t0 = &vxm->tunnels[t_index0];
1320           b0->flow_id = 0;
1321
1322           u32 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX] =
1323             t0->sw_if_index;
1324           vlib_increment_combined_counter (rx_counter[next0], thread_index,
1325                                            sw_if_index0, 1, len0);
1326
1327           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1328             {
1329               vxlan_rx_trace_t *tr =
1330                 vlib_add_trace (vm, node, b0, sizeof *tr);
1331               u8 error0 = vxlan_err_code (ip_err0, udp_err0, csum_err0);
1332               tr->next_index = next0;
1333               tr->error = error0;
1334               tr->tunnel_index = t_index0;
1335               tr->vni = t0->vni;
1336             }
1337           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1338                                            to_next, n_left_to_next,
1339                                            bi0, next0);
1340         }
1341
1342       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1343     }
1344
1345   return f->n_vectors;
1346 }
1347
1348 /* *INDENT-OFF* */
1349 #ifndef CLIB_MULTIARCH_VARIANT
1350 VLIB_REGISTER_NODE (vxlan4_flow_input_node) = {
1351   .name = "vxlan-flow-input",
1352   .type = VLIB_NODE_TYPE_INTERNAL,
1353   .vector_size = sizeof (u32),
1354
1355   .format_trace = format_vxlan_rx_trace,
1356
1357   .n_errors = VXLAN_FLOW_N_ERROR,
1358   .error_strings = vxlan_flow_error_strings,
1359
1360   .n_next_nodes = VXLAN_FLOW_N_NEXT,
1361   .next_nodes = {
1362 #define _(s,n) [VXLAN_FLOW_NEXT_##s] = n,
1363     foreach_vxlan_flow_input_next
1364 #undef _
1365   },
1366 };
1367 #endif
1368 /* *INDENT-ON* */
1369
1370 /*
1371  * fd.io coding-style-patch-verification: ON
1372  *
1373  * Local Variables:
1374  * eval: (c-set-style "gnu")
1375  * End:
1376  */