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