FD.io VPP  v20.01-48-g3e0dafb74
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 static uword
388 vtep_addr_ref (ip46_address_t * ip)
389 {
390  uword *vtep = ip46_address_is_ip4 (ip) ?
391  hash_get (vxlan_gpe_main.vtep4, ip->ip4.as_u32) :
392  hash_get_mem (vxlan_gpe_main.vtep6, &ip->ip6);
393  if (vtep)
394  return ++(*vtep);
395  ip46_address_is_ip4 (ip) ?
396  hash_set (vxlan_gpe_main.vtep4, ip->ip4.as_u32, 1) :
397  hash_set_mem_alloc (&vxlan_gpe_main.vtep6, &ip->ip6, 1);
398  return 1;
399 }
400 
401 static uword
402 vtep_addr_unref (ip46_address_t * ip)
403 {
404  uword *vtep = ip46_address_is_ip4 (ip) ?
405  hash_get (vxlan_gpe_main.vtep4, ip->ip4.as_u32) :
406  hash_get_mem (vxlan_gpe_main.vtep6, &ip->ip6);
407  ASSERT (vtep);
408  if (--(*vtep) != 0)
409  return *vtep;
410  ip46_address_is_ip4 (ip) ?
411  hash_unset (vxlan_gpe_main.vtep4, ip->ip4.as_u32) :
412  hash_unset_mem_free (&vxlan_gpe_main.vtep6, &ip->ip6);
413  return 0;
414 }
415 
416 /* *INDENT-OFF* */
417 typedef CLIB_PACKED(union {
418  struct {
419  fib_node_index_t mfib_entry_index;
420  adj_index_t mcast_adj_index;
421  };
422  u64 as_u64;
423 }) mcast_shared_t;
424 /* *INDENT-ON* */
425 
426 static inline mcast_shared_t
427 mcast_shared_get (ip46_address_t * ip)
428 {
430  uword *p = hash_get_mem (vxlan_gpe_main.mcast_shared, ip);
431  ASSERT (p);
432  return (mcast_shared_t)
433  {
434  .as_u64 = *p};
435 }
436 
437 static inline void
438 mcast_shared_add (ip46_address_t * remote,
439  fib_node_index_t mfei, adj_index_t ai)
440 {
441  mcast_shared_t new_ep = {
442  .mcast_adj_index = ai,
443  .mfib_entry_index = mfei,
444  };
445 
446  hash_set_mem_alloc (&vxlan_gpe_main.mcast_shared, remote, new_ep.as_u64);
447 }
448 
449 static inline void
450 mcast_shared_remove (ip46_address_t * remote)
451 {
452  mcast_shared_t ep = mcast_shared_get (remote);
453 
454  adj_unlock (ep.mcast_adj_index);
456 
457  hash_unset_mem_free (&vxlan_gpe_main.mcast_shared, remote);
458 }
459 
460 /**
461  * @brief Add or Del a VXLAN GPE tunnel
462  *
463  * @param *a
464  * @param *sw_if_index
465  *
466  * @return rc
467  *
468  */
471 {
473  vxlan_gpe_tunnel_t *t = 0;
474  vnet_main_t *vnm = ngm->vnet_main;
476  uword *p;
477  u32 hw_if_index = ~0;
478  u32 sw_if_index = ~0;
479  int rv;
480  vxlan4_gpe_tunnel_key_t key4, *key4_copy;
481  vxlan6_gpe_tunnel_key_t key6, *key6_copy;
482  u32 is_ip6 = a->is_ip6;
483 
484  if (!is_ip6)
485  {
486  key4.local = a->local.ip4.as_u32;
487  key4.remote = a->remote.ip4.as_u32;
488  key4.vni = clib_host_to_net_u32 (a->vni << 8);
489  key4.pad = 0;
490 
491  p = hash_get_mem (ngm->vxlan4_gpe_tunnel_by_key, &key4);
492  }
493  else
494  {
495  key6.local.as_u64[0] = a->local.ip6.as_u64[0];
496  key6.local.as_u64[1] = a->local.ip6.as_u64[1];
497  key6.remote.as_u64[0] = a->remote.ip6.as_u64[0];
498  key6.remote.as_u64[1] = a->remote.ip6.as_u64[1];
499  key6.vni = clib_host_to_net_u32 (a->vni << 8);
500 
501  p = hash_get_mem (ngm->vxlan6_gpe_tunnel_by_key, &key6);
502  }
503 
504  if (a->is_add)
505  {
506  l2input_main_t *l2im = &l2input_main;
507 
508  /* adding a tunnel: tunnel must not already exist */
509  if (p)
510  return VNET_API_ERROR_TUNNEL_EXIST;
511 
513  clib_memset (t, 0, sizeof (*t));
514 
515  /* copy from arg structure */
516 /* *INDENT-OFF* */
517 #define _(x) t->x = a->x;
519  if (!a->is_ip6)
521  else
523 #undef _
524 /* *INDENT-ON* */
525 
526  if (!a->is_ip6)
528 
529  if (!a->is_ip6)
530  {
532  }
533  else
534  {
536  }
537 
538  if (rv)
539  {
540  pool_put (ngm->tunnels, t);
541  return rv;
542  }
543 
544  if (!is_ip6)
545  {
546  key4_copy = clib_mem_alloc (sizeof (*key4_copy));
547  clib_memcpy_fast (key4_copy, &key4, sizeof (*key4_copy));
548  hash_set_mem (ngm->vxlan4_gpe_tunnel_by_key, key4_copy,
549  t - ngm->tunnels);
550  }
551  else
552  {
553  key6_copy = clib_mem_alloc (sizeof (*key6_copy));
554  clib_memcpy_fast (key6_copy, &key6, sizeof (*key6_copy));
555  hash_set_mem (ngm->vxlan6_gpe_tunnel_by_key, key6_copy,
556  t - ngm->tunnels);
557  }
558 
560  {
562  hw_if_index = ngm->free_vxlan_gpe_tunnel_hw_if_indices
564  _vec_len (ngm->free_vxlan_gpe_tunnel_hw_if_indices) -= 1;
565 
566  hi = vnet_get_hw_interface (vnm, hw_if_index);
567  hi->dev_instance = t - ngm->tunnels;
568  hi->hw_instance = hi->dev_instance;
569  /* clear old stats of freed tunnel before reuse */
570  sw_if_index = hi->sw_if_index;
574  sw_if_index);
577  sw_if_index);
580  sw_if_index);
582  }
583  else
584  {
585  hw_if_index = vnet_register_interface
586  (vnm, vxlan_gpe_device_class.index, t - ngm->tunnels,
587  vxlan_gpe_hw_class.index, t - ngm->tunnels);
588  hi = vnet_get_hw_interface (vnm, hw_if_index);
589  }
590 
591  /* Set vxlan-gpe tunnel output node */
592  u32 encap_index = vxlan_gpe_encap_node.index;
593  vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
594 
595  t->hw_if_index = hw_if_index;
596  t->sw_if_index = sw_if_index = hi->sw_if_index;
598  ~0);
600 
601  /* setup l2 input config with l2 feature and bd 0 to drop packet */
602  vec_validate (l2im->configs, sw_if_index);
603  l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
604  l2im->configs[sw_if_index].bd_index = 0;
605 
606  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
611  fib_prefix_t tun_remote_pfx;
613 
614  fib_prefix_from_ip46_addr (&t->remote, &tun_remote_pfx);
616  {
617  /* Unicast tunnel -
618  * source the FIB entry for the tunnel's destination
619  * and become a child thereof. The tunnel will then get poked
620  * when the forwarding for the entry updates, and the tunnel can
621  * re-stack accordingly
622  */
623  vtep_addr_ref (&t->local);
625  &tun_remote_pfx,
627  t - ngm->tunnels,
628  &t->sibling_index);
630  }
631  else
632  {
633  /* Multicast tunnel -
634  * as the same mcast group can be used for multiple mcast tunnels
635  * with different VNIs, create the output fib adjacency only if
636  * it does not already exist
637  */
638  fib_protocol_t fp = fib_ip_proto (is_ip6);
639 
640  if (vtep_addr_ref (&t->remote) == 1)
641  {
642  fib_node_index_t mfei;
643  adj_index_t ai;
645  .frp_proto = fib_proto_to_dpo (fp),
646  .frp_addr = zero_addr,
647  .frp_sw_if_index = 0xffffffff,
648  .frp_fib_index = ~0,
649  .frp_weight = 1,
650  .frp_flags = FIB_ROUTE_PATH_LOCAL,
651  .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
652  };
653  const mfib_prefix_t mpfx = {
654  .fp_proto = fp,
655  .fp_len = (is_ip6 ? 128 : 32),
656  .fp_grp_addr = tun_remote_pfx.fp_addr,
657  };
658 
659  /*
660  * Setup the (*,G) to receive traffic on the mcast group
661  * - the forwarding interface is for-us
662  * - the accepting interface is that from the API
663  */
665  &mpfx,
666  MFIB_SOURCE_VXLAN_GPE, &path);
667 
672  &mpfx,
674  &path);
675 
676  /*
677  * Create the mcast adjacency to send traffic to the group
678  */
679  ai = adj_mcast_add_or_lock (fp,
680  fib_proto_to_link (fp),
681  a->mcast_sw_if_index);
682 
683  /*
684  * create a new end-point
685  */
686  mcast_shared_add (&t->remote, mfei, ai);
687  }
688 
689  dpo_id_t dpo = DPO_INVALID;
690  mcast_shared_t ep = mcast_shared_get (&t->remote);
691 
692  /* Stack shared mcast remote mac addr rewrite on encap */
694  fib_proto_to_dpo (fp), ep.mcast_adj_index);
695 
696  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
697  dpo_reset (&dpo);
698  flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
699  }
700 
701  vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
702  flood_class;
703  }
704  else
705  {
706  /* deleting a tunnel: tunnel must exist */
707  if (!p)
708  return VNET_API_ERROR_NO_SUCH_ENTRY;
709 
710  t = pool_elt_at_index (ngm->tunnels, p[0]);
711 
712  sw_if_index = t->sw_if_index;
713  vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */ );
716  set_int_l2_mode (ngm->vlib_main, vnm, MODE_L3, t->sw_if_index, 0,
717  L2_BD_PORT_TYPE_NORMAL, 0, 0);
719 
721 
722  if (!is_ip6)
723  hash_unset (ngm->vxlan4_gpe_tunnel_by_key, key4.as_u64);
724  else
726 
728  {
729  vtep_addr_unref (&t->local);
731  }
732  else if (vtep_addr_unref (&t->remote) == 0)
733  {
735  }
736 
737  fib_node_deinit (&t->node);
738  vec_free (t->rewrite);
739  pool_put (ngm->tunnels, t);
740  }
741 
742  if (sw_if_indexp)
743  *sw_if_indexp = sw_if_index;
744 
745  if (a->is_add)
746  {
747  /* register udp ports */
748  if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_VXLAN_GPE, 1))
749  udp_register_dst_port (ngm->vlib_main, UDP_DST_PORT_VXLAN_GPE,
750  vxlan4_gpe_input_node.index, 1 /* is_ip4 */ );
751  if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_VXLAN6_GPE, 0))
752  udp_register_dst_port (ngm->vlib_main, UDP_DST_PORT_VXLAN6_GPE,
753  vxlan6_gpe_input_node.index, 0 /* is_ip4 */ );
754  }
755 
756  return 0;
757 }
758 
759 static clib_error_t *
761  unformat_input_t * input,
762  vlib_cli_command_t * cmd)
763 {
764  unformat_input_t _line_input, *line_input = &_line_input;
765  u8 is_add = 1;
766  ip46_address_t local, remote;
767  u8 local_set = 0;
768  u8 remote_set = 0;
769  u8 grp_set = 0;
770  u8 ipv4_set = 0;
771  u8 ipv6_set = 0;
772  u32 mcast_sw_if_index = ~0;
773  u32 encap_fib_index = 0;
774  u32 decap_fib_index = 0;
775  u8 protocol = VXLAN_GPE_PROTOCOL_IP4;
776  u32 vni;
777  u8 vni_set = 0;
778  int rv;
779  u32 tmp;
782  clib_error_t *error = NULL;
783 
784  /* Get a line of input. */
785  if (!unformat_user (input, unformat_line_input, line_input))
786  return 0;
787 
788  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
789  {
790  if (unformat (line_input, "del"))
791  is_add = 0;
792  else if (unformat (line_input, "local %U",
793  unformat_ip4_address, &local.ip4))
794  {
795  local_set = 1;
796  ipv4_set = 1;
797  }
798  else if (unformat (line_input, "remote %U",
799  unformat_ip4_address, &remote.ip4))
800  {
801  remote_set = 1;
802  ipv4_set = 1;
803  }
804  else if (unformat (line_input, "local %U",
805  unformat_ip6_address, &local.ip6))
806  {
807  local_set = 1;
808  ipv6_set = 1;
809  }
810  else if (unformat (line_input, "remote %U",
811  unformat_ip6_address, &remote.ip6))
812  {
813  remote_set = 1;
814  ipv6_set = 1;
815  }
816  else if (unformat (line_input, "group %U %U",
817  unformat_ip4_address, &remote.ip4,
819  vnet_get_main (), &mcast_sw_if_index))
820  {
821  grp_set = remote_set = 1;
822  ipv4_set = 1;
823  }
824  else if (unformat (line_input, "group %U %U",
825  unformat_ip6_address, &remote.ip6,
827  vnet_get_main (), &mcast_sw_if_index))
828  {
829  grp_set = remote_set = 1;
830  ipv6_set = 1;
831  }
832  else if (unformat (line_input, "encap-vrf-id %d", &tmp))
833  {
834  if (ipv6_set)
835  encap_fib_index = fib_table_find (FIB_PROTOCOL_IP6, tmp);
836  else
837  encap_fib_index = fib_table_find (FIB_PROTOCOL_IP4, tmp);
838 
839  if (encap_fib_index == ~0)
840  {
841  error =
842  clib_error_return (0, "nonexistent encap fib id %d", tmp);
843  goto done;
844  }
845  }
846  else if (unformat (line_input, "decap-vrf-id %d", &tmp))
847  {
848  if (ipv6_set)
849  decap_fib_index = fib_table_find (FIB_PROTOCOL_IP6, tmp);
850  else
851  decap_fib_index = fib_table_find (FIB_PROTOCOL_IP4, tmp);
852 
853  if (decap_fib_index == ~0)
854  {
855  error =
856  clib_error_return (0, "nonexistent decap fib id %d", tmp);
857  goto done;
858  }
859  }
860  else if (unformat (line_input, "vni %d", &vni))
861  vni_set = 1;
862  else if (unformat (line_input, "next-ip4"))
863  protocol = VXLAN_GPE_PROTOCOL_IP4;
864  else if (unformat (line_input, "next-ip6"))
865  protocol = VXLAN_GPE_PROTOCOL_IP6;
866  else if (unformat (line_input, "next-ethernet"))
867  protocol = VXLAN_GPE_PROTOCOL_ETHERNET;
868  else if (unformat (line_input, "next-nsh"))
869  protocol = VXLAN_GPE_PROTOCOL_NSH;
870  else
871  {
872  error = clib_error_return (0, "parse error: '%U'",
873  format_unformat_error, line_input);
874  goto done;
875  }
876  }
877 
878  if (local_set == 0)
879  {
880  error = clib_error_return (0, "tunnel local address not specified");
881  goto done;
882  }
883 
884  if (remote_set == 0)
885  {
886  error = clib_error_return (0, "tunnel remote address not specified");
887  goto done;
888  }
889 
890  if (grp_set && !ip46_address_is_multicast (&remote))
891  {
892  error = clib_error_return (0, "tunnel group address not multicast");
893  goto done;
894  }
895 
896  if (grp_set == 0 && ip46_address_is_multicast (&remote))
897  {
898  error = clib_error_return (0, "remote address must be unicast");
899  goto done;
900  }
901 
902  if (grp_set && mcast_sw_if_index == ~0)
903  {
904  error = clib_error_return (0, "tunnel nonexistent multicast device");
905  goto done;
906  }
907  if (ipv4_set && ipv6_set)
908  {
909  error = clib_error_return (0, "both IPv4 and IPv6 addresses specified");
910  goto done;
911  }
912 
913  if ((ipv4_set && memcmp (&local.ip4, &remote.ip4, sizeof (local.ip4)) == 0)
914  || (ipv6_set
915  && memcmp (&local.ip6, &remote.ip6, sizeof (local.ip6)) == 0))
916  {
917  error = clib_error_return (0, "src and remote addresses are identical");
918  goto done;
919  }
920 
921  if (vni_set == 0)
922  {
923  error = clib_error_return (0, "vni not specified");
924  goto done;
925  }
926 
927  clib_memset (a, 0, sizeof (*a));
928 
929  a->is_add = is_add;
930  a->is_ip6 = ipv6_set;
931 
932 /* *INDENT-OFF* */
933 #define _(x) a->x = x;
935  if (ipv4_set)
937  else
939 #undef _
940 /* *INDENT-ON* */
941 
942  rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
943 
944  switch (rv)
945  {
946  case 0:
948  vnet_get_main (), sw_if_index);
949  break;
950  case VNET_API_ERROR_INVALID_DECAP_NEXT:
951  error = clib_error_return (0, "invalid decap-next...");
952  goto done;
953 
954  case VNET_API_ERROR_TUNNEL_EXIST:
955  error = clib_error_return (0, "tunnel already exists...");
956  goto done;
957 
958  case VNET_API_ERROR_NO_SUCH_ENTRY:
959  error = clib_error_return (0, "tunnel does not exist...");
960  goto done;
961 
962  default:
963  error = clib_error_return
964  (0, "vnet_vxlan_gpe_add_del_tunnel returned %d", rv);
965  goto done;
966  }
967 
968 done:
969  unformat_free (line_input);
970 
971  return error;
972 }
973 
974 /*?
975  * Add or delete a VXLAN-GPE Tunnel.
976  *
977  * VXLAN-GPE provides the features needed to allow L2 bridge domains (BDs)
978  * to span multiple servers. This is done by building an L2 overlay on
979  * top of an L3 network underlay using VXLAN-GPE tunnels.
980  *
981  * This makes it possible for servers to be co-located in the same data
982  * center or be separated geographically as long as they are reachable
983  * through the underlay L3 network.
984  *
985  * You can refer to this kind of L2 overlay bridge domain as a VXLAN-GPE segment.
986  *
987  * @cliexpar
988  * Example of how to create a VXLAN-GPE Tunnel:
989  * @cliexcmd{create vxlan-gpe tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 encap-vrf-id 7}
990  * Example of how to delete a VXLAN-GPE Tunnel:
991  * @cliexcmd{create vxlan-gpe tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 del}
992  ?*/
993 /* *INDENT-OFF* */
994 VLIB_CLI_COMMAND (create_vxlan_gpe_tunnel_command, static) = {
995  .path = "create vxlan-gpe tunnel",
996  .short_help =
997  "create vxlan-gpe tunnel local <local-addr> "
998  " {remote <remote-addr>|group <mcast-addr> <intf-name>}"
999  " vni <nn> [next-ip4][next-ip6][next-ethernet][next-nsh]"
1000  " [encap-vrf-id <nn>] [decap-vrf-id <nn>] [del]\n",
1002 };
1003 /* *INDENT-ON* */
1004 
1005 /**
1006  * @brief CLI function for showing VXLAN GPE tunnels
1007  *
1008  * @param *vm
1009  * @param *input
1010  * @param *cmd
1011  *
1012  * @return error
1013  *
1014  */
1015 static clib_error_t *
1017  unformat_input_t * input,
1018  vlib_cli_command_t * cmd)
1019 {
1021  vxlan_gpe_tunnel_t *t;
1022 
1023  if (pool_elts (ngm->tunnels) == 0)
1024  vlib_cli_output (vm, "No vxlan-gpe tunnels configured.");
1025 
1026  /* *INDENT-OFF* */
1027  pool_foreach (t, ngm->tunnels,
1028  ({
1029  vlib_cli_output (vm, "%U", format_vxlan_gpe_tunnel, t);
1030  }));
1031  /* *INDENT-ON* */
1032 
1033  return 0;
1034 }
1035 
1036 /*?
1037  * Display all the VXLAN-GPE Tunnel entries.
1038  *
1039  * @cliexpar
1040  * Example of how to display the VXLAN-GPE Tunnel entries:
1041  * @cliexstart{show vxlan-gpe tunnel}
1042  * [0] local 10.0.3.1 remote 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
1043  * @cliexend
1044  ?*/
1045 /* *INDENT-OFF* */
1046 VLIB_CLI_COMMAND (show_vxlan_gpe_tunnel_command, static) = {
1047  .path = "show vxlan-gpe",
1049 };
1050 /* *INDENT-ON* */
1051 
1052 void
1054 {
1055  if (is_ip6)
1056  vnet_feature_enable_disable ("ip6-unicast", "ip6-vxlan-gpe-bypass",
1057  sw_if_index, is_enable, 0, 0);
1058  else
1059  vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-gpe-bypass",
1060  sw_if_index, is_enable, 0, 0);
1061 }
1062 
1063 
1064 static clib_error_t *
1066  unformat_input_t * input, vlib_cli_command_t * cmd)
1067 {
1068  unformat_input_t _line_input, *line_input = &_line_input;
1069  vnet_main_t *vnm = vnet_get_main ();
1070  clib_error_t *error = 0;
1071  u32 sw_if_index, is_enable;
1072 
1073  sw_if_index = ~0;
1074  is_enable = 1;
1075 
1076  if (!unformat_user (input, unformat_line_input, line_input))
1077  return 0;
1078 
1079  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1080  {
1081  if (unformat_user
1082  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1083  ;
1084  else if (unformat (line_input, "del"))
1085  is_enable = 0;
1086  else
1087  {
1088  error = unformat_parse_error (line_input);
1089  goto done;
1090  }
1091  }
1092 
1093  if (~0 == sw_if_index)
1094  {
1095  error = clib_error_return (0, "unknown interface `%U'",
1096  format_unformat_error, line_input);
1097  goto done;
1098  }
1099 
1100  vnet_int_vxlan_gpe_bypass_mode (sw_if_index, is_ip6, is_enable);
1101 
1102 done:
1103  unformat_free (line_input);
1104 
1105  return error;
1106 }
1107 
1108 static clib_error_t *
1110  unformat_input_t * input, vlib_cli_command_t * cmd)
1111 {
1112  return set_ip_vxlan_gpe_bypass (0, input, cmd);
1113 }
1114 
1115 /*?
1116  * This command adds the 'ip4-vxlan-gpe-bypass' graph node for a given interface.
1117  * By adding the IPv4 vxlan-gpe-bypass graph node to an interface, the node checks
1118  * for and validate input vxlan_gpe packet and bypass ip4-lookup, ip4-local,
1119  * ip4-udp-lookup nodes to speedup vxlan_gpe packet forwarding. This node will
1120  * cause extra overhead to for non-vxlan_gpe packets which is kept at a minimum.
1121  *
1122  * @cliexpar
1123  * @parblock
1124  * Example of graph node before ip4-vxlan-gpe-bypass is enabled:
1125  * @cliexstart{show vlib graph ip4-vxlan-gpe-bypass}
1126  * Name Next Previous
1127  * ip4-vxlan-gpe-bypass error-drop [0]
1128  * vxlan4-gpe-input [1]
1129  * ip4-lookup [2]
1130  * @cliexend
1131  *
1132  * Example of how to enable ip4-vxlan-gpe-bypass on an interface:
1133  * @cliexcmd{set interface ip vxlan-gpe-bypass GigabitEthernet2/0/0}
1134  *
1135  * Example of graph node after ip4-vxlan-gpe-bypass is enabled:
1136  * @cliexstart{show vlib graph ip4-vxlan-gpe-bypass}
1137  * Name Next Previous
1138  * ip4-vxlan-gpe-bypass error-drop [0] ip4-input
1139  * vxlan4-gpe-input [1] ip4-input-no-checksum
1140  * ip4-lookup [2]
1141  * @cliexend
1142  *
1143  * Example of how to display the feature enabled on an interface:
1144  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1145  * IP feature paths configured on GigabitEthernet2/0/0...
1146  * ...
1147  * ipv4 unicast:
1148  * ip4-vxlan-gpe-bypass
1149  * ip4-lookup
1150  * ...
1151  * @cliexend
1152  *
1153  * Example of how to disable ip4-vxlan-gpe-bypass on an interface:
1154  * @cliexcmd{set interface ip vxlan-gpe-bypass GigabitEthernet2/0/0 del}
1155  * @endparblock
1156 ?*/
1157 /* *INDENT-OFF* */
1158 VLIB_CLI_COMMAND (set_interface_ip_vxlan_gpe_bypass_command, static) = {
1159  .path = "set interface ip vxlan-gpe-bypass",
1160  .function = set_ip4_vxlan_gpe_bypass,
1161  .short_help = "set interface ip vxlan-gpe-bypass <interface> [del]",
1162 };
1163 /* *INDENT-ON* */
1164 
1165 static clib_error_t *
1167  unformat_input_t * input, vlib_cli_command_t * cmd)
1168 {
1169  return set_ip_vxlan_gpe_bypass (1, input, cmd);
1170 }
1171 
1172 /*?
1173  * This command adds the 'ip6-vxlan-gpe-bypass' graph node for a given interface.
1174  * By adding the IPv6 vxlan-gpe-bypass graph node to an interface, the node checks
1175  * for and validate input vxlan_gpe packet and bypass ip6-lookup, ip6-local,
1176  * ip6-udp-lookup nodes to speedup vxlan_gpe packet forwarding. This node will
1177  * cause extra overhead to for non-vxlan_gpe packets which is kept at a minimum.
1178  *
1179  * @cliexpar
1180  * @parblock
1181  * Example of graph node before ip6-vxlan-gpe-bypass is enabled:
1182  * @cliexstart{show vlib graph ip6-vxlan-gpe-bypass}
1183  * Name Next Previous
1184  * ip6-vxlan-gpe-bypass error-drop [0]
1185  * vxlan6-gpe-input [1]
1186  * ip6-lookup [2]
1187  * @cliexend
1188  *
1189  * Example of how to enable ip6-vxlan-gpe-bypass on an interface:
1190  * @cliexcmd{set interface ip6 vxlan-gpe-bypass GigabitEthernet2/0/0}
1191  *
1192  * Example of graph node after ip6-vxlan-gpe-bypass is enabled:
1193  * @cliexstart{show vlib graph ip6-vxlan-gpe-bypass}
1194  * Name Next Previous
1195  * ip6-vxlan-gpe-bypass error-drop [0] ip6-input
1196  * vxlan6-gpe-input [1] ip4-input-no-checksum
1197  * ip6-lookup [2]
1198  * @cliexend
1199  *
1200  * Example of how to display the feature enabled on an interface:
1201  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1202  * IP feature paths configured on GigabitEthernet2/0/0...
1203  * ...
1204  * ipv6 unicast:
1205  * ip6-vxlan-gpe-bypass
1206  * ip6-lookup
1207  * ...
1208  * @cliexend
1209  *
1210  * Example of how to disable ip6-vxlan-gpe-bypass on an interface:
1211  * @cliexcmd{set interface ip6 vxlan-gpe-bypass GigabitEthernet2/0/0 del}
1212  * @endparblock
1213 ?*/
1214 /* *INDENT-OFF* */
1215 VLIB_CLI_COMMAND (set_interface_ip6_vxlan_gpe_bypass_command, static) = {
1216  .path = "set interface ip6 vxlan-gpe-bypass",
1217  .function = set_ip6_vxlan_gpe_bypass,
1218  .short_help = "set interface ip6 vxlan-gpe-bypass <interface> [del]",
1219 };
1220 /* *INDENT-ON* */
1221 
1222 /* *INDENT-OFF* */
1223 VNET_FEATURE_INIT (ip4_vxlan_gpe_bypass, static) =
1224 {
1225  .arc_name = "ip4-unicast",
1226  .node_name = "ip4-vxlan-gpe-bypass",
1227  .runs_before = VNET_FEATURES ("ip4-lookup"),
1228 };
1229 
1230 VNET_FEATURE_INIT (ip6_vxlan_gpe_bypass, static) =
1231 {
1232  .arc_name = "ip6-unicast",
1233  .node_name = "ip6-vxlan-gpe-bypass",
1234  .runs_before = VNET_FEATURES ("ip6-lookup"),
1235 };
1236 /* *INDENT-ON* */
1237 
1238 /**
1239  * @brief Feature init function for VXLAN GPE
1240  *
1241  * @param *vm
1242  *
1243  * @return error
1244  *
1245  */
1246 clib_error_t *
1248 {
1250 
1251  ngm->vnet_main = vnet_get_main ();
1252  ngm->vlib_main = vm;
1253 
1255  = hash_create_mem (0, sizeof (vxlan4_gpe_tunnel_key_t), sizeof (uword));
1256 
1258  = hash_create_mem (0, sizeof (vxlan6_gpe_tunnel_key_t), sizeof (uword));
1259 
1260 
1261  ngm->mcast_shared = hash_create_mem (0,
1262  sizeof (ip46_address_t),
1263  sizeof (mcast_shared_t));
1264  ngm->vtep6 = hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword));
1265 
1266  /* Register the list of standard decap protocols supported */
1267  vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IP4,
1268  VXLAN_GPE_INPUT_NEXT_IP4_INPUT);
1269  vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_IP6,
1270  VXLAN_GPE_INPUT_NEXT_IP6_INPUT);
1271  vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_ETHERNET,
1272  VXLAN_GPE_INPUT_NEXT_L2_INPUT);
1273 
1275 
1276  return 0;
1277 }
1278 
1280 
1281 
1282 /*
1283  * fd.io coding-style-patch-verification: ON
1284  *
1285  * Local Variables:
1286  * eval: (c-set-style "gnu")
1287  * End:
1288  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
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:204
u32 sibling_index
The tunnel is a child of the FIB entry for its destination.
Definition: vxlan_gpe.h:163
fib_node_index_t fib_entry_track(u32 fib_index, const fib_prefix_t *prefix, fib_node_type_t child_type, index_t child_index, u32 *sibling)
Trackers are used on FIB entries by objects that which to track the changing state of the entry...
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:113
#define hash_set(h, key, value)
Definition: hash.h:255
l2_input_config_t * configs
Definition: l2_input.h:62
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:137
clib_error_t * vxlan_gpe_init(vlib_main_t *vm)
Feature init function for VXLAN GPE.
Definition: vxlan_gpe.c:1247
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
A representation of a path as described by a route producer.
Definition: fib_types.h:485
ip4_address_t src_address
Definition: ip4_packet.h:170
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
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:56
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
u64 as_u64
Definition: bihash_doc.h:63
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath)
Add n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:325
u32 frp_mitf_flags
MFIB interface flags.
Definition: fib_types.h:554
static mcast_shared_t mcast_shared_get(ip46_address_t *ip)
Definition: geneve.c:335
u64 as_u64[2]
Definition: ip6_packet.h:51
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
#define NULL
Definition: clib.h:58
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:523
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:65
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:197
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
vl_api_fib_path_t path
Definition: mfib_types.api:34
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:451
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:470
#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:307
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:745
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:498
unformat_function_t unformat_ip4_address
Definition: format.h:68
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:525
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ip46_address_t local
tunnel local address
Definition: vxlan_gpe.h:116
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:170
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:863
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
static uword vtep_addr_unref(ip46_address_t *ip)
Definition: vxlan_gpe.c:402
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:324
unsigned int u32
Definition: types.h:88
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1097
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:762
fib_node_index_t fib_entry_index
Definition: vxlan_gpe.h:154
bool is_ip6
Definition: ip.api:43
u8 * rewrite
Rewrite string.
Definition: vxlan_gpe.h:108
VNET_FEATURE_INIT(ip4_vxlan_gpe_bypass, static)
static uword vtep_addr_ref(ip46_address_t *ip)
Definition: vxlan_gpe.c:388
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:1053
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
#define hash_get(h, key)
Definition: hash.h:249
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:519
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread counters.
Definition: counter.h:285
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:102
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:417
struct _unformat_input_t unformat_input_t
u32 vni
Definition: lisp_gpe.api:129
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
static void mcast_shared_remove(ip46_address_t *remote)
Definition: vxlan_gpe.c:450
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:111
vnet_sw_interface_flags_t flags
Definition: interface.h:720
u8 protocol
encapsulated protocol
Definition: vxlan_gpe.h:111
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:862
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:1109
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
ip46_address_t remote
tunnel remote address
Definition: vxlan_gpe.h:118
vlib_main_t * vm
Definition: in2out_ed.c:1810
u32 vni
VXLAN GPE VNI in HOST byte order, shifted left 8 bits.
Definition: vxlan_gpe.h:129
u8 len
Definition: ip_types.api:91
format_function_t format_ip46_address
Definition: ip46_address.h:50
unformat_function_t unformat_ip6_address
Definition: format.h:89
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:231
static 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:1166
Struct for VXLAN GPE add/del args.
Definition: vxlan_gpe.h:236
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:141
VNET_DEVICE_CLASS(vxlan_gpe_device_class, static)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
vnet_flood_class_t
Definition: interface.h:661
fib_node_get_t fnv_get
Definition: fib_node.h:283
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:893
fib_node_t node
Linkage into the FIB object graph.
Definition: vxlan_gpe.h:148
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
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
u8 * default_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Return a complete, zero-length (aka dummy) rewrite.
Definition: interface.c:1629
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:886
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:760
#define ASSERT(truth)
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
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:140
Struct for VXLAN GPE node state.
Definition: vxlan_gpe.h:196
dpo_id_t next_dpo
Definition: vxlan_gpe.h:114
u32 set_int_l2_mode(vlib_main_t *vm, vnet_main_t *vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, l2_bd_port_type_t port_type, u32 shg, u32 xc_sw_if_index)
Set the subinterface to run in l2 or l3 mode.
Definition: l2_input.c:591
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:595
static void hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:139
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:260
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:153
#define VNET_FEATURES(...)
Definition: feature.h:442
vl_api_ip4_address_t hi
Definition: arp.api:37
vxlan_gpe_tunnel_t * tunnels
vector of encap tunnel instances
Definition: vxlan_gpe.h:199
#define unformat_parse_error(input)
Definition: format.h:269
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:294
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
uword * vxlan4_gpe_tunnel_by_key
lookup IPv4 VXLAN GPE tunnel by key
Definition: vxlan_gpe.h:202
l2input_main_t l2input_main
Definition: l2_input.c:128
u32 decap_fib_index
FIB indices - inner IP packet lookup here.
Definition: vxlan_gpe.h:126
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
A for-us/local path.
Definition: fib_types.h:338
bool udp_is_valid_dst_port(udp_dst_port_t dst_port, u8 is_ip4)
Definition: udp_local.c:532
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static fib_protocol_t fib_ip_proto(bool is_ip6)
Convert from boolean is_ip6 to FIB protocol.
Definition: fib_types.h:80
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:492
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:1016
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 hw_if_index
vnet intfc hw_if_index
Definition: vxlan_gpe.h:132
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:124
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:501
uword encap_next_node
Next node after VxLAN-GPE encap.
Definition: vxlan_gpe.h:143
u32 sw_if_index
vnet intfc sw_if_index
Definition: vxlan_gpe.h:134
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:294
static void mcast_shared_add(ip46_address_t *remote, fib_node_index_t mfei, adj_index_t ai)
Definition: vxlan_gpe.c:438
static void hash_set_mem_alloc(uword **h, const void *key, uword v)
Definition: hash.h:279
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:471
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
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:487
#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:168
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:1065
#define foreach_copy_ipv6
Definition: vxlan_gpe.c:262
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
const ip46_address_t zero_addr
Definition: lookup.c:307
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:304
ip6_address_t dst_address
Definition: ip6_packet.h:307
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
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