FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
gtpu_decap.c
Go to the documentation of this file.
1 /*
2  * decap.c: gtpu tunnel decap packet processing
3  *
4  * Copyright (c) 2017 Intel 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 <gtpu/gtpu.h>
21 
24 
25 typedef struct {
31 
32 static u8 * format_gtpu_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  gtpu_rx_trace_t * t = va_arg (*args, gtpu_rx_trace_t *);
37 
38  if (t->tunnel_index != ~0)
39  {
40  s = format (s, "GTPU decap from gtpu_tunnel%d teid %d next %d error %d",
41  t->tunnel_index, t->teid, t->next_index, t->error);
42  }
43  else
44  {
45  s = format (s, "GTPU decap error - tunnel for teid %d does not exist",
46  t->teid);
47  }
48  return s;
49 }
50 
53 {
54  u32 fib_index, sw_if_index;
55 
56  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
57 
58  if (is_ip4)
59  fib_index = (vnet_buffer (b)->sw_if_index[VLIB_TX] == (u32) ~ 0) ?
61  vnet_buffer (b)->sw_if_index[VLIB_TX];
62  else
63  fib_index = (vnet_buffer (b)->sw_if_index[VLIB_TX] == (u32) ~ 0) ?
65  vnet_buffer (b)->sw_if_index[VLIB_TX];
66 
67  return (fib_index == t->encap_fib_index);
68 }
69 
72  vlib_node_runtime_t * node,
73  vlib_frame_t * from_frame,
74  u32 is_ip4)
75 {
76  u32 n_left_from, next_index, * from, * to_next;
77  gtpu_main_t * gtm = &gtpu_main;
78  vnet_main_t * vnm = gtm->vnet_main;
80  u32 last_tunnel_index = ~0;
81  gtpu4_tunnel_key_t last_key4;
82  gtpu6_tunnel_key_t last_key6;
83  u32 pkts_decapsulated = 0;
84  u32 thread_index = vlib_get_thread_index();
85  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
86 
87  if (is_ip4)
88  last_key4.as_u64 = ~0;
89  else
90  clib_memset (&last_key6, 0xff, sizeof (last_key6));
91 
92  from = vlib_frame_vector_args (from_frame);
93  n_left_from = from_frame->n_vectors;
94 
95  next_index = node->cached_next_index;
96  stats_sw_if_index = node->runtime_data[0];
97  stats_n_packets = stats_n_bytes = 0;
98 
99  while (n_left_from > 0)
100  {
101  u32 n_left_to_next;
102 
103  vlib_get_next_frame (vm, node, next_index,
104  to_next, n_left_to_next);
105  while (n_left_from >= 4 && n_left_to_next >= 2)
106  {
107  u32 bi0, bi1;
108  vlib_buffer_t * b0, * b1;
109  u32 next0, next1;
110  ip4_header_t * ip4_0, * ip4_1;
111  ip6_header_t * ip6_0, * ip6_1;
112  gtpu_header_t * gtpu0, * gtpu1;
113  u32 gtpu_hdr_len0 = 0, gtpu_hdr_len1 =0 ;
114  uword * p0, * p1;
115  u32 tunnel_index0, tunnel_index1;
116  gtpu_tunnel_t * t0, * t1, * mt0 = NULL, * mt1 = NULL;
117  gtpu4_tunnel_key_t key4_0, key4_1;
118  gtpu6_tunnel_key_t key6_0, key6_1;
119  u32 error0, error1;
120  u32 sw_if_index0, sw_if_index1, len0, len1;
121 
122  /* Prefetch next iteration. */
123  {
124  vlib_buffer_t * p2, * p3;
125 
126  p2 = vlib_get_buffer (vm, from[2]);
127  p3 = vlib_get_buffer (vm, from[3]);
128 
129  vlib_prefetch_buffer_header (p2, LOAD);
130  vlib_prefetch_buffer_header (p3, LOAD);
131 
134  }
135 
136  bi0 = from[0];
137  bi1 = from[1];
138  to_next[0] = bi0;
139  to_next[1] = bi1;
140  from += 2;
141  to_next += 2;
142  n_left_to_next -= 2;
143  n_left_from -= 2;
144 
145  b0 = vlib_get_buffer (vm, bi0);
146  b1 = vlib_get_buffer (vm, bi1);
147 
148  /* udp leaves current_data pointing at the gtpu header */
149  gtpu0 = vlib_buffer_get_current (b0);
150  gtpu1 = vlib_buffer_get_current (b1);
151  if (is_ip4) {
153  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip4_header_t)));
155  (b1, -(word)(sizeof(udp_header_t)+sizeof(ip4_header_t)));
156  ip4_0 = vlib_buffer_get_current (b0);
157  ip4_1 = vlib_buffer_get_current (b1);
158  } else {
160  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip6_header_t)));
162  (b1, -(word)(sizeof(udp_header_t)+sizeof(ip6_header_t)));
163  ip6_0 = vlib_buffer_get_current (b0);
164  ip6_1 = vlib_buffer_get_current (b1);
165  }
166 
167  /* pop (ip, udp, gtpu) */
168  if (is_ip4) {
170  (b0, sizeof(*ip4_0)+sizeof(udp_header_t));
172  (b1, sizeof(*ip4_1)+sizeof(udp_header_t));
173  } else {
175  (b0, sizeof(*ip6_0)+sizeof(udp_header_t));
177  (b1, sizeof(*ip6_1)+sizeof(udp_header_t));
178  }
179 
180  tunnel_index0 = ~0;
181  error0 = 0;
182 
183  tunnel_index1 = ~0;
184  error1 = 0;
185 
186  if (PREDICT_FALSE ((gtpu0->ver_flags & GTPU_VER_MASK) != GTPU_V1_VER))
187  {
188  error0 = GTPU_ERROR_BAD_VER;
189  next0 = GTPU_INPUT_NEXT_DROP;
190  goto trace0;
191  }
192 
193  /* Manipulate packet 0 */
194  if (is_ip4) {
195  key4_0.src = ip4_0->src_address.as_u32;
196  key4_0.teid = gtpu0->teid;
197 
198  /* Make sure GTPU tunnel exist according to packet SIP and teid
199  * SIP identify a GTPU path, and teid identify a tunnel in a given GTPU path */
200  if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
201  {
202  p0 = hash_get (gtm->gtpu4_tunnel_by_key, key4_0.as_u64);
203  if (PREDICT_FALSE (p0 == NULL))
204  {
205  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
206  next0 = GTPU_INPUT_NEXT_DROP;
207  goto trace0;
208  }
209  last_key4.as_u64 = key4_0.as_u64;
210  tunnel_index0 = last_tunnel_index = p0[0];
211  }
212  else
213  tunnel_index0 = last_tunnel_index;
214  t0 = pool_elt_at_index (gtm->tunnels, tunnel_index0);
215 
216  /* Validate GTPU tunnel encap-fib index against packet */
217  if (PREDICT_FALSE (validate_gtpu_fib (b0, t0, is_ip4) == 0))
218  {
219  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
220  next0 = GTPU_INPUT_NEXT_DROP;
221  goto trace0;
222  }
223 
224  /* Validate GTPU tunnel SIP against packet DIP */
225  if (PREDICT_TRUE (ip4_0->dst_address.as_u32 == t0->src.ip4.as_u32))
226  goto next0; /* valid packet */
228  {
229  key4_0.src = ip4_0->dst_address.as_u32;
230  key4_0.teid = gtpu0->teid;
231  /* Make sure mcast GTPU tunnel exist by packet DIP and teid */
232  p0 = hash_get (gtm->gtpu4_tunnel_by_key, key4_0.as_u64);
233  if (PREDICT_TRUE (p0 != NULL))
234  {
235  mt0 = pool_elt_at_index (gtm->tunnels, p0[0]);
236  goto next0; /* valid packet */
237  }
238  }
239  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
240  next0 = GTPU_INPUT_NEXT_DROP;
241  goto trace0;
242 
243  } else /* !is_ip4 */ {
244  key6_0.src.as_u64[0] = ip6_0->src_address.as_u64[0];
245  key6_0.src.as_u64[1] = ip6_0->src_address.as_u64[1];
246  key6_0.teid = gtpu0->teid;
247 
248  /* Make sure GTPU tunnel exist according to packet SIP and teid
249  * SIP identify a GTPU path, and teid identify a tunnel in a given GTPU path */
250  if (PREDICT_FALSE (memcmp(&key6_0, &last_key6, sizeof(last_key6)) != 0))
251  {
252  p0 = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6_0);
253  if (PREDICT_FALSE (p0 == NULL))
254  {
255  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
256  next0 = GTPU_INPUT_NEXT_DROP;
257  goto trace0;
258  }
259  clib_memcpy_fast (&last_key6, &key6_0, sizeof(key6_0));
260  tunnel_index0 = last_tunnel_index = p0[0];
261  }
262  else
263  tunnel_index0 = last_tunnel_index;
264  t0 = pool_elt_at_index (gtm->tunnels, tunnel_index0);
265 
266  /* Validate GTPU tunnel encap-fib index against packet */
267  if (PREDICT_FALSE (validate_gtpu_fib (b0, t0, is_ip4) == 0))
268  {
269  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
270  next0 = GTPU_INPUT_NEXT_DROP;
271  goto trace0;
272  }
273 
274  /* Validate GTPU tunnel SIP against packet DIP */
276  &t0->src.ip6)))
277  goto next0; /* valid packet */
279  {
280  key6_0.src.as_u64[0] = ip6_0->dst_address.as_u64[0];
281  key6_0.src.as_u64[1] = ip6_0->dst_address.as_u64[1];
282  key6_0.teid = gtpu0->teid;
283  p0 = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6_0);
284  if (PREDICT_TRUE (p0 != NULL))
285  {
286  mt0 = pool_elt_at_index (gtm->tunnels, p0[0]);
287  goto next0; /* valid packet */
288  }
289  }
290  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
291  next0 = GTPU_INPUT_NEXT_DROP;
292  goto trace0;
293  }
294 
295  next0:
296  /* Manipulate gtpu header */
297  if (PREDICT_FALSE((gtpu0->ver_flags & GTPU_E_S_PN_BIT) != 0))
298  {
299  gtpu_hdr_len0 = sizeof(gtpu_header_t);
300 
301  /* Manipulate Sequence Number and N-PDU Number */
302  /* TBD */
303 
304  /* Manipulate Next Extension Header */
305  /* TBD */
306  }
307  else
308  {
309  gtpu_hdr_len0 = sizeof(gtpu_header_t) - 4;
310  }
311 
312  /* Pop gtpu header */
313  vlib_buffer_advance (b0, gtpu_hdr_len0);
314 
315  next0 = t0->decap_next_index;
316  sw_if_index0 = t0->sw_if_index;
317  len0 = vlib_buffer_length_in_chain (vm, b0);
318 
319  /* Required to make the l2 tag push / pop code work on l2 subifs */
320  if (PREDICT_TRUE(next0 == GTPU_INPUT_NEXT_L2_INPUT))
321  vnet_update_l2_len (b0);
322 
323  /* Set packet input sw_if_index to unicast GTPU tunnel for learning */
324  vnet_buffer(b0)->sw_if_index[VLIB_RX] = sw_if_index0;
325  sw_if_index0 = (mt0) ? mt0->sw_if_index : sw_if_index0;
326 
327  pkts_decapsulated ++;
328  stats_n_packets += 1;
329  stats_n_bytes += len0;
330 
331  /* Batch stats increment on the same gtpu tunnel so counter
332  is not incremented per packet */
333  if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index))
334  {
335  stats_n_packets -= 1;
336  stats_n_bytes -= len0;
337  if (stats_n_packets)
340  thread_index, stats_sw_if_index,
341  stats_n_packets, stats_n_bytes);
342  stats_n_packets = 1;
343  stats_n_bytes = len0;
344  stats_sw_if_index = sw_if_index0;
345  }
346 
347  trace0:
348  b0->error = error0 ? node->errors[error0] : 0;
349 
350  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
351  {
352  gtpu_rx_trace_t *tr
353  = vlib_add_trace (vm, node, b0, sizeof (*tr));
354  tr->next_index = next0;
355  tr->error = error0;
356  tr->tunnel_index = tunnel_index0;
357  tr->teid = clib_net_to_host_u32(gtpu0->teid);
358  }
359 
360  if (PREDICT_FALSE ((gtpu1->ver_flags & GTPU_VER_MASK) != GTPU_V1_VER))
361  {
362  error1 = GTPU_ERROR_BAD_VER;
363  next1 = GTPU_INPUT_NEXT_DROP;
364  goto trace1;
365  }
366 
367  /* Manipulate packet 1 */
368  if (is_ip4) {
369  key4_1.src = ip4_1->src_address.as_u32;
370  key4_1.teid = gtpu1->teid;
371 
372  /* Make sure GTPU tunnel exist according to packet SIP and teid
373  * SIP identify a GTPU path, and teid identify a tunnel in a given GTPU path */
374  if (PREDICT_FALSE (key4_1.as_u64 != last_key4.as_u64))
375  {
376  p1 = hash_get (gtm->gtpu4_tunnel_by_key, key4_1.as_u64);
377  if (PREDICT_FALSE (p1 == NULL))
378  {
379  error1 = GTPU_ERROR_NO_SUCH_TUNNEL;
380  next1 = GTPU_INPUT_NEXT_DROP;
381  goto trace1;
382  }
383  last_key4.as_u64 = key4_1.as_u64;
384  tunnel_index1 = last_tunnel_index = p1[0];
385  }
386  else
387  tunnel_index1 = last_tunnel_index;
388  t1 = pool_elt_at_index (gtm->tunnels, tunnel_index1);
389 
390  /* Validate GTPU tunnel encap-fib index against packet */
391  if (PREDICT_FALSE (validate_gtpu_fib (b1, t1, is_ip4) == 0))
392  {
393  error1 = GTPU_ERROR_NO_SUCH_TUNNEL;
394  next1 = GTPU_INPUT_NEXT_DROP;
395  goto trace1;
396  }
397 
398  /* Validate GTPU tunnel SIP against packet DIP */
399  if (PREDICT_TRUE (ip4_1->dst_address.as_u32 == t1->src.ip4.as_u32))
400  goto next1; /* valid packet */
402  {
403  key4_1.src = ip4_1->dst_address.as_u32;
404  key4_1.teid = gtpu1->teid;
405  /* Make sure mcast GTPU tunnel exist by packet DIP and teid */
406  p1 = hash_get (gtm->gtpu4_tunnel_by_key, key4_1.as_u64);
407  if (PREDICT_TRUE (p1 != NULL))
408  {
409  mt1 = pool_elt_at_index (gtm->tunnels, p1[0]);
410  goto next1; /* valid packet */
411  }
412  }
413  error1 = GTPU_ERROR_NO_SUCH_TUNNEL;
414  next1 = GTPU_INPUT_NEXT_DROP;
415  goto trace1;
416 
417  } else /* !is_ip4 */ {
418  key6_1.src.as_u64[0] = ip6_1->src_address.as_u64[0];
419  key6_1.src.as_u64[1] = ip6_1->src_address.as_u64[1];
420  key6_1.teid = gtpu1->teid;
421 
422  /* Make sure GTPU tunnel exist according to packet SIP and teid
423  * SIP identify a GTPU path, and teid identify a tunnel in a given GTPU path */
424  if (PREDICT_FALSE (memcmp(&key6_1, &last_key6, sizeof(last_key6)) != 0))
425  {
426  p1 = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6_1);
427 
428  if (PREDICT_FALSE (p1 == NULL))
429  {
430  error1 = GTPU_ERROR_NO_SUCH_TUNNEL;
431  next1 = GTPU_INPUT_NEXT_DROP;
432  goto trace1;
433  }
434 
435  clib_memcpy_fast (&last_key6, &key6_1, sizeof(key6_1));
436  tunnel_index1 = last_tunnel_index = p1[0];
437  }
438  else
439  tunnel_index1 = last_tunnel_index;
440  t1 = pool_elt_at_index (gtm->tunnels, tunnel_index1);
441 
442  /* Validate GTPU tunnel encap-fib index against packet */
443  if (PREDICT_FALSE (validate_gtpu_fib (b1, t1, is_ip4) == 0))
444  {
445  error1 = GTPU_ERROR_NO_SUCH_TUNNEL;
446  next1 = GTPU_INPUT_NEXT_DROP;
447  goto trace1;
448  }
449 
450  /* Validate GTPU tunnel SIP against packet DIP */
452  &t1->src.ip6)))
453  goto next1; /* valid packet */
455  {
456  key6_1.src.as_u64[0] = ip6_1->dst_address.as_u64[0];
457  key6_1.src.as_u64[1] = ip6_1->dst_address.as_u64[1];
458  key6_1.teid = gtpu1->teid;
459  p1 = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6_1);
460  if (PREDICT_TRUE (p1 != NULL))
461  {
462  mt1 = pool_elt_at_index (gtm->tunnels, p1[0]);
463  goto next1; /* valid packet */
464  }
465  }
466  error1 = GTPU_ERROR_NO_SUCH_TUNNEL;
467  next1 = GTPU_INPUT_NEXT_DROP;
468  goto trace1;
469  }
470 
471  next1:
472  /* Manipulate gtpu header */
473  if (PREDICT_FALSE((gtpu1->ver_flags & GTPU_E_S_PN_BIT) != 0))
474  {
475  gtpu_hdr_len1 = sizeof(gtpu_header_t);
476 
477  /* Manipulate Sequence Number and N-PDU Number */
478  /* TBD */
479 
480  /* Manipulate Next Extension Header */
481  /* TBD */
482  }
483  else
484  {
485  gtpu_hdr_len1 = sizeof(gtpu_header_t) - 4;
486  }
487 
488  /* Pop gtpu header */
489  vlib_buffer_advance (b1, gtpu_hdr_len1);
490 
491  next1 = t1->decap_next_index;
492  sw_if_index1 = t1->sw_if_index;
493  len1 = vlib_buffer_length_in_chain (vm, b1);
494 
495  /* Required to make the l2 tag push / pop code work on l2 subifs */
496  if (PREDICT_TRUE(next1 == GTPU_INPUT_NEXT_L2_INPUT))
497  vnet_update_l2_len (b1);
498 
499  /* Set packet input sw_if_index to unicast GTPU tunnel for learning */
500  vnet_buffer(b1)->sw_if_index[VLIB_RX] = sw_if_index1;
501  sw_if_index1 = (mt1) ? mt1->sw_if_index : sw_if_index1;
502 
503  pkts_decapsulated ++;
504  stats_n_packets += 1;
505  stats_n_bytes += len1;
506 
507  /* Batch stats increment on the same gtpu tunnel so counter
508  is not incremented per packet */
509  if (PREDICT_FALSE (sw_if_index1 != stats_sw_if_index))
510  {
511  stats_n_packets -= 1;
512  stats_n_bytes -= len1;
513  if (stats_n_packets)
516  thread_index, stats_sw_if_index,
517  stats_n_packets, stats_n_bytes);
518  stats_n_packets = 1;
519  stats_n_bytes = len1;
520  stats_sw_if_index = sw_if_index1;
521  }
522 
523  trace1:
524  b1->error = error1 ? node->errors[error1] : 0;
525 
526  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
527  {
528  gtpu_rx_trace_t *tr
529  = vlib_add_trace (vm, node, b1, sizeof (*tr));
530  tr->next_index = next1;
531  tr->error = error1;
532  tr->tunnel_index = tunnel_index1;
533  tr->teid = clib_net_to_host_u32(gtpu1->teid);
534  }
535 
536  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
537  to_next, n_left_to_next,
538  bi0, bi1, next0, next1);
539  }
540 
541  while (n_left_from > 0 && n_left_to_next > 0)
542  {
543  u32 bi0;
544  vlib_buffer_t * b0;
545  u32 next0;
546  ip4_header_t * ip4_0;
547  ip6_header_t * ip6_0;
548  gtpu_header_t * gtpu0;
549  u32 gtpu_hdr_len0 = 0;
550  uword * p0;
551  u32 tunnel_index0;
552  gtpu_tunnel_t * t0, * mt0 = NULL;
553  gtpu4_tunnel_key_t key4_0;
554  gtpu6_tunnel_key_t key6_0;
555  u32 error0;
556  u32 sw_if_index0, len0;
557 
558  bi0 = from[0];
559  to_next[0] = bi0;
560  from += 1;
561  to_next += 1;
562  n_left_from -= 1;
563  n_left_to_next -= 1;
564 
565  b0 = vlib_get_buffer (vm, bi0);
566 
567  /* udp leaves current_data pointing at the gtpu header */
568  gtpu0 = vlib_buffer_get_current (b0);
569  if (is_ip4) {
571  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip4_header_t)));
572  ip4_0 = vlib_buffer_get_current (b0);
573  } else {
575  (b0, -(word)(sizeof(udp_header_t)+sizeof(ip6_header_t)));
576  ip6_0 = vlib_buffer_get_current (b0);
577  }
578 
579  /* pop (ip, udp) */
580  if (is_ip4) {
582  (b0, sizeof(*ip4_0)+sizeof(udp_header_t));
583  } else {
585  (b0, sizeof(*ip6_0)+sizeof(udp_header_t));
586  }
587 
588  tunnel_index0 = ~0;
589  error0 = 0;
590  if (PREDICT_FALSE ((gtpu0->ver_flags & GTPU_VER_MASK) != GTPU_V1_VER))
591  {
592  error0 = GTPU_ERROR_BAD_VER;
593  next0 = GTPU_INPUT_NEXT_DROP;
594  goto trace00;
595  }
596 
597  if (is_ip4) {
598  key4_0.src = ip4_0->src_address.as_u32;
599  key4_0.teid = gtpu0->teid;
600 
601  /* Make sure GTPU tunnel exist according to packet SIP and teid
602  * SIP identify a GTPU path, and teid identify a tunnel in a given GTPU path */
603  if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
604  {
605  p0 = hash_get (gtm->gtpu4_tunnel_by_key, key4_0.as_u64);
606  if (PREDICT_FALSE (p0 == NULL))
607  {
608  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
609  next0 = GTPU_INPUT_NEXT_DROP;
610  goto trace00;
611  }
612  last_key4.as_u64 = key4_0.as_u64;
613  tunnel_index0 = last_tunnel_index = p0[0];
614  }
615  else
616  tunnel_index0 = last_tunnel_index;
617  t0 = pool_elt_at_index (gtm->tunnels, tunnel_index0);
618 
619  /* Validate GTPU tunnel encap-fib index against packet */
620  if (PREDICT_FALSE (validate_gtpu_fib (b0, t0, is_ip4) == 0))
621  {
622  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
623  next0 = GTPU_INPUT_NEXT_DROP;
624  goto trace00;
625  }
626 
627  /* Validate GTPU tunnel SIP against packet DIP */
628  if (PREDICT_TRUE (ip4_0->dst_address.as_u32 == t0->src.ip4.as_u32))
629  goto next00; /* valid packet */
631  {
632  key4_0.src = ip4_0->dst_address.as_u32;
633  key4_0.teid = gtpu0->teid;
634  /* Make sure mcast GTPU tunnel exist by packet DIP and teid */
635  p0 = hash_get (gtm->gtpu4_tunnel_by_key, key4_0.as_u64);
636  if (PREDICT_TRUE (p0 != NULL))
637  {
638  mt0 = pool_elt_at_index (gtm->tunnels, p0[0]);
639  goto next00; /* valid packet */
640  }
641  }
642  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
643  next0 = GTPU_INPUT_NEXT_DROP;
644  goto trace00;
645 
646  } else /* !is_ip4 */ {
647  key6_0.src.as_u64[0] = ip6_0->src_address.as_u64[0];
648  key6_0.src.as_u64[1] = ip6_0->src_address.as_u64[1];
649  key6_0.teid = gtpu0->teid;
650 
651  /* Make sure GTPU tunnel exist according to packet SIP and teid
652  * SIP identify a GTPU path, and teid identify a tunnel in a given GTPU path */
653  if (PREDICT_FALSE (memcmp(&key6_0, &last_key6, sizeof(last_key6)) != 0))
654  {
655  p0 = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6_0);
656  if (PREDICT_FALSE (p0 == NULL))
657  {
658  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
659  next0 = GTPU_INPUT_NEXT_DROP;
660  goto trace00;
661  }
662  clib_memcpy_fast (&last_key6, &key6_0, sizeof(key6_0));
663  tunnel_index0 = last_tunnel_index = p0[0];
664  }
665  else
666  tunnel_index0 = last_tunnel_index;
667  t0 = pool_elt_at_index (gtm->tunnels, tunnel_index0);
668 
669  /* Validate GTPU tunnel encap-fib index against packet */
670  if (PREDICT_FALSE (validate_gtpu_fib (b0, t0, is_ip4) == 0))
671  {
672  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
673  next0 = GTPU_INPUT_NEXT_DROP;
674  goto trace00;
675  }
676 
677  /* Validate GTPU tunnel SIP against packet DIP */
679  &t0->src.ip6)))
680  goto next00; /* valid packet */
682  {
683  key6_0.src.as_u64[0] = ip6_0->dst_address.as_u64[0];
684  key6_0.src.as_u64[1] = ip6_0->dst_address.as_u64[1];
685  key6_0.teid = gtpu0->teid;
686  p0 = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6_0);
687  if (PREDICT_TRUE (p0 != NULL))
688  {
689  mt0 = pool_elt_at_index (gtm->tunnels, p0[0]);
690  goto next00; /* valid packet */
691  }
692  }
693  error0 = GTPU_ERROR_NO_SUCH_TUNNEL;
694  next0 = GTPU_INPUT_NEXT_DROP;
695  goto trace00;
696  }
697 
698  next00:
699  /* Manipulate gtpu header */
700  if (PREDICT_FALSE((gtpu0->ver_flags & GTPU_E_S_PN_BIT) != 0))
701  {
702  gtpu_hdr_len0 = sizeof(gtpu_header_t);
703 
704  /* Manipulate Sequence Number and N-PDU Number */
705  /* TBD */
706 
707  /* Manipulate Next Extension Header */
708  /* TBD */
709  }
710  else
711  {
712  gtpu_hdr_len0 = sizeof(gtpu_header_t) - 4;
713  }
714 
715  /* Pop gtpu header */
716  vlib_buffer_advance (b0, gtpu_hdr_len0);
717 
718  next0 = t0->decap_next_index;
719  sw_if_index0 = t0->sw_if_index;
720  len0 = vlib_buffer_length_in_chain (vm, b0);
721 
722  /* Required to make the l2 tag push / pop code work on l2 subifs */
723  if (PREDICT_TRUE(next0 == GTPU_INPUT_NEXT_L2_INPUT))
724  vnet_update_l2_len (b0);
725 
726  /* Set packet input sw_if_index to unicast GTPU tunnel for learning */
727  vnet_buffer(b0)->sw_if_index[VLIB_RX] = sw_if_index0;
728  sw_if_index0 = (mt0) ? mt0->sw_if_index : sw_if_index0;
729 
730  pkts_decapsulated ++;
731  stats_n_packets += 1;
732  stats_n_bytes += len0;
733 
734  /* Batch stats increment on the same gtpu tunnel so counter
735  is not incremented per packet */
736  if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index))
737  {
738  stats_n_packets -= 1;
739  stats_n_bytes -= len0;
740  if (stats_n_packets)
743  thread_index, stats_sw_if_index,
744  stats_n_packets, stats_n_bytes);
745  stats_n_packets = 1;
746  stats_n_bytes = len0;
747  stats_sw_if_index = sw_if_index0;
748  }
749 
750  trace00:
751  b0->error = error0 ? node->errors[error0] : 0;
752 
753  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
754  {
755  gtpu_rx_trace_t *tr
756  = vlib_add_trace (vm, node, b0, sizeof (*tr));
757  tr->next_index = next0;
758  tr->error = error0;
759  tr->tunnel_index = tunnel_index0;
760  tr->teid = clib_net_to_host_u32(gtpu0->teid);
761  }
762  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
763  to_next, n_left_to_next,
764  bi0, next0);
765  }
766 
767  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
768  }
769  /* Do we still need this now that tunnel tx stats is kept? */
770  vlib_node_increment_counter (vm, is_ip4?
772  GTPU_ERROR_DECAPSULATED,
773  pkts_decapsulated);
774 
775  /* Increment any remaining batch stats */
776  if (stats_n_packets)
777  {
780  thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
781  node->runtime_data[0] = stats_sw_if_index;
782  }
783 
784  return from_frame->n_vectors;
785 }
786 
788  vlib_node_runtime_t * node,
789  vlib_frame_t * from_frame)
790 {
791  return gtpu_input(vm, node, from_frame, /* is_ip4 */ 1);
792 }
793 
795  vlib_node_runtime_t * node,
796  vlib_frame_t * from_frame)
797 {
798  return gtpu_input(vm, node, from_frame, /* is_ip4 */ 0);
799 }
800 
801 static char * gtpu_error_strings[] = {
802 #define gtpu_error(n,s) s,
803 #include <gtpu/gtpu_error.def>
804 #undef gtpu_error
805 #undef _
806 };
807 
809  .name = "gtpu4-input",
810  /* Takes a vector of packets. */
811  .vector_size = sizeof (u32),
812 
813  .n_errors = GTPU_N_ERROR,
814  .error_strings = gtpu_error_strings,
815 
816  .n_next_nodes = GTPU_INPUT_N_NEXT,
817  .next_nodes = {
818 #define _(s,n) [GTPU_INPUT_NEXT_##s] = n,
820 #undef _
821  },
822 
823 //temp .format_buffer = format_gtpu_header,
824  .format_trace = format_gtpu_rx_trace,
825  // $$$$ .unformat_buffer = unformat_gtpu_header,
826 };
827 
829  .name = "gtpu6-input",
830  /* Takes a vector of packets. */
831  .vector_size = sizeof (u32),
832 
833  .n_errors = GTPU_N_ERROR,
834  .error_strings = gtpu_error_strings,
835 
836  .n_next_nodes = GTPU_INPUT_N_NEXT,
837  .next_nodes = {
838 #define _(s,n) [GTPU_INPUT_NEXT_##s] = n,
840 #undef _
841  },
842 
843 //temp .format_buffer = format_gtpu_header,
844  .format_trace = format_gtpu_rx_trace,
845  // $$$$ .unformat_buffer = unformat_gtpu_header,
846 };
847 
848 typedef enum {
853 
856  vlib_node_runtime_t * node,
857  vlib_frame_t * frame,
858  u32 is_ip4)
859 {
860  gtpu_main_t * gtm = &gtpu_main;
861  u32 * from, * to_next, n_left_from, n_left_to_next, next_index;
862  vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index);
863  ip4_address_t addr4; /* last IPv4 address matching a local VTEP address */
864  ip6_address_t addr6; /* last IPv6 address matching a local VTEP address */
865 
866  from = vlib_frame_vector_args (frame);
867  n_left_from = frame->n_vectors;
868  next_index = node->cached_next_index;
869 
870  if (node->flags & VLIB_NODE_FLAG_TRACE)
871  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
872 
873  if (is_ip4) addr4.data_u32 = ~0;
874  else ip6_address_set_zero (&addr6);
875 
876  while (n_left_from > 0)
877  {
878  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
879 
880  while (n_left_from >= 4 && n_left_to_next >= 2)
881  {
882  vlib_buffer_t * b0, * b1;
883  ip4_header_t * ip40, * ip41;
884  ip6_header_t * ip60, * ip61;
885  udp_header_t * udp0, * udp1;
886  u32 bi0, ip_len0, udp_len0, flags0, next0;
887  u32 bi1, ip_len1, udp_len1, flags1, next1;
888  i32 len_diff0, len_diff1;
889  u8 error0, good_udp0, proto0;
890  u8 error1, good_udp1, proto1;
891 
892  /* Prefetch next iteration. */
893  {
894  vlib_buffer_t * p2, * p3;
895 
896  p2 = vlib_get_buffer (vm, from[2]);
897  p3 = vlib_get_buffer (vm, from[3]);
898 
899  vlib_prefetch_buffer_header (p2, LOAD);
900  vlib_prefetch_buffer_header (p3, LOAD);
901 
904  }
905 
906  bi0 = to_next[0] = from[0];
907  bi1 = to_next[1] = from[1];
908  from += 2;
909  n_left_from -= 2;
910  to_next += 2;
911  n_left_to_next -= 2;
912 
913  b0 = vlib_get_buffer (vm, bi0);
914  b1 = vlib_get_buffer (vm, bi1);
915  if (is_ip4)
916  {
917  ip40 = vlib_buffer_get_current (b0);
918  ip41 = vlib_buffer_get_current (b1);
919  }
920  else
921  {
922  ip60 = vlib_buffer_get_current (b0);
923  ip61 = vlib_buffer_get_current (b1);
924  }
925 
926  /* Setup packet for next IP feature */
927  vnet_feature_next(&next0, b0);
928  vnet_feature_next(&next1, b1);
929 
930  if (is_ip4)
931  {
932  /* Treat IP frag packets as "experimental" protocol for now
933  until support of IP frag reassembly is implemented */
934  proto0 = ip4_is_fragment(ip40) ? 0xfe : ip40->protocol;
935  proto1 = ip4_is_fragment(ip41) ? 0xfe : ip41->protocol;
936  }
937  else
938  {
939  proto0 = ip60->protocol;
940  proto1 = ip61->protocol;
941  }
942 
943  /* Process packet 0 */
944  if (proto0 != IP_PROTOCOL_UDP)
945  goto exit0; /* not UDP packet */
946 
947  if (is_ip4)
948  udp0 = ip4_next_header (ip40);
949  else
950  udp0 = ip6_next_header (ip60);
951 
952  if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_GTPU))
953  goto exit0; /* not GTPU packet */
954 
955  /* Validate DIP against VTEPs*/
956  if (is_ip4)
957  {
958  if (addr4.as_u32 != ip40->dst_address.as_u32)
959  {
960  if (!hash_get (gtm->vtep4, ip40->dst_address.as_u32))
961  goto exit0; /* no local VTEP for GTPU packet */
962  addr4 = ip40->dst_address;
963  }
964  }
965  else
966  {
967  if (!ip6_address_is_equal (&addr6, &ip60->dst_address))
968  {
969  if (!hash_get_mem (gtm->vtep6, &ip60->dst_address))
970  goto exit0; /* no local VTEP for GTPU packet */
971  addr6 = ip60->dst_address;
972  }
973  }
974 
975  flags0 = b0->flags;
976  good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
977 
978  /* Don't verify UDP checksum for packets with explicit zero checksum. */
979  good_udp0 |= udp0->checksum == 0;
980 
981  /* Verify UDP length */
982  if (is_ip4)
983  ip_len0 = clib_net_to_host_u16 (ip40->length);
984  else
985  ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
986  udp_len0 = clib_net_to_host_u16 (udp0->length);
987  len_diff0 = ip_len0 - udp_len0;
988 
989  /* Verify UDP checksum */
990  if (PREDICT_FALSE (!good_udp0))
991  {
992  if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
993  {
994  if (is_ip4)
995  flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
996  else
997  flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
998  good_udp0 =
999  (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1000  }
1001  }
1002 
1003  if (is_ip4)
1004  {
1005  error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1006  error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
1007  }
1008  else
1009  {
1010  error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1011  error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
1012  }
1013 
1014  next0 = error0 ?
1016  b0->error = error0 ? error_node->errors[error0] : 0;
1017 
1018  /* gtpu-input node expect current at GTPU header */
1019  if (is_ip4)
1020  vlib_buffer_advance (b0, sizeof(ip4_header_t)+sizeof(udp_header_t));
1021  else
1022  vlib_buffer_advance (b0, sizeof(ip6_header_t)+sizeof(udp_header_t));
1023 
1024  exit0:
1025  /* Process packet 1 */
1026  if (proto1 != IP_PROTOCOL_UDP)
1027  goto exit1; /* not UDP packet */
1028 
1029  if (is_ip4)
1030  udp1 = ip4_next_header (ip41);
1031  else
1032  udp1 = ip6_next_header (ip61);
1033 
1034  if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_GTPU))
1035  goto exit1; /* not GTPU packet */
1036 
1037  /* Validate DIP against VTEPs*/
1038  if (is_ip4)
1039  {
1040  if (addr4.as_u32 != ip41->dst_address.as_u32)
1041  {
1042  if (!hash_get (gtm->vtep4, ip41->dst_address.as_u32))
1043  goto exit1; /* no local VTEP for GTPU packet */
1044  addr4 = ip41->dst_address;
1045  }
1046  }
1047  else
1048  {
1049  if (!ip6_address_is_equal (&addr6, &ip61->dst_address))
1050  {
1051  if (!hash_get_mem (gtm->vtep6, &ip61->dst_address))
1052  goto exit1; /* no local VTEP for GTPU packet */
1053  addr6 = ip61->dst_address;
1054  }
1055  }
1056 
1057  flags1 = b1->flags;
1058  good_udp1 = (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1059 
1060  /* Don't verify UDP checksum for packets with explicit zero checksum. */
1061  good_udp1 |= udp1->checksum == 0;
1062 
1063  /* Verify UDP length */
1064  if (is_ip4)
1065  ip_len1 = clib_net_to_host_u16 (ip41->length);
1066  else
1067  ip_len1 = clib_net_to_host_u16 (ip61->payload_length);
1068  udp_len1 = clib_net_to_host_u16 (udp1->length);
1069  len_diff1 = ip_len1 - udp_len1;
1070 
1071  /* Verify UDP checksum */
1072  if (PREDICT_FALSE (!good_udp1))
1073  {
1074  if ((flags1 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1075  {
1076  if (is_ip4)
1077  flags1 = ip4_tcp_udp_validate_checksum (vm, b1);
1078  else
1079  flags1 = ip6_tcp_udp_icmp_validate_checksum (vm, b1);
1080  good_udp1 =
1081  (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1082  }
1083  }
1084 
1085  if (is_ip4)
1086  {
1087  error1 = good_udp1 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1088  error1 = (len_diff1 >= 0) ? error1 : IP4_ERROR_UDP_LENGTH;
1089  }
1090  else
1091  {
1092  error1 = good_udp1 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1093  error1 = (len_diff1 >= 0) ? error1 : IP6_ERROR_UDP_LENGTH;
1094  }
1095 
1096  next1 = error1 ?
1098  b1->error = error1 ? error_node->errors[error1] : 0;
1099 
1100  /* gtpu-input node expect current at GTPU header */
1101  if (is_ip4)
1102  vlib_buffer_advance (b1, sizeof(ip4_header_t)+sizeof(udp_header_t));
1103  else
1104  vlib_buffer_advance (b1, sizeof(ip6_header_t)+sizeof(udp_header_t));
1105 
1106  exit1:
1107  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1108  to_next, n_left_to_next,
1109  bi0, bi1, next0, next1);
1110  }
1111 
1112  while (n_left_from > 0 && n_left_to_next > 0)
1113  {
1114  vlib_buffer_t * b0;
1115  ip4_header_t * ip40;
1116  ip6_header_t * ip60;
1117  udp_header_t * udp0;
1118  u32 bi0, ip_len0, udp_len0, flags0, next0;
1119  i32 len_diff0;
1120  u8 error0, good_udp0, proto0;
1121 
1122  bi0 = to_next[0] = from[0];
1123  from += 1;
1124  n_left_from -= 1;
1125  to_next += 1;
1126  n_left_to_next -= 1;
1127 
1128  b0 = vlib_get_buffer (vm, bi0);
1129  if (is_ip4)
1130  ip40 = vlib_buffer_get_current (b0);
1131  else
1132  ip60 = vlib_buffer_get_current (b0);
1133 
1134  /* Setup packet for next IP feature */
1135  vnet_feature_next(&next0, b0);
1136 
1137  if (is_ip4)
1138  /* Treat IP4 frag packets as "experimental" protocol for now
1139  until support of IP frag reassembly is implemented */
1140  proto0 = ip4_is_fragment(ip40) ? 0xfe : ip40->protocol;
1141  else
1142  proto0 = ip60->protocol;
1143 
1144  if (proto0 != IP_PROTOCOL_UDP)
1145  goto exit; /* not UDP packet */
1146 
1147  if (is_ip4)
1148  udp0 = ip4_next_header (ip40);
1149  else
1150  udp0 = ip6_next_header (ip60);
1151 
1152  if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_GTPU))
1153  goto exit; /* not GTPU packet */
1154 
1155  /* Validate DIP against VTEPs*/
1156  if (is_ip4)
1157  {
1158  if (addr4.as_u32 != ip40->dst_address.as_u32)
1159  {
1160  if (!hash_get (gtm->vtep4, ip40->dst_address.as_u32))
1161  goto exit; /* no local VTEP for GTPU packet */
1162  addr4 = ip40->dst_address;
1163  }
1164  }
1165  else
1166  {
1167  if (!ip6_address_is_equal (&addr6, &ip60->dst_address))
1168  {
1169  if (!hash_get_mem (gtm->vtep6, &ip60->dst_address))
1170  goto exit; /* no local VTEP for GTPU packet */
1171  addr6 = ip60->dst_address;
1172  }
1173  }
1174 
1175  flags0 = b0->flags;
1176  good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1177 
1178  /* Don't verify UDP checksum for packets with explicit zero checksum. */
1179  good_udp0 |= udp0->checksum == 0;
1180 
1181  /* Verify UDP length */
1182  if (is_ip4)
1183  ip_len0 = clib_net_to_host_u16 (ip40->length);
1184  else
1185  ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
1186  udp_len0 = clib_net_to_host_u16 (udp0->length);
1187  len_diff0 = ip_len0 - udp_len0;
1188 
1189  /* Verify UDP checksum */
1190  if (PREDICT_FALSE (!good_udp0))
1191  {
1192  if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1193  {
1194  if (is_ip4)
1195  flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
1196  else
1197  flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
1198  good_udp0 =
1199  (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1200  }
1201  }
1202 
1203  if (is_ip4)
1204  {
1205  error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1206  error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
1207  }
1208  else
1209  {
1210  error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1211  error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
1212  }
1213 
1214  next0 = error0 ?
1216  b0->error = error0 ? error_node->errors[error0] : 0;
1217 
1218  /* gtpu-input node expect current at GTPU header */
1219  if (is_ip4)
1220  vlib_buffer_advance (b0, sizeof(ip4_header_t)+sizeof(udp_header_t));
1221  else
1222  vlib_buffer_advance (b0, sizeof(ip6_header_t)+sizeof(udp_header_t));
1223 
1224  exit:
1225  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1226  to_next, n_left_to_next,
1227  bi0, next0);
1228  }
1229 
1230  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1231  }
1232 
1233  return frame->n_vectors;
1234 }
1235 
1237  vlib_node_runtime_t * node,
1238  vlib_frame_t * frame)
1239 {
1240  return ip_gtpu_bypass_inline (vm, node, frame, /* is_ip4 */ 1);
1241 }
1242 
1244  .name = "ip4-gtpu-bypass",
1245  .vector_size = sizeof (u32),
1246 
1247  .n_next_nodes = IP_GTPU_BYPASS_N_NEXT,
1248  .next_nodes = {
1249  [IP_GTPU_BYPASS_NEXT_DROP] = "error-drop",
1250  [IP_GTPU_BYPASS_NEXT_GTPU] = "gtpu4-input",
1251  },
1252 
1253  .format_buffer = format_ip4_header,
1254  .format_trace = format_ip4_forward_next_trace,
1255 };
1256 
1257 #ifndef CLIB_MARCH_VARIANT
1258 /* Dummy init function to get us linked in. */
1260 { return 0; }
1261 
1263 #endif /* CLIB_MARCH_VARIANT */
1264 
1266  vlib_node_runtime_t * node,
1267  vlib_frame_t * frame)
1268 {
1269  return ip_gtpu_bypass_inline (vm, node, frame, /* is_ip4 */ 0);
1270 }
1271 
1273  .name = "ip6-gtpu-bypass",
1274  .vector_size = sizeof (u32),
1275 
1276  .n_next_nodes = IP_GTPU_BYPASS_N_NEXT,
1277  .next_nodes = {
1278  [IP_GTPU_BYPASS_NEXT_DROP] = "error-drop",
1279  [IP_GTPU_BYPASS_NEXT_GTPU] = "gtpu6-input",
1280  },
1281 
1282  .format_buffer = format_ip6_header,
1283  .format_trace = format_ip6_forward_next_trace,
1284 };
1285 
1286 #ifndef CLIB_MARCH_VARIANT
1287 /* Dummy init function to get us linked in. */
1289 { return 0; }
1290 
1292 #endif /* CLIB_MARCH_VARIANT */
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 CLIB_UNUSED(x)
Definition: clib.h:82
vnet_main_t * vnet_main
Definition: gtpu.h:233
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
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:521
ip4_address_t src_address
Definition: ip4_packet.h:170
u32 teid
Definition: gtpu.h:59
static u8 * format_gtpu_rx_trace(u8 *s, va_list *args)
Definition: gtpu_decap.c:32
vnet_interface_main_t interface_main
Definition: vnet.h:56
format_function_t format_ip4_header
Definition: format.h:83
#define PREDICT_TRUE(x)
Definition: clib.h:112
u64 as_u64[2]
Definition: ip6_packet.h:51
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
u8 data[0]
Packet data.
Definition: buffer.h:181
static u32 validate_gtpu_fib(vlib_buffer_t *b, gtpu_tunnel_t *t, u32 is_ip4)
Definition: gtpu_decap.c:52
vlib_node_registration_t ip6_gtpu_bypass_node
(constructor) VLIB_REGISTER_NODE (ip6_gtpu_bypass_node)
Definition: gtpu_decap.c:1272
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:121
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
clib_error_t * ip6_gtpu_bypass_init(vlib_main_t *vm)
Definition: gtpu_decap.c:1288
#define VLIB_NODE_FN(node)
Definition: node.h:201
static uword ip4_address_is_multicast(const ip4_address_t *a)
Definition: ip4_packet.h:318
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:468
uword * vtep4
Definition: gtpu.h:211
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:366
ip6_address_t src_address
Definition: ip6_packet.h:383
unsigned char u8
Definition: types.h:56
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:213
i64 word
Definition: types.h:111
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ip46_address_t src
Definition: gtpu.h:141
vlib_node_registration_t ip4_gtpu_bypass_node
(constructor) VLIB_REGISTER_NODE (ip4_gtpu_bypass_node)
Definition: gtpu_decap.c:1243
#define always_inline
Definition: clib.h:98
ip4_address_t dst_address
Definition: ip4_packet.h:170
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:842
#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
gtpu_main_t gtpu_main
Definition: gtpu.c:35
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
u32 decap_next_index
Definition: gtpu.h:148
vlib_node_registration_t ip4_input_node
Global ip4 input node.
Definition: ip4_input.c:317
uword * vtep6
Definition: gtpu.h:212
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define GTPU_V1_VER
Definition: gtpu.h:74
static char * gtpu_error_strings[]
Definition: gtpu_decap.c:801
#define PREDICT_FALSE(x)
Definition: clib.h:111
static uword ip_gtpu_bypass_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 is_ip4)
Definition: gtpu_decap.c:855
u32 ip4_tcp_udp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip4_forward.c:1217
#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
#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:218
#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_node_registration_t gtpu4_input_node
(constructor) VLIB_REGISTER_NODE (gtpu4_input_node)
Definition: gtpu_decap.c:808
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
clib_error_t * ip4_gtpu_bypass_init(vlib_main_t *vm)
Definition: gtpu_decap.c:1259
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:213
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
vlib_main_t * vm
Definition: buffer.c:312
static void ip6_address_set_zero(ip6_address_t *a)
Definition: ip6_packet.h:276
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:295
static uword gtpu_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u32 is_ip4)
Definition: gtpu_decap.c:71
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
#define GTPU_E_S_PN_BIT
Definition: gtpu.h:72
u32 sw_if_index
Definition: gtpu.h:154
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:458
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:410
#define foreach_gtpu_input_next
Definition: gtpu.h:178
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:513
ip6_main_t ip6_main
Definition: ip6_forward.c:2671
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
u32 encap_fib_index
Definition: gtpu.h:151
format_function_t format_ip6_header
Definition: format.h:97
static uword ip6_address_is_equal(const ip6_address_t *a, const ip6_address_t *b)
Definition: ip6_packet.h:240
#define GTPU_VER_MASK
Definition: gtpu.h:67
static uword ip6_address_is_multicast(const ip6_address_t *a)
Definition: ip6_packet.h:187
ip_vxan_bypass_next_t
Definition: gtpu_decap.c:848
uword * gtpu4_tunnel_by_key
Definition: gtpu.h:206
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
#define vec_elt(v, i)
Get vector value at index i.
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:374
u32 ip6_tcp_udp_icmp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip6_forward.c:1004
static void vnet_update_l2_len(vlib_buffer_t *b)
Definition: l2_input.h:235
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:1056
uword * gtpu6_tunnel_by_key
Definition: gtpu.h:207
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
u8 * format_ip4_forward_next_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1006
Bits Octets 8 7 6 5 4 3 2 1 1 Version PT (*) E S PN 2 Message Type 3 Length (1st Octet) 4 Length...
Definition: gtpu.h:54
#define hash_get_mem(h, key)
Definition: hash.h:269
#define vnet_buffer(b)
Definition: buffer.h:361
gtpu_tunnel_t * tunnels
Definition: gtpu.h:203
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:921
u8 ver_flags
Definition: gtpu.h:56
u16 flags
Copy of main node flags.
Definition: node.h:507
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 * fib_index_by_sw_if_index
Definition: ip6.h:194
vlib_node_registration_t gtpu6_input_node
(constructor) VLIB_REGISTER_NODE (gtpu6_input_node)
Definition: gtpu_decap.c:828
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
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:383
u8 * format_ip6_forward_next_trace(u8 *s, va_list *args)
Definition: ip6_forward.c:762