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