FD.io VPP  v21.01.1
Vector Packet Processing
geneve.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 SUSE LLC.
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 #include <geneve/geneve.h>
16 #include <vnet/ip/format.h>
17 #include <vnet/fib/fib_entry.h>
18 #include <vnet/fib/fib_table.h>
20 #include <vnet/mfib/mfib_table.h>
21 #include <vnet/adj/adj_mcast.h>
22 #include <vnet/interface.h>
23 #include <vlib/vlib.h>
24 
25 /**
26  * @file
27  * @brief GENEVE.
28  *
29  * GENEVE provides the features needed to allow L2 bridge domains (BDs)
30  * to span multiple servers. This is done by building an L2 overlay on
31  * top of an L3 network underlay using GENEVE tunnels.
32  *
33  * This makes it possible for servers to be co-located in the same data
34  * center or be separated geographically as long as they are reachable
35  * through the underlay L3 network.
36  */
37 
38 
40 
41 u8 *
42 format_geneve_encap_trace (u8 * s, va_list * args)
43 {
44  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
45  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
46  geneve_encap_trace_t *t = va_arg (*args, geneve_encap_trace_t *);
47 
48  s = format (s, "GENEVE encap to geneve_tunnel%d vni %d",
49  t->tunnel_index, t->vni);
50  return s;
51 }
52 
53 static u8 *
54 format_decap_next (u8 * s, va_list * args)
55 {
56  u32 next_index = va_arg (*args, u32);
57 
58  switch (next_index)
59  {
60  case GENEVE_INPUT_NEXT_DROP:
61  return format (s, "drop");
62  case GENEVE_INPUT_NEXT_L2_INPUT:
63  return format (s, "l2");
64  default:
65  return format (s, "index %d", next_index);
66  }
67  return s;
68 }
69 
70 u8 *
71 format_geneve_tunnel (u8 * s, va_list * args)
72 {
73  geneve_tunnel_t *t = va_arg (*args, geneve_tunnel_t *);
74  geneve_main_t *ngm = &geneve_main;
75 
76  s = format (s, "[%d] lcl %U rmt %U vni %d fib-idx %d sw-if-idx %d ",
77  t - ngm->tunnels,
80  t->vni, t->encap_fib_index, t->sw_if_index);
81 
82  s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
83  s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index);
84  s = format (s, "l3-mode %u ", t->l3_mode);
85 
87  s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index);
88 
89  return s;
90 }
91 
92 static u8 *
93 format_geneve_name (u8 * s, va_list * args)
94 {
95  u32 dev_instance = va_arg (*args, u32);
96  return format (s, "geneve_tunnel%d", dev_instance);
97 }
98 
99 static clib_error_t *
101 {
102  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
104  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
105 
106  return /* no error */ 0;
107 }
108 
109 static clib_error_t *
111  const u8 * old_address, const u8 * mac_address)
112 {
113  l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);
114  return (NULL);
115 }
116 
117 /* *INDENT-OFF* */
118 VNET_DEVICE_CLASS (geneve_device_class, static) = {
119  .name = "GENEVE",
120  .format_device_name = format_geneve_name,
121  .format_tx_trace = format_geneve_encap_trace,
122  .admin_up_down_function = geneve_interface_admin_up_down,
123  .mac_addr_change_function = geneve_mac_change,
124 };
125 /* *INDENT-ON* */
126 
127 static u8 *
129 {
130  u32 dev_instance = va_arg (*args, u32);
131  s = format (s, "unimplemented dev %u", dev_instance);
132  return s;
133 }
134 
135 /* *INDENT-OFF* */
136 VNET_HW_INTERFACE_CLASS (geneve_hw_class) = {
137  .name = "GENEVE",
138  .format_header = format_geneve_header_with_length,
139  .build_rewrite = default_build_rewrite,
140 };
141 /* *INDENT-ON* */
142 
143 static void
145 {
146  dpo_id_t dpo = DPO_INVALID;
147  u32 encap_index = ip46_address_is_ip4 (&t->remote) ?
151 
152  fib_entry_contribute_forwarding (t->fib_entry_index, forw_type, &dpo);
153 
154  /* geneve uses the flow hash as the udp source port
155  * hence the packet's hash is unknown at this time.
156  * However, we can still skip single bucket load balance dpo's */
157  while (DPO_LOAD_BALANCE == dpo.dpoi_type)
158  {
160  if (lb->lb_n_buckets > 1)
161  break;
162 
163  dpo_copy (&dpo, load_balance_get_bucket_i (lb, 0));
164  }
165  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
166  dpo_reset (&dpo);
167 }
168 
169 static geneve_tunnel_t *
171 {
173  return ((geneve_tunnel_t *) (((char *) node) -
175 }
176 
177 /**
178  * Function definition to backwalk a FIB node -
179  * Here we will restack the new dpo of GENEVE DIP to encap node.
180  */
183 {
186 }
187 
188 /**
189  * Function definition to get a FIB node from its index
190  */
191 static fib_node_t *
193 {
194  geneve_tunnel_t *t;
195  geneve_main_t *vxm = &geneve_main;
196 
197  t = pool_elt_at_index (vxm->tunnels, index);
198 
199  return (&t->node);
200 }
201 
202 /**
203  * Function definition to inform the FIB node that its last lock has gone.
204  */
205 static void
207 {
208  /*
209  * The GENEVE tunnel is a root of the graph. As such
210  * it never has children and thus is never locked.
211  */
212  ASSERT (0);
213 }
214 
215 /*
216  * Virtual function table registered by GENEVE tunnels
217  * for participation in the FIB object graph.
218  */
219 const static fib_node_vft_t geneve_vft = {
221  .fnv_last_lock = geneve_tunnel_last_lock_gone,
222  .fnv_back_walk = geneve_tunnel_back_walk,
223 };
224 
225 
226 #define foreach_copy_field \
227 _(vni) \
228 _(mcast_sw_if_index) \
229 _(encap_fib_index) \
230 _(decap_next_index) \
231 _(local) \
232 _(remote) \
233 _(l3_mode)
234 
235 static int
237 {
238  union
239  {
240  ip4_geneve_header_t *h4;
241  ip6_geneve_header_t *h6;
242  u8 *rw;
243  } r =
244  {
245  .rw = 0};
246  int len = is_ip6 ? sizeof *r.h6 : sizeof *r.h4;
247 #if SUPPORT_OPTIONS_HEADER==1
248  len += t->options_len;
249 #endif
250 
252 
253  udp_header_t *udp;
254  geneve_header_t *geneve;
255  /* Fixed portion of the (outer) ip header */
256  if (!is_ip6)
257  {
258  ip4_header_t *ip = &r.h4->ip4;
259  udp = &r.h4->udp, geneve = &r.h4->geneve;
260  ip->ip_version_and_header_length = 0x45;
261  ip->ttl = 254;
262  ip->protocol = IP_PROTOCOL_UDP;
263 
264  ip->src_address = t->local.ip4;
265  ip->dst_address = t->remote.ip4;
266 
267  /* we fix up the ip4 header length and checksum after-the-fact */
268  ip->checksum = ip4_header_checksum (ip);
269  }
270  else
271  {
272  ip6_header_t *ip = &r.h6->ip6;
273  udp = &r.h6->udp, geneve = &r.h6->geneve;
275  clib_host_to_net_u32 (6 << 28);
276  ip->hop_limit = 255;
277  ip->protocol = IP_PROTOCOL_UDP;
278 
279  ip->src_address = t->local.ip6;
280  ip->dst_address = t->remote.ip6;
281  }
282 
283  /* UDP header, randomize local port on something, maybe? */
284  udp->src_port = clib_host_to_net_u16 (5251);
285  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_geneve);
286 
287  /* GENEVE header */
289 #if SUPPORT_OPTIONS_HEADER==1
290  vnet_set_geneve_options_len (geneve, t->options_len);
291 #else
292  vnet_set_geneve_options_len (geneve, 0);
293 #endif
294  vnet_set_geneve_oamframe_bit (geneve, 0);
295  vnet_set_geneve_critical_bit (geneve, 0);
297 
299 
300  vnet_set_geneve_vni (geneve, t->vni);
301 
302  t->rewrite = r.rw;
303  return (0);
304 }
305 
306 static bool
308  u32 decap_next_index)
309 {
310  vlib_main_t *vm = vxm->vlib_main;
311  u32 input_idx =
312  (!is_ip6) ? geneve4_input_node.index : geneve6_input_node.index;
313  vlib_node_runtime_t *r = vlib_node_get_runtime (vm, input_idx);
314 
315  return decap_next_index < r->n_next_nodes;
316 }
317 
318 typedef union
319 {
320  struct
321  {
322  fib_node_index_t mfib_entry_index;
323  adj_index_t mcast_adj_index;
324  };
325  u64 as_u64;
326 } __clib_packed mcast_shared_t;
327 
328 static inline mcast_shared_t
329 mcast_shared_get (ip46_address_t * ip)
330 {
332  uword *p = hash_get_mem (geneve_main.mcast_shared, ip);
333  ALWAYS_ASSERT (p);
334  return (mcast_shared_t)
335  {
336  .as_u64 = *p};
337 }
338 
339 static inline void
340 mcast_shared_add (ip46_address_t * remote,
341  fib_node_index_t mfei, adj_index_t ai)
342 {
343  mcast_shared_t new_ep = {
344  .mcast_adj_index = ai,
345  .mfib_entry_index = mfei,
346  };
347 
348  hash_set_mem_alloc (&geneve_main.mcast_shared, remote, new_ep.as_u64);
349 }
350 
351 static inline void
352 mcast_shared_remove (ip46_address_t * remote)
353 {
354  mcast_shared_t ep = mcast_shared_get (remote);
355 
356  adj_unlock (ep.mcast_adj_index);
357  mfib_table_entry_delete_index (ep.mfib_entry_index, MFIB_SOURCE_GENEVE);
358 
359  hash_unset_mem_free (&geneve_main.mcast_shared, remote);
360 }
361 
364 {
365  geneve_main_t *vxm = &geneve_main;
366  geneve_tunnel_t *t = 0;
367  vnet_main_t *vnm = vxm->vnet_main;
368  uword *p;
369  u32 hw_if_index = ~0;
370  u32 sw_if_index = ~0;
371  int rv;
372  geneve4_tunnel_key_t key4;
373  geneve6_tunnel_key_t key6;
374  u32 is_ip6 = a->is_ip6;
375 
376  if (!is_ip6)
377  {
378  key4.remote = a->remote.ip4.as_u32;
379  key4.vni = clib_host_to_net_u32 (a->vni << GENEVE_VNI_SHIFT);
380  p = hash_get (vxm->geneve4_tunnel_by_key, key4.as_u64);
381  }
382  else
383  {
384  key6.remote = a->remote.ip6;
385  key6.vni = clib_host_to_net_u32 (a->vni << GENEVE_VNI_SHIFT);
386  p = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6);
387  }
388 
389  if (a->is_add)
390  {
391  l2input_main_t *l2im = &l2input_main;
392 
393  /* adding a tunnel: tunnel must not already exist */
394  if (p)
395  return VNET_API_ERROR_TUNNEL_EXIST;
396 
397  /*if not set explicitly, default to l2 */
398  if (a->decap_next_index == ~0)
399  a->decap_next_index = GENEVE_INPUT_NEXT_L2_INPUT;
400  if (!geneve_decap_next_is_valid (vxm, is_ip6, a->decap_next_index))
401  return VNET_API_ERROR_INVALID_DECAP_NEXT;
402 
404  clib_memset (t, 0, sizeof (*t));
405 
406  /* copy from arg structure */
407 #define _(x) t->x = a->x;
409 #undef _
410 
411  rv = geneve_rewrite (t, is_ip6);
412  if (rv)
413  {
414  pool_put (vxm->tunnels, t);
415  return rv;
416  }
417 
418  /* copy the key */
419  if (is_ip6)
421  t - vxm->tunnels);
422  else
423  hash_set (vxm->geneve4_tunnel_by_key, key4.as_u64, t - vxm->tunnels);
424 
426  if (a->l3_mode)
427  {
428  u32 t_idx = t - vxm->tunnels;
429  u8 address[6] =
430  { 0xd0, 0x0b, 0xee, 0xd0, (u8) (t_idx >> 8), (u8) t_idx };
432  ethernet_register_interface (vnm, geneve_device_class.index,
433  t_idx,
434  address, &hw_if_index, 0);
435  if (error)
436  {
437  clib_error_report (error);
438  return VNET_API_ERROR_INVALID_REGISTRATION;
439  }
440  }
441  else
442  {
443  hw_if_index = vnet_register_interface
444  (vnm, geneve_device_class.index, t - vxm->tunnels,
445  geneve_hw_class.index, t - vxm->tunnels);
446  }
447 
448  hi = vnet_get_hw_interface (vnm, hw_if_index);
449 
450  /* Set geneve tunnel output node */
451  u32 encap_index = !is_ip6 ?
453  vnet_set_interface_output_node (vnm, hw_if_index, encap_index);
454 
455  t->hw_if_index = hw_if_index;
456  t->sw_if_index = sw_if_index = hi->sw_if_index;
457 
459  ~0);
461 
462  /* setup l2 input config with l2 feature and bd 0 to drop packet */
463  vec_validate (l2im->configs, sw_if_index);
464  l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
465  l2im->configs[sw_if_index].bd_index = 0;
466 
467  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
469  vnet_sw_interface_set_flags (vnm, sw_if_index,
471 
473  fib_prefix_t tun_remote_pfx;
475 
476  fib_prefix_from_ip46_addr (&t->remote, &tun_remote_pfx);
478  {
479  /* Unicast tunnel -
480  * source the FIB entry for the tunnel's destination
481  * and become a child thereof. The tunnel will then get poked
482  * when the forwarding for the entry updates, and the tunnel can
483  * re-stack accordingly
484  */
487  &tun_remote_pfx,
489  t - vxm->tunnels,
490  &t->sibling_index);
492  }
493  else
494  {
495  /* Multicast tunnel -
496  * as the same mcast group can be used for mutiple mcast tunnels
497  * with different VNIs, create the output fib adjecency only if
498  * it does not already exist
499  */
500  fib_protocol_t fp = fib_ip_proto (is_ip6);
501 
502  if (vtep_addr_ref (&vxm->vtep_table,
503  t->encap_fib_index, &t->remote) == 1)
504  {
505  fib_node_index_t mfei;
506  adj_index_t ai;
508  .frp_proto = fib_proto_to_dpo (fp),
509  .frp_addr = zero_addr,
510  .frp_sw_if_index = 0xffffffff,
511  .frp_fib_index = ~0,
512  .frp_weight = 1,
513  .frp_flags = FIB_ROUTE_PATH_LOCAL,
514  .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
515  };
516  const mfib_prefix_t mpfx = {
517  .fp_proto = fp,
518  .fp_len = (is_ip6 ? 128 : 32),
519  .fp_grp_addr = tun_remote_pfx.fp_addr,
520  };
521 
522  /*
523  * Setup the (*,G) to receive traffic on the mcast group
524  * - the forwarding interface is for-us
525  * - the accepting interface is that from the API
526  */
528  &mpfx, MFIB_SOURCE_GENEVE, &path);
529 
534  &mpfx,
535  MFIB_SOURCE_GENEVE, &path);
536 
537  /*
538  * Create the mcast adjacency to send traffic to the group
539  */
540  ai = adj_mcast_add_or_lock (fp,
541  fib_proto_to_link (fp),
542  a->mcast_sw_if_index);
543 
544  /*
545  * create a new end-point
546  */
547  mcast_shared_add (&t->remote, mfei, ai);
548  }
549 
550  dpo_id_t dpo = DPO_INVALID;
551  mcast_shared_t ep = mcast_shared_get (&t->remote);
552 
553  /* Stack shared mcast remote mac addr rewrite on encap */
555  fib_proto_to_dpo (fp), ep.mcast_adj_index);
556 
557  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
558  dpo_reset (&dpo);
559  flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
560  }
561 
562  vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
563  flood_class;
564  }
565  else
566  {
567  /* deleting a tunnel: tunnel must exist */
568  if (!p)
569  return VNET_API_ERROR_NO_SUCH_ENTRY;
570 
571  t = pool_elt_at_index (vxm->tunnels, p[0]);
572 
573  sw_if_index = t->sw_if_index;
574  vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */ );
577 
578  /* make sure tunnel is removed from l2 bd or xconnect */
579  set_int_l2_mode (vxm->vlib_main, vnm, MODE_L3, t->sw_if_index, 0,
580  L2_BD_PORT_TYPE_NORMAL, 0, 0);
581 
582  if (t->l3_mode)
584  else
586 
588 
589  if (!is_ip6)
590  hash_unset (vxm->geneve4_tunnel_by_key, key4.as_u64);
591  else
593 
595  {
598  }
599  else if (vtep_addr_unref (&vxm->vtep_table,
600  t->encap_fib_index, &t->remote) == 0)
601  {
603  }
604 
605  fib_node_deinit (&t->node);
606  vec_free (t->rewrite);
607  pool_put (vxm->tunnels, t);
608  }
609 
610  if (sw_if_indexp)
611  *sw_if_indexp = sw_if_index;
612 
613  if (a->is_add)
614  {
615  /* register udp ports */
616  if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_geneve, 1))
617  udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_geneve,
618  geneve4_input_node.index, 1);
619  if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_geneve6, 0))
620  udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_geneve6,
621  geneve6_input_node.index, 0);
622  }
623 
624  return 0;
625 }
626 
627 static uword
628 get_decap_next_for_node (u32 node_index, u32 ipv4_set)
629 {
630  geneve_main_t *vxm = &geneve_main;
631  vlib_main_t *vm = vxm->vlib_main;
632  uword input_node = (ipv4_set) ? geneve4_input_node.index :
633  geneve6_input_node.index;
634 
635  return vlib_node_add_next (vm, input_node, node_index);
636 }
637 
638 static uword
639 unformat_decap_next (unformat_input_t * input, va_list * args)
640 {
641  u32 *result = va_arg (*args, u32 *);
642  u32 ipv4_set = va_arg (*args, int);
643  geneve_main_t *vxm = &geneve_main;
644  vlib_main_t *vm = vxm->vlib_main;
645  u32 node_index;
646  u32 tmp;
647 
648  if (unformat (input, "l2"))
649  *result = GENEVE_INPUT_NEXT_L2_INPUT;
650  else if (unformat (input, "node %U", unformat_vlib_node, vm, &node_index))
651  *result = get_decap_next_for_node (node_index, ipv4_set);
652  else if (unformat (input, "%d", &tmp))
653  *result = tmp;
654  else
655  return 0;
656  return 1;
657 }
658 
659 static clib_error_t *
661  unformat_input_t * input,
662  vlib_cli_command_t * cmd)
663 {
664  unformat_input_t _line_input, *line_input = &_line_input;
665  ip46_address_t local, remote;
666  u8 is_add = 1;
667  u8 local_set = 0;
668  u8 remote_set = 0;
669  u8 grp_set = 0;
670  u8 ipv4_set = 0;
671  u8 ipv6_set = 0;
672  u8 l3_mode = 0;
673  u32 encap_fib_index = 0;
674  u32 mcast_sw_if_index = ~0;
675  u32 decap_next_index = GENEVE_INPUT_NEXT_L2_INPUT;
676  u32 vni = 0;
677  u32 tmp;
678  int rv;
680  u32 tunnel_sw_if_index;
681  clib_error_t *error = NULL;
682 
683  /* Cant "universally zero init" (={0}) due to GCC bug 53119 */
684  clib_memset (&local, 0, sizeof local);
685  clib_memset (&remote, 0, sizeof remote);
686 
687  /* Get a line of input. */
688  if (!unformat_user (input, unformat_line_input, line_input))
689  return 0;
690 
691  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
692  {
693  if (unformat (line_input, "del"))
694  {
695  is_add = 0;
696  }
697  else if (unformat (line_input, "local %U",
698  unformat_ip4_address, &local.ip4))
699  {
700  local_set = 1;
701  ipv4_set = 1;
702  }
703  else if (unformat (line_input, "remote %U",
704  unformat_ip4_address, &remote.ip4))
705  {
706  remote_set = 1;
707  ipv4_set = 1;
708  }
709  else if (unformat (line_input, "local %U",
710  unformat_ip6_address, &local.ip6))
711  {
712  local_set = 1;
713  ipv6_set = 1;
714  }
715  else if (unformat (line_input, "remote %U",
716  unformat_ip6_address, &remote.ip6))
717  {
718  remote_set = 1;
719  ipv6_set = 1;
720  }
721  else if (unformat (line_input, "group %U %U",
722  unformat_ip4_address, &remote.ip4,
724  vnet_get_main (), &mcast_sw_if_index))
725  {
726  grp_set = remote_set = 1;
727  ipv4_set = 1;
728  }
729  else if (unformat (line_input, "group %U %U",
730  unformat_ip6_address, &remote.ip6,
732  vnet_get_main (), &mcast_sw_if_index))
733  {
734  grp_set = remote_set = 1;
735  ipv6_set = 1;
736  }
737  else if (unformat (line_input, "encap-vrf-id %d", &tmp))
738  {
739  encap_fib_index = fib_table_find (fib_ip_proto (ipv6_set), tmp);
740  if (encap_fib_index == ~0)
741  {
742  error =
743  clib_error_return (0, "nonexistent encap-vrf-id %d", tmp);
744  goto done;
745  }
746  }
747  else if (unformat (line_input, "decap-next %U", unformat_decap_next,
748  &decap_next_index, ipv4_set))
749  ;
750  else if (unformat (line_input, "vni %d", &vni))
751  {
752  if (vni >> 24)
753  {
754  error = clib_error_return (0, "vni %d out of range", vni);
755  goto done;
756  }
757  }
758  else if (unformat (line_input, "l3-mode"))
759  {
760  l3_mode = 1;
761  }
762  else
763  {
764  error = clib_error_return (0, "parse error: '%U'",
765  format_unformat_error, line_input);
766  goto done;
767  }
768  }
769 
770  if (local_set == 0)
771  {
772  error = clib_error_return (0, "tunnel local address not specified");
773  goto done;
774  }
775 
776  if (remote_set == 0)
777  {
778  error = clib_error_return (0, "tunnel remote address not specified");
779  goto done;
780  }
781 
782  if (grp_set && !ip46_address_is_multicast (&remote))
783  {
784  error = clib_error_return (0, "tunnel group address not multicast");
785  goto done;
786  }
787 
788  if (grp_set == 0 && ip46_address_is_multicast (&remote))
789  {
790  error = clib_error_return (0, "remote address must be unicast");
791  goto done;
792  }
793 
794  if (grp_set && mcast_sw_if_index == ~0)
795  {
796  error = clib_error_return (0, "tunnel nonexistent multicast device");
797  goto done;
798  }
799 
800  if (ipv4_set && ipv6_set)
801  {
802  error = clib_error_return (0, "both IPv4 and IPv6 addresses specified");
803  goto done;
804  }
805 
806  if (ip46_address_cmp (&local, &remote) == 0)
807  {
808  error =
809  clib_error_return (0, "local and remote addresses are identical");
810  goto done;
811  }
812 
813  if (decap_next_index == ~0)
814  {
815  error = clib_error_return (0, "next node not found");
816  goto done;
817  }
818 
819  if (vni == 0)
820  {
821  error = clib_error_return (0, "vni not specified");
822  goto done;
823  }
824 
825  clib_memset (a, 0, sizeof (*a));
826 
827  a->is_add = is_add;
828  a->is_ip6 = ipv6_set;
829 
830 #define _(x) a->x = x;
832 #undef _
833 
834  rv = vnet_geneve_add_del_tunnel (a, &tunnel_sw_if_index);
835 
836  switch (rv)
837  {
838  case 0:
839  if (is_add)
841  vnet_get_main (), tunnel_sw_if_index);
842  break;
843 
844  case VNET_API_ERROR_TUNNEL_EXIST:
845  error = clib_error_return (0, "tunnel already exists...");
846  goto done;
847 
848  case VNET_API_ERROR_NO_SUCH_ENTRY:
849  error = clib_error_return (0, "tunnel does not exist...");
850  goto done;
851 
852  default:
853  error = clib_error_return
854  (0, "vnet_geneve_add_del_tunnel returned %d", rv);
855  goto done;
856  }
857 
858 done:
859  unformat_free (line_input);
860 
861  return error;
862 }
863 
864 /*?
865  * Add or delete a GENEVE Tunnel.
866  *
867  * GENEVE provides the features needed to allow L2 bridge domains (BDs)
868  * to span multiple servers. This is done by building an L2 overlay on
869  * top of an L3 network underlay using GENEVE tunnels.
870  *
871  * This makes it possible for servers to be co-located in the same data
872  * center or be separated geographically as long as they are reachable
873  * through the underlay L3 network.
874  *
875  * You can refer to this kind of L2 overlay bridge domain as a GENEVE
876  * segment.
877  *
878  * @cliexpar
879  * Example of how to create a GENEVE Tunnel:
880  * @cliexcmd{create geneve tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 encap-vrf-id 7}
881  * Example of how to delete a GENEVE Tunnel:
882  * @cliexcmd{create geneve tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 del}
883  ?*/
884 /* *INDENT-OFF* */
885 VLIB_CLI_COMMAND (create_geneve_tunnel_command, static) = {
886  .path = "create geneve tunnel",
887  .short_help =
888  "create geneve tunnel local <local-vtep-addr>"
889  " {remote <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} vni <nn>"
890  " [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [l3-mode] [del]",
892 };
893 /* *INDENT-ON* */
894 
895 static clib_error_t *
897  unformat_input_t * input,
898  vlib_cli_command_t * cmd)
899 {
900  geneve_main_t *vxm = &geneve_main;
901  geneve_tunnel_t *t;
902 
903  if (pool_elts (vxm->tunnels) == 0)
904  vlib_cli_output (vm, "No geneve tunnels configured...");
905 
906  pool_foreach (t, vxm->tunnels)
907  {
908  vlib_cli_output (vm, "%U", format_geneve_tunnel, t);
909  }
910 
911  return 0;
912 }
913 
914 /*?
915  * Display all the GENEVE Tunnel entries.
916  *
917  * @cliexpar
918  * Example of how to display the GENEVE Tunnel entries:
919  * @cliexstart{show geneve tunnel}
920  * [0] local 10.0.3.1 remote 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
921  * @cliexend
922  ?*/
923 /* *INDENT-OFF* */
924 VLIB_CLI_COMMAND (show_geneve_tunnel_command, static) = {
925  .path = "show geneve tunnel",
926  .short_help = "show geneve tunnel",
927  .function = show_geneve_tunnel_command_fn,
928 };
929 /* *INDENT-ON* */
930 
931 
932 void
934 {
935  if (is_ip6)
936  vnet_feature_enable_disable ("ip6-unicast", "ip6-geneve-bypass",
937  sw_if_index, is_enable, 0, 0);
938  else
939  vnet_feature_enable_disable ("ip4-unicast", "ip4-geneve-bypass",
940  sw_if_index, is_enable, 0, 0);
941 }
942 
943 
944 static clib_error_t *
946  unformat_input_t * input, vlib_cli_command_t * cmd)
947 {
948  unformat_input_t _line_input, *line_input = &_line_input;
949  vnet_main_t *vnm = vnet_get_main ();
950  clib_error_t *error = 0;
951  u32 sw_if_index, is_enable;
952 
953  sw_if_index = ~0;
954  is_enable = 1;
955 
956  if (!unformat_user (input, unformat_line_input, line_input))
957  return 0;
958 
959  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
960  {
961  if (unformat_user
962  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
963  ;
964  else if (unformat (line_input, "del"))
965  is_enable = 0;
966  else
967  {
968  error = unformat_parse_error (line_input);
969  goto done;
970  }
971  }
972 
973  if (~0 == sw_if_index)
974  {
975  error = clib_error_return (0, "unknown interface `%U'",
976  format_unformat_error, line_input);
977  goto done;
978  }
979 
980  vnet_int_geneve_bypass_mode (sw_if_index, is_ip6, is_enable);
981 
982 done:
983  unformat_free (line_input);
984 
985  return error;
986 }
987 
988 static clib_error_t *
990  unformat_input_t * input, vlib_cli_command_t * cmd)
991 {
992  return set_ip_geneve_bypass (0, input, cmd);
993 }
994 
995 /*?
996  * This command adds the 'ip4-geneve-bypass' graph node for a given interface.
997  * By adding the IPv4 geneve-bypass graph node to an interface, the node checks
998  * for and validate input geneve packet and bypass ip4-lookup, ip4-local,
999  * ip4-udp-lookup nodes to speedup geneve packet forwarding. This node will
1000  * cause extra overhead to for non-geneve packets which is kept at a minimum.
1001  *
1002  * @cliexpar
1003  * @parblock
1004  * Example of graph node before ip4-geneve-bypass is enabled:
1005  * @cliexstart{show vlib graph ip4-geneve-bypass}
1006  * Name Next Previous
1007  * ip4-geneve-bypass error-drop [0]
1008  * geneve4-input [1]
1009  * ip4-lookup [2]
1010  * @cliexend
1011  *
1012  * Example of how to enable ip4-geneve-bypass on an interface:
1013  * @cliexcmd{set interface ip geneve-bypass GigabitEthernet2/0/0}
1014  *
1015  * Example of graph node after ip4-geneve-bypass is enabled:
1016  * @cliexstart{show vlib graph ip4-geneve-bypass}
1017  * Name Next Previous
1018  * ip4-geneve-bypass error-drop [0] ip4-input
1019  * geneve4-input [1] ip4-input-no-checksum
1020  * ip4-lookup [2]
1021  * @cliexend
1022  *
1023  * Example of how to display the feature enabed on an interface:
1024  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1025  * IP feature paths configured on GigabitEthernet2/0/0...
1026  * ...
1027  * ipv4 unicast:
1028  * ip4-geneve-bypass
1029  * ip4-lookup
1030  * ...
1031  * @cliexend
1032  *
1033  * Example of how to disable ip4-geneve-bypass on an interface:
1034  * @cliexcmd{set interface ip geneve-bypass GigabitEthernet2/0/0 del}
1035  * @endparblock
1036 ?*/
1037 /* *INDENT-OFF* */
1038 VLIB_CLI_COMMAND (set_interface_ip_geneve_bypass_command, static) = {
1039  .path = "set interface ip geneve-bypass",
1040  .function = set_ip4_geneve_bypass,
1041  .short_help = "set interface ip geneve-bypass <interface> [del]",
1042 };
1043 /* *INDENT-ON* */
1044 
1045 static clib_error_t *
1047  unformat_input_t * input, vlib_cli_command_t * cmd)
1048 {
1049  return set_ip_geneve_bypass (1, input, cmd);
1050 }
1051 
1052 /*?
1053  * This command adds the 'ip6-geneve-bypass' graph node for a given interface.
1054  * By adding the IPv6 geneve-bypass graph node to an interface, the node checks
1055  * for and validate input geneve packet and bypass ip6-lookup, ip6-local,
1056  * ip6-udp-lookup nodes to speedup geneve packet forwarding. This node will
1057  * cause extra overhead to for non-geneve packets which is kept at a minimum.
1058  *
1059  * @cliexpar
1060  * @parblock
1061  * Example of graph node before ip6-geneve-bypass is enabled:
1062  * @cliexstart{show vlib graph ip6-geneve-bypass}
1063  * Name Next Previous
1064  * ip6-geneve-bypass error-drop [0]
1065  * geneve6-input [1]
1066  * ip6-lookup [2]
1067  * @cliexend
1068  *
1069  * Example of how to enable ip6-geneve-bypass on an interface:
1070  * @cliexcmd{set interface ip6 geneve-bypass GigabitEthernet2/0/0}
1071  *
1072  * Example of graph node after ip6-geneve-bypass is enabled:
1073  * @cliexstart{show vlib graph ip6-geneve-bypass}
1074  * Name Next Previous
1075  * ip6-geneve-bypass error-drop [0] ip6-input
1076  * geneve6-input [1] ip4-input-no-checksum
1077  * ip6-lookup [2]
1078  * @cliexend
1079  *
1080  * Example of how to display the feature enabed on an interface:
1081  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1082  * IP feature paths configured on GigabitEthernet2/0/0...
1083  * ...
1084  * ipv6 unicast:
1085  * ip6-geneve-bypass
1086  * ip6-lookup
1087  * ...
1088  * @cliexend
1089  *
1090  * Example of how to disable ip6-geneve-bypass on an interface:
1091  * @cliexcmd{set interface ip6 geneve-bypass GigabitEthernet2/0/0 del}
1092  * @endparblock
1093 ?*/
1094 /* *INDENT-OFF* */
1095 VLIB_CLI_COMMAND (set_interface_ip6_geneve_bypass_command, static) = {
1096  .path = "set interface ip6 geneve-bypass",
1097  .function = set_ip6_geneve_bypass,
1098  .short_help = "set interface ip6 geneve-bypass <interface> [del]",
1099 };
1100 /* *INDENT-ON* */
1101 
1102 clib_error_t *
1104 {
1105  geneve_main_t *vxm = &geneve_main;
1106 
1107  vxm->vnet_main = vnet_get_main ();
1108  vxm->vlib_main = vm;
1109 
1110  /* initialize the ip6 hash */
1112  sizeof (geneve6_tunnel_key_t),
1113  sizeof (uword));
1114  vxm->vtep_table = vtep_table_create ();
1115  vxm->mcast_shared = hash_create_mem (0,
1116  sizeof (ip46_address_t),
1117  sizeof (mcast_shared_t));
1118 
1120 
1121  return 0;
1122 }
1123 
1125 
1126 /*
1127  * fd.io coding-style-patch-verification: ON
1128  *
1129  * Local Variables:
1130  * eval: (c-set-style "gnu")
1131  * End:
1132  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
vlib_main_t * vlib_main
Definition: geneve.h:185
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 ...
static void vnet_geneve_hdr_1word_hton(geneve_header_t *h)
static clib_error_t * set_ip6_geneve_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: geneve.c:1046
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:116
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
u16 vni
Definition: flow_types.api:160
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
#define hash_set(h, key, value)
Definition: hash.h:255
l2_input_config_t * configs
Definition: l2_input.h:90
static u8 * format_geneve_header_with_length(u8 *s, va_list *args)
Definition: geneve.c:128
#define CLIB_UNUSED(x)
Definition: clib.h:87
uword vtep_addr_ref(vtep_table_t *t, u32 fib_index, ip46_address_t *ip)
Definition: vtep.c:19
u32 hw_if_index
Definition: geneve.h:120
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
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
ip4_address_t src_address
Definition: ip4_packet.h:125
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static void mcast_shared_add(ip46_address_t *remote, fib_node_index_t mfei, adj_index_t ai)
Definition: geneve.c:340
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
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
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 decap_next_index
Definition: geneve.h:113
fib_node_t node
Linkage into the FIB object graph.
Definition: geneve.h:125
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
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:262
#define foreach_copy_field
Definition: geneve.c:226
static geneve_tunnel_t * geneve_tunnel_from_fib_node(fib_node_t *node)
Definition: geneve.c:170
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
u32 mcast_sw_if_index
Definition: geneve.h:110
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
static clib_error_t * geneve_add_del_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: geneve.c:660
#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
dpo_id_t next_dpo
Definition: geneve.h:95
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
uword * mcast_shared
Definition: geneve.h:179
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
int vnet_geneve_add_del_tunnel(vnet_geneve_add_del_tunnel_args_t *a, u32 *sw_if_indexp)
Definition: geneve.c:363
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
u32 * tunnel_index_by_sw_if_index
Definition: geneve.h:182
u8 * format_geneve_encap_trace(u8 *s, va_list *args)
Definition: geneve.c:42
ip6_address_t src_address
Definition: ip6_packet.h:310
format_function_t format_vnet_sw_if_index_name
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1173
unsigned char u8
Definition: types.h:56
geneve_tunnel_t * tunnels
Definition: geneve.h:168
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
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
static clib_error_t * show_geneve_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: geneve.c:896
VNET_HW_INTERFACE_CLASS(geneve_hw_class)
vnet_flood_class_t flood_class
Definition: interface.h:764
clib_error_t * geneve_init(vlib_main_t *vm)
Definition: geneve.c:1103
unformat_function_t unformat_ip4_address
Definition: format.h:68
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:545
static fib_node_back_walk_rc_t geneve_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 GENEVE DIP to encap ...
Definition: geneve.c:182
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static void vnet_set_geneve_oamframe_bit(geneve_header_t *h, u8 oam)
u8 * rewrite
Definition: geneve.h:92
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
static int ip46_address_cmp(const ip46_address_t *ip46_1, const ip46_address_t *ip46_2)
Definition: ip46_address.h:80
description fragment has unexpected format
Definition: map.api:433
vlib_node_registration_t geneve4_encap_node
(constructor) VLIB_REGISTER_NODE (geneve4_encap_node)
Definition: encap.c:548
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
static void vnet_set_geneve_options_len(geneve_header_t *h, u8 len)
vtep_table_t vtep_table
Definition: geneve.h:176
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:347
#define ALWAYS_ASSERT(truth)
static clib_error_t * set_ip_geneve_bypass(u32 is_ip6, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: geneve.c:945
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
l2input_main_t l2input_main
Definition: l2_input_node.c:78
bool is_ip6
Definition: ip.api:43
unformat_function_t unformat_line_input
Definition: format.h:282
static void vnet_set_geneve_vni(geneve_header_t *h, u32 vni)
#define GENEVE_ETH_PROTOCOL
Definition: geneve_packet.h:99
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
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
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
u32 encap_fib_index
Definition: geneve.h:116
dpo_type_t dpoi_type
the type
Definition: dpo.h:176
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:229
long ctx[MAX_CONNS]
Definition: main.c:144
static clib_error_t * set_ip4_geneve_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: geneve.c:989
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
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:102
u8 * format_geneve_tunnel(u8 *s, va_list *args)
Definition: geneve.c:71
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
The FIB DPO provieds;.
Definition: load_balance.h:106
#define PREDICT_FALSE(x)
Definition: clib.h:121
static void vnet_set_geneve_version(geneve_header_t *h, u8 version)
vlib_node_registration_t geneve6_input_node
(constructor) VLIB_REGISTER_NODE (geneve6_input_node)
Definition: decap.c:834
vnet_sw_interface_flags_t flags
Definition: interface.h:739
static u8 * format_geneve_name(u8 *s, va_list *args)
Definition: geneve.c:93
static void vnet_set_geneve_protocol(geneve_header_t *h, u16 protocol)
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
static void geneve_tunnel_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: geneve.c:206
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
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
ip46_address_t local
Definition: geneve.h:106
vnet_flood_class_t
Definition: interface.h:680
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:115
fib_node_get_t fnv_get
Definition: fib_node.h:283
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
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
uword * geneve4_tunnel_by_key
Definition: geneve.h:171
Aggregate type for a prefix.
Definition: mfib_types.h:24
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
VNET_DEVICE_CLASS(geneve_device_class, static)
u32 sw_if_index
Definition: geneve.h:119
#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
manual_print typedef address
Definition: ip_types.api:96
static clib_error_t * geneve_mac_change(vnet_hw_interface_t *hi, const u8 *old_address, const u8 *mac_address)
Definition: geneve.c:110
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:1011
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.
static fib_node_t * geneve_tunnel_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: geneve.c:192
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:609
static void geneve_tunnel_restack_dpo(geneve_tunnel_t *t)
Definition: geneve.c:144
#define clib_error_report(e)
Definition: error.h:113
static void hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
u32 sibling_index
The tunnel is a child of the FIB entry for its desintion.
Definition: geneve.h:140
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:343
static int geneve_rewrite(geneve_tunnel_t *t, bool is_ip6)
Definition: geneve.c:236
vlib_node_registration_t geneve6_encap_node
(constructor) VLIB_REGISTER_NODE (geneve6_encap_node)
Definition: encap.c:561
static vtep_table_t vtep_table_create()
Definition: vtep.h:69
vl_api_ip4_address_t hi
Definition: arp.api:37
static void vnet_set_geneve_critical_bit(geneve_header_t *h, u8 critical_opts)
vnet_main_t * vnet_main
Definition: geneve.h:186
static clib_error_t * geneve_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: geneve.c:100
#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
ip46_address_t remote
Definition: geneve.h:107
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
vl_api_address_t ip
Definition: l2.api:501
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 GENEVE_VNI_SHIFT
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:348
static fib_protocol_t fib_ip_proto(bool is_ip6)
Convert from boolean is_ip6 to FIB protocol.
Definition: fib_types.h:79
void l2input_interface_mac_change(u32 sw_if_index, const u8 *old_address, const u8 *new_address)
Definition: l2_input.c:201
u64 uword
Definition: types.h:112
uword * geneve6_tunnel_by_key
Definition: geneve.h:172
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
fib_node_index_t fib_entry_index
Definition: geneve.h:131
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:202
#define GENEVE_VERSION
Definition: geneve_packet.h:98
u32 index
Definition: flow_types.api:221
static uword get_decap_next_for_node(u32 node_index, u32 ipv4_set)
Definition: geneve.c:628
static void mcast_shared_remove(ip46_address_t *remote)
Definition: geneve.c:352
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1228
#define hash_get_mem(h, key)
Definition: hash.h:269
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static u8 * format_decap_next(u8 *s, va_list *args)
Definition: geneve.c:54
geneve_main_t geneve_main
Definition: geneve.c:39
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
static bool geneve_decap_next_is_valid(geneve_main_t *vxm, u32 is_ip6, u32 decap_next_index)
Definition: geneve.c:307
static uword unformat_decap_next(unformat_input_t *input, va_list *args)
Definition: geneve.c:639
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 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
manual_print typedef u8 mac_address[6]
#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
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
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
vlib_node_registration_t geneve4_input_node
(constructor) VLIB_REGISTER_NODE (geneve4_input_node)
Definition: decap.c:816
#define MODE_L3
Definition: l2_input.h:282
void vnet_int_geneve_bypass_mode(u32 sw_if_index, u8 is_ip6, u8 is_enable)
Definition: geneve.c:933
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127