FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
vxlan_gpe.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief Common utility functions for IPv4 and IPv6 VXLAN GPE tunnels
18  *
19 */
21 #include <vnet/fib/fib.h>
22 #include <vnet/ip/format.h>
23 #include <vnet/fib/fib_entry.h>
24 #include <vnet/fib/fib_table.h>
26 #include <vnet/mfib/mfib_table.h>
27 #include <vnet/adj/adj_mcast.h>
28 #include <vnet/interface.h>
29 #include <vlib/vlib.h>
30 
31 /**
32  * @file
33  * @brief VXLAN-GPE.
34  *
35  * VXLAN-GPE provides the features needed to allow L2 bridge domains (BDs)
36  * to span multiple servers. This is done by building an L2 overlay on
37  * top of an L3 network underlay using VXLAN-GPE tunnels.
38  *
39  * This makes it possible for servers to be co-located in the same data
40  * center or be separated geographically as long as they are reachable
41  * through the underlay L3 network.
42  *
43  * You can refer to this kind of L2 overlay bridge domain as a VXLAN-GPE segment.
44  */
45 
47 
48 static u8 *
49 format_decap_next (u8 * s, va_list * args)
50 {
51  vxlan_gpe_tunnel_t *t = va_arg (*args, vxlan_gpe_tunnel_t *);
52 
53  switch (t->protocol)
54  {
55  case VXLAN_GPE_PROTOCOL_IP4:
56  s = format (s, "protocol ip4 fib-idx %d", t->decap_fib_index);
57  break;
58  case VXLAN_GPE_PROTOCOL_IP6:
59  s = format (s, "protocol ip6 fib-idx %d", t->decap_fib_index);
60  break;
61  case VXLAN_GPE_PROTOCOL_ETHERNET:
62  s = format (s, "protocol ethernet");
63  break;
64  case VXLAN_GPE_PROTOCOL_NSH:
65  s = format (s, "protocol nsh");
66  break;
67  default:
68  s = format (s, "protocol unknown %d", t->protocol);
69  }
70 
71  return s;
72 }
73 
74 /**
75  * @brief Format function for VXLAN GPE tunnel
76  *
77  * @param *s formatting string
78  * @param *args
79  *
80  * @return *s formatted string
81  *
82  */
83 u8 *
84 format_vxlan_gpe_tunnel (u8 * s, va_list * args)
85 {
86  vxlan_gpe_tunnel_t *t = va_arg (*args, vxlan_gpe_tunnel_t *);
88 
89  s = format (s, "[%d] lcl %U rmt %U vni %d fib-idx %d sw-if-idx %d ",
90  t - ngm->tunnels,
93  t->vni, t->encap_fib_index, t->sw_if_index);
94 
95 #if 0
96  /* next_dpo not yet used by vxlan-gpe-encap node */
97  s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
98  */
99 #endif
100  s = format (s, "decap-next-%U ", format_decap_next, t);
101 
103  s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index);
104 
105  return s;
106 }
107 
108 /**
109  * @brief Naming for VXLAN GPE tunnel
110  *
111  * @param *s formatting string
112  * @param *args
113  *
114  * @return *s formatted string
115  *
116  */
117 static u8 *
118 format_vxlan_gpe_name (u8 * s, va_list * args)
119 {
120  u32 dev_instance = va_arg (*args, u32);
121  return format (s, "vxlan_gpe_tunnel%d", dev_instance);
122 }
123 
124 /**
125  * @brief CLI function for VXLAN GPE admin up/down
126  *
127  * @param *vnm
128  * @param hw_if_index
129  * @param flag
130  *
131  * @return *rc
132  *
133  */
134 static clib_error_t *
136  u32 flags)
137 {
138  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
140  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
141 
142  return 0;
143 }
144 
145 /* *INDENT-OFF* */
146 VNET_DEVICE_CLASS (vxlan_gpe_device_class,static) = {
147  .name = "VXLAN_GPE",
148  .format_device_name = format_vxlan_gpe_name,
149  .format_tx_trace = format_vxlan_gpe_encap_trace,
150  .admin_up_down_function = vxlan_gpe_interface_admin_up_down,
151 };
152 /* *INDENT-ON* */
153 
154 
155 /**
156  * @brief Formatting function for tracing VXLAN GPE with length
157  *
158  * @param *s
159  * @param *args
160  *
161  * @return *s
162  *
163  */
164 static u8 *
166 {
167  u32 dev_instance = va_arg (*args, u32);
168  s = format (s, "unimplemented dev %u", dev_instance);
169  return s;
170 }
171 
172 /* *INDENT-OFF* */
173 VNET_HW_INTERFACE_CLASS (vxlan_gpe_hw_class) = {
174  .name = "VXLAN_GPE",
175  .format_header = format_vxlan_gpe_header_with_length,
176  .build_rewrite = default_build_rewrite,
177 };
178 /* *INDENT-ON* */
179 
180 static void
182 {
183  dpo_id_t dpo = DPO_INVALID;
184  u32 encap_index = vxlan_gpe_encap_node.index;
187 
188  fib_entry_contribute_forwarding (t->fib_entry_index, forw_type, &dpo);
189  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
190  dpo_reset (&dpo);
191 }
192 
193 static vxlan_gpe_tunnel_t *
195 {
197  return ((vxlan_gpe_tunnel_t *) (((char *) node) -
199  node)));
200 }
201 
202 /**
203  * Function definition to backwalk a FIB node -
204  * Here we will restack the new dpo of VXLAN_GPE DIP to encap node.
205  */
208 {
211 }
212 
213 /**
214  * Function definition to get a FIB node from its index
215  */
216 static fib_node_t *
218 {
221 
222  t = pool_elt_at_index (ngm->tunnels, index);
223 
224  return (&t->node);
225 }
226 
227 /**
228  * Function definition to inform the FIB node that its last lock has gone.
229  */
230 static void
232 {
233  /*
234  * The VXLAN_GPE tunnel is a root of the graph. As such
235  * it never has children and thus is never locked.
236  */
237  ASSERT (0);
238 }
239 
240 /*
241  * Virtual function table registered by VXLAN_GPE tunnels
242  * for participation in the FIB object graph.
243  */
244 const static fib_node_vft_t vxlan_gpe_vft = {
246  .fnv_last_lock = vxlan_gpe_tunnel_last_lock_gone,
247  .fnv_back_walk = vxlan_gpe_tunnel_back_walk,
248 };
249 
250 #define foreach_gpe_copy_field \
251 _(vni) \
252 _(protocol) \
253 _(mcast_sw_if_index) \
254 _(encap_fib_index) \
255 _(decap_fib_index)
256 
257 #define foreach_copy_ipv4 { \
258  _(local.ip4.as_u32) \
259  _(remote.ip4.as_u32) \
260 }
261 
262 #define foreach_copy_ipv6 { \
263  _(local.ip6.as_u64[0]) \
264  _(local.ip6.as_u64[1]) \
265  _(remote.ip6.as_u64[0]) \
266  _(remote.ip6.as_u64[1]) \
267 }
268 
269 
270 /**
271  * @brief Calculate IPv4 VXLAN GPE rewrite header
272  *
273  * @param *t
274  *
275  * @return rc
276  *
277  */
278 int
280  u8 protocol_override, uword encap_next_node)
281 {
282  u8 *rw = 0;
283  ip4_header_t *ip0;
284  ip4_vxlan_gpe_header_t *h0;
285  int len;
286 
287  len = sizeof (*h0) + extension_size;
288 
289  vec_free (t->rewrite);
291 
292  h0 = (ip4_vxlan_gpe_header_t *) rw;
293 
294  /* Fixed portion of the (outer) ip4 header */
295  ip0 = &h0->ip4;
296  ip0->ip_version_and_header_length = 0x45;
297  ip0->ttl = 254;
298  ip0->protocol = IP_PROTOCOL_UDP;
299 
300  /* we fix up the ip4 header length and checksum after-the-fact */
301  ip0->src_address.as_u32 = t->local.ip4.as_u32;
302  ip0->dst_address.as_u32 = t->remote.ip4.as_u32;
303  ip0->checksum = ip4_header_checksum (ip0);
304 
305  /* UDP header, randomize src port on something, maybe? */
306  h0->udp.src_port = clib_host_to_net_u16 (4790);
307  h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
308 
309  /* VXLAN header. Are we having fun yet? */
310  h0->vxlan.flags = VXLAN_GPE_FLAGS_I | VXLAN_GPE_FLAGS_P;
311  h0->vxlan.ver_res = VXLAN_GPE_VERSION;
312  if (protocol_override)
313  {
314  h0->vxlan.protocol = protocol_override;
315  }
316  else
317  {
318  h0->vxlan.protocol = t->protocol;
319  }
320  t->rewrite_size = sizeof (ip4_vxlan_gpe_header_t) + extension_size;
321  h0->vxlan.vni_res = clib_host_to_net_u32 (t->vni << 8);
322 
323  t->rewrite = rw;
324  t->encap_next_node = encap_next_node;
325  return (0);
326 }
327 
328 /**
329  * @brief Calculate IPv6 VXLAN GPE rewrite header
330  *
331  * @param *t
332  *
333  * @return rc
334  *
335  */
336 int
338  u8 protocol_override, uword encap_next_node)
339 {
340  u8 *rw = 0;
341  ip6_header_t *ip0;
342  ip6_vxlan_gpe_header_t *h0;
343  int len;
344 
345  len = sizeof (*h0) + extension_size;
346 
347  vec_free (t->rewrite);
349 
350  h0 = (ip6_vxlan_gpe_header_t *) rw;
351 
352  /* Fixed portion of the (outer) ip4 header */
353  ip0 = &h0->ip6;
355  clib_host_to_net_u32 (6 << 28);
356  ip0->hop_limit = 255;
357  ip0->protocol = IP_PROTOCOL_UDP;
358 
359  ip0->src_address.as_u64[0] = t->local.ip6.as_u64[0];
360  ip0->src_address.as_u64[1] = t->local.ip6.as_u64[1];
361  ip0->dst_address.as_u64[0] = t->remote.ip6.as_u64[0];
362  ip0->dst_address.as_u64[1] = t->remote.ip6.as_u64[1];
363 
364  /* UDP header, randomize src port on something, maybe? */
365  h0->udp.src_port = clib_host_to_net_u16 (4790);
366  h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
367 
368  /* VXLAN header. Are we having fun yet? */
369  h0->vxlan.flags = VXLAN_GPE_FLAGS_I | VXLAN_GPE_FLAGS_P;
370  h0->vxlan.ver_res = VXLAN_GPE_VERSION;
371  if (protocol_override)
372  {
373  h0->vxlan.protocol = t->protocol;
374  }
375  else
376  {
377  h0->vxlan.protocol = protocol_override;
378  }
379  t->rewrite_size = sizeof (ip4_vxlan_gpe_header_t) + extension_size;
380  h0->vxlan.vni_res = clib_host_to_net_u32 (t->vni << 8);
381 
382  t->rewrite = rw;
383  t->encap_next_node = encap_next_node;
384  return (0);
385 }
386 
387 /* *INDENT-OFF* */
388 typedef CLIB_PACKED(union {
389  struct {
390  fib_node_index_t mfib_entry_index;
391  adj_index_t mcast_adj_index;
392  };
393  u64 as_u64;
394 }) mcast_shared_t;
395 /* *INDENT-ON* */
396 
397 static inline mcast_shared_t
398 mcast_shared_get (ip46_address_t * ip)
399 {
401  uword *p = hash_get_mem (vxlan_gpe_main.mcast_shared, ip);
402  ALWAYS_ASSERT (p);
403  return (mcast_shared_t)
404  {
405  .as_u64 = *p};
406 }
407 
408 static inline void
409 mcast_shared_add (ip46_address_t * remote,
410  fib_node_index_t mfei, adj_index_t ai)
411 {
412  mcast_shared_t new_ep = {
413  .mcast_adj_index = ai,
414  .mfib_entry_index = mfei,
415  };
416 
417  hash_set_mem_alloc (&vxlan_gpe_main.mcast_shared, remote, new_ep.as_u64);
418 }
419 
420 static inline void
421 mcast_shared_remove (ip46_address_t * remote)
422 {
423  mcast_shared_t ep = mcast_shared_get (remote);
424 
425  adj_unlock (ep.mcast_adj_index);
427 
428  hash_unset_mem_free (&vxlan_gpe_main.mcast_shared, remote);
429 }
430 
431 /**
432  * @brief Add or Del a VXLAN GPE tunnel
433  *
434  * @param *a
435  * @param *sw_if_index
436  *
437  * @return rc
438  *
439  */
442 {
444  vxlan_gpe_tunnel_t *t = 0;
445  vnet_main_t *vnm = ngm->vnet_main;
447  uword *p;
448  u32 hw_if_index = ~0;
449  u32 sw_if_index = ~0;
450  int rv;
451  vxlan4_gpe_tunnel_key_t key4, *key4_copy;
452  vxlan6_gpe_tunnel_key_t key6, *key6_copy;
453  u32 is_ip6 = a->is_ip6;
454 
455  if (!is_ip6)
456  {
457  key4.local = a->local.ip4.as_u32;
458  key4.remote = a->remote.ip4.as_u32;
459  key4.vni = clib_host_to_net_u32 (a->vni << 8);
460  key4.pad = 0;
461 
462  p = hash_get_mem (ngm->vxlan4_gpe_tunnel_by_key, &key4);
463  }
464  else
465  {
466  key6.local.as_u64[0] = a->local.ip6.as_u64[0];
467  key6.local.as_u64[1] = a->local.ip6.as_u64[1];
468  key6.remote.as_u64[0] = a->remote.ip6.as_u64[0];
469  key6.remote.as_u64[1] = a->remote.ip6.as_u64[1];
470  key6.vni = clib_host_to_net_u32 (a->vni << 8);
471 
472  p = hash_get_mem (ngm->vxlan6_gpe_tunnel_by_key, &key6);
473  }
474 
475  if (a->is_add)
476  {
477  l2input_main_t *l2im = &l2input_main;
478 
479  /* adding a tunnel: tunnel must not already exist */
480  if (p)
481  return VNET_API_ERROR_TUNNEL_EXIST;
482 
484  clib_memset (t, 0, sizeof (*t));
485 
486  /* copy from arg structure */
487 /* *INDENT-OFF* */
488 #define _(x) t->x = a->x;
490  if (!a->is_ip6)
492  else
494 #undef _
495 /* *INDENT-ON* */
496 
497  if (!a->is_ip6)
499 
500  if (!a->is_ip6)
501  {
503  }
504  else
505  {
507  }
508 
509  if (rv)
510  {
511  pool_put (ngm->tunnels, t);
512  return rv;
513  }
514 
515  if (!is_ip6)
516  {
517  key4_copy = clib_mem_alloc (sizeof (*key4_copy));
518  clib_memcpy_fast (key4_copy, &key4, sizeof (*key4_copy));
519  hash_set_mem (ngm->vxlan4_gpe_tunnel_by_key, key4_copy,
520  t - ngm->tunnels);
521  }
522  else
523  {
524  key6_copy = clib_mem_alloc (sizeof (*key6_copy));
525  clib_memcpy_fast (key6_copy, &key6, sizeof (*key6_copy));
526  hash_set_mem (ngm->vxlan6_gpe_tunnel_by_key, key6_copy,
527  t - ngm->tunnels);
528  }
529 
531  {
533  hw_if_index = ngm->free_vxlan_gpe_tunnel_hw_if_indices
535  _vec_len (ngm->free_vxlan_gpe_tunnel_hw_if_indices) -= 1;
536 
537  hi = vnet_get_hw_interface (vnm, hw_if_index);
538  hi->dev_instance = t - ngm->tunnels;
539  hi->hw_instance = hi->dev_instance;
540  /* clear old stats of freed tunnel before reuse */
541  sw_if_index = hi->sw_if_index;
545  sw_if_index);
548  sw_if_index);
551  sw_if_index);
553  }
554  else
555  {
556  hw_if_index = vnet_register_interface
557  (vnm, vxlan_gpe_device_class.index, t - ngm->tunnels,
558  vxlan_gpe_hw_class.index, t - ngm->tunnels);
559  hi = vnet_get_hw_interface (vnm, hw_if_index);
560  }
561 
562  /* Set vxlan-gpe tunnel output node */
563  u32 encap_index = vxlan_gpe_encap_node.index;
564  vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
565 
566  t->hw_if_index = hw_if_index;
567  t->sw_if_index = sw_if_index = hi->sw_if_index;
569  ~0);
571 
572  /* setup l2 input config with l2 feature and bd 0 to drop packet */
573  vec_validate (l2im->configs, sw_if_index);
574  l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
575  l2im->configs[sw_if_index].bd_index = 0;
576 
577  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
582  fib_prefix_t tun_remote_pfx;
584 
585  fib_prefix_from_ip46_addr (&t->remote, &tun_remote_pfx);
587  {
588  /* Unicast tunnel -
589  * source the FIB entry for the tunnel's destination
590  * and become a child thereof. The tunnel will then get poked
591  * when the forwarding for the entry updates, and the tunnel can
592  * re-stack accordingly
593  */
596  &tun_remote_pfx,
598  t - ngm->tunnels,
599  &t->sibling_index);
601  }
602  else
603  {
604  /* Multicast tunnel -
605  * as the same mcast group can be used for multiple mcast tunnels
606  * with different VNIs, create the output fib adjacency only if
607  * it does not already exist
608  */
609  fib_protocol_t fp = fib_ip_proto (is_ip6);
610 
611  if (vtep_addr_ref (&ngm->vtep_table,
612  t->encap_fib_index, &t->remote) == 1)
613  {
614  fib_node_index_t mfei;
615  adj_index_t ai;
617  .frp_proto = fib_proto_to_dpo (fp),
618  .frp_addr = zero_addr,
619  .frp_sw_if_index = 0xffffffff,
620  .frp_fib_index = ~0,
621  .frp_weight = 1,
622  .frp_flags = FIB_ROUTE_PATH_LOCAL,
623  .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
624  };
625  const mfib_prefix_t mpfx = {
626  .fp_proto = fp,
627  .fp_len = (is_ip6 ? 128 : 32),
628  .fp_grp_addr = tun_remote_pfx.fp_addr,
629  };
630 
631  /*
632  * Setup the (*,G) to receive traffic on the mcast group
633  * - the forwarding interface is for-us
634  * - the accepting interface is that from the API
635  */
637  &mpfx,
638  MFIB_SOURCE_VXLAN_GPE, &path);
639 
644  &mpfx,
646  &path);
647 
648  /*
649  * Create the mcast adjacency to send traffic to the group
650  */
651  ai = adj_mcast_add_or_lock (fp,
652  fib_proto_to_link (fp),
653  a->mcast_sw_if_index);
654 
655  /*
656  * create a new end-point
657  */
658  mcast_shared_add (&t->remote, mfei, ai);
659  }
660 
661  dpo_id_t dpo = DPO_INVALID;
662  mcast_shared_t ep = mcast_shared_get (&t->remote);
663 
664  /* Stack shared mcast remote mac addr rewrite on encap */
666  fib_proto_to_dpo (fp), ep.mcast_adj_index);
667 
668  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
669  dpo_reset (&dpo);
670  flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
671  }
672 
673  vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
674  flood_class;
675  }
676  else
677  {
678  /* deleting a tunnel: tunnel must exist */
679  if (!p)
680  return VNET_API_ERROR_NO_SUCH_ENTRY;
681 
682  t = pool_elt_at_index (ngm->tunnels, p[0]);
683 
684  sw_if_index = t->sw_if_index;
685  vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */ );
688  set_int_l2_mode (ngm->vlib_main, vnm, MODE_L3, t->sw_if_index, 0,
689  L2_BD_PORT_TYPE_NORMAL, 0, 0);
691 
693 
694  if (!is_ip6)
695  hash_unset (ngm->vxlan4_gpe_tunnel_by_key, key4.as_u64);
696  else
698 
700  {
703  }
704  else if (vtep_addr_unref (&ngm->vtep_table,
705  t->encap_fib_index, &t->remote) == 0)
706  {
708  }
709 
710  fib_node_deinit (&t->node);
711  vec_free (t->rewrite);
712  pool_put (ngm->tunnels, t);
713  }
714 
715  if (sw_if_indexp)
716  *sw_if_indexp = sw_if_index;
717 
718  if (a->is_add)
719  {
720  /* register udp ports */
721  if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_VXLAN_GPE, 1))
722  udp_register_dst_port (ngm->vlib_main, UDP_DST_PORT_VXLAN_GPE,
723  vxlan4_gpe_input_node.index, 1 /* is_ip4 */ );
724  if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_VXLAN6_GPE, 0))
725  udp_register_dst_port (ngm->vlib_main, UDP_DST_PORT_VXLAN6_GPE,
726  vxlan6_gpe_input_node.index, 0 /* is_ip4 */ );
727  }
728 
729  return 0;
730 }
731 
732 static clib_error_t *
734  unformat_input_t * input,
735  vlib_cli_command_t * cmd)
736 {
737  unformat_input_t _line_input, *line_input = &_line_input;
738  u8 is_add = 1;
739  ip46_address_t local, remote;
740  u8 local_set = 0;
741  u8 remote_set = 0;
742  u8 grp_set = 0;
743  u8 ipv4_set = 0;
744  u8 ipv6_set = 0;
745  u32 mcast_sw_if_index = ~0;
746  u32 encap_fib_index = 0;
747  u32 decap_fib_index = 0;
748  u8 protocol = VXLAN_GPE_PROTOCOL_IP4;
749  u32 vni;
750  u8 vni_set = 0;
751  int rv;
752  u32 tmp;
755  clib_error_t *error = NULL;
756 
757  /* Get a line of input. */
758  if (!unformat_user (input, unformat_line_input, line_input))
759  return 0;
760 
761  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
762  {
763  if (unformat (line_input, "del"))
764  is_add = 0;
765  else if (unformat (line_input, "local %U",
766  unformat_ip4_address, &local.ip4))
767  {
768  local_set = 1;
769  ipv4_set = 1;
770  }
771  else if (unformat (line_input, "remote %U",
772  unformat_ip4_address, &remote.ip4))
773  {
774  remote_set = 1;
775  ipv4_set = 1;
776  }
777  else if (unformat (line_input, "local %U",
778  unformat_ip6_address, &local.ip6))
779  {
780  local_set = 1;
781  ipv6_set = 1;
782  }
783  else if (unformat (line_input, "remote %U",
784  unformat_ip6_address, &remote.ip6))
785  {
786  remote_set = 1;
787  ipv6_set = 1;
788  }
789  else if (unformat (line_input, "group %U %U",
790  unformat_ip4_address, &remote.ip4,
792  vnet_get_main (), &mcast_sw_if_index))
793  {
794  grp_set = remote_set = 1;
795  ipv4_set = 1;
796  }
797  else if (unformat (line_input, "group %U %U",
798  unformat_ip6_address, &remote.ip6,
800  vnet_get_main (), &mcast_sw_if_index))
801  {
802  grp_set = remote_set = 1;
803  ipv6_set = 1;
804  }
805  else if (unformat (line_input, "encap-vrf-id %d", &tmp))
806  {
807  if (ipv6_set)
808  encap_fib_index = fib_table_find (FIB_PROTOCOL_IP6, tmp);
809  else
810  encap_fib_index = fib_table_find (FIB_PROTOCOL_IP4, tmp);
811 
812  if (encap_fib_index == ~0)
813  {
814  error =
815  clib_error_return (0, "nonexistent encap fib id %d", tmp);
816  goto done;
817  }
818  }
819  else if (unformat (line_input, "decap-vrf-id %d", &tmp))
820  {
821  if (ipv6_set)
822  decap_fib_index = fib_table_find (FIB_PROTOCOL_IP6, tmp);
823  else
824  decap_fib_index = fib_table_find (FIB_PROTOCOL_IP4, tmp);
825 
826  if (decap_fib_index == ~0)
827  {
828  error =
829  clib_error_return (0, "nonexistent decap fib id %d", tmp);
830  goto done;
831  }
832  }
833  else if (unformat (line_input, "vni %d", &vni))
834  vni_set = 1;
835  else if (unformat (line_input, "next-ip4"))
836  protocol = VXLAN_GPE_PROTOCOL_IP4;
837  else if (unformat (line_input, "next-ip6"))
838  protocol = VXLAN_GPE_PROTOCOL_IP6;
839  else if (unformat (line_input, "next-ethernet"))
840  protocol = VXLAN_GPE_PROTOCOL_ETHERNET;
841  else if (unformat (line_input, "next-nsh"))
842  protocol = VXLAN_GPE_PROTOCOL_NSH;
843  else
844  {
845  error = clib_error_return (0, "parse error: '%U'",
846  format_unformat_error, line_input);
847  goto done;
848  }
849  }
850 
851  if (local_set == 0)
852  {
853  error = clib_error_return (0, "tunnel local address not specified");
854  goto done;
855  }
856 
857  if (remote_set == 0)
858  {
859  error = clib_error_return (0, "tunnel remote address not specified");
860  goto done;
861  }
862 
863  if (grp_set && !ip46_address_is_multicast (&remote))
864  {
865  error = clib_error_return (0, "tunnel group address not multicast");
866  goto done;
867  }
868 
869  if (grp_set == 0 && ip46_address_is_multicast (&remote))
870  {
871  error = clib_error_return (0, "remote address must be unicast");
872  goto done;
873  }
874 
875  if (grp_set && mcast_sw_if_index == ~0)
876  {
877  error = clib_error_return (0, "tunnel nonexistent multicast device");
878  goto done;
879  }
880  if (ipv4_set && ipv6_set)
881  {
882  error = clib_error_return (0, "both IPv4 and IPv6 addresses specified");
883  goto done;
884  }
885 
886  if ((ipv4_set && memcmp (&local.ip4, &remote.ip4, sizeof (local.ip4)) == 0)
887  || (ipv6_set
888  && memcmp (&local.ip6, &remote.ip6, sizeof (local.ip6)) == 0))
889  {
890  error = clib_error_return (0, "src and remote addresses are identical");
891  goto done;
892  }
893 
894  if (vni_set == 0)
895  {
896  error = clib_error_return (0, "vni not specified");
897  goto done;
898  }
899 
900  clib_memset (a, 0, sizeof (*a));
901 
902  a->is_add = is_add;
903  a->is_ip6 = ipv6_set;
904 
905 /* *INDENT-OFF* */
906 #define _(x) a->x = x;
908  if (ipv4_set)
910  else
912 #undef _
913 /* *INDENT-ON* */
914 
915  rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
916 
917  switch (rv)
918  {
919  case 0:
921  vnet_get_main (), sw_if_index);
922  break;
923  case VNET_API_ERROR_INVALID_DECAP_NEXT:
924  error = clib_error_return (0, "invalid decap-next...");
925  goto done;
926 
927  case VNET_API_ERROR_TUNNEL_EXIST:
928  error = clib_error_return (0, "tunnel already exists...");
929  goto done;
930 
931  case VNET_API_ERROR_NO_SUCH_ENTRY:
932  error = clib_error_return (0, "tunnel does not exist...");
933  goto done;
934 
935  default:
936  error = clib_error_return
937  (0, "vnet_vxlan_gpe_add_del_tunnel returned %d", rv);
938  goto done;
939  }
940 
941 done:
942  unformat_free (line_input);
943 
944  return error;
945 }
946 
947 /*?
948  * Add or delete a VXLAN-GPE Tunnel.
949  *
950  * VXLAN-GPE provides the features needed to allow L2 bridge domains (BDs)
951  * to span multiple servers. This is done by building an L2 overlay on
952  * top of an L3 network underlay using VXLAN-GPE tunnels.
953  *
954  * This makes it possible for servers to be co-located in the same data
955  * center or be separated geographically as long as they are reachable
956  * through the underlay L3 network.
957  *
958  * You can refer to this kind of L2 overlay bridge domain as a VXLAN-GPE segment.
959  *
960  * @cliexpar
961  * Example of how to create a VXLAN-GPE Tunnel:
962  * @cliexcmd{create vxlan-gpe tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 encap-vrf-id 7}
963  * Example of how to delete a VXLAN-GPE Tunnel:
964  * @cliexcmd{create vxlan-gpe tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 del}
965  ?*/
966 /* *INDENT-OFF* */
967 VLIB_CLI_COMMAND (create_vxlan_gpe_tunnel_command, static) = {
968  .path = "create vxlan-gpe tunnel",
969  .short_help =
970  "create vxlan-gpe tunnel local <local-addr> "
971  " {remote <remote-addr>|group <mcast-addr> <intf-name>}"
972  " vni <nn> [next-ip4][next-ip6][next-ethernet][next-nsh]"
973  " [encap-vrf-id <nn>] [decap-vrf-id <nn>] [del]\n",
975 };
976 /* *INDENT-ON* */
977 
978 /**
979  * @brief CLI function for showing VXLAN GPE tunnels
980  *
981  * @param *vm
982  * @param *input
983  * @param *cmd
984  *
985  * @return error
986  *
987  */
988 static clib_error_t *
990  unformat_input_t * input,
991  vlib_cli_command_t * cmd)
992 {
995 
996  if (pool_elts (ngm->tunnels) == 0)
997  vlib_cli_output (vm, "No vxlan-gpe tunnels configured.");
998 
999  /* *INDENT-OFF* */
1000  pool_foreach (t, ngm->tunnels,
1001  ({
1002  vlib_cli_output (vm, "%U", format_vxlan_gpe_tunnel, t);
1003  }));
1004  /* *INDENT-ON* */
1005 
1006  return 0;
1007 }
1008 
1009 /*?
1010  * Display all the VXLAN-GPE Tunnel entries.
1011  *
1012  * @cliexpar
1013  * Example of how to display the VXLAN-GPE Tunnel entries:
1014  * @cliexstart{show vxlan-gpe tunnel}
1015  * [0] local 10.0.3.1 remote 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
1016  * @cliexend
1017  ?*/
1018 /* *INDENT-OFF* */
1019 VLIB_CLI_COMMAND (show_vxlan_gpe_tunnel_command, static) = {
1020  .path = "show vxlan-gpe",
1022 };
1023 /* *INDENT-ON* */
1024 
1025 void
1027 {
1028  if (is_ip6)
1029  vnet_feature_enable_disable ("ip6-unicast", "ip6-vxlan-gpe-bypass",
1030  sw_if_index, is_enable, 0, 0);
1031  else
1032  vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-gpe-bypass",
1033  sw_if_index, is_enable, 0, 0);
1034 }
1035 
1036 
1037 static clib_error_t *
1039  unformat_input_t * input, vlib_cli_command_t * cmd)
1040 {
1041  unformat_input_t _line_input, *line_input = &_line_input;
1042  vnet_main_t *vnm = vnet_get_main ();
1043  clib_error_t *error = 0;
1044  u32 sw_if_index, is_enable;
1045 
1046  sw_if_index = ~0;
1047  is_enable = 1;
1048 
1049  if (!unformat_user (input, unformat_line_input, line_input))
1050  return 0;
1051 
1052  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1053  {
1054  if (unformat_user
1055  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1056  ;
1057  else if (unformat (line_input, "del"))
1058  is_enable = 0;
1059  else
1060  {
1061  error = unformat_parse_error (line_input);
1062  goto done;
1063  }
1064  }
1065 
1066  if (~0 == sw_if_index)
1067  {
1068  error = clib_error_return (0, "unknown interface `%U'",
1069  format_unformat_error, line_input);
1070  goto done;
1071  }
1072 
1073  vnet_int_vxlan_gpe_bypass_mode (sw_if_index, is_ip6, is_enable);
1074 
1075 done:
1076  unformat_free (line_input);
1077 
1078  return error;
1079 }
1080 
1081 static clib_error_t *
1083  unformat_input_t * input, vlib_cli_command_t * cmd)
1084 {
1085  return set_ip_vxlan_gpe_bypass (0, input, cmd);
1086 }
1087 
1088 /*?
1089  * This command adds the 'ip4-vxlan-gpe-bypass' graph node for a given interface.
1090  * By adding the IPv4 vxlan-gpe-bypass graph node to an interface, the node checks
1091  * for and validate input vxlan_gpe packet and bypass ip4-lookup, ip4-local,
1092  * ip4-udp-lookup nodes to speedup vxlan_gpe packet forwarding. This node will
1093  * cause extra overhead to for non-vxlan_gpe packets which is kept at a minimum.
1094  *
1095  * @cliexpar
1096  * @parblock
1097  * Example of graph node before ip4-vxlan-gpe-bypass is enabled:
1098  * @cliexstart{show vlib graph ip4-vxlan-gpe-bypass}
1099  * Name Next Previous
1100  * ip4-vxlan-gpe-bypass error-drop [0]
1101  * vxlan4-gpe-input [1]
1102  * ip4-lookup [2]
1103  * @cliexend
1104  *
1105  * Example of how to enable ip4-vxlan-gpe-bypass on an interface:
1106  * @cliexcmd{set interface ip vxlan-gpe-bypass GigabitEthernet2/0/0}
1107  *
1108  * Example of graph node after ip4-vxlan-gpe-bypass is enabled:
1109  * @cliexstart{show vlib graph ip4-vxlan-gpe-bypass}
1110  * Name Next Previous
1111  * ip4-vxlan-gpe-bypass error-drop [0] ip4-input
1112  * vxlan4-gpe-input [1] ip4-input-no-checksum
1113  * ip4-lookup [2]
1114  * @cliexend
1115  *
1116  * Example of how to display the feature enabled on an interface:
1117  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1118  * IP feature paths configured on GigabitEthernet2/0/0...
1119  * ...
1120  * ipv4 unicast:
1121  * ip4-vxlan-gpe-bypass
1122  * ip4-lookup
1123  * ...
1124  * @cliexend
1125  *
1126  * Example of how to disable ip4-vxlan-gpe-bypass on an interface:
1127  * @cliexcmd{set interface ip vxlan-gpe-bypass GigabitEthernet2/0/0 del}
1128  * @endparblock
1129 ?*/
1130 /* *INDENT-OFF* */
1131 VLIB_CLI_COMMAND (set_interface_ip_vxlan_gpe_bypass_command, static) = {
1132  .path = "set interface ip vxlan-gpe-bypass",
1133  .function = set_ip4_vxlan_gpe_bypass,
1134  .short_help = "set interface ip vxlan-gpe-bypass <interface> [del]",
1135 };
1136 /* *INDENT-ON* */
1137 
1138 static clib_error_t *
1140  unformat_input_t * input, vlib_cli_command_t * cmd)
1141 {
1142  return set_ip_vxlan_gpe_bypass (1, input, cmd);
1143 }
1144 
1145 /*?
1146  * This command adds the 'ip6-vxlan-gpe-bypass' graph node for a given interface.
1147  * By adding the IPv6 vxlan-gpe-bypass graph node to an interface, the node checks
1148  * for and validate input vxlan_gpe packet and bypass ip6-lookup, ip6-local,
1149  * ip6-udp-lookup nodes to speedup vxlan_gpe packet forwarding. This node will
1150  * cause extra overhead to for non-vxlan_gpe packets which is kept at a minimum.
1151  *
1152  * @cliexpar
1153  * @parblock
1154  * Example of graph node before ip6-vxlan-gpe-bypass is enabled:
1155  * @cliexstart{show vlib graph ip6-vxlan-gpe-bypass}
1156  * Name Next Previous
1157  * ip6-vxlan-gpe-bypass error-drop [0]
1158  * vxlan6-gpe-input [1]
1159  * ip6-lookup [2]
1160  * @cliexend
1161  *
1162  * Example of how to enable ip6-vxlan-gpe-bypass on an interface:
1163  * @cliexcmd{set interface ip6 vxlan-gpe-bypass GigabitEthernet2/0/0}
1164  *
1165  * Example of graph node after ip6-vxlan-gpe-bypass is enabled:
1166  * @cliexstart{show vlib graph ip6-vxlan-gpe-bypass}
1167  * Name Next Previous
1168  * ip6-vxlan-gpe-bypass error-drop [0] ip6-input
1169  * vxlan6-gpe-input [1] ip4-input-no-checksum
1170  * ip6-lookup [2]
1171  * @cliexend
1172  *
1173  * Example of how to display the feature enabled on an interface:
1174  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1175  * IP feature paths configured on GigabitEthernet2/0/0...
1176  * ...
1177  * ipv6 unicast:
1178  * ip6-vxlan-gpe-bypass
1179  * ip6-lookup
1180  * ...
1181  * @cliexend
1182  *
1183  * Example of how to disable ip6-vxlan-gpe-bypass on an interface:
1184  * @cliexcmd{set interface ip6 vxlan-gpe-bypass GigabitEthernet2/0/0 del}
1185  * @endparblock
1186 ?*/
1187 /* *INDENT-OFF* */
1188 VLIB_CLI_COMMAND (set_interface_ip6_vxlan_gpe_bypass_command, static) = {
1189  .path = "set interface ip6 vxlan-gpe-bypass",
1190  .function = set_ip6_vxlan_gpe_bypass,
1191  .short_help = "set interface ip6 vxlan-gpe-bypass <interface> [del]",
1192 };
1193 /* *INDENT-ON* */
1194 
1195 /* *INDENT-OFF* */
1196 VNET_FEATURE_INIT (ip4_vxlan_gpe_bypass, static) =
1197 {
1198  .arc_name = "ip4-unicast",
1199  .node_name = "ip4-vxlan-gpe-bypass",
1200  .runs_before = VNET_FEATURES ("ip4-lookup"),
1201 };
1202 
1203 VNET_FEATURE_INIT (ip6_vxlan_gpe_bypass, static) =
1204 {
1205  .arc_name = "ip6-unicast",
1206  .node_name = "ip6-vxlan-gpe-bypass",
1207  .runs_before = VNET_FEATURES ("ip6-lookup"),
1208 };
1209 /* *INDENT-ON* */
1210 
1211 /**
1212  * @brief Feature init function for VXLAN GPE
1213  *
1214  * @param *vm
1215  *
1216  * @return error
1217  *
1218  */
1219 clib_error_t *
1221 {
1223 
1224  ngm->vnet_main = vnet_get_main ();
1225  ngm->vlib_main = vm;
1226 
1228  = hash_create_mem (0, sizeof (vxlan4_gpe_tunnel_key_t), sizeof (uword));
1229 
1231  = hash_create_mem (0, sizeof (vxlan6_gpe_tunnel_key_t), sizeof (uword));
1232 
1233 
1234  ngm->mcast_shared = hash_create_mem (0,
1235  sizeof (ip46_address_t),
1236  sizeof (mcast_shared_t));
1237  ngm->vtep_table = vtep_table_create ();
1238 
1239  /* Register the list of standard decap protocols supported */
1240  vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IP4,
1241  VXLAN_GPE_INPUT_NEXT_IP4_INPUT);
1242  vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IP6,
1243  VXLAN_GPE_INPUT_NEXT_IP6_INPUT);
1244  vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_ETHERNET,
1245  VXLAN_GPE_INPUT_NEXT_L2_INPUT);
1246 
1248 
1249  return 0;
1250 }
1251 
1253 
1254 
1255 /*
1256  * fd.io coding-style-patch-verification: ON
1257  *
1258  * Local Variables:
1259  * eval: (c-set-style "gnu")
1260  * End:
1261  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
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
uword * vxlan6_gpe_tunnel_by_key
lookup IPv6 VXLAN GPE tunnel by key
Definition: vxlan_gpe.h:205
u16 vni
Definition: flow_types.api:160
u32 sibling_index
The tunnel is a child of the FIB entry for its destination.
Definition: vxlan_gpe.h:164
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
l2_input_config_t * configs
Definition: l2_input.h:62
uword vtep_addr_ref(vtep_table_t *t, u32 fib_index, ip46_address_t *ip)
Definition: vtep.c:19
static fib_node_back_walk_rc_t vxlan_gpe_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 VXLAN_GPE DIP to enc...
Definition: vxlan_gpe.c:207
static void vxlan_gpe_tunnel_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: vxlan_gpe.c:231
u32 flags
flags
Definition: vxlan_gpe.h:138
clib_error_t * vxlan_gpe_init(vlib_main_t *vm)
Feature init function for VXLAN GPE.
Definition: vxlan_gpe.c:1220
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
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
A representation of a path as described by a route producer.
Definition: fib_types.h:490
ip4_address_t src_address
Definition: ip4_packet.h:125
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vlib_node_registration_t vxlan4_gpe_input_node
(constructor) VLIB_REGISTER_NODE (vxlan4_gpe_input_node)
Definition: decap.c:732
vnet_interface_main_t interface_main
Definition: vnet.h:59
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:559
static mcast_shared_t mcast_shared_get(ip46_address_t *ip)
Definition: geneve.c:317
unsigned long u64
Definition: types.h:89
#define foreach_copy_ipv4
Definition: vxlan_gpe.c:257
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
uword * mcast_shared
Definition: vxlan_gpe.h:211
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 * tunnel_index_by_sw_if_index
Mapping from sw_if_index to tunnel index.
Definition: vxlan_gpe.h:216
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
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
VXLAN GPE definitions.
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:592
int vxlan6_gpe_rewrite(vxlan_gpe_tunnel_t *t, u32 extension_size, u8 protocol_override, uword encap_next_node)
Calculate IPv6 VXLAN GPE rewrite header.
Definition: vxlan_gpe.c:337
vlib_node_registration_t vxlan6_gpe_input_node
(constructor) VLIB_REGISTER_NODE (vxlan6_gpe_input_node)
Definition: decap.c:754
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
#define hash_set_mem(h, key, value)
Definition: hash.h:275
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
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)
vlib_main_t * vm
Definition: in2out_ed.c:1582
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:520
int vnet_vxlan_gpe_add_del_tunnel(vnet_vxlan_gpe_add_del_tunnel_args_t *a, u32 *sw_if_indexp)
Add or Del a VXLAN GPE tunnel.
Definition: vxlan_gpe.c:441
#define VXLAN_GPE_FLAGS_P
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:310
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
vnet_main_t * vnet_main
State convenience vnet_main_t.
Definition: vxlan_gpe.h:221
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
#define VXLAN_GPE_VERSION
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:60
#define VXLAN_GPE_FLAGS_I
vl_api_ip_proto_t protocol
Definition: lb_types.api:71
#define foreach_gpe_copy_field
Definition: vxlan_gpe.c:250
vnet_flood_class_t flood_class
Definition: interface.h:763
static fib_node_t * vxlan_gpe_tunnel_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: vxlan_gpe.c:217
u8 * format_vxlan_gpe_tunnel(u8 *s, va_list *args)
Format function for VXLAN GPE tunnel.
Definition: vxlan_gpe.c:84
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
unformat_function_t unformat_ip4_address
Definition: format.h:68
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:530
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ip46_address_t local
tunnel local address
Definition: vxlan_gpe.h:117
static u8 * format_vxlan_gpe_header_with_length(u8 *s, va_list *args)
Formatting function for tracing VXLAN GPE with length.
Definition: vxlan_gpe.c:165
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:125
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:881
vl_api_interface_index_t mcast_sw_if_index
Definition: vxlan_gbp.api:41
u8 * format_vxlan_gpe_encap_trace(u8 *s, va_list *args)
Trace of packets encapsulated in VXLAN GPE.
Definition: encap.c:69
Aggregate type for a prefix.
Definition: fib_types.h:203
#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:348
#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:1097
void vxlan_gpe_register_decap_protocol(u8 protocol_id, uword next_node_index)
Definition: decap.c:687
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:768
fib_node_index_t fib_entry_index
Definition: vxlan_gpe.h:155
bool is_ip6
Definition: ip.api:43
u8 * rewrite
Rewrite string.
Definition: vxlan_gpe.h:109
VNET_FEATURE_INIT(ip4_vxlan_gpe_bypass, static)
unformat_function_t unformat_line_input
Definition: format.h:283
void vnet_int_vxlan_gpe_bypass_mode(u32 sw_if_index, u8 is_ip6, u8 is_enable)
Definition: vxlan_gpe.c:1026
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
int vxlan4_gpe_rewrite(vxlan_gpe_tunnel_t *t, u32 extension_size, u8 protocol_override, uword encap_next_node)
Calculate IPv4 VXLAN GPE rewrite header.
Definition: vxlan_gpe.c:279
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
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
uword vtep_addr_unref(vtep_table_t *t, u32 fib_index, ip46_address_t *ip)
Definition: vtep.c:34
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
Struct for VXLAN GPE tunnel.
Definition: vxlan_gpe.h:103
long ctx[MAX_CONNS]
Definition: main.c:144
typedef CLIB_PACKED(union { struct { fib_node_index_t mfib_entry_index;adj_index_t mcast_adj_index;};u64 as_u64;})
Definition: vxlan_gpe.c:388
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
static void mcast_shared_remove(ip46_address_t *remote)
Definition: vxlan_gpe.c:421
vxlan_gpe_main_t vxlan_gpe_main
Definition: vxlan_gpe.c:46
static vxlan_gpe_tunnel_t * vxlan_gpe_tunnel_from_fib_node(fib_node_t *node)
Definition: vxlan_gpe.c:194
vlib_main_t * vlib_main
State convenience vlib_main_t.
Definition: vxlan_gpe.h:219
#define PREDICT_FALSE(x)
Definition: clib.h:120
vnet_sw_interface_flags_t flags
Definition: interface.h:738
u8 protocol
encapsulated protocol
Definition: vxlan_gpe.h:112
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:880
static clib_error_t * set_ip4_vxlan_gpe_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan_gpe.c:1082
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:299
An node in the FIB graph.
Definition: fib_node.h:295
vtep_table_t vtep_table
Definition: vxlan_gpe.h:209
ip46_address_t remote
tunnel remote address
Definition: vxlan_gpe.h:119
u32 vni
VXLAN GPE VNI in HOST byte order, shifted left 8 bits.
Definition: vxlan_gpe.h:130
u8 len
Definition: ip_types.api:92
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:246
static clib_error_t * set_ip6_vxlan_gpe_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan_gpe.c:1139
Struct for VXLAN GPE add/del args.
Definition: vxlan_gpe.h:236
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
VNET_DEVICE_CLASS(vxlan_gpe_device_class, static)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
vnet_flood_class_t
Definition: interface.h:679
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:911
fib_node_t node
Linkage into the FIB object graph.
Definition: vxlan_gpe.h:149
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
static u8 * format_vxlan_gpe_name(u8 *s, va_list *args)
Naming for VXLAN GPE tunnel.
Definition: vxlan_gpe.c:118
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
Aggregate type for a prefix.
Definition: mfib_types.h:24
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 placeholder) rewrite.
Definition: interface.c:1639
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:904
static clib_error_t * vxlan_gpe_add_del_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan_gpe.c:733
#define ASSERT(truth)
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
VNET_HW_INTERFACE_CLASS(vxlan_gpe_hw_class)
static clib_error_t * vxlan_gpe_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
CLI function for VXLAN GPE admin up/down.
Definition: vxlan_gpe.c:135
u8 rewrite_size
rewrite size for dynamic plugins like iOAM
Definition: vxlan_gpe.h:141
Struct for VXLAN GPE node state.
Definition: vxlan_gpe.h:197
dpo_id_t next_dpo
Definition: vxlan_gpe.h:115
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:580
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:600
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
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:324
static u8 * format_decap_next(u8 *s, va_list *args)
Definition: vxlan_gpe.c:49
static void * clib_mem_alloc(uword size)
Definition: mem.h:157
#define VNET_FEATURES(...)
Definition: feature.h:470
static vtep_table_t vtep_table_create()
Definition: vtep.h:70
vl_api_ip4_address_t hi
Definition: arp.api:37
vxlan_gpe_tunnel_t * tunnels
vector of encap tunnel instances
Definition: vxlan_gpe.h:200
#define unformat_parse_error(input)
Definition: format.h:269
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
uword * vxlan4_gpe_tunnel_by_key
lookup IPv4 VXLAN GPE tunnel by key
Definition: vxlan_gpe.h:203
l2input_main_t l2input_main
Definition: l2_input.c:127
u32 decap_fib_index
FIB indices - inner IP packet lookup here.
Definition: vxlan_gpe.h:127
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
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:498
static clib_error_t * show_vxlan_gpe_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI function for showing VXLAN GPE tunnels.
Definition: vxlan_gpe.c:989
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
u32 index
Definition: flow_types.api:221
u32 hw_if_index
vnet intfc hw_if_index
Definition: vxlan_gpe.h:133
static void vxlan_gpe_tunnel_restack_dpo(vxlan_gpe_tunnel_t *t)
Definition: vxlan_gpe.c:181
#define hash_get_mem(h, key)
Definition: hash.h:269
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
u32 encap_fib_index
FIB indices - tunnel partner lookup here.
Definition: vxlan_gpe.h:125
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
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:507
uword encap_next_node
Next node after VxLAN-GPE encap.
Definition: vxlan_gpe.h:144
u32 sw_if_index
vnet intfc sw_if_index
Definition: vxlan_gpe.h:135
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
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:358
static void mcast_shared_add(ip46_address_t *remote, fib_node_index_t mfei, adj_index_t ai)
Definition: vxlan_gpe.c:409
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:468
u8 si
Definition: lisp_types.api:47
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
vlib_node_registration_t vxlan_gpe_encap_node
(constructor) VLIB_REGISTER_NODE (vxlan_gpe_encap_node)
Definition: encap.c:402
#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:556
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define VXLAN_GPE_TUNNEL_IS_IPV4
Flags for vxlan_gpe_tunnel_t.
Definition: vxlan_gpe.h:169
static clib_error_t * set_ip_vxlan_gpe_bypass(u32 is_ip6, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan_gpe.c:1038
#define foreach_copy_ipv6
Definition: vxlan_gpe.c:262
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
const ip46_address_t zero_addr
Definition: lookup.c:181
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
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:303
ip6_address_t dst_address
Definition: ip6_packet.h:310
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
u32 * free_vxlan_gpe_tunnel_hw_if_indices
Free vlib hw_if_indices.
Definition: vxlan_gpe.h:213
#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