FD.io VPP  v17.01.1-3-gc6833f8
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 
24 
25 typedef struct {
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 
53  vlib_node_runtime_t * node,
54  vlib_frame_t * from_frame,
55  u32 is_ip4)
56 {
57  u32 n_left_from, next_index, * from, * to_next;
58  vxlan_main_t * vxm = &vxlan_main;
59  vnet_main_t * vnm = vxm->vnet_main;
61  u32 last_tunnel_index = ~0;
62  vxlan4_tunnel_key_t last_key4;
63  vxlan6_tunnel_key_t last_key6;
64  u32 pkts_decapsulated = 0;
65  u32 cpu_index = os_get_cpu_number();
66  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
67 
68  if (is_ip4)
69  last_key4.as_u64 = ~0;
70  else
71  memset (&last_key6, 0xff, sizeof (last_key6));
72 
73  from = vlib_frame_vector_args (from_frame);
74  n_left_from = from_frame->n_vectors;
75 
76  next_index = node->cached_next_index;
77  stats_sw_if_index = node->runtime_data[0];
78  stats_n_packets = stats_n_bytes = 0;
79 
80  while (n_left_from > 0)
81  {
82  u32 n_left_to_next;
83 
84  vlib_get_next_frame (vm, node, next_index,
85  to_next, n_left_to_next);
86  while (n_left_from >= 4 && n_left_to_next >= 2)
87  {
88  u32 bi0, bi1;
89  vlib_buffer_t * b0, * b1;
90  u32 next0, next1;
91  ip4_header_t * ip4_0, * ip4_1;
92  ip6_header_t * ip6_0, * ip6_1;
93  vxlan_header_t * vxlan0, * vxlan1;
94  uword * p0, * p1;
95  u32 tunnel_index0, tunnel_index1;
96  vxlan_tunnel_t * t0, * t1, * mt0 = NULL, * mt1 = NULL;
97  vxlan4_tunnel_key_t key4_0, key4_1;
98  vxlan6_tunnel_key_t key6_0, key6_1;
99  u32 error0, error1;
100  u32 sw_if_index0, sw_if_index1, len0, len1;
101 
102  /* Prefetch next iteration. */
103  {
104  vlib_buffer_t * p2, * p3;
105 
106  p2 = vlib_get_buffer (vm, from[2]);
107  p3 = vlib_get_buffer (vm, from[3]);
108 
109  vlib_prefetch_buffer_header (p2, LOAD);
110  vlib_prefetch_buffer_header (p3, LOAD);
111 
114  }
115 
116  bi0 = from[0];
117  bi1 = from[1];
118  to_next[0] = bi0;
119  to_next[1] = bi1;
120  from += 2;
121  to_next += 2;
122  n_left_to_next -= 2;
123  n_left_from -= 2;
124 
125  b0 = vlib_get_buffer (vm, bi0);
126  b1 = vlib_get_buffer (vm, bi1);
127 
128  /* udp leaves current_data pointing at the vxlan header */
129  vxlan0 = vlib_buffer_get_current (b0);
130  vxlan1 = vlib_buffer_get_current (b1);
131  if (is_ip4) {
133  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip4_header_t)));
135  (b1, -(word)(sizeof(udp_header_t)+sizeof(ip4_header_t)));
136  ip4_0 = vlib_buffer_get_current (b0);
137  ip4_1 = vlib_buffer_get_current (b1);
138  } else {
140  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip6_header_t)));
142  (b1, -(word)(sizeof(udp_header_t)+sizeof(ip6_header_t)));
143  ip6_0 = vlib_buffer_get_current (b0);
144  ip6_1 = vlib_buffer_get_current (b1);
145  }
146 
147  /* pop (ip, udp, vxlan) */
148  if (is_ip4) {
150  (b0, sizeof(*ip4_0)+sizeof(udp_header_t)+sizeof(*vxlan0));
152  (b1, sizeof(*ip4_1)+sizeof(udp_header_t)+sizeof(*vxlan1));
153  } else {
155  (b0, sizeof(*ip6_0)+sizeof(udp_header_t)+sizeof(*vxlan0));
157  (b1, sizeof(*ip6_1)+sizeof(udp_header_t)+sizeof(*vxlan1));
158  }
159 
160  tunnel_index0 = ~0;
161  error0 = 0;
162 
163  tunnel_index1 = ~0;
164  error1 = 0;
165 
166  if (PREDICT_FALSE (vxlan0->flags != VXLAN_FLAGS_I))
167  {
168  error0 = VXLAN_ERROR_BAD_FLAGS;
169  next0 = VXLAN_INPUT_NEXT_DROP;
170  goto trace0;
171  }
172 
173  if (is_ip4) {
174  key4_0.src = ip4_0->src_address.as_u32;
175  key4_0.vni = vxlan0->vni_reserved;
176 
177  /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
178  if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
179  {
180  p0 = hash_get (vxm->vxlan4_tunnel_by_key, key4_0.as_u64);
181  if (PREDICT_FALSE (p0 == NULL))
182  {
183  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
184  next0 = VXLAN_INPUT_NEXT_DROP;
185  goto trace0;
186  }
187  last_key4.as_u64 = key4_0.as_u64;
188  tunnel_index0 = last_tunnel_index = p0[0];
189  }
190  else
191  tunnel_index0 = last_tunnel_index;
192  t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
193 
194  /* Validate VXLAN tunnel SIP against packet DIP */
195  if (PREDICT_TRUE (ip4_0->dst_address.as_u32 == t0->src.ip4.as_u32))
196  goto next0; /* valid packet */
198  {
199  key4_0.src = ip4_0->dst_address.as_u32;
200  key4_0.vni = vxlan0->vni_reserved;
201  /* Make sure mcast VXLAN tunnel exist by packet DIP and VNI */
202  p0 = hash_get (vxm->vxlan4_tunnel_by_key, key4_0.as_u64);
203  if (PREDICT_TRUE (p0 != NULL))
204  {
205  mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
206  goto next0; /* valid packet */
207  }
208  }
209  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
210  next0 = VXLAN_INPUT_NEXT_DROP;
211  goto trace0;
212 
213  } else /* !is_ip4 */ {
214  key6_0.src.as_u64[0] = ip6_0->src_address.as_u64[0];
215  key6_0.src.as_u64[1] = ip6_0->src_address.as_u64[1];
216  key6_0.vni = vxlan0->vni_reserved;
217 
218  /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
219  if (PREDICT_FALSE (memcmp(&key6_0, &last_key6, sizeof(last_key6)) != 0))
220  {
221  p0 = hash_get_mem (vxm->vxlan6_tunnel_by_key, &key6_0);
222  if (PREDICT_FALSE (p0 == NULL))
223  {
224  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
225  next0 = VXLAN_INPUT_NEXT_DROP;
226  goto trace0;
227  }
228  clib_memcpy (&last_key6, &key6_0, sizeof(key6_0));
229  tunnel_index0 = last_tunnel_index = p0[0];
230  }
231  else
232  tunnel_index0 = last_tunnel_index;
233  t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
234 
235  /* Validate VXLAN tunnel SIP against packet DIP */
237  &t0->src.ip6)))
238  goto next0; /* valid packet */
240  {
241  key6_0.src.as_u64[0] = ip6_0->dst_address.as_u64[0];
242  key6_0.src.as_u64[1] = ip6_0->dst_address.as_u64[1];
243  key6_0.vni = vxlan0->vni_reserved;
244  p0 = hash_get (vxm->vxlan6_tunnel_by_key, &key6_0);
245  if (PREDICT_TRUE (p0 != NULL))
246  {
247  mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
248  goto next0; /* valid packet */
249  }
250  }
251  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
252  next0 = VXLAN_INPUT_NEXT_DROP;
253  goto trace0;
254  }
255 
256  next0:
257  next0 = t0->decap_next_index;
258  sw_if_index0 = t0->sw_if_index;
259  len0 = vlib_buffer_length_in_chain (vm, b0);
260 
261  /* Required to make the l2 tag push / pop code work on l2 subifs */
262  if (PREDICT_TRUE(next0 == VXLAN_INPUT_NEXT_L2_INPUT))
263  vnet_update_l2_len (b0);
264 
265  /* Set packet input sw_if_index to unicast VXLAN tunnel for learning */
266  vnet_buffer(b0)->sw_if_index[VLIB_RX] = sw_if_index0;
267  sw_if_index0 = (mt0) ? mt0->sw_if_index : sw_if_index0;
268 
269  pkts_decapsulated ++;
270  stats_n_packets += 1;
271  stats_n_bytes += len0;
272 
273  /* Batch stats increment on the same vxlan tunnel so counter
274  is not incremented per packet */
275  if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index))
276  {
277  stats_n_packets -= 1;
278  stats_n_bytes -= len0;
279  if (stats_n_packets)
282  cpu_index, stats_sw_if_index,
283  stats_n_packets, stats_n_bytes);
284  stats_n_packets = 1;
285  stats_n_bytes = len0;
286  stats_sw_if_index = sw_if_index0;
287  }
288 
289  trace0:
290  b0->error = error0 ? node->errors[error0] : 0;
291 
293  {
294  vxlan_rx_trace_t *tr
295  = vlib_add_trace (vm, node, b0, sizeof (*tr));
296  tr->next_index = next0;
297  tr->error = error0;
298  tr->tunnel_index = tunnel_index0;
299  tr->vni = vnet_get_vni (vxlan0);
300  }
301 
302  if (PREDICT_FALSE (vxlan1->flags != VXLAN_FLAGS_I))
303  {
304  error1 = VXLAN_ERROR_BAD_FLAGS;
305  next1 = VXLAN_INPUT_NEXT_DROP;
306  goto trace1;
307  }
308 
309  if (is_ip4) {
310  key4_1.src = ip4_1->src_address.as_u32;
311  key4_1.vni = vxlan1->vni_reserved;
312 
313  /* Make sure unicast VXLAN tunnel exist by packet SIP and VNI */
314  if (PREDICT_FALSE (key4_1.as_u64 != last_key4.as_u64))
315  {
316  p1 = hash_get (vxm->vxlan4_tunnel_by_key, key4_1.as_u64);
317  if (PREDICT_FALSE (p1 == NULL))
318  {
319  error1 = VXLAN_ERROR_NO_SUCH_TUNNEL;
320  next1 = VXLAN_INPUT_NEXT_DROP;
321  goto trace1;
322  }
323  last_key4.as_u64 = key4_1.as_u64;
324  tunnel_index1 = last_tunnel_index = p1[0];
325  }
326  else
327  tunnel_index1 = last_tunnel_index;
328  t1 = pool_elt_at_index (vxm->tunnels, tunnel_index1);
329 
330  /* Validate VXLAN tunnel SIP against packet DIP */
331  if (PREDICT_TRUE (ip4_1->dst_address.as_u32 == t1->src.ip4.as_u32))
332  goto next1; /* valid packet */
334  {
335  key4_1.src = ip4_1->dst_address.as_u32;
336  key4_1.vni = vxlan1->vni_reserved;
337  /* Make sure mcast VXLAN tunnel exist by packet DIP and VNI */
338  p1 = hash_get (vxm->vxlan4_tunnel_by_key, key4_1.as_u64);
339  if (PREDICT_TRUE (p1 != NULL))
340  {
341  mt1 = pool_elt_at_index (vxm->tunnels, p1[0]);
342  goto next1; /* valid packet */
343  }
344  }
345  error1 = VXLAN_ERROR_NO_SUCH_TUNNEL;
346  next1 = VXLAN_INPUT_NEXT_DROP;
347  goto trace1;
348 
349  } else /* !is_ip4 */ {
350  key6_1.src.as_u64[0] = ip6_1->src_address.as_u64[0];
351  key6_1.src.as_u64[1] = ip6_1->src_address.as_u64[1];
352  key6_1.vni = vxlan1->vni_reserved;
353 
354  /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
355  if (PREDICT_FALSE (memcmp(&key6_1, &last_key6, sizeof(last_key6)) != 0))
356  {
357  p1 = hash_get_mem (vxm->vxlan6_tunnel_by_key, &key6_1);
358 
359  if (PREDICT_FALSE (p1 == NULL))
360  {
361  error1 = VXLAN_ERROR_NO_SUCH_TUNNEL;
362  next1 = VXLAN_INPUT_NEXT_DROP;
363  goto trace1;
364  }
365 
366  clib_memcpy (&last_key6, &key6_1, sizeof(key6_1));
367  tunnel_index1 = last_tunnel_index = p1[0];
368  }
369  else
370  tunnel_index1 = last_tunnel_index;
371  t1 = pool_elt_at_index (vxm->tunnels, tunnel_index1);
372 
373  /* Validate VXLAN tunnel SIP against packet DIP */
375  &t1->src.ip6)))
376  goto next1; /* valid packet */
378  {
379  key6_1.src.as_u64[0] = ip6_1->dst_address.as_u64[0];
380  key6_1.src.as_u64[1] = ip6_1->dst_address.as_u64[1];
381  key6_1.vni = vxlan1->vni_reserved;
382  p1 = hash_get (vxm->vxlan6_tunnel_by_key, &key6_1);
383  if (PREDICT_TRUE (p1 != NULL))
384  {
385  mt1 = pool_elt_at_index (vxm->tunnels, p1[0]);
386  goto next1; /* valid packet */
387  }
388  }
389  error1 = VXLAN_ERROR_NO_SUCH_TUNNEL;
390  next1 = VXLAN_INPUT_NEXT_DROP;
391  goto trace1;
392  }
393 
394  next1:
395  next1 = t1->decap_next_index;
396  sw_if_index1 = t1->sw_if_index;
397  len1 = vlib_buffer_length_in_chain (vm, b1);
398 
399  /* Required to make the l2 tag push / pop code work on l2 subifs */
400  if (PREDICT_TRUE(next1 == VXLAN_INPUT_NEXT_L2_INPUT))
401  vnet_update_l2_len (b1);
402 
403  /* Set packet input sw_if_index to unicast VXLAN tunnel for learning */
404  vnet_buffer(b1)->sw_if_index[VLIB_RX] = sw_if_index1;
405  sw_if_index1 = (mt1) ? mt1->sw_if_index : sw_if_index1;
406 
407  pkts_decapsulated ++;
408  stats_n_packets += 1;
409  stats_n_bytes += len1;
410 
411  /* Batch stats increment on the same vxlan tunnel so counter
412  is not incremented per packet */
413  if (PREDICT_FALSE (sw_if_index1 != stats_sw_if_index))
414  {
415  stats_n_packets -= 1;
416  stats_n_bytes -= len1;
417  if (stats_n_packets)
420  cpu_index, stats_sw_if_index,
421  stats_n_packets, stats_n_bytes);
422  stats_n_packets = 1;
423  stats_n_bytes = len1;
424  stats_sw_if_index = sw_if_index1;
425  }
426 
427  trace1:
428  b1->error = error1 ? node->errors[error1] : 0;
429 
431  {
432  vxlan_rx_trace_t *tr
433  = vlib_add_trace (vm, node, b1, sizeof (*tr));
434  tr->next_index = next1;
435  tr->error = error1;
436  tr->tunnel_index = tunnel_index1;
437  tr->vni = vnet_get_vni (vxlan1);
438  }
439 
440  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
441  to_next, n_left_to_next,
442  bi0, bi1, next0, next1);
443  }
444 
445  while (n_left_from > 0 && n_left_to_next > 0)
446  {
447  u32 bi0;
448  vlib_buffer_t * b0;
449  u32 next0;
450  ip4_header_t * ip4_0;
451  ip6_header_t * ip6_0;
452  vxlan_header_t * vxlan0;
453  uword * p0;
454  u32 tunnel_index0;
455  vxlan_tunnel_t * t0, * mt0 = NULL;
456  vxlan4_tunnel_key_t key4_0;
457  vxlan6_tunnel_key_t key6_0;
458  u32 error0;
459  u32 sw_if_index0, len0;
460 
461  bi0 = from[0];
462  to_next[0] = bi0;
463  from += 1;
464  to_next += 1;
465  n_left_from -= 1;
466  n_left_to_next -= 1;
467 
468  b0 = vlib_get_buffer (vm, bi0);
469 
470  /* udp leaves current_data pointing at the vxlan header */
471  vxlan0 = vlib_buffer_get_current (b0);
472  if (is_ip4) {
474  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip4_header_t)));
475  ip4_0 = vlib_buffer_get_current (b0);
476  } else {
478  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip6_header_t)));
479  ip6_0 = vlib_buffer_get_current (b0);
480  }
481 
482  /* pop (ip, udp, vxlan) */
483  if (is_ip4) {
485  (b0, sizeof(*ip4_0)+sizeof(udp_header_t)+sizeof(*vxlan0));
486  } else {
488  (b0, sizeof(*ip6_0)+sizeof(udp_header_t)+sizeof(*vxlan0));
489  }
490 
491  tunnel_index0 = ~0;
492  error0 = 0;
493 
494  if (PREDICT_FALSE (vxlan0->flags != VXLAN_FLAGS_I))
495  {
496  error0 = VXLAN_ERROR_BAD_FLAGS;
497  next0 = VXLAN_INPUT_NEXT_DROP;
498  goto trace00;
499  }
500 
501  if (is_ip4) {
502  key4_0.src = ip4_0->src_address.as_u32;
503  key4_0.vni = vxlan0->vni_reserved;
504 
505  /* Make sure unicast VXLAN tunnel exist by packet SIP and VNI */
506  if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
507  {
508  p0 = hash_get (vxm->vxlan4_tunnel_by_key, key4_0.as_u64);
509  if (PREDICT_FALSE (p0 == NULL))
510  {
511  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
512  next0 = VXLAN_INPUT_NEXT_DROP;
513  goto trace00;
514  }
515  last_key4.as_u64 = key4_0.as_u64;
516  tunnel_index0 = last_tunnel_index = p0[0];
517  }
518  else
519  tunnel_index0 = last_tunnel_index;
520  t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
521 
522  /* Validate VXLAN tunnel SIP against packet DIP */
523  if (PREDICT_TRUE (ip4_0->dst_address.as_u32 == t0->src.ip4.as_u32))
524  goto next00; /* valid packet */
526  {
527  key4_0.src = ip4_0->dst_address.as_u32;
528  key4_0.vni = vxlan0->vni_reserved;
529  /* Make sure mcast VXLAN tunnel exist by packet DIP and VNI */
530  p0 = hash_get (vxm->vxlan4_tunnel_by_key, key4_0.as_u64);
531  if (PREDICT_TRUE (p0 != NULL))
532  {
533  mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
534  goto next00; /* valid packet */
535  }
536  }
537  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
538  next0 = VXLAN_INPUT_NEXT_DROP;
539  goto trace00;
540 
541  } else /* !is_ip4 */ {
542  key6_0.src.as_u64[0] = ip6_0->src_address.as_u64[0];
543  key6_0.src.as_u64[1] = ip6_0->src_address.as_u64[1];
544  key6_0.vni = vxlan0->vni_reserved;
545 
546  /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
547  if (PREDICT_FALSE (memcmp(&key6_0, &last_key6, sizeof(last_key6)) != 0))
548  {
549  p0 = hash_get_mem (vxm->vxlan6_tunnel_by_key, &key6_0);
550  if (PREDICT_FALSE (p0 == NULL))
551  {
552  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
553  next0 = VXLAN_INPUT_NEXT_DROP;
554  goto trace00;
555  }
556  clib_memcpy (&last_key6, &key6_0, sizeof(key6_0));
557  tunnel_index0 = last_tunnel_index = p0[0];
558  }
559  else
560  tunnel_index0 = last_tunnel_index;
561  t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
562 
563  /* Validate VXLAN tunnel SIP against packet DIP */
565  &t0->src.ip6)))
566  goto next00; /* valid packet */
568  {
569  key6_0.src.as_u64[0] = ip6_0->dst_address.as_u64[0];
570  key6_0.src.as_u64[1] = ip6_0->dst_address.as_u64[1];
571  key6_0.vni = vxlan0->vni_reserved;
572  p0 = hash_get (vxm->vxlan6_tunnel_by_key, &key6_0);
573  if (PREDICT_TRUE (p0 != NULL))
574  {
575  mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
576  goto next00; /* valid packet */
577  }
578  }
579  error0 = VXLAN_ERROR_NO_SUCH_TUNNEL;
580  next0 = VXLAN_INPUT_NEXT_DROP;
581  goto trace00;
582  }
583 
584  next00:
585  next0 = t0->decap_next_index;
586  sw_if_index0 = t0->sw_if_index;
587  len0 = vlib_buffer_length_in_chain (vm, b0);
588 
589  /* Required to make the l2 tag push / pop code work on l2 subifs */
590  if (PREDICT_TRUE(next0 == VXLAN_INPUT_NEXT_L2_INPUT))
591  vnet_update_l2_len (b0);
592 
593  /* Set packet input sw_if_index to unicast VXLAN tunnel for learning */
594  vnet_buffer(b0)->sw_if_index[VLIB_RX] = sw_if_index0;
595  sw_if_index0 = (mt0) ? mt0->sw_if_index : sw_if_index0;
596 
597  pkts_decapsulated ++;
598  stats_n_packets += 1;
599  stats_n_bytes += len0;
600 
601  /* Batch stats increment on the same vxlan tunnel so counter
602  is not incremented per packet */
603  if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index))
604  {
605  stats_n_packets -= 1;
606  stats_n_bytes -= len0;
607  if (stats_n_packets)
610  cpu_index, stats_sw_if_index,
611  stats_n_packets, stats_n_bytes);
612  stats_n_packets = 1;
613  stats_n_bytes = len0;
614  stats_sw_if_index = sw_if_index0;
615  }
616 
617  trace00:
618  b0->error = error0 ? node->errors[error0] : 0;
619 
621  {
622  vxlan_rx_trace_t *tr
623  = vlib_add_trace (vm, node, b0, sizeof (*tr));
624  tr->next_index = next0;
625  tr->error = error0;
626  tr->tunnel_index = tunnel_index0;
627  tr->vni = vnet_get_vni (vxlan0);
628  }
629  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
630  to_next, n_left_to_next,
631  bi0, next0);
632  }
633 
634  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
635  }
636  /* Do we still need this now that tunnel tx stats is kept? */
637  vlib_node_increment_counter (vm, is_ip4?
639  VXLAN_ERROR_DECAPSULATED,
640  pkts_decapsulated);
641 
642  /* Increment any remaining batch stats */
643  if (stats_n_packets)
644  {
647  cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
648  node->runtime_data[0] = stats_sw_if_index;
649  }
650 
651  return from_frame->n_vectors;
652 }
653 
654 static uword
656  vlib_node_runtime_t * node,
657  vlib_frame_t * from_frame)
658 {
659  return vxlan_input(vm, node, from_frame, /* is_ip4 */ 1);
660 }
661 
662 static uword
664  vlib_node_runtime_t * node,
665  vlib_frame_t * from_frame)
666 {
667  return vxlan_input(vm, node, from_frame, /* is_ip4 */ 0);
668 }
669 
670 static char * vxlan_error_strings[] = {
671 #define vxlan_error(n,s) s,
673 #undef vxlan_error
674 #undef _
675 };
676 
678  .function = vxlan4_input,
679  .name = "vxlan4-input",
680  /* Takes a vector of packets. */
681  .vector_size = sizeof (u32),
682 
683  .n_errors = VXLAN_N_ERROR,
684  .error_strings = vxlan_error_strings,
685 
686  .n_next_nodes = VXLAN_INPUT_N_NEXT,
687  .next_nodes = {
688 #define _(s,n) [VXLAN_INPUT_NEXT_##s] = n,
690 #undef _
691  },
692 
693 //temp .format_buffer = format_vxlan_header,
694  .format_trace = format_vxlan_rx_trace,
695  // $$$$ .unformat_buffer = unformat_vxlan_header,
696 };
697 
699 
701  .function = vxlan6_input,
702  .name = "vxlan6-input",
703  /* Takes a vector of packets. */
704  .vector_size = sizeof (u32),
705 
706  .n_errors = VXLAN_N_ERROR,
707  .error_strings = vxlan_error_strings,
708 
709  .n_next_nodes = VXLAN_INPUT_N_NEXT,
710  .next_nodes = {
711 #define _(s,n) [VXLAN_INPUT_NEXT_##s] = n,
713 #undef _
714  },
715 
716 //temp .format_buffer = format_vxlan_header,
717  .format_trace = format_vxlan_rx_trace,
718  // $$$$ .unformat_buffer = unformat_vxlan_header,
719 };
720 
722 
723 
724 typedef enum {
729 
732  vlib_node_runtime_t * node,
733  vlib_frame_t * frame,
734  u32 is_ip4)
735 {
736  vxlan_main_t * vxm = &vxlan_main;
737  u32 * from, * to_next, n_left_from, n_left_to_next, next_index;
738  vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index);
739  ip4_address_t addr4; /* last IPv4 address matching a local VTEP address */
740  ip6_address_t addr6; /* last IPv6 address matching a local VTEP address */
741 
742  from = vlib_frame_vector_args (frame);
743  n_left_from = frame->n_vectors;
744  next_index = node->cached_next_index;
745 
746  if (node->flags & VLIB_NODE_FLAG_TRACE)
747  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
748 
749  if (is_ip4) addr4.data_u32 = ~0;
750  else ip6_address_set_zero (&addr6);
751 
752  while (n_left_from > 0)
753  {
754  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
755 
756  while (n_left_from >= 4 && n_left_to_next >= 2)
757  {
758  vlib_buffer_t * b0, * b1;
759  ip4_header_t * ip0, * ip1;
760  udp_header_t * udp0, * udp1;
761  u32 bi0, ip_len0, udp_len0, flags0, next0;
762  u32 bi1, ip_len1, udp_len1, flags1, next1;
763  i32 len_diff0, len_diff1;
764  u8 error0, good_udp0, proto0;
765  u8 error1, good_udp1, proto1;
766 
767  /* Prefetch next iteration. */
768  {
769  vlib_buffer_t * p2, * p3;
770 
771  p2 = vlib_get_buffer (vm, from[2]);
772  p3 = vlib_get_buffer (vm, from[3]);
773 
774  vlib_prefetch_buffer_header (p2, LOAD);
775  vlib_prefetch_buffer_header (p3, LOAD);
776 
779  }
780 
781  bi0 = to_next[0] = from[0];
782  bi1 = to_next[1] = from[1];
783  from += 2;
784  n_left_from -= 2;
785  to_next += 2;
786  n_left_to_next -= 2;
787 
788  b0 = vlib_get_buffer (vm, bi0);
789  b1 = vlib_get_buffer (vm, bi1);
790  ip0 = vlib_buffer_get_current (b0);
791  ip1 = vlib_buffer_get_current (b1);
792 
793  /* Setup packet for next IP feature */
794  vnet_feature_next(vnet_buffer(b0)->sw_if_index[VLIB_RX], &next0, b0);
795  vnet_feature_next(vnet_buffer(b1)->sw_if_index[VLIB_RX], &next1, b1);
796 
797  /* Treat IP frag packets as "experimental" protocol for now
798  until support of IP frag reassembly is implemented */
799  proto0 = ip4_is_fragment(ip0) ? 0xfe : ip0->protocol;
800  proto1 = ip4_is_fragment(ip1) ? 0xfe : ip1->protocol;
801 
802  /* Process packet 0 */
803  if (proto0 != IP_PROTOCOL_UDP)
804  goto exit0; /* not UDP packet */
805 
806  udp0 = ip4_next_header (ip0);
807  if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
808  goto exit0; /* not VXLAN packet */
809 
810  if (is_ip4)
811  {
812  if (addr4.as_u32 != ip0->dst_address.as_u32)
813  {
814  if (!hash_get (vxm->vtep4, ip0->dst_address.as_u32))
815  goto exit0; /* no local VTEP for VXLAN packet */
816  addr4 = ip0->dst_address;
817  }
818  }
819  else goto exit0; /* IP6 VXLAN bypass not yet supported */
820 
821  /* vxlan-input node expect current at VXLAN header */
822  vlib_buffer_advance (b0, sizeof(ip4_header_t)+sizeof(udp_header_t));
823 
824  flags0 = b0->flags;
825  good_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
826 
827  /* Don't verify UDP checksum for packets with explicit zero checksum. */
828  good_udp0 |= udp0->checksum == 0;
829 
830  /* Verify UDP length */
831  ip_len0 = clib_net_to_host_u16 (ip0->length);
832  udp_len0 = clib_net_to_host_u16 (udp0->length);
833 
834  len_diff0 = ip_len0 - udp_len0;
835 
836  /* Verify UDP checksum */
837  if (PREDICT_FALSE (!good_udp0))
838  {
839  if (!(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
840  flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
841  good_udp0 =
842  (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
843  }
844 
845  error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
846  error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
847 
848  next0 = error0 ?
850  b0->error = error0 ? error_node->errors[error0] : 0;
851 
852  exit0:
853  /* Process packet 1 */
854  if (proto1 != IP_PROTOCOL_UDP)
855  goto exit1; /* not UDP packet */
856 
857  udp1 = ip4_next_header (ip1);
858  if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
859  goto exit1; /* not VXLAN packet */
860 
861  if (is_ip4)
862  {
863  if (addr4.as_u32 != ip1->dst_address.as_u32)
864  {
865  if (!hash_get (vxm->vtep4, ip1->dst_address.as_u32))
866  goto exit1; /* no local VTEP for VXLAN packet */
867  addr4 = ip1->dst_address;
868  }
869  }
870  else goto exit1; /* IP6 VXLAN bypass not yet supported */
871 
872  /* vxlan-input node expect current at VXLAN header */
873  vlib_buffer_advance (b1, sizeof(ip4_header_t)+sizeof(udp_header_t));
874 
875  flags1 = b1->flags;
876  good_udp1 = (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
877 
878  /* Don't verify UDP checksum for packets with explicit zero checksum. */
879  good_udp1 |= udp1->checksum == 0;
880 
881  /* Verify UDP length */
882  ip_len1 = clib_net_to_host_u16 (ip1->length);
883  udp_len1 = clib_net_to_host_u16 (udp1->length);
884 
885  len_diff1 = ip_len1 - udp_len1;
886 
887  /* Verify UDP checksum */
888  if (PREDICT_FALSE (!good_udp1))
889  {
890  if (!(flags1 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
891  flags1 = ip4_tcp_udp_validate_checksum (vm, b1);
892  good_udp1 =
893  (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
894  }
895 
896  error1 = good_udp1 ? 0 : IP4_ERROR_UDP_CHECKSUM;
897  error1 = (len_diff1 >= 0) ? error1 : IP4_ERROR_UDP_LENGTH;
898 
899  next1 = error1 ?
901  b1->error = error1 ? error_node->errors[error1] : 0;
902 
903  exit1:
904  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
905  to_next, n_left_to_next,
906  bi0, bi1, next0, next1);
907  }
908 
909  while (n_left_from > 0 && n_left_to_next > 0)
910  {
911  vlib_buffer_t * b0;
912  ip4_header_t * ip0;
913  udp_header_t * udp0;
914  u32 bi0, ip_len0, udp_len0, flags0, next0;
915  i32 len_diff0;
916  u8 error0, good_udp0, proto0;
917 
918  bi0 = to_next[0] = from[0];
919  from += 1;
920  n_left_from -= 1;
921  to_next += 1;
922  n_left_to_next -= 1;
923 
924  b0 = vlib_get_buffer (vm, bi0);
925  ip0 = vlib_buffer_get_current (b0);
926 
927  /* Setup packet for next IP feature */
928  vnet_feature_next(vnet_buffer(b0)->sw_if_index[VLIB_RX], &next0, b0);
929 
930  /* Treat IP frag packets as "experimental" protocol for now
931  until support of IP frag reassembly is implemented */
932  proto0 = ip4_is_fragment(ip0) ? 0xfe : ip0->protocol;
933 
934  if (proto0 != IP_PROTOCOL_UDP)
935  goto exit; /* not UDP packet */
936 
937  udp0 = ip4_next_header (ip0);
938  if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
939  goto exit; /* not VXLAN packet */
940 
941  if (is_ip4)
942  {
943  if (addr4.as_u32 != ip0->dst_address.as_u32)
944  {
945  if (!hash_get (vxm->vtep4, ip0->dst_address.as_u32))
946  goto exit; /* no local VTEP for VXLAN packet */
947  addr4 = ip0->dst_address;
948  }
949  }
950  else goto exit; /* IP6 VXLAN bypass not yet supported */
951 
952  /* vxlan-input node expect current at VXLAN header */
953  vlib_buffer_advance (b0, sizeof(ip4_header_t)+sizeof(udp_header_t));
954 
955  flags0 = b0->flags;
956  good_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
957 
958  /* Don't verify UDP checksum for packets with explicit zero checksum. */
959  good_udp0 |= udp0->checksum == 0;
960 
961  /* Verify UDP length */
962  ip_len0 = clib_net_to_host_u16 (ip0->length);
963  udp_len0 = clib_net_to_host_u16 (udp0->length);
964 
965  len_diff0 = ip_len0 - udp_len0;
966 
967  /* Verify UDP checksum */
968  if (PREDICT_FALSE (!good_udp0))
969  {
970  if (!(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
971  flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
972  good_udp0 =
973  (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
974  }
975 
976  error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
977  error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
978 
979  next0 = error0 ?
981  b0->error = error0 ? error_node->errors[error0] : 0;
982 
983  exit:
984  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
985  to_next, n_left_to_next,
986  bi0, next0);
987  }
988 
989  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
990  }
991 
992  return frame->n_vectors;
993 }
994 
995 static uword
997  vlib_node_runtime_t * node,
998  vlib_frame_t * frame)
999 {
1000  return ip_vxlan_bypass_inline (vm, node, frame, /* is_ip4 */ 1);
1001 }
1002 
1004  .function = ip4_vxlan_bypass,
1005  .name = "ip4-vxlan-bypass",
1006  .vector_size = sizeof (u32),
1007 
1008  .n_next_nodes = IP_VXLAN_BYPASS_N_NEXT,
1009  .next_nodes = {
1010  [IP_VXLAN_BYPASS_NEXT_DROP] = "error-drop",
1011  [IP_VXLAN_BYPASS_NEXT_VXLAN] = "vxlan4-input",
1012  },
1013 
1014  .format_buffer = format_ip4_header,
1015  .format_trace = format_ip4_forward_next_trace,
1016 };
1017 
1019 
1020 
1021 static clib_error_t *
1023  unformat_input_t * input,
1024  vlib_cli_command_t * cmd)
1025 {
1026  unformat_input_t _line_input, * line_input = &_line_input;
1027  vnet_main_t * vnm = vnet_get_main();
1028  clib_error_t * error = 0;
1029  u32 sw_if_index, is_del;
1030 
1031  sw_if_index = ~0;
1032  is_del = 0;
1033 
1034  if (! unformat_user (input, unformat_line_input, line_input))
1035  return 0;
1036 
1037  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1038  {
1039  if (unformat_user (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1040  ;
1041  else if (unformat (line_input, "del"))
1042  is_del = 1;
1043  else
1044  {
1045  error = unformat_parse_error (line_input);
1046  goto done;
1047  }
1048  }
1049 
1050  if (~0 == sw_if_index)
1051  {
1052  error = clib_error_return (0, "unknown interface `%U'",
1053  format_unformat_error, line_input);
1054  goto done;
1055  }
1056 
1057  vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass", sw_if_index,
1058  is_del == 0, 0, 0);
1059  done:
1060  return error;
1061 }
1062 
1063 /*?
1064  * This command adds the 'ip4-vxlan-bypass' graph node for a given interface.
1065  * By adding the IPv4 vxlan-bypass graph node to an interface, the node checks
1066  * for and validate input vxlan packet and bypass ip4-lookup, ip4-local,
1067  * ip4-udp-lookup nodes to speedup vxlan packet forwarding. This node will
1068  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
1069  *
1070  * @cliexpar
1071  * @parblock
1072  * Example of graph node before ip4-vxlan-bypass is enabled:
1073  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1074  * Name Next Previous
1075  * ip4-vxlan-bypass error-drop [0]
1076  * vxlan4-input [1]
1077  * ip4-lookup [2]
1078  * @cliexend
1079  *
1080  * Example of how to enable ip4-vxlan-bypass on an interface:
1081  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0}
1082  *
1083  * Example of graph node after ip4-vxlan-bypass is enabled:
1084  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1085  * Name Next Previous
1086  * ip4-vxlan-bypass error-drop [0] ip4-input
1087  * vxlan4-input [1] ip4-input-no-checksum
1088  * ip4-lookup [2]
1089  * @cliexend
1090  *
1091  * Example of how to display the feature enabed on an interface:
1092  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1093  * IP feature paths configured on GigabitEthernet2/0/0...
1094  *
1095  * ipv4 unicast:
1096  * ip4-vxlan-bypass
1097  * ip4-lookup
1098  *
1099  * ipv4 multicast:
1100  * ip4-lookup-multicast
1101  *
1102  * ipv4 multicast:
1103  * interface-output
1104  *
1105  * ipv6 unicast:
1106  * ip6-lookup
1107  *
1108  * ipv6 multicast:
1109  * ip6-lookup
1110  *
1111  * ipv6 multicast:
1112  * interface-output
1113  * @cliexend
1114  *
1115  * Example of how to disable unicast source checking on an interface:
1116  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0 del}
1117  * @endparblock
1118 ?*/
1119 /* *INDENT-OFF* */
1120 VLIB_CLI_COMMAND (set_interface_ip_vxlan_bypass_command, static) = {
1121  .path = "set interface ip vxlan-bypass",
1122  .function = set_ip_vxlan_bypass,
1123  .short_help = "set interface ip vxlan-bypass <interface> [del]",
1124 };
1125 
1126 /* Dummy init function to get us linked in. */
1128 { return 0; }
1129 
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:459
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
u8 runtime_data[0]
Definition: node.h:469
ip4_address_t src_address
Definition: ip4_packet.h:163
vnet_interface_main_t interface_main
Definition: vnet.h:57
vlib_node_registration_t vxlan4_input_node
(constructor) VLIB_REGISTER_NODE (vxlan4_input_node)
Definition: decap.c:22
#define foreach_vxlan_input_next
Definition: vxlan.h:122
#define PREDICT_TRUE(x)
Definition: clib.h:98
u64 as_u64[2]
Definition: ip6_packet.h:51
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define NULL
Definition: clib.h:55
static uword vxlan_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u32 is_ip4)
Definition: decap.c:52
struct _vlib_node_registration vlib_node_registration_t
unformat_function_t unformat_vnet_sw_interface
vlib_node_registration_t ip4_vxlan_bypass_node
(constructor) VLIB_REGISTER_NODE (ip4_vxlan_bypass_node)
Definition: decap.c:1003
vlib_error_t * errors
Definition: node.h:419
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:100
ip6_address_t src_address
Definition: ip6_packet.h:337
#define VXLAN_FLAGS_I
Definition: vxlan_packet.h:52
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_main_t * vnet_main
Definition: vxlan.h:171
u32 tunnel_index
Definition: decap.c:27
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define always_inline
Definition: clib.h:84
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
ip4_address_t dst_address
Definition: ip4_packet.h:163
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:615
#define IP_BUFFER_L4_CHECKSUM_CORRECT
Definition: buffer.h:50
static uword ip6_address_is_equal(ip6_address_t *a, ip6_address_t *b)
Definition: ip6_packet.h:204
int i32
Definition: types.h:81
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:232
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
static int ip4_is_fragment(ip4_header_t *i)
Definition: ip4_packet.h:204
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
vlib_node_registration_t ip4_input_node
Global ip4 input node.
Definition: ip4_input.c:416
uword * vxlan4_tunnel_by_key
Definition: vxlan.h:151
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define unformat_parse_error(input)
Definition: format.h:267
vxlan_main_t vxlan_main
Definition: vxlan.c:39
static uword ip4_address_is_multicast(ip4_address_t *a)
Definition: ip4_packet.h:309
#define PREDICT_FALSE(x)
Definition: clib.h:97
u32 ip4_tcp_udp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip4_forward.c:1423
vlib_node_registration_t vxlan6_input_node
(constructor) VLIB_REGISTER_NODE (vxlan6_input_node)
Definition: decap.c:23
#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
static_always_inline void vnet_feature_next(u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:223
#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:216
#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:350
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:121
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1113
static u32 vnet_get_vni(vxlan_header_t *h)
Definition: vxlan_packet.h:54
static uword vxlan4_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: decap.c:655
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
static void ip6_address_set_zero(ip6_address_t *a)
Definition: ip6_packet.h:239
static char * vxlan_error_strings[]
Definition: decap.c:670
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:88
#define clib_memcpy(a, b, c)
Definition: string.h:69
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:207
u32 decap_next_index
Definition: vxlan.h:92
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u16 cached_next_index
Definition: node.h:463
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Increment a combined counter.
Definition: counter.h:241
format_function_t format_ip4_header
Definition: format.h:86
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:361
uword * vtep4
Definition: vxlan.h:156
uword * vxlan6_tunnel_by_key
Definition: vxlan.h:152
u32 sw_if_index
Definition: vxlan.h:98
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
u64 uword
Definition: types.h:112
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
static clib_error_t * set_ip_vxlan_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: decap.c:1022
#define IP_BUFFER_L4_CHECKSUM_COMPUTED
Definition: buffer.h:49
Definition: defs.h:47
static uword ip6_address_is_multicast(ip6_address_t *a)
Definition: ip6_packet.h:141
i64 word
Definition: types.h:111
unsigned char u8
Definition: types.h:56
static void vnet_update_l2_len(vlib_buffer_t *b)
Definition: l2_input.h:193
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:1226
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
u8 * format_ip4_forward_next_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1177
#define hash_get_mem(h, key)
Definition: hash.h:268
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:170
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
VLIB_NODE_FUNCTION_MULTIARCH(l2t_decap_node, l2t_decap_node_fn)
static u8 * format_vxlan_rx_trace(u8 *s, va_list *args)
Definition: decap.c:32
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 data[0]
Packet data.
Definition: buffer.h:158
#define clib_error_return(e, args...)
Definition: error.h:111
ip_vxan_bypass_next_t
Definition: decap.c:724
struct _unformat_input_t unformat_input_t
u32 next_index
Definition: decap.c:26
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static uword ip4_vxlan_bypass(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: decap.c:996
unformat_function_t unformat_line_input
Definition: format.h:281
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
vxlan_tunnel_t * tunnels
Definition: vxlan.h:148
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:731
ip46_address_t src
Definition: vxlan.h:85
static uword vxlan6_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: decap.c:663
Definition: defs.h:46
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:238
ip6_address_t dst_address
Definition: ip6_packet.h:337
clib_error_t * ip4_vxlan_bypass_init(vlib_main_t *vm)
Definition: decap.c:1127