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