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