FD.io VPP  v20.01-48-g3e0dafb74
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
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  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  bool is_ip6 = !ip46_address_is_ip4 (&a->dst);
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;
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 
824 #define _(x) a->x = x;
826 #undef _
827 
828  rv = vnet_gtpu_add_del_tunnel (a, &tunnel_sw_if_index);
829 
830  switch (rv)
831  {
832  case 0:
833  if (is_add)
835  vnet_get_main (), tunnel_sw_if_index);
836  break;
837 
838  case VNET_API_ERROR_TUNNEL_EXIST:
839  error = clib_error_return (0, "tunnel already exists...");
840  goto done;
841 
842  case VNET_API_ERROR_NO_SUCH_ENTRY:
843  error = clib_error_return (0, "tunnel does not exist...");
844  goto done;
845 
846  default:
847  error = clib_error_return
848  (0, "vnet_gtpu_add_del_tunnel returned %d", rv);
849  goto done;
850  }
851 
852 done:
853  unformat_free (line_input);
854 
855  return error;
856 }
857 
858 /*?
859  * Add or delete a GTPU Tunnel.
860  *
861  * GTPU provides the features needed to allow L2 bridge domains (BDs)
862  * to span multiple servers. This is done by building an L2 overlay on
863  * top of an L3 network underlay using GTPU tunnels.
864  *
865  * This makes it possible for servers to be co-located in the same data
866  * center or be separated geographically as long as they are reachable
867  * through the underlay L3 network.
868  *
869  * You can refer to this kind of L2 overlay bridge domain as a GTPU
870  * (Virtual eXtensible VLAN) segment.
871  *
872  * @cliexpar
873  * Example of how to create a GTPU Tunnel:
874  * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 encap-vrf-id 7}
875  * Example of how to delete a GTPU Tunnel:
876  * @cliexcmd{create gtpu tunnel src 10.0.3.1 dst 10.0.3.3 teid 13 del}
877  ?*/
878 /* *INDENT-OFF* */
879 VLIB_CLI_COMMAND (create_gtpu_tunnel_command, static) = {
880  .path = "create gtpu tunnel",
881  .short_help =
882  "create gtpu tunnel src <local-vtep-addr>"
883  " {dst <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} teid <nn>"
884  " [encap-vrf-id <nn>] [decap-next [l2|ip4|ip6|node <name>]] [del]",
885  .function = gtpu_add_del_tunnel_command_fn,
886 };
887 /* *INDENT-ON* */
888 
889 static clib_error_t *
891  unformat_input_t * input,
892  vlib_cli_command_t * cmd)
893 {
894  gtpu_main_t *gtm = &gtpu_main;
895  gtpu_tunnel_t *t;
896 
897  if (pool_elts (gtm->tunnels) == 0)
898  vlib_cli_output (vm, "No gtpu tunnels configured...");
899 
900  pool_foreach (t, gtm->tunnels, (
901  {
902  vlib_cli_output (vm, "%U",
903  format_gtpu_tunnel, t);
904  }
905  ));
906 
907  return 0;
908 }
909 
910 /*?
911  * Display all the GTPU Tunnel entries.
912  *
913  * @cliexpar
914  * Example of how to display the GTPU Tunnel entries:
915  * @cliexstart{show gtpu tunnel}
916  * [0] src 10.0.3.1 dst 10.0.3.3 teid 13 encap_fib_index 0 sw_if_index 5 decap_next l2
917  * @cliexend
918  ?*/
919 /* *INDENT-OFF* */
920 VLIB_CLI_COMMAND (show_gtpu_tunnel_command, static) = {
921  .path = "show gtpu tunnel",
922  .short_help = "show gtpu tunnel",
923  .function = show_gtpu_tunnel_command_fn,
924 };
925 /* *INDENT-ON* */
926 
927 void
929 {
930  if (is_ip6)
931  vnet_feature_enable_disable ("ip6-unicast", "ip6-gtpu-bypass",
932  sw_if_index, is_enable, 0, 0);
933  else
934  vnet_feature_enable_disable ("ip4-unicast", "ip4-gtpu-bypass",
935  sw_if_index, is_enable, 0, 0);
936 }
937 
938 static clib_error_t *
940  unformat_input_t * input, vlib_cli_command_t * cmd)
941 {
942  unformat_input_t _line_input, *line_input = &_line_input;
943  vnet_main_t *vnm = vnet_get_main ();
944  clib_error_t *error = 0;
945  u32 sw_if_index, is_enable;
946 
947  sw_if_index = ~0;
948  is_enable = 1;
949 
950  if (!unformat_user (input, unformat_line_input, line_input))
951  return 0;
952 
953  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
954  {
955  if (unformat_user
956  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
957  ;
958  else if (unformat (line_input, "del"))
959  is_enable = 0;
960  else
961  {
962  error = unformat_parse_error (line_input);
963  goto done;
964  }
965  }
966 
967  if (~0 == sw_if_index)
968  {
969  error = clib_error_return (0, "unknown interface `%U'",
970  format_unformat_error, line_input);
971  goto done;
972  }
973 
974  vnet_int_gtpu_bypass_mode (sw_if_index, is_ip6, is_enable);
975 
976 done:
977  unformat_free (line_input);
978 
979  return error;
980 }
981 
982 static clib_error_t *
984  unformat_input_t * input, vlib_cli_command_t * cmd)
985 {
986  return set_ip_gtpu_bypass (0, input, cmd);
987 }
988 
989 /*?
990  * This command adds the 'ip4-gtpu-bypass' graph node for a given interface.
991  * By adding the IPv4 gtpu-bypass graph node to an interface, the node checks
992  * for and validate input gtpu packet and bypass ip4-lookup, ip4-local,
993  * ip4-udp-lookup nodes to speedup gtpu packet forwarding. This node will
994  * cause extra overhead to for non-gtpu packets which is kept at a minimum.
995  *
996  * @cliexpar
997  * @parblock
998  * Example of graph node before ip4-gtpu-bypass is enabled:
999  * @cliexstart{show vlib graph ip4-gtpu-bypass}
1000  * Name Next Previous
1001  * ip4-gtpu-bypass error-drop [0]
1002  * gtpu4-input [1]
1003  * ip4-lookup [2]
1004  * @cliexend
1005  *
1006  * Example of how to enable ip4-gtpu-bypass on an interface:
1007  * @cliexcmd{set interface ip gtpu-bypass GigabitEthernet2/0/0}
1008  *
1009  * Example of graph node after ip4-gtpu-bypass is enabled:
1010  * @cliexstart{show vlib graph ip4-gtpu-bypass}
1011  * Name Next Previous
1012  * ip4-gtpu-bypass error-drop [0] ip4-input
1013  * gtpu4-input [1] ip4-input-no-checksum
1014  * ip4-lookup [2]
1015  * @cliexend
1016  *
1017  * Example of how to display the feature enabled on an interface:
1018  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1019  * IP feature paths configured on GigabitEthernet2/0/0...
1020  * ...
1021  * ipv4 unicast:
1022  * ip4-gtpu-bypass
1023  * ip4-lookup
1024  * ...
1025  * @cliexend
1026  *
1027  * Example of how to disable ip4-gtpu-bypass on an interface:
1028  * @cliexcmd{set interface ip gtpu-bypass GigabitEthernet2/0/0 del}
1029  * @endparblock
1030 ?*/
1031 /* *INDENT-OFF* */
1032 VLIB_CLI_COMMAND (set_interface_ip_gtpu_bypass_command, static) = {
1033  .path = "set interface ip gtpu-bypass",
1034  .function = set_ip4_gtpu_bypass,
1035  .short_help = "set interface ip gtpu-bypass <interface> [del]",
1036 };
1037 /* *INDENT-ON* */
1038 
1039 static clib_error_t *
1041  unformat_input_t * input, vlib_cli_command_t * cmd)
1042 {
1043  return set_ip_gtpu_bypass (1, input, cmd);
1044 }
1045 
1046 /*?
1047  * This command adds the 'ip6-gtpu-bypass' graph node for a given interface.
1048  * By adding the IPv6 gtpu-bypass graph node to an interface, the node checks
1049  * for and validate input gtpu packet and bypass ip6-lookup, ip6-local,
1050  * ip6-udp-lookup nodes to speedup gtpu packet forwarding. This node will
1051  * cause extra overhead to for non-gtpu packets which is kept at a minimum.
1052  *
1053  * @cliexpar
1054  * @parblock
1055  * Example of graph node before ip6-gtpu-bypass is enabled:
1056  * @cliexstart{show vlib graph ip6-gtpu-bypass}
1057  * Name Next Previous
1058  * ip6-gtpu-bypass error-drop [0]
1059  * gtpu6-input [1]
1060  * ip6-lookup [2]
1061  * @cliexend
1062  *
1063  * Example of how to enable ip6-gtpu-bypass on an interface:
1064  * @cliexcmd{set interface ip6 gtpu-bypass GigabitEthernet2/0/0}
1065  *
1066  * Example of graph node after ip6-gtpu-bypass is enabled:
1067  * @cliexstart{show vlib graph ip6-gtpu-bypass}
1068  * Name Next Previous
1069  * ip6-gtpu-bypass error-drop [0] ip6-input
1070  * gtpu6-input [1] ip4-input-no-checksum
1071  * ip6-lookup [2]
1072  * @cliexend
1073  *
1074  * Example of how to display the feature enabled on an interface:
1075  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1076  * IP feature paths configured on GigabitEthernet2/0/0...
1077  * ...
1078  * ipv6 unicast:
1079  * ip6-gtpu-bypass
1080  * ip6-lookup
1081  * ...
1082  * @cliexend
1083  *
1084  * Example of how to disable ip6-gtpu-bypass on an interface:
1085  * @cliexcmd{set interface ip6 gtpu-bypass GigabitEthernet2/0/0 del}
1086  * @endparblock
1087 ?*/
1088 /* *INDENT-OFF* */
1089 VLIB_CLI_COMMAND (set_interface_ip6_gtpu_bypass_command, static) = {
1090  .path = "set interface ip6 gtpu-bypass",
1091  .function = set_ip6_gtpu_bypass,
1092  .short_help = "set interface ip6 gtpu-bypass <interface> [del]",
1093 };
1094 /* *INDENT-ON* */
1095 
1096 clib_error_t *
1098 {
1099  gtpu_main_t *gtm = &gtpu_main;
1100 
1101  gtm->vnet_main = vnet_get_main ();
1102  gtm->vlib_main = vm;
1103 
1104  /* initialize the ip6 hash */
1106  sizeof (gtpu6_tunnel_key_t),
1107  sizeof (uword));
1108  gtm->vtep6 = hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword));
1109  gtm->mcast_shared = hash_create_mem (0,
1110  sizeof (ip46_address_t),
1111  sizeof (mcast_shared_t));
1112 
1113  gtm->fib_node_type = fib_node_register_new_type (&gtpu_vft);
1114 
1115  return 0;
1116 }
1117 
1119 
1120 /* *INDENT-OFF* */
1121 VLIB_PLUGIN_REGISTER () = {
1122  .version = VPP_BUILD_VER,
1123  .description = "GPRS Tunnelling Protocol, User Data (GTPv1-U)",
1124 };
1125 /* *INDENT-ON* */
1126 
1127 /*
1128  * fd.io coding-style-patch-verification: ON
1129  *
1130  * Local Variables:
1131  * eval: (c-set-style "gnu")
1132  * End:
1133  */
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:440
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
clib_error_t * gtpu_init(vlib_main_t *vm)
Definition: gtpu.c:1097
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...
#define GTPU_PT_GTP
Definition: mobile.h:146
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
#define CLIB_UNUSED(x)
Definition: clib.h:82
vnet_main_t * vnet_main
Definition: gtpu.h:233
static uword ip46_address_is_multicast(const ip46_address_t *a)
Definition: ip46_address.h:154
#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: mobile.h:77
u32 teid
Definition: gtpu.h:138
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define GTPU_TYPE_GTPU
Definition: mobile.h:86
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:325
u32 frp_mitf_flags
MFIB interface flags.
Definition: fib_types.h:554
static mcast_shared_t mcast_shared_get(ip46_address_t *ip)
Definition: geneve.c:335
unsigned long u64
Definition: types.h:89
u32 * tunnel_index_by_sw_if_index
Definition: gtpu.h:221
#define NULL
Definition: clib.h:58
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:437
static uword vtep_addr_unref(ip46_address_t *ip)
Definition: gtpu.c:316
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
vl_api_address_t src
Definition: gre.api:60
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
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:65
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
unformat_function_t unformat_vnet_sw_interface
vl_api_fib_path_t path
Definition: mfib_types.api:34
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:451
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
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
ip6_address_t src_address
Definition: ip6_packet.h:307
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 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:745
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:498
unformat_function_t unformat_ip4_address
Definition: format.h:68
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:525
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
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:517
ip4_address_t dst_address
Definition: ip4_packet.h:170
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:863
static int ip46_address_cmp(const ip46_address_t *ip46_1, const ip46_address_t *ip46_2)
Definition: ip46_address.h:80
vl_api_interface_index_t mcast_sw_if_index
Definition: vxlan_gbp.api:41
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:890
#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:324
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:1097
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
bool is_ip6
Definition: ip.api:43
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:519
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:287
#define PREDICT_FALSE(x)
Definition: clib.h:111
vnet_sw_interface_flags_t flags
Definition: interface.h:720
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:862
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:61
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
vlib_main_t * vm
Definition: in2out_ed.c:1810
ip46_address_t dst
Definition: gtpu.h:142
u8 len
Definition: ip_types.api:91
format_function_t format_ip46_address
Definition: ip46_address.h:50
unformat_function_t unformat_ip6_address
Definition: format.h:89
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:231
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
u32 flags
Definition: vhost_user.h:141
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
vnet_flood_class_t
Definition: interface.h:661
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:893
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
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
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:1629
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
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:886
static clib_error_t * set_ip4_gtpu_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:983
#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 hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
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:928
u32 encap_fib_index
Definition: gtpu.h:151
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:260
#define GTPU_V1_VER
Definition: mobile.h:144
#define VNET_FEATURES(...)
Definition: feature.h:442
vl_api_ip4_address_t hi
Definition: arp.api:37
uword * gtpu4_tunnel_by_key
Definition: gtpu.h:206
u32 tunnel_index
Definition: gtpu.h:260
#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:294
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:532
#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 clib_error_t * set_ip6_gtpu_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:1040
#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:375
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: mobile.h:72
#define hash_get_mem(h, key)
Definition: hash.h:269
static clib_error_t * set_ip_gtpu_bypass(u32 is_ip6, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gtpu.c:939
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: mobile.h:74
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:294
static void hash_set_mem_alloc(uword **h, const void *key, uword v)
Definition: hash.h:279
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:471
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:487
#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:689
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:307
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:304
ip6_address_t dst_address
Definition: ip6_packet.h:307
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