FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
gtpu.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Intel and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 #include <stdint.h>
18 #include <net/if.h>
19 #include <sys/ioctl.h>
20 #include <inttypes.h>
21 
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/fib/fib_entry.h>
26 #include <vnet/fib/fib_table.h>
28 #include <vnet/mfib/mfib_table.h>
29 #include <vnet/adj/adj_mcast.h>
30 #include <vnet/dpo/dpo.h>
31 #include <vnet/plugin/plugin.h>
32 #include <vpp/app/version.h>
33 #include <gtpu/gtpu.h>
34 
35 
37 
38 /* *INDENT-OFF* */
39 VNET_FEATURE_INIT (ip4_gtpu_bypass, static) = {
40  .arc_name = "ip4-unicast",
41  .node_name = "ip4-gtpu-bypass",
42  .runs_before = VNET_FEATURES ("ip4-lookup"),
43 };
44 
45 VNET_FEATURE_INIT (ip6_gtpu_bypass, static) = {
46  .arc_name = "ip6-unicast",
47  .node_name = "ip6-gtpu-bypass",
48  .runs_before = VNET_FEATURES ("ip6-lookup"),
49 };
50 /* *INDENT-on* */
51 
52 u8 * format_gtpu_encap_trace (u8 * s, va_list * args)
53 {
54  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
55  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
57  = va_arg (*args, gtpu_encap_trace_t *);
58 
59  s = format (s, "GTPU encap to gtpu_tunnel%d teid %d",
60  t->tunnel_index, t->teid);
61  return s;
62 }
63 
64 static u8 *
65 format_decap_next (u8 * s, va_list * args)
66 {
67  u32 next_index = va_arg (*args, u32);
68 
69  switch (next_index)
70  {
71  case GTPU_INPUT_NEXT_DROP:
72  return format (s, "drop");
73  case GTPU_INPUT_NEXT_L2_INPUT:
74  return format (s, "l2");
75  case GTPU_INPUT_NEXT_IP4_INPUT:
76  return format (s, "ip4");
77  case GTPU_INPUT_NEXT_IP6_INPUT:
78  return format (s, "ip6");
79  default:
80  return format (s, "index %d", next_index);
81  }
82  return s;
83 }
84 
85 u8 *
86 format_gtpu_tunnel (u8 * s, va_list * args)
87 {
88  gtpu_tunnel_t *t = va_arg (*args, gtpu_tunnel_t *);
89  gtpu_main_t *ngm = &gtpu_main;
90 
91  s = format (s, "[%d] src %U dst %U teid %d fib-idx %d sw-if-idx %d ",
92  t - ngm->tunnels,
95  t->teid, t->encap_fib_index, t->sw_if_index);
96 
97  s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
98  s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index);
99 
101  s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index);
102 
103  return s;
104 }
105 
106 static u8 *
107 format_gtpu_name (u8 * s, va_list * args)
108 {
109  u32 dev_instance = va_arg (*args, u32);
110  return format (s, "gtpu_tunnel%d", dev_instance);
111 }
112 
113 static clib_error_t *
115 {
116  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
118  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
119 
120  return /* no error */ 0;
121 }
122 
123 /* *INDENT-OFF* */
124 VNET_DEVICE_CLASS (gtpu_device_class,static) = {
125  .name = "GTPU",
126  .format_device_name = format_gtpu_name,
127  .format_tx_trace = format_gtpu_encap_trace,
128  .admin_up_down_function = gtpu_interface_admin_up_down,
129 };
130 /* *INDENT-ON* */
131 
132 static u8 *
133 format_gtpu_header_with_length (u8 * s, va_list * args)
134 {
135  u32 dev_instance = va_arg (*args, u32);
136  s = format (s, "unimplemented dev %u", dev_instance);
137  return s;
138 }
139 
140 /* *INDENT-OFF* */
141 VNET_HW_INTERFACE_CLASS (gtpu_hw_class) =
142 {
143  .name = "GTPU",
144  .format_header = format_gtpu_header_with_length,
145  .build_rewrite = default_build_rewrite,
147 };
148 /* *INDENT-ON* */
149 
150 static void
152 {
153  dpo_id_t dpo = DPO_INVALID;
154  u32 encap_index = ip46_address_is_ip4 (&t->dst) ?
155  gtpu4_encap_node.index : gtpu6_encap_node.index;
158 
159  fib_entry_contribute_forwarding (t->fib_entry_index, forw_type, &dpo);
160  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
161  dpo_reset (&dpo);
162 }
163 
164 static gtpu_tunnel_t *
166 {
167  return ((gtpu_tunnel_t *) (((char *) node) -
169 }
170 
171 /**
172  * Function definition to backwalk a FIB node -
173  * Here we will restack the new dpo of GTPU DIP to encap node.
174  */
177 {
180 }
181 
182 /**
183  * Function definition to get a FIB node from its index
184  */
185 static fib_node_t *
187 {
188  gtpu_tunnel_t *t;
189  gtpu_main_t *gtm = &gtpu_main;
190 
191  t = pool_elt_at_index (gtm->tunnels, index);
192 
193  return (&t->node);
194 }
195 
196 /**
197  * Function definition to inform the FIB node that its last lock has gone.
198  */
199 static void
201 {
202  /*
203  * The GTPU tunnel is a root of the graph. As such
204  * it never has children and thus is never locked.
205  */
206  ASSERT (0);
207 }
208 
209 /*
210  * Virtual function table registered by GTPU tunnels
211  * for participation in the FIB object graph.
212  */
213 const static fib_node_vft_t gtpu_vft = {
215  .fnv_last_lock = gtpu_tunnel_last_lock_gone,
216  .fnv_back_walk = gtpu_tunnel_back_walk,
217 };
218 
219 
220 #define foreach_copy_field \
221 _(teid) \
222 _(mcast_sw_if_index) \
223 _(encap_fib_index) \
224 _(decap_next_index) \
225 _(src) \
226 _(dst)
227 
228 static void
230 {
231  union
232  {
233  ip4_gtpu_header_t *h4;
234  ip6_gtpu_header_t *h6;
235  u8 *rw;
236  } r =
237  {
238  .rw = 0};
239  int len = is_ip6 ? sizeof *r.h6 : sizeof *r.h4;
240 
242 
243  udp_header_t *udp;
244  gtpu_header_t *gtpu;
245  /* Fixed portion of the (outer) ip header */
246  if (!is_ip6)
247  {
248  ip4_header_t *ip = &r.h4->ip4;
249  udp = &r.h4->udp;
250  gtpu = &r.h4->gtpu;
251  ip->ip_version_and_header_length = 0x45;
252  ip->ttl = 254;
253  ip->protocol = IP_PROTOCOL_UDP;
254 
255  ip->src_address = t->src.ip4;
256  ip->dst_address = t->dst.ip4;
257 
258  /* we fix up the ip4 header length and checksum after-the-fact */
259  ip->checksum = ip4_header_checksum (ip);
260  }
261  else
262  {
263  ip6_header_t *ip = &r.h6->ip6;
264  udp = &r.h6->udp;
265  gtpu = &r.h6->gtpu;
267  clib_host_to_net_u32 (6 << 28);
268  ip->hop_limit = 255;
269  ip->protocol = IP_PROTOCOL_UDP;
270 
271  ip->src_address = t->src.ip6;
272  ip->dst_address = t->dst.ip6;
273  }
274 
275  /* UDP header, randomize src port on something, maybe? */
276  udp->src_port = clib_host_to_net_u16 (2152);
277  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_GTPU);
278 
279  /* GTPU header */
281  gtpu->type = GTPU_TYPE_GTPU;
282  gtpu->teid = clib_host_to_net_u32 (t->teid);
283 
284  t->rewrite = r.rw;
285  /* Now only support 8-byte gtpu header. TBD */
286  _vec_len (t->rewrite) = sizeof (ip4_gtpu_header_t) - 4;
287 
288  return;
289 }
290 
291 static bool
292 gtpu_decap_next_is_valid (gtpu_main_t * gtm, u32 is_ip6, u32 decap_next_index)
293 {
294  vlib_main_t *vm = gtm->vlib_main;
295  u32 input_idx = (!is_ip6) ? gtpu4_input_node.index : gtpu6_input_node.index;
296  vlib_node_runtime_t *r = vlib_node_get_runtime (vm, input_idx);
297 
298  return decap_next_index < r->n_next_nodes;
299 }
300 
301 static uword
302 vtep_addr_ref (ip46_address_t * ip)
303 {
304  uword *vtep = ip46_address_is_ip4 (ip) ?
305  hash_get (gtpu_main.vtep4, ip->ip4.as_u32) :
306  hash_get_mem (gtpu_main.vtep6, &ip->ip6);
307  if (vtep)
308  return ++(*vtep);
309  ip46_address_is_ip4 (ip) ?
310  hash_set (gtpu_main.vtep4, ip->ip4.as_u32, 1) :
311  hash_set_mem_alloc (&gtpu_main.vtep6, &ip->ip6, 1);
312  return 1;
313 }
314 
315 static uword
316 vtep_addr_unref (ip46_address_t * ip)
317 {
318  uword *vtep = ip46_address_is_ip4 (ip) ?
319  hash_get (gtpu_main.vtep4, ip->ip4.as_u32) :
320  hash_get_mem (gtpu_main.vtep6, &ip->ip6);
321  ALWAYS_ASSERT (vtep);
322  if (--(*vtep) != 0)
323  return *vtep;
324  ip46_address_is_ip4 (ip) ?
325  hash_unset (gtpu_main.vtep4, ip->ip4.as_u32) :
326  hash_unset_mem_free (&gtpu_main.vtep6, &ip->ip6);
327  return 0;
328 }
329 
330 typedef CLIB_PACKED (union
331  {
332  struct
333  {
334  fib_node_index_t mfib_entry_index;
335  adj_index_t mcast_adj_index;
336  }; u64 as_u64;
337  }) mcast_shared_t;
338 
339 static inline mcast_shared_t
340 mcast_shared_get (ip46_address_t * ip)
341 {
343  uword *p = hash_get_mem (gtpu_main.mcast_shared, ip);
344  ASSERT (p);
345  return (mcast_shared_t)
346  {
347  .as_u64 = *p};
348 }
349 
350 static inline void
351 mcast_shared_add (ip46_address_t * dst, fib_node_index_t mfei, adj_index_t ai)
352 {
353  mcast_shared_t new_ep = {
354  .mcast_adj_index = ai,
355  .mfib_entry_index = mfei,
356  };
357 
358  hash_set_mem_alloc (&gtpu_main.mcast_shared, dst, new_ep.as_u64);
359 }
360 
361 static inline void
362 mcast_shared_remove (ip46_address_t * dst)
363 {
364  mcast_shared_t ep = mcast_shared_get (dst);
365 
366  adj_unlock (ep.mcast_adj_index);
367  mfib_table_entry_delete_index (ep.mfib_entry_index, MFIB_SOURCE_GTPU);
368 
369  hash_unset_mem_free (&gtpu_main.mcast_shared, dst);
370 }
371 
373  (vnet_gtpu_add_del_tunnel_args_t * a, u32 * sw_if_indexp)
374 {
375  gtpu_main_t *gtm = &gtpu_main;
376  gtpu_tunnel_t *t = 0;
377  vnet_main_t *vnm = gtm->vnet_main;
378  uword *p;
379  u32 hw_if_index = ~0;
380  u32 sw_if_index = ~0;
381  gtpu4_tunnel_key_t key4;
382  gtpu6_tunnel_key_t key6;
383  u32 is_ip6 = a->is_ip6;
384 
385  if (!is_ip6)
386  {
387  key4.src = a->dst.ip4.as_u32; /* decap src in key is encap dst in config */
388  key4.teid = clib_host_to_net_u32 (a->teid);
389  p = hash_get (gtm->gtpu4_tunnel_by_key, key4.as_u64);
390  }
391  else
392  {
393  key6.src = a->dst.ip6;
394  key6.teid = clib_host_to_net_u32 (a->teid);
395  p = hash_get_mem (gtm->gtpu6_tunnel_by_key, &key6);
396  }
397 
398  if (a->is_add)
399  {
400  l2input_main_t *l2im = &l2input_main;
401 
402  /* adding a tunnel: tunnel must not already exist */
403  if (p)
404  return VNET_API_ERROR_TUNNEL_EXIST;
405 
406  /*if not set explicitly, default to l2 */
407  if (a->decap_next_index == ~0)
408  a->decap_next_index = GTPU_INPUT_NEXT_L2_INPUT;
409  if (!gtpu_decap_next_is_valid (gtm, is_ip6, a->decap_next_index))
410  return VNET_API_ERROR_INVALID_DECAP_NEXT;
411 
413  clib_memset (t, 0, sizeof (*t));
414 
415  /* copy from arg structure */
416 #define _(x) t->x = a->x;
418 #undef _
419 
420  ip_udp_gtpu_rewrite (t, is_ip6);
421 
422  /* copy the key */
423  if (is_ip6)
425  t - gtm->tunnels);
426  else
427  hash_set (gtm->gtpu4_tunnel_by_key, key4.as_u64, t - gtm->tunnels);
428 
431  {
433  hw_if_index = gtm->free_gtpu_tunnel_hw_if_indices
435  _vec_len (gtm->free_gtpu_tunnel_hw_if_indices) -= 1;
436 
437  hi = vnet_get_hw_interface (vnm, hw_if_index);
438  hi->dev_instance = t - gtm->tunnels;
439  hi->hw_instance = hi->dev_instance;
440 
441  /* clear old stats of freed tunnel before reuse */
442  sw_if_index = hi->sw_if_index;
446  sw_if_index);
449  sw_if_index);
452  sw_if_index);
454  }
455  else
456  {
457  hw_if_index = vnet_register_interface
458  (vnm, gtpu_device_class.index, t - gtm->tunnels,
459  gtpu_hw_class.index, t - gtm->tunnels);
460  hi = vnet_get_hw_interface (vnm, hw_if_index);
461  }
462 
463  /* Set gtpu tunnel output node */
464  u32 encap_index = !is_ip6 ?
465  gtpu4_encap_node.index : gtpu6_encap_node.index;
466  vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
467 
468  t->hw_if_index = hw_if_index;
469  t->sw_if_index = sw_if_index = hi->sw_if_index;
470 
472  ~0);
474 
475  /* setup l2 input config with l2 feature and bd 0 to drop packet */
476  vec_validate (l2im->configs, sw_if_index);
477  l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
478  l2im->configs[sw_if_index].bd_index = 0;
479 
480  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
482  vnet_sw_interface_set_flags (vnm, sw_if_index,
484 
485  fib_node_init (&t->node, gtm->fib_node_type);
486  fib_prefix_t tun_dst_pfx;
488 
489  fib_prefix_from_ip46_addr (&t->dst, &tun_dst_pfx);
490  if (!ip46_address_is_multicast (&t->dst))
491  {
492  /* Unicast tunnel -
493  * Track the FIB entry for the tunnel's destination.
494  * The tunnel will then get poked
495  * when the forwarding for the entry updates, and the tunnel can
496  * re-stack accordingly
497  */
498  vtep_addr_ref (&t->src);
500  &tun_dst_pfx,
501  gtm->fib_node_type,
502  t - gtm->tunnels,
503  &t->sibling_index);
505  }
506  else
507  {
508  /* Multicast tunnel -
509  * as the same mcast group can be used for multiple mcast tunnels
510  * with different VNIs, create the output adjacency only if
511  * it does not already exist
512  */
513  fib_protocol_t fp = fib_ip_proto (is_ip6);
514 
515  if (vtep_addr_ref (&t->dst) == 1)
516  {
517  fib_node_index_t mfei;
518  adj_index_t ai;
519  fib_route_path_t path = {
520  .frp_proto = fib_proto_to_dpo (fp),
521  .frp_addr = zero_addr,
522  .frp_sw_if_index = 0xffffffff,
523  .frp_fib_index = ~0,
524  .frp_weight = 1,
525  .frp_flags = FIB_ROUTE_PATH_LOCAL,
526  .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
527  };
528  const mfib_prefix_t mpfx = {
529  .fp_proto = fp,
530  .fp_len = (is_ip6 ? 128 : 32),
531  .fp_grp_addr = tun_dst_pfx.fp_addr,
532  };
533 
534  /*
535  * Setup the (*,G) to receive traffic on the mcast group
536  * - the forwarding interface is for-us
537  * - the accepting interface is that from the API
538  */
540  &mpfx, MFIB_SOURCE_GTPU, &path);
541 
546  &mpfx,
547  MFIB_SOURCE_GTPU, &path);
548 
549  /*
550  * Create the mcast adjacency to send traffic to the group
551  */
552  ai = adj_mcast_add_or_lock (fp,
553  fib_proto_to_link (fp),
554  a->mcast_sw_if_index);
555 
556  /*
557  * create a new end-point
558  */
559  mcast_shared_add (&t->dst, mfei, ai);
560  }
561 
562  dpo_id_t dpo = DPO_INVALID;
563  mcast_shared_t ep = mcast_shared_get (&t->dst);
564 
565  /* Stack shared mcast dst mac addr rewrite on encap */
567  fib_proto_to_dpo (fp), ep.mcast_adj_index);
568 
569  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
570 
571  dpo_reset (&dpo);
572  flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
573  }
574 
575  vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
576  flood_class;
577  }
578  else
579  {
580  /* deleting a tunnel: tunnel must exist */
581  if (!p)
582  return VNET_API_ERROR_NO_SUCH_ENTRY;
583 
584  t = pool_elt_at_index (gtm->tunnels, p[0]);
585  sw_if_index = t->sw_if_index;
586 
587  vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */ );
590 
591  /* make sure tunnel is removed from l2 bd or xconnect */
592  set_int_l2_mode (gtm->vlib_main, vnm, MODE_L3, t->sw_if_index, 0,
593  L2_BD_PORT_TYPE_NORMAL, 0, 0);
595 
597 
598  if (!is_ip6)
599  hash_unset (gtm->gtpu4_tunnel_by_key, key4.as_u64);
600  else
602 
603  if (!ip46_address_is_multicast (&t->dst))
604  {
605  vtep_addr_unref (&t->src);
607  }
608  else if (vtep_addr_unref (&t->dst) == 0)
609  {
610  mcast_shared_remove (&t->dst);
611  }
612 
613  fib_node_deinit (&t->node);
614  vec_free (t->rewrite);
615  pool_put (gtm->tunnels, t);
616  }
617 
618  if (sw_if_indexp)
619  *sw_if_indexp = sw_if_index;
620 
621  if (a->is_add)
622  {
623  /* register udp ports */
624  if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_GTPU, 1))
625  udp_register_dst_port (gtm->vlib_main, UDP_DST_PORT_GTPU,
626  gtpu4_input_node.index, /* is_ip4 */ 1);
627  if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_GTPU6, 0))
628  udp_register_dst_port (gtm->vlib_main, UDP_DST_PORT_GTPU6,
629  gtpu6_input_node.index, /* is_ip4 */ 0);
630  }
631 
632  return 0;
633 }
634 
635 static uword
636 get_decap_next_for_node (u32 node_index, u32 ipv4_set)
637 {
638  gtpu_main_t *gtm = &gtpu_main;
639  vlib_main_t *vm = gtm->vlib_main;
640  uword input_node = (ipv4_set) ? gtpu4_input_node.index :
641  gtpu6_input_node.index;
642 
643  return vlib_node_add_next (vm, input_node, node_index);
644 }
645 
646 static uword
647 unformat_decap_next (unformat_input_t * input, va_list * args)
648 {
649  u32 *result = va_arg (*args, u32 *);
650  u32 ipv4_set = va_arg (*args, int);
651  gtpu_main_t *gtm = &gtpu_main;
652  vlib_main_t *vm = gtm->vlib_main;
653  u32 node_index;
654  u32 tmp;
655 
656  if (unformat (input, "l2"))
657  *result = GTPU_INPUT_NEXT_L2_INPUT;
658  else if (unformat (input, "ip4"))
659  *result = GTPU_INPUT_NEXT_IP4_INPUT;
660  else if (unformat (input, "ip6"))
661  *result = GTPU_INPUT_NEXT_IP6_INPUT;
662  else if (unformat (input, "node %U", unformat_vlib_node, vm, &node_index))
663  *result = get_decap_next_for_node (node_index, ipv4_set);
664  else if (unformat (input, "%d", &tmp))
665  *result = tmp;
666  else
667  return 0;
668 
669  return 1;
670 }
671 
672 static clib_error_t *
674  unformat_input_t * input,
675  vlib_cli_command_t * cmd)
676 {
677  unformat_input_t _line_input, *line_input = &_line_input;
678  ip46_address_t src, dst;
679  u8 is_add = 1;
680  u8 src_set = 0;
681  u8 dst_set = 0;
682  u8 grp_set = 0;
683  u8 ipv4_set = 0;
684  u8 ipv6_set = 0;
685  u32 encap_fib_index = 0;
686  u32 mcast_sw_if_index = ~0;
687  u32 decap_next_index = GTPU_INPUT_NEXT_L2_INPUT;
688  u32 teid = 0;
689  u32 tmp;
690  int rv;
691  vnet_gtpu_add_del_tunnel_args_t _a, *a = &_a;
692  u32 tunnel_sw_if_index;
693  clib_error_t *error = NULL;
694 
695  /* Cant "universally zero init" (={0}) due to GCC bug 53119 */
696  clib_memset (&src, 0, sizeof src);
697  clib_memset (&dst, 0, sizeof dst);
698 
699  /* Get a line of input. */
700  if (!unformat_user (input, unformat_line_input, line_input))
701  return 0;
702 
703  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
704  {
705  if (unformat (line_input, "del"))
706  {
707  is_add = 0;
708  }
709  else if (unformat (line_input, "src %U",
710  unformat_ip4_address, &src.ip4))
711  {
712  src_set = 1;
713  ipv4_set = 1;
714  }
715  else if (unformat (line_input, "dst %U",
716  unformat_ip4_address, &dst.ip4))
717  {
718  dst_set = 1;
719  ipv4_set = 1;
720  }
721  else if (unformat (line_input, "src %U",
722  unformat_ip6_address, &src.ip6))
723  {
724  src_set = 1;
725  ipv6_set = 1;
726  }
727  else if (unformat (line_input, "dst %U",
728  unformat_ip6_address, &dst.ip6))
729  {
730  dst_set = 1;
731  ipv6_set = 1;
732  }
733  else if (unformat (line_input, "group %U %U",
734  unformat_ip4_address, &dst.ip4,
736  vnet_get_main (), &mcast_sw_if_index))
737  {
738  grp_set = dst_set = 1;
739  ipv4_set = 1;
740  }
741  else if (unformat (line_input, "group %U %U",
742  unformat_ip6_address, &dst.ip6,
744  vnet_get_main (), &mcast_sw_if_index))
745  {
746  grp_set = dst_set = 1;
747  ipv6_set = 1;
748  }
749  else if (unformat (line_input, "encap-vrf-id %d", &tmp))
750  {
751  encap_fib_index = fib_table_find (fib_ip_proto (ipv6_set), tmp);
752  if (encap_fib_index == ~0)
753  {
754  error =
755  clib_error_return (0, "nonexistent encap-vrf-id %d", tmp);
756  goto done;
757  }
758  }
759  else if (unformat (line_input, "decap-next %U", unformat_decap_next,
760  &decap_next_index, ipv4_set))
761  ;
762  else if (unformat (line_input, "teid %d", &teid))
763  ;
764  else
765  {
766  error = clib_error_return (0, "parse error: '%U'",
767  format_unformat_error, line_input);
768  goto done;
769  }
770  }
771 
772  if (src_set == 0)
773  {
774  error = clib_error_return (0, "tunnel src address not specified");
775  goto done;
776  }
777 
778  if (dst_set == 0)
779  {
780  error = clib_error_return (0, "tunnel dst address not specified");
781  goto done;
782  }
783 
784  if (grp_set && !ip46_address_is_multicast (&dst))
785  {
786  error = clib_error_return (0, "tunnel group address not multicast");
787  goto done;
788  }
789 
790  if (grp_set == 0 && ip46_address_is_multicast (&dst))
791  {
792  error = clib_error_return (0, "dst address must be unicast");
793  goto done;
794  }
795 
796  if (grp_set && mcast_sw_if_index == ~0)
797  {
798  error = clib_error_return (0, "tunnel nonexistent multicast device");
799  goto done;
800  }
801 
802  if (ipv4_set && ipv6_set)
803  {
804  error = clib_error_return (0, "both IPv4 and IPv6 addresses specified");
805  goto done;
806  }
807 
808  if (ip46_address_cmp (&src, &dst) == 0)
809  {
810  error = clib_error_return (0, "src and dst addresses are identical");
811  goto done;
812  }
813 
814  if (decap_next_index == ~0)
815  {
816  error = clib_error_return (0, "next node not found");
817  goto done;
818  }
819 
820  clib_memset (a, 0, sizeof (*a));
821 
822  a->is_add = is_add;
823  a->is_ip6 = ipv6_set;
824 
825 #define _(x) a->x = x;
827 #undef _
828 
829  rv = vnet_gtpu_add_del_tunnel (a, &tunnel_sw_if_index);
830 
831  switch (rv)
832  {
833  case 0:
834  if (is_add)
836  vnet_get_main (), tunnel_sw_if_index);
837  break;
838 
839  case VNET_API_ERROR_TUNNEL_EXIST:
840  error = clib_error_return (0, "tunnel already exists...");
841  goto done;
842 
843  case VNET_API_ERROR_NO_SUCH_ENTRY:
844  error = clib_error_return (0, "tunnel does not exist...");
845  goto done;
846 
847  default:
848  error = clib_error_return
849  (0, "vnet_gtpu_add_del_tunnel returned %d", rv);
850  goto done;
851  }
852 
853 done:
854  unformat_free (line_input);
855 
856  return error;
857 }
858 
859 /*?
860  * Add or delete a GTPU Tunnel.
861  *
862  * GTPU provides the features needed to allow L2 bridge domains (BDs)
863  * to span multiple servers. This is done by building an L2 overlay on
864  * top of an L3 network underlay using GTPU tunnels.
865  *
866  * This makes it possible for servers to be co-located in the same data
867  * center or be separated geographically as long as they are reachable
868  * through the underlay L3 network.
869  *
870  * You can refer to this kind of L2 overlay bridge domain as a GTPU
871  * (Virtual eXtensible VLAN) segment.
872  *
873  * @cliexpar
874  * Example of how to create a GTPU Tunnel:
875  * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 encap-vrf-id 7}
876  * Example of how to delete a GTPU Tunnel:
877  * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 del}
878  ?*/
879 /* *INDENT-OFF* */
880 VLIB_CLI_COMMAND (create_gtpu_tunnel_command, static) = {
881  .path = "create gtpu tunnel",
882  .short_help =
883  "create gtpu tunnel src <local-vtep-addr>"
884  " {dst <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} teid <nn>"
885  " [encap-vrf-id <nn>] [decap-next [l2|ip4|ip6|node <name>]] [del]",
886  .function = gtpu_add_del_tunnel_command_fn,
887 };
888 /* *INDENT-ON* */
889 
890 static clib_error_t *
892  unformat_input_t * input,
893  vlib_cli_command_t * cmd)
894 {
895  gtpu_main_t *gtm = &gtpu_main;
896  gtpu_tunnel_t *t;
897 
898  if (pool_elts (gtm->tunnels) == 0)
899  vlib_cli_output (vm, "No gtpu tunnels configured...");
900 
901  pool_foreach (t, gtm->tunnels, (
902  {
903  vlib_cli_output (vm, "%U",
904  format_gtpu_tunnel, t);
905  }
906  ));
907 
908  return 0;
909 }
910 
911 /*?
912  * Display all the GTPU Tunnel entries.
913  *
914  * @cliexpar
915  * Example of how to display the GTPU Tunnel entries:
916  * @cliexstart{show gtpu tunnel}
917  * [0] src 10.0.3.1 dst 10.0.3.3 teid 13 encap_fib_index 0 sw_if_index 5 decap_next l2
918  * @cliexend
919  ?*/
920 /* *INDENT-OFF* */
921 VLIB_CLI_COMMAND (show_gtpu_tunnel_command, static) = {
922  .path = "show gtpu tunnel",
923  .short_help = "show gtpu tunnel",
924  .function = show_gtpu_tunnel_command_fn,
925 };
926 /* *INDENT-ON* */
927 
928 void
930 {
931  if (is_ip6)
932  vnet_feature_enable_disable ("ip6-unicast", "ip6-gtpu-bypass",
933  sw_if_index, is_enable, 0, 0);
934  else
935  vnet_feature_enable_disable ("ip4-unicast", "ip4-gtpu-bypass",
936  sw_if_index, is_enable, 0, 0);
937 }
938 
939 static clib_error_t *
941  unformat_input_t * input, vlib_cli_command_t * cmd)
942 {
943  unformat_input_t _line_input, *line_input = &_line_input;
944  vnet_main_t *vnm = vnet_get_main ();
945  clib_error_t *error = 0;
946  u32 sw_if_index, is_enable;
947 
948  sw_if_index = ~0;
949  is_enable = 1;
950 
951  if (!unformat_user (input, unformat_line_input, line_input))
952  return 0;
953 
954  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
955  {
956  if (unformat_user
957  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
958  ;
959  else if (unformat (line_input, "del"))
960  is_enable = 0;
961  else
962  {
963  error = unformat_parse_error (line_input);
964  goto done;
965  }
966  }
967 
968  if (~0 == sw_if_index)
969  {
970  error = clib_error_return (0, "unknown interface `%U'",
971  format_unformat_error, line_input);
972  goto done;
973  }
974 
975  vnet_int_gtpu_bypass_mode (sw_if_index, is_ip6, is_enable);
976 
977 done:
978  unformat_free (line_input);
979 
980  return error;
981 }
982 
983 static clib_error_t *
985  unformat_input_t * input, vlib_cli_command_t * cmd)
986 {
987  return set_ip_gtpu_bypass (0, input, cmd);
988 }
989 
990 /*?
991  * This command adds the 'ip4-gtpu-bypass' graph node for a given interface.
992  * By adding the IPv4 gtpu-bypass graph node to an interface, the node checks
993  * for and validate input gtpu packet and bypass ip4-lookup, ip4-local,
994  * ip4-udp-lookup nodes to speedup gtpu packet forwarding. This node will
995  * cause extra overhead to for non-gtpu packets which is kept at a minimum.
996  *
997  * @cliexpar
998  * @parblock
999  * Example of graph node before ip4-gtpu-bypass is enabled:
1000  * @cliexstart{show vlib graph ip4-gtpu-bypass}
1001  * Name Next Previous
1002  * ip4-gtpu-bypass error-drop [0]
1003  * gtpu4-input [1]
1004  * ip4-lookup [2]
1005  * @cliexend
1006  *
1007  * Example of how to enable ip4-gtpu-bypass on an interface:
1008  * @cliexcmd{set interface ip gtpu-bypass GigabitEthernet2/0/0}
1009  *
1010  * Example of graph node after ip4-gtpu-bypass is enabled:
1011  * @cliexstart{show vlib graph ip4-gtpu-bypass}
1012  * Name Next Previous
1013  * ip4-gtpu-bypass error-drop [0] ip4-input
1014  * gtpu4-input [1] ip4-input-no-checksum
1015  * ip4-lookup [2]
1016  * @cliexend
1017  *
1018  * Example of how to display the feature enabled on an interface:
1019  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1020  * IP feature paths configured on GigabitEthernet2/0/0...
1021  * ...
1022  * ipv4 unicast:
1023  * ip4-gtpu-bypass
1024  * ip4-lookup
1025  * ...
1026  * @cliexend
1027  *
1028  * Example of how to disable ip4-gtpu-bypass on an interface:
1029  * @cliexcmd{set interface ip gtpu-bypass GigabitEthernet2/0/0 del}
1030  * @endparblock
1031 ?*/
1032 /* *INDENT-OFF* */
1033 VLIB_CLI_COMMAND (set_interface_ip_gtpu_bypass_command, static) = {
1034  .path = "set interface ip gtpu-bypass",
1035  .function = set_ip4_gtpu_bypass,
1036  .short_help = "set interface ip gtpu-bypass <interface> [del]",
1037 };
1038 /* *INDENT-ON* */
1039 
1040 static clib_error_t *
1042  unformat_input_t * input, vlib_cli_command_t * cmd)
1043 {
1044  return set_ip_gtpu_bypass (1, input, cmd);
1045 }
1046 
1047 /*?
1048  * This command adds the 'ip6-gtpu-bypass' graph node for a given interface.
1049  * By adding the IPv6 gtpu-bypass graph node to an interface, the node checks
1050  * for and validate input gtpu packet and bypass ip6-lookup, ip6-local,
1051  * ip6-udp-lookup nodes to speedup gtpu packet forwarding. This node will
1052  * cause extra overhead to for non-gtpu packets which is kept at a minimum.
1053  *
1054  * @cliexpar
1055  * @parblock
1056  * Example of graph node before ip6-gtpu-bypass is enabled:
1057  * @cliexstart{show vlib graph ip6-gtpu-bypass}
1058  * Name Next Previous
1059  * ip6-gtpu-bypass error-drop [0]
1060  * gtpu6-input [1]
1061  * ip6-lookup [2]
1062  * @cliexend
1063  *
1064  * Example of how to enable ip6-gtpu-bypass on an interface:
1065  * @cliexcmd{set interface ip6 gtpu-bypass GigabitEthernet2/0/0}
1066  *
1067  * Example of graph node after ip6-gtpu-bypass is enabled:
1068  * @cliexstart{show vlib graph ip6-gtpu-bypass}
1069  * Name Next Previous
1070  * ip6-gtpu-bypass error-drop [0] ip6-input
1071  * gtpu6-input [1] ip4-input-no-checksum
1072  * ip6-lookup [2]
1073  * @cliexend
1074  *
1075  * Example of how to display the feature enabled on an interface:
1076  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1077  * IP feature paths configured on GigabitEthernet2/0/0...
1078  * ...
1079  * ipv6 unicast:
1080  * ip6-gtpu-bypass
1081  * ip6-lookup
1082  * ...
1083  * @cliexend
1084  *
1085  * Example of how to disable ip6-gtpu-bypass on an interface:
1086  * @cliexcmd{set interface ip6 gtpu-bypass GigabitEthernet2/0/0 del}
1087  * @endparblock
1088 ?*/
1089 /* *INDENT-OFF* */
1090 VLIB_CLI_COMMAND (set_interface_ip6_gtpu_bypass_command, static) = {
1091  .path = "set interface ip6 gtpu-bypass",
1092  .function = set_ip6_gtpu_bypass,
1093  .short_help = "set interface ip6 gtpu-bypass <interface> [del]",
1094 };
1095 /* *INDENT-ON* */
1096 
1097 clib_error_t *
1099 {
1100  gtpu_main_t *gtm = &gtpu_main;
1101 
1102  gtm->vnet_main = vnet_get_main ();
1103  gtm->vlib_main = vm;
1104 
1105  /* initialize the ip6 hash */
1107  sizeof (gtpu6_tunnel_key_t),
1108  sizeof (uword));
1109  gtm->vtep6 = hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword));
1110  gtm->mcast_shared = hash_create_mem (0,
1111  sizeof (ip46_address_t),
1112  sizeof (mcast_shared_t));
1113 
1114  gtm->fib_node_type = fib_node_register_new_type (&gtpu_vft);
1115 
1116  return 0;
1117 }
1118 
1120 
1121 /* *INDENT-OFF* */
1122 VLIB_PLUGIN_REGISTER () = {
1123  .version = VPP_BUILD_VER,
1124  .description = "GPRS Tunnelling Protocol, User Data (GTPv1-U)",
1125 };
1126 /* *INDENT-ON* */
1127 
1128 /*
1129  * fd.io coding-style-patch-verification: ON
1130  *
1131  * Local Variables:
1132  * eval: (c-set-style "gnu")
1133  * End:
1134  */
vlib_main_t * vlib_main
Definition: gtpu.h:232
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
vlib_node_registration_t gtpu4_encap_node
(constructor) VLIB_REGISTER_NODE (gtpu4_encap_node)
Definition: gtpu_encap.c:687
void vnet_set_interface_output_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Set interface output node - for interface registered without its output/tx nodes created because its ...
void dpo_stack_from_node(u32 child_node_index, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child parent relationship.
Definition: dpo.c:531
vmrglw vmrglh hi
clib_error_t * gtpu_init(vlib_main_t *vm)
Definition: gtpu.c:1098
fib_node_index_t fib_entry_track(u32 fib_index, const fib_prefix_t *prefix, fib_node_type_t child_type, index_t child_index, u32 *sibling)
Trackers are used on FIB entries by objects that which to track the changing state of the entry...
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:113
#define hash_set(h, key, value)
Definition: hash.h:255
l2_input_config_t * configs
Definition: l2_input.h:62
u32 flags
Definition: vhost_user.h:141
#define CLIB_UNUSED(x)
Definition: clib.h:83
vnet_main_t * vnet_main
Definition: gtpu.h:233
#define hash_unset(h, key)
Definition: hash.h:261
static uword get_decap_next_for_node(u32 node_index, u32 ipv4_set)
Definition: gtpu.c:636
A representation of a path as described by a route producer.
Definition: fib_types.h:485
ip4_address_t src_address
Definition: ip4_packet.h:170
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u32 teid
Definition: gtpu.h:59
u32 teid
Definition: gtpu.h:138
#define GTPU_TYPE_GTPU
Definition: gtpu.h:77
vnet_interface_main_t interface_main
Definition: vnet.h:56
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
u64 as_u64
Definition: bihash_doc.h:63
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath)
Add n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:323
u32 frp_mitf_flags
MFIB interface flags.
Definition: fib_types.h:554
unsigned long u64
Definition: types.h:89
u32 * tunnel_index_by_sw_if_index
Definition: gtpu.h:221
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
fib_node_type_t fib_node_type
Node type for registering to fib changes.
Definition: gtpu.h:226
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
#define foreach_copy_field
Definition: gtpu.c:220
void fib_entry_contribute_forwarding(fib_node_index_t fib_entry_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_entry.c:448
static uword vtep_addr_unref(ip46_address_t *ip)
Definition: gtpu.c:316
u32 mcast_sw_if_index
Definition: vxlan_gbp.api:40
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define GTPU_PT_GTP
Definition: gtpu.h:76
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
vl_api_address_t src
Definition: gre.api:51
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
format_function_t format_ip46_address
Definition: format.h:61
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:109
VNET_FEATURE_INIT(ip4_gtpu_bypass, static)
static void gtpu_tunnel_restack_dpo(gtpu_tunnel_t *t)
Definition: gtpu.c:151
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:66
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:197
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:490
unformat_function_t unformat_vnet_sw_interface
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:450
uword * vtep4
Definition: gtpu.h:211
typedef CLIB_PACKED(union { struct { fib_node_index_t mfib_entry_index;adj_index_t mcast_adj_index;};u64 as_u64;})
Definition: gtpu.c:330
ip6_address_t src_address
Definition: ip6_packet.h:383
#define ip46_address_cmp(ip46_1, ip46_2)
Definition: ip6_packet.h:92
format_function_t format_vnet_sw_if_index_name
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1092
unsigned char u8
Definition: types.h:56
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it.
Definition: fib_node.c:80
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
static uword ip46_address_is_multicast(const ip46_address_t *a)
Definition: ip6_packet.h:193
static u8 * format_decap_next(u8 *s, va_list *args)
Definition: gtpu.c:65
static fib_node_t * gtpu_tunnel_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: gtpu.c:186
u8 * format_gtpu_encap_trace(u8 *s, va_list *args)
Definition: gtpu.c:52
VNET_DEVICE_CLASS(gtpu_device_class, static)
static u8 * format_gtpu_name(u8 *s, va_list *args)
Definition: gtpu.c:107
vnet_flood_class_t flood_class
Definition: interface.h:728
VNET_HW_INTERFACE_CLASS(gtpu_hw_class)
static gtpu_tunnel_t * gtpu_tunnel_from_fib_node(fib_node_t *node)
Definition: gtpu.c:165
dpo_id_t next_dpo
Definition: gtpu.h:135
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
unformat_function_t unformat_ip4_address
Definition: format.h:70
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:525
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
int vnet_gtpu_add_del_tunnel(vnet_gtpu_add_del_tunnel_args_t *a, u32 *sw_if_indexp)
Definition: gtpu.c:373
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ip46_address_t src
Definition: gtpu.h:141
void mfib_table_entry_delete_index(fib_node_index_t mfib_entry_index, mfib_source_t source)
Delete a FIB entry.
Definition: mfib_table.c:515
ip4_address_t dst_address
Definition: ip4_packet.h:170
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:846
Aggregate type for a prefix.
Definition: fib_types.h:203
static clib_error_t * show_gtpu_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:891
#define clib_error_return(e, args...)
Definition: error.h:99
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:347
#define ALWAYS_ASSERT(truth)
unsigned int u32
Definition: types.h:88
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1080
gtpu_main_t gtpu_main
Definition: gtpu.c:36
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:762
static u8 * format_gtpu_header_with_length(u8 *s, va_list *args)
Definition: gtpu.c:133
u8 * format_gtpu_tunnel(u8 *s, va_list *args)
Definition: gtpu.c:86
unformat_function_t unformat_line_input
Definition: format.h:283
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
#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
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread counters.
Definition: counter.h:285
u32 decap_next_index
Definition: gtpu.h:148
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
uword * vtep6
Definition: gtpu.h:212
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
#define GTPU_V1_VER
Definition: gtpu.h:74
#define PREDICT_FALSE(x)
Definition: clib.h:112
vnet_sw_interface_flags_t flags
Definition: interface.h:703
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:845
static uword vtep_addr_ref(ip46_address_t *ip)
Definition: gtpu.c:302
static fib_node_back_walk_rc_t gtpu_tunnel_back_walk(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Function definition to backwalk a FIB node - Here we will restack the new dpo of GTPU DIP to encap no...
Definition: gtpu.c:176
An node in the FIB graph.
Definition: fib_node.h:295
vl_api_address_t dst
Definition: gre.api:52
static clib_error_t * gtpu_add_del_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:673
ip46_address_t dst
Definition: gtpu.h:142
u8 len
Definition: ip_types.api:90
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:88
unformat_function_t unformat_ip6_address
Definition: format.h:91
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:230
u8 type
Definition: gtpu.h:57
static void ip_udp_gtpu_rewrite(gtpu_tunnel_t *t, bool is_ip6)
Definition: gtpu.c:229
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
vlib_main_t * vm
Definition: buffer.c:323
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
vnet_flood_class_t
Definition: interface.h:644
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
fib_node_get_t fnv_get
Definition: fib_node.h:283
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:879
static void mcast_shared_remove(ip46_address_t *dst)
Definition: gtpu.c:362
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
u32 sw_if_index
Definition: gtpu.h:154
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void fib_prefix_from_ip46_addr(const ip46_address_t *addr, fib_prefix_t *pfx)
Host prefix from ip.
Definition: fib_types.c:81
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
u32 sibling_index
The tunnel is a child of the FIB entry for its destination.
Definition: gtpu.h:175
Aggregate type for a prefix.
Definition: mfib_types.h:24
static bool gtpu_decap_next_is_valid(gtpu_main_t *gtm, u32 is_ip6, u32 decap_next_index)
Definition: gtpu.c:292
u8 * default_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Return a complete, zero-length (aka dummy) rewrite.
Definition: interface.c:1578
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:161
u32 * free_gtpu_tunnel_hw_if_indices
Definition: gtpu.h:218
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:872
static clib_error_t * set_ip4_gtpu_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:984
#define ASSERT(truth)
fib_node_index_t fib_entry_index
Definition: gtpu.h:166
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
fib_node_t node
Linkage into the FIB object graph.
Definition: gtpu.h:160
u32 hw_if_index
Definition: gtpu.h:155
static void gtpu_tunnel_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: gtpu.c:200
u32 set_int_l2_mode(vlib_main_t *vm, vnet_main_t *vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, l2_bd_port_type_t port_type, u32 shg, u32 xc_sw_if_index)
Set the subinterface to run in l2 or l3 mode.
Definition: l2_input.c:591
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:595
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:139
void vnet_int_gtpu_bypass_mode(u32 sw_if_index, u8 is_ip6, u8 is_enable)
Definition: gtpu.c:929
u32 encap_fib_index
Definition: gtpu.h:151
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:247
#define VNET_FEATURES(...)
Definition: feature.h:442
uword * gtpu4_tunnel_by_key
Definition: gtpu.h:206
u32 tunnel_index
Definition: gtpu.h:261
#define unformat_parse_error(input)
Definition: format.h:269
vlib_node_registration_t gtpu6_input_node
(constructor) VLIB_REGISTER_NODE (gtpu6_input_node)
Definition: gtpu_decap.c:781
static void mcast_shared_add(ip46_address_t *dst, fib_node_index_t mfei, adj_index_t ai)
Definition: gtpu.c:351
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:370
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
l2input_main_t l2input_main
Definition: l2_input.c:128
uword * mcast_shared
Definition: gtpu.h:215
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
A for-us/local path.
Definition: fib_types.h:338
bool udp_is_valid_dst_port(udp_dst_port_t dst_port, u8 is_ip4)
Definition: udp_local.c:529
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static fib_protocol_t fib_ip_proto(bool is_ip6)
Convert from boolean is_ip6 to FIB protocol.
Definition: fib_types.h:80
uword * gtpu6_tunnel_by_key
Definition: gtpu.h:207
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:492
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
static void hash_set_mem_alloc(uword **h, void *key, uword v)
Definition: hash.h:279
static clib_error_t * set_ip6_gtpu_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:1041
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
vlib_node_registration_t gtpu6_encap_node
(constructor) VLIB_REGISTER_NODE (gtpu6_encap_node)
Definition: gtpu_encap.c:702
a point 2 point interface
Definition: interface.h:368
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1147
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
static void hash_unset_mem_free(uword **h, void *key)
Definition: hash.h:295
static clib_error_t * set_ip_gtpu_bypass(u32 is_ip6, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:940
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
gtpu_tunnel_t * tunnels
Definition: gtpu.h:203
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags)
Definition: interface.c:501
adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto, vnet_link_t link_type, u32 sw_if_index)
Mcast Adjacency.
Definition: adj_mcast.c:51
u8 * rewrite
Definition: gtpu.h:132
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
VLIB_PLUGIN_REGISTER()
u8 ver_flags
Definition: gtpu.h:56
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:281
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:468
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
static clib_error_t * gtpu_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: gtpu.c:114
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
vlib_node_registration_t gtpu4_input_node
(constructor) VLIB_REGISTER_NODE (gtpu4_input_node)
Definition: gtpu_decap.c:761
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:772
static uword unformat_decap_next(unformat_input_t *input, va_list *args)
Definition: gtpu.c:647
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
const ip46_address_t zero_addr
Definition: lookup.c:326
u32 mcast_sw_if_index
Definition: gtpu.h:145
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
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:275
ip6_address_t dst_address
Definition: ip6_packet.h:383
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
#define MODE_L3
Definition: l2_input.h:220
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128