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