FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
vxlan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vnet/vxlan/vxlan.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/adj/rewrite.h>
23 #include <vnet/interface.h>
24 #include <vnet/flow/flow.h>
25 #include <vlib/vlib.h>
26 
27 /**
28  * @file
29  * @brief VXLAN.
30  *
31  * VXLAN provides the features needed to allow L2 bridge domains (BDs)
32  * to span multiple servers. This is done by building an L2 overlay on
33  * top of an L3 network underlay using VXLAN tunnels.
34  *
35  * This makes it possible for servers to be co-located in the same data
36  * center or be separated geographically as long as they are reachable
37  * through the underlay L3 network.
38  *
39  * You can refer to this kind of L2 overlay bridge domain as a VXLAN
40  * (Virtual eXtensible VLAN) segment.
41  */
42 
43 
45 
46 static u8 *
47 format_decap_next (u8 * s, va_list * args)
48 {
49  u32 next_index = va_arg (*args, u32);
50 
51  if (next_index == VXLAN_INPUT_NEXT_DROP)
52  return format (s, "drop");
53  else
54  return format (s, "index %d", next_index);
55  return s;
56 }
57 
58 u8 *
59 format_vxlan_tunnel (u8 * s, va_list * args)
60 {
61  vxlan_tunnel_t *t = va_arg (*args, vxlan_tunnel_t *);
62 
63  s = format (s,
64  "[%d] instance %d src %U dst %U vni %d fib-idx %d sw-if-idx %d ",
68  t->vni, t->encap_fib_index, t->sw_if_index);
69 
70  s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
71 
72  if (PREDICT_FALSE (t->decap_next_index != VXLAN_INPUT_NEXT_L2_INPUT))
73  s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index);
74 
76  s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index);
77 
78  if (t->flow_index != ~0)
79  s = format (s, "flow-index %d [%U]", t->flow_index,
81 
82  return s;
83 }
84 
85 static u8 *
86 format_vxlan_name (u8 * s, va_list * args)
87 {
88  u32 dev_instance = va_arg (*args, u32);
89  vxlan_main_t *vxm = &vxlan_main;
90  vxlan_tunnel_t *t;
91 
92  if (dev_instance == ~0)
93  return format (s, "<cached-unused>");
94 
95  if (dev_instance >= vec_len (vxm->tunnels))
96  return format (s, "<improperly-referenced>");
97 
98  t = pool_elt_at_index (vxm->tunnels, dev_instance);
99 
100  return format (s, "vxlan_tunnel%d", t->user_instance);
101 }
102 
103 static clib_error_t *
105 {
106  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
108  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
109 
110  return /* no error */ 0;
111 }
112 
113 /* *INDENT-OFF* */
114 VNET_DEVICE_CLASS (vxlan_device_class, static) = {
115  .name = "VXLAN",
116  .format_device_name = format_vxlan_name,
117  .format_tx_trace = format_vxlan_encap_trace,
118  .admin_up_down_function = vxlan_interface_admin_up_down,
119 };
120 /* *INDENT-ON* */
121 
122 static u8 *
123 format_vxlan_header_with_length (u8 * s, va_list * args)
124 {
125  u32 dev_instance = va_arg (*args, u32);
126  s = format (s, "unimplemented dev %u", dev_instance);
127  return s;
128 }
129 
130 /* *INDENT-OFF* */
131 VNET_HW_INTERFACE_CLASS (vxlan_hw_class) = {
132  .name = "VXLAN",
133  .format_header = format_vxlan_header_with_length,
134  .build_rewrite = default_build_rewrite,
135 };
136 /* *INDENT-ON* */
137 
138 static void
140 {
141  u8 is_ip4 = ip46_address_is_ip4 (&t->dst);
142  dpo_id_t dpo = DPO_INVALID;
143  fib_forward_chain_type_t forw_type = is_ip4 ?
145 
146  fib_entry_contribute_forwarding (t->fib_entry_index, forw_type, &dpo);
147 
148  /* vxlan uses the payload hash as the udp source port
149  * hence the packet's hash is unknown
150  * skip single bucket load balance dpo's */
151  while (DPO_LOAD_BALANCE == dpo.dpoi_type)
152  {
154  if (lb->lb_n_buckets > 1)
155  break;
156 
157  dpo_copy (&dpo, load_balance_get_bucket_i (lb, 0));
158  }
159 
160  u32 encap_index = is_ip4 ?
161  vxlan4_encap_node.index : vxlan6_encap_node.index;
162  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
163  dpo_reset (&dpo);
164 }
165 
166 static vxlan_tunnel_t *
168 {
170  return ((vxlan_tunnel_t *) (((char *) node) -
172 }
173 
174 /**
175  * Function definition to backwalk a FIB node -
176  * Here we will restack the new dpo of VXLAN DIP to encap node.
177  */
180 {
183 }
184 
185 /**
186  * Function definition to get a FIB node from its index
187  */
188 static fib_node_t *
190 {
191  vxlan_tunnel_t *t;
192  vxlan_main_t *vxm = &vxlan_main;
193 
194  t = pool_elt_at_index (vxm->tunnels, index);
195 
196  return (&t->node);
197 }
198 
199 /**
200  * Function definition to inform the FIB node that its last lock has gone.
201  */
202 static void
204 {
205  /*
206  * The VXLAN tunnel is a root of the graph. As such
207  * it never has children and thus is never locked.
208  */
209  ASSERT (0);
210 }
211 
212 /*
213  * Virtual function table registered by VXLAN tunnels
214  * for participation in the FIB object graph.
215  */
216 const static fib_node_vft_t vxlan_vft = {
218  .fnv_last_lock = vxlan_tunnel_last_lock_gone,
219  .fnv_back_walk = vxlan_tunnel_back_walk,
220 };
221 
222 
223 #define foreach_copy_field \
224 _(vni) \
225 _(mcast_sw_if_index) \
226 _(encap_fib_index) \
227 _(decap_next_index) \
228 _(src) \
229 _(dst)
230 
231 static void
233 {
234  union
235  {
236  ip4_vxlan_header_t h4;
237  ip6_vxlan_header_t h6;
238  } h;
239  int len = is_ip6 ? sizeof h.h6 : sizeof h.h4;
240 
241  udp_header_t *udp;
242  vxlan_header_t *vxlan;
243  /* Fixed portion of the (outer) ip header */
244 
245  clib_memset (&h, 0, sizeof (h));
246  if (!is_ip6)
247  {
248  ip4_header_t *ip = &h.h4.ip4;
249  udp = &h.h4.udp, vxlan = &h.h4.vxlan;
250  ip->ip_version_and_header_length = 0x45;
251  ip->ttl = 254;
252  ip->protocol = IP_PROTOCOL_UDP;
253 
254  ip->src_address = t->src.ip4;
255  ip->dst_address = t->dst.ip4;
256 
257  /* we fix up the ip4 header length and checksum after-the-fact */
258  ip->checksum = ip4_header_checksum (ip);
259  }
260  else
261  {
262  ip6_header_t *ip = &h.h6.ip6;
263  udp = &h.h6.udp, vxlan = &h.h6.vxlan;
265  clib_host_to_net_u32 (6 << 28);
266  ip->hop_limit = 255;
267  ip->protocol = IP_PROTOCOL_UDP;
268 
269  ip->src_address = t->src.ip6;
270  ip->dst_address = t->dst.ip6;
271  }
272 
273  /* UDP header, randomize src port on something, maybe? */
274  udp->src_port = clib_host_to_net_u16 (4789);
275  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_vxlan);
276 
277  /* VXLAN header */
278  vnet_set_vni_and_flags (vxlan, t->vni);
279  vnet_rewrite_set_data (*t, &h, len);
280 }
281 
282 static bool
284  u32 decap_next_index)
285 {
286  vlib_main_t *vm = vxm->vlib_main;
287  u32 input_idx = (!is_ip6) ?
288  vxlan4_input_node.index : vxlan6_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 /* *INDENT-OFF* */
295 typedef CLIB_PACKED(union
296 {
297  struct
298  {
299  fib_node_index_t mfib_entry_index;
300  adj_index_t mcast_adj_index;
301  };
302  u64 as_u64;
303 }) mcast_shared_t;
304 /* *INDENT-ON* */
305 
306 static inline mcast_shared_t
307 mcast_shared_get (ip46_address_t * ip)
308 {
310  uword *p = hash_get_mem (vxlan_main.mcast_shared, ip);
311  ALWAYS_ASSERT (p);
312  mcast_shared_t ret = {.as_u64 = *p };
313  return ret;
314 }
315 
316 static inline void
317 mcast_shared_add (ip46_address_t * dst, fib_node_index_t mfei, adj_index_t ai)
318 {
319  mcast_shared_t new_ep = {
320  .mcast_adj_index = ai,
321  .mfib_entry_index = mfei,
322  };
323 
324  hash_set_mem_alloc (&vxlan_main.mcast_shared, dst, new_ep.as_u64);
325 }
326 
327 static inline void
328 mcast_shared_remove (ip46_address_t * dst)
329 {
330  mcast_shared_t ep = mcast_shared_get (dst);
331 
332  adj_unlock (ep.mcast_adj_index);
333  mfib_table_entry_delete_index (ep.mfib_entry_index, MFIB_SOURCE_VXLAN);
334 
335  hash_unset_mem_free (&vxlan_main.mcast_shared, dst);
336 }
337 
339  (vnet_vxlan_add_del_tunnel_args_t * a, u32 * sw_if_indexp)
340 {
341  vxlan_main_t *vxm = &vxlan_main;
342  vnet_main_t *vnm = vxm->vnet_main;
344  u32 sw_if_index = ~0;
345  vxlan4_tunnel_key_t key4;
346  vxlan6_tunnel_key_t key6;
347  u32 is_ip6 = a->is_ip6;
348 
349  int not_found;
350  if (!is_ip6)
351  {
352  /* ip4 mcast is indexed by mcast addr only */
353  key4.key[0] = ip46_address_is_multicast (&a->dst) ?
354  a->dst.ip4.as_u32 :
355  a->dst.ip4.as_u32 | (((u64) a->src.ip4.as_u32) << 32);
356  key4.key[1] = (((u64) a->encap_fib_index) << 32)
357  | clib_host_to_net_u32 (a->vni << 8);
358  not_found =
359  clib_bihash_search_inline_16_8 (&vxm->vxlan4_tunnel_by_key, &key4);
360  p = (void *) &key4.value;
361  }
362  else
363  {
364  key6.key[0] = a->dst.ip6.as_u64[0];
365  key6.key[1] = a->dst.ip6.as_u64[1];
366  key6.key[2] = (((u64) a->encap_fib_index) << 32)
367  | clib_host_to_net_u32 (a->vni << 8);
368  not_found =
369  clib_bihash_search_inline_24_8 (&vxm->vxlan6_tunnel_by_key, &key6);
370  p = (void *) &key6.value;
371  }
372 
373  if (not_found)
374  p = 0;
375 
376  if (a->is_add)
377  {
378  l2input_main_t *l2im = &l2input_main;
379  u32 dev_instance; /* real dev instance tunnel index */
380  u32 user_instance; /* request and actual instance number */
381 
382  /* adding a tunnel: tunnel must not already exist */
383  if (p)
384  return VNET_API_ERROR_TUNNEL_EXIST;
385 
386  /*if not set explicitly, default to l2 */
387  if (a->decap_next_index == ~0)
388  a->decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
389  if (!vxlan_decap_next_is_valid (vxm, is_ip6, a->decap_next_index))
390  return VNET_API_ERROR_INVALID_DECAP_NEXT;
391 
392  vxlan_tunnel_t *t;
394  clib_memset (t, 0, sizeof (*t));
395  dev_instance = t - vxm->tunnels;
396 
397  /* copy from arg structure */
398 #define _(x) t->x = a->x;
400 #undef _
401 
402  vxlan_rewrite (t, is_ip6);
403  /*
404  * Reconcile the real dev_instance and a possible requested instance.
405  */
406  user_instance = a->instance;
407  if (user_instance == ~0)
408  user_instance = dev_instance;
409  if (hash_get (vxm->instance_used, user_instance))
410  {
411  pool_put (vxm->tunnels, t);
412  return VNET_API_ERROR_INSTANCE_IN_USE;
413  }
414  hash_set (vxm->instance_used, user_instance, 1);
415 
416  t->dev_instance = dev_instance; /* actual */
417  t->user_instance = user_instance; /* name */
418  t->flow_index = ~0;
419 
421  (vnm, vxlan_device_class.index, dev_instance,
422  vxlan_hw_class.index, dev_instance);
424 
425  /* Set vxlan tunnel output node */
426  u32 encap_index = !is_ip6 ?
427  vxlan4_encap_node.index : vxlan6_encap_node.index;
428  vnet_set_interface_output_node (vnm, t->hw_if_index, encap_index);
429 
430  t->sw_if_index = sw_if_index = hi->sw_if_index;
431 
432  /* copy the key */
433  int add_failed;
434  if (is_ip6)
435  {
436  key6.value = (u64) dev_instance;
437  add_failed = clib_bihash_add_del_24_8 (&vxm->vxlan6_tunnel_by_key,
438  &key6, 1 /*add */ );
439  }
440  else
441  {
442  vxlan_decap_info_t di = {.sw_if_index = t->sw_if_index, };
443  if (ip46_address_is_multicast (&t->dst))
444  di.local_ip = t->src.ip4;
445  else
447  key4.value = di.as_u64;
448  add_failed = clib_bihash_add_del_16_8 (&vxm->vxlan4_tunnel_by_key,
449  &key4, 1 /*add */ );
450  }
451 
452  if (add_failed)
453  {
456  pool_put (vxm->tunnels, t);
457  return VNET_API_ERROR_INVALID_REGISTRATION;
458  }
459 
461  ~0);
462  vxm->tunnel_index_by_sw_if_index[sw_if_index] = dev_instance;
463 
464  /* setup l2 input config with l2 feature and bd 0 to drop packet */
465  vec_validate (l2im->configs, sw_if_index);
466  l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
467  l2im->configs[sw_if_index].bd_index = 0;
468 
469  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
471  vnet_sw_interface_set_flags (vnm, sw_if_index,
473 
475  fib_prefix_t tun_dst_pfx;
477 
478  fib_prefix_from_ip46_addr (&t->dst, &tun_dst_pfx);
479  if (!ip46_address_is_multicast (&t->dst))
480  {
481  /* Unicast tunnel -
482  * source the FIB entry for the tunnel's destination
483  * and become a child thereof. The tunnel will then get poked
484  * when the forwarding for the entry updates, and the tunnel can
485  * re-stack accordingly
486  */
487  vtep_addr_ref (&vxm->vtep_table, t->encap_fib_index, &t->src);
489  &tun_dst_pfx,
491  dev_instance,
492  &t->sibling_index);
494  }
495  else
496  {
497  /* Multicast tunnel -
498  * as the same mcast group can be used for multiple mcast tunnels
499  * with different VNIs, create the output fib adjacency only if
500  * it does not already exist
501  */
502  fib_protocol_t fp = fib_ip_proto (is_ip6);
503 
504  if (vtep_addr_ref (&vxm->vtep_table,
505  t->encap_fib_index, &t->dst) == 1)
506  {
507  fib_node_index_t mfei;
508  adj_index_t ai;
510  .frp_proto = fib_proto_to_dpo (fp),
511  .frp_addr = zero_addr,
512  .frp_sw_if_index = 0xffffffff,
513  .frp_fib_index = ~0,
514  .frp_weight = 1,
515  .frp_flags = FIB_ROUTE_PATH_LOCAL,
516  .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
517  };
518  const mfib_prefix_t mpfx = {
519  .fp_proto = fp,
520  .fp_len = (is_ip6 ? 128 : 32),
521  .fp_grp_addr = tun_dst_pfx.fp_addr,
522  };
523 
524  /*
525  * Setup the (*,G) to receive traffic on the mcast group
526  * - the forwarding interface is for-us
527  * - the accepting interface is that from the API
528  */
530  &mpfx, MFIB_SOURCE_VXLAN, &path);
531 
536  &mpfx,
537  MFIB_SOURCE_VXLAN, &path);
538 
539  /*
540  * Create the mcast adjacency to send traffic to the group
541  */
542  ai = adj_mcast_add_or_lock (fp,
543  fib_proto_to_link (fp),
544  a->mcast_sw_if_index);
545 
546  /*
547  * create a new end-point
548  */
549  mcast_shared_add (&t->dst, mfei, ai);
550  }
551 
552  dpo_id_t dpo = DPO_INVALID;
553  mcast_shared_t ep = mcast_shared_get (&t->dst);
554 
555  /* Stack shared mcast dst mac addr rewrite on encap */
557  fib_proto_to_dpo (fp), ep.mcast_adj_index);
558 
559  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
560  dpo_reset (&dpo);
561  flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
562  }
563 
564  vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
565  flood_class;
566  }
567  else
568  {
569  /* deleting a tunnel: tunnel must exist */
570  if (!p)
571  return VNET_API_ERROR_NO_SUCH_ENTRY;
572 
573  u32 instance = is_ip6 ? key6.value :
575  vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, instance);
576 
577  sw_if_index = t->sw_if_index;
578  vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */ );
579 
581 
582  if (!is_ip6)
583  clib_bihash_add_del_16_8 (&vxm->vxlan4_tunnel_by_key, &key4,
584  0 /*del */ );
585  else
586  clib_bihash_add_del_24_8 (&vxm->vxlan6_tunnel_by_key, &key6,
587  0 /*del */ );
588 
589  if (!ip46_address_is_multicast (&t->dst))
590  {
591  if (t->flow_index != ~0)
592  vnet_flow_del (vnm, t->flow_index);
593 
596  }
597  else if (vtep_addr_unref (&vxm->vtep_table,
598  t->encap_fib_index, &t->dst) == 0)
599  {
600  mcast_shared_remove (&t->dst);
601  }
602 
605 
606  fib_node_deinit (&t->node);
607  pool_put (vxm->tunnels, t);
608  }
609 
610  if (sw_if_indexp)
611  *sw_if_indexp = sw_if_index;
612 
613  if (a->is_add)
614  {
615  /* register udp ports */
616  if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_vxlan, 1))
617  udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_vxlan,
618  vxlan4_input_node.index, 1);
619  if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_vxlan6, 0))
620  udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_vxlan6,
621  vxlan6_input_node.index, 0);
622  }
623 
624  return 0;
625 }
626 
627 static uword
628 get_decap_next_for_node (u32 node_index, u32 ipv4_set)
629 {
630  vxlan_main_t *vxm = &vxlan_main;
631  vlib_main_t *vm = vxm->vlib_main;
632  uword input_node = (ipv4_set) ? vxlan4_input_node.index :
633  vxlan6_input_node.index;
634 
635  return vlib_node_add_next (vm, input_node, node_index);
636 }
637 
638 static uword
639 unformat_decap_next (unformat_input_t * input, va_list * args)
640 {
641  u32 *result = va_arg (*args, u32 *);
642  u32 ipv4_set = va_arg (*args, int);
643  vxlan_main_t *vxm = &vxlan_main;
644  vlib_main_t *vm = vxm->vlib_main;
645  u32 node_index;
646  u32 tmp;
647 
648  if (unformat (input, "l2"))
649  *result = VXLAN_INPUT_NEXT_L2_INPUT;
650  else if (unformat (input, "node %U", unformat_vlib_node, vm, &node_index))
651  *result = get_decap_next_for_node (node_index, ipv4_set);
652  else if (unformat (input, "%d", &tmp))
653  *result = tmp;
654  else
655  return 0;
656  return 1;
657 }
658 
659 static clib_error_t *
661  unformat_input_t * input,
662  vlib_cli_command_t * cmd)
663 {
664  unformat_input_t _line_input, *line_input = &_line_input;
665  ip46_address_t src = ip46_address_initializer, dst =
667  u8 is_add = 1;
668  u8 src_set = 0;
669  u8 dst_set = 0;
670  u8 grp_set = 0;
671  u8 ipv4_set = 0;
672  u8 ipv6_set = 0;
673  u32 instance = ~0;
674  u32 encap_fib_index = 0;
675  u32 mcast_sw_if_index = ~0;
676  u32 decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
677  u32 vni = 0;
678  u32 table_id;
679  clib_error_t *parse_error = NULL;
680 
681  /* Get a line of input. */
682  if (!unformat_user (input, unformat_line_input, line_input))
683  return 0;
684 
685  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
686  {
687  if (unformat (line_input, "del"))
688  {
689  is_add = 0;
690  }
691  else if (unformat (line_input, "instance %d", &instance))
692  ;
693  else if (unformat (line_input, "src %U",
695  {
696  src_set = 1;
697  ip46_address_is_ip4 (&src) ? (ipv4_set = 1) : (ipv6_set = 1);
698  }
699  else if (unformat (line_input, "dst %U",
701  {
702  dst_set = 1;
703  ip46_address_is_ip4 (&dst) ? (ipv4_set = 1) : (ipv6_set = 1);
704  }
705  else if (unformat (line_input, "group %U %U",
708  vnet_get_main (), &mcast_sw_if_index))
709  {
710  grp_set = dst_set = 1;
711  ip46_address_is_ip4 (&dst) ? (ipv4_set = 1) : (ipv6_set = 1);
712  }
713  else if (unformat (line_input, "encap-vrf-id %d", &table_id))
714  {
715  encap_fib_index =
716  fib_table_find (fib_ip_proto (ipv6_set), table_id);
717  }
718  else if (unformat (line_input, "decap-next %U", unformat_decap_next,
719  &decap_next_index, ipv4_set))
720  ;
721  else if (unformat (line_input, "vni %d", &vni))
722  ;
723  else
724  {
725  parse_error = clib_error_return (0, "parse error: '%U'",
726  format_unformat_error, line_input);
727  break;
728  }
729  }
730 
731  unformat_free (line_input);
732 
733  if (parse_error)
734  return parse_error;
735 
736  if (encap_fib_index == ~0)
737  return clib_error_return (0, "nonexistent encap-vrf-id %d", table_id);
738 
739  if (src_set == 0)
740  return clib_error_return (0, "tunnel src address not specified");
741 
742  if (dst_set == 0)
743  return clib_error_return (0, "tunnel dst address not specified");
744 
745  if (grp_set && !ip46_address_is_multicast (&dst))
746  return clib_error_return (0, "tunnel group address not multicast");
747 
748  if (grp_set == 0 && ip46_address_is_multicast (&dst))
749  return clib_error_return (0, "dst address must be unicast");
750 
751  if (grp_set && mcast_sw_if_index == ~0)
752  return clib_error_return (0, "tunnel nonexistent multicast device");
753 
754  if (ipv4_set && ipv6_set)
755  return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
756 
757  if (ip46_address_cmp (&src, &dst) == 0)
758  return clib_error_return (0, "src and dst addresses are identical");
759 
760  if (decap_next_index == ~0)
761  return clib_error_return (0, "next node not found");
762 
763  if (vni == 0)
764  return clib_error_return (0, "vni not specified");
765 
766  if (vni >> 24)
767  return clib_error_return (0, "vni %d out of range", vni);
768 
770  .is_add = is_add,
771  .is_ip6 = ipv6_set,
772  .instance = instance,
773 #define _(x) .x = x,
775 #undef _
776  };
777 
778  u32 tunnel_sw_if_index;
779  int rv = vnet_vxlan_add_del_tunnel (&a, &tunnel_sw_if_index);
780 
781  switch (rv)
782  {
783  case 0:
784  if (is_add)
786  vnet_get_main (), tunnel_sw_if_index);
787  break;
788 
789  case VNET_API_ERROR_TUNNEL_EXIST:
790  return clib_error_return (0, "tunnel already exists...");
791 
792  case VNET_API_ERROR_NO_SUCH_ENTRY:
793  return clib_error_return (0, "tunnel does not exist...");
794 
795  case VNET_API_ERROR_INSTANCE_IN_USE:
796  return clib_error_return (0, "Instance is in use");
797 
798  default:
799  return clib_error_return
800  (0, "vnet_vxlan_add_del_tunnel returned %d", rv);
801  }
802 
803  return 0;
804 }
805 
806 /*?
807  * Add or delete a VXLAN Tunnel.
808  *
809  * VXLAN provides the features needed to allow L2 bridge domains (BDs)
810  * to span multiple servers. This is done by building an L2 overlay on
811  * top of an L3 network underlay using VXLAN tunnels.
812  *
813  * This makes it possible for servers to be co-located in the same data
814  * center or be separated geographically as long as they are reachable
815  * through the underlay L3 network.
816  *
817  * You can refer to this kind of L2 overlay bridge domain as a VXLAN
818  * (Virtual eXtensible VLAN) segment.
819  *
820  * @cliexpar
821  * Example of how to create a VXLAN Tunnel:
822  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 encap-vrf-id 7}
823  * Example of how to create a VXLAN Tunnel with a known name, vxlan_tunnel42:
824  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 instance 42}
825  * Example of how to create a multicast VXLAN Tunnel with a known name, vxlan_tunnel23:
826  * @cliexcmd{create vxlan tunnel src 10.0.3.1 group 239.1.1.1 GigabitEthernet0/8/0 instance 23}
827  * Example of how to delete a VXLAN Tunnel:
828  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 del}
829  ?*/
830 /* *INDENT-OFF* */
831 VLIB_CLI_COMMAND (create_vxlan_tunnel_command, static) = {
832  .path = "create vxlan tunnel",
833  .short_help =
834  "create vxlan tunnel src <local-vtep-addr>"
835  " {dst <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} vni <nn>"
836  " [instance <id>]"
837  " [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [del]",
839 };
840 /* *INDENT-ON* */
841 
842 static clib_error_t *
844  unformat_input_t * input,
845  vlib_cli_command_t * cmd)
846 {
847  vxlan_main_t *vxm = &vxlan_main;
848  vxlan_tunnel_t *t;
849  int raw = 0;
850 
852  {
853  if (unformat (input, "raw"))
854  raw = 1;
855  else
856  return clib_error_return (0, "parse error: '%U'",
857  format_unformat_error, input);
858  }
859 
860  if (pool_elts (vxm->tunnels) == 0)
861  vlib_cli_output (vm, "No vxlan tunnels configured...");
862 
863 /* *INDENT-OFF* */
864  pool_foreach (t, vxm->tunnels,
865  ({
866  vlib_cli_output (vm, "%U", format_vxlan_tunnel, t);
867  }));
868 /* *INDENT-ON* */
869 
870  if (raw)
871  {
872  vlib_cli_output (vm, "Raw IPv4 Hash Table:\n%U\n",
873  format_bihash_16_8, &vxm->vxlan4_tunnel_by_key,
874  1 /* verbose */ );
875  vlib_cli_output (vm, "Raw IPv6 Hash Table:\n%U\n",
876  format_bihash_24_8, &vxm->vxlan6_tunnel_by_key,
877  1 /* verbose */ );
878  }
879 
880  return 0;
881 }
882 
883 /*?
884  * Display all the VXLAN Tunnel entries.
885  *
886  * @cliexpar
887  * Example of how to display the VXLAN Tunnel entries:
888  * @cliexstart{show vxlan tunnel}
889  * [0] src 10.0.3.1 dst 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
890  * @cliexend
891  ?*/
892 /* *INDENT-OFF* */
893 VLIB_CLI_COMMAND (show_vxlan_tunnel_command, static) = {
894  .path = "show vxlan tunnel",
895  .short_help = "show vxlan tunnel [raw]",
896  .function = show_vxlan_tunnel_command_fn,
897 };
898 /* *INDENT-ON* */
899 
900 
901 void
903 {
904  vxlan_main_t *vxm = &vxlan_main;
905 
907  sw_if_index))
908  return;
909 
910  is_enable = ! !is_enable;
911 
912  if (is_ip6)
913  {
914  if (clib_bitmap_get (vxm->bm_ip6_bypass_enabled_by_sw_if, sw_if_index)
915  != is_enable)
916  {
917  vnet_feature_enable_disable ("ip6-unicast", "ip6-vxlan-bypass",
918  sw_if_index, is_enable, 0, 0);
921  sw_if_index, is_enable);
922  }
923  }
924  else
925  {
926  if (clib_bitmap_get (vxm->bm_ip4_bypass_enabled_by_sw_if, sw_if_index)
927  != is_enable)
928  {
929  vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
930  sw_if_index, is_enable, 0, 0);
933  sw_if_index, is_enable);
934  }
935  }
936 }
937 
938 
939 static clib_error_t *
941  unformat_input_t * input, vlib_cli_command_t * cmd)
942 {
943  unformat_input_t _line_input, *line_input = &_line_input;
944  vnet_main_t *vnm = vnet_get_main ();
945  clib_error_t *error = 0;
946  u32 sw_if_index, is_enable;
947 
948  sw_if_index = ~0;
949  is_enable = 1;
950 
951  if (!unformat_user (input, unformat_line_input, line_input))
952  return 0;
953 
954  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
955  {
956  if (unformat_user
957  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
958  ;
959  else if (unformat (line_input, "del"))
960  is_enable = 0;
961  else
962  {
963  error = unformat_parse_error (line_input);
964  goto done;
965  }
966  }
967 
968  if (~0 == sw_if_index)
969  {
970  error = clib_error_return (0, "unknown interface `%U'",
971  format_unformat_error, line_input);
972  goto done;
973  }
974 
975  vnet_int_vxlan_bypass_mode (sw_if_index, is_ip6, is_enable);
976 
977 done:
978  unformat_free (line_input);
979 
980  return error;
981 }
982 
983 static clib_error_t *
985  unformat_input_t * input, vlib_cli_command_t * cmd)
986 {
987  return set_ip_vxlan_bypass (0, input, cmd);
988 }
989 
990 /*?
991  * This command adds the 'ip4-vxlan-bypass' graph node for a given interface.
992  * By adding the IPv4 vxlan-bypass graph node to an interface, the node checks
993  * for and validate input vxlan packet and bypass ip4-lookup, ip4-local,
994  * ip4-udp-lookup nodes to speedup vxlan packet forwarding. This node will
995  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
996  *
997  * @cliexpar
998  * @parblock
999  * Example of graph node before ip4-vxlan-bypass is enabled:
1000  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1001  * Name Next Previous
1002  * ip4-vxlan-bypass error-drop [0]
1003  * vxlan4-input [1]
1004  * ip4-lookup [2]
1005  * @cliexend
1006  *
1007  * Example of how to enable ip4-vxlan-bypass on an interface:
1008  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0}
1009  *
1010  * Example of graph node after ip4-vxlan-bypass is enabled:
1011  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1012  * Name Next Previous
1013  * ip4-vxlan-bypass error-drop [0] ip4-input
1014  * vxlan4-input [1] ip4-input-no-checksum
1015  * ip4-lookup [2]
1016  * @cliexend
1017  *
1018  * Example of how to display the feature enabled on an interface:
1019  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1020  * IP feature paths configured on GigabitEthernet2/0/0...
1021  * ...
1022  * ipv4 unicast:
1023  * ip4-vxlan-bypass
1024  * ip4-lookup
1025  * ...
1026  * @cliexend
1027  *
1028  * Example of how to disable ip4-vxlan-bypass on an interface:
1029  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0 del}
1030  * @endparblock
1031 ?*/
1032 /* *INDENT-OFF* */
1033 VLIB_CLI_COMMAND (set_interface_ip_vxlan_bypass_command, static) = {
1034  .path = "set interface ip vxlan-bypass",
1035  .function = set_ip4_vxlan_bypass,
1036  .short_help = "set interface ip vxlan-bypass <interface> [del]",
1037 };
1038 /* *INDENT-ON* */
1039 
1040 static clib_error_t *
1042  unformat_input_t * input, vlib_cli_command_t * cmd)
1043 {
1044  return set_ip_vxlan_bypass (1, input, cmd);
1045 }
1046 
1047 /*?
1048  * This command adds the 'ip6-vxlan-bypass' graph node for a given interface.
1049  * By adding the IPv6 vxlan-bypass graph node to an interface, the node checks
1050  * for and validate input vxlan packet and bypass ip6-lookup, ip6-local,
1051  * ip6-udp-lookup nodes to speedup vxlan packet forwarding. This node will
1052  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
1053  *
1054  * @cliexpar
1055  * @parblock
1056  * Example of graph node before ip6-vxlan-bypass is enabled:
1057  * @cliexstart{show vlib graph ip6-vxlan-bypass}
1058  * Name Next Previous
1059  * ip6-vxlan-bypass error-drop [0]
1060  * vxlan6-input [1]
1061  * ip6-lookup [2]
1062  * @cliexend
1063  *
1064  * Example of how to enable ip6-vxlan-bypass on an interface:
1065  * @cliexcmd{set interface ip6 vxlan-bypass GigabitEthernet2/0/0}
1066  *
1067  * Example of graph node after ip6-vxlan-bypass is enabled:
1068  * @cliexstart{show vlib graph ip6-vxlan-bypass}
1069  * Name Next Previous
1070  * ip6-vxlan-bypass error-drop [0] ip6-input
1071  * vxlan6-input [1] ip4-input-no-checksum
1072  * ip6-lookup [2]
1073  * @cliexend
1074  *
1075  * Example of how to display the feature enabled on an interface:
1076  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1077  * IP feature paths configured on GigabitEthernet2/0/0...
1078  * ...
1079  * ipv6 unicast:
1080  * ip6-vxlan-bypass
1081  * ip6-lookup
1082  * ...
1083  * @cliexend
1084  *
1085  * Example of how to disable ip6-vxlan-bypass on an interface:
1086  * @cliexcmd{set interface ip6 vxlan-bypass GigabitEthernet2/0/0 del}
1087  * @endparblock
1088 ?*/
1089 /* *INDENT-OFF* */
1090 VLIB_CLI_COMMAND (set_interface_ip6_vxlan_bypass_command, static) = {
1091  .path = "set interface ip6 vxlan-bypass",
1092  .function = set_ip6_vxlan_bypass,
1093  .short_help = "set interface ip6 vxlan-bypass <interface> [del]",
1094 };
1095 /* *INDENT-ON* */
1096 
1097 int
1098 vnet_vxlan_add_del_rx_flow (u32 hw_if_index, u32 t_index, int is_add)
1099 {
1100  vxlan_main_t *vxm = &vxlan_main;
1101  vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
1102  vnet_main_t *vnm = vnet_get_main ();
1103  if (is_add)
1104  {
1105  if (t->flow_index == ~0)
1106  {
1107  vxlan_main_t *vxm = &vxlan_main;
1108  vnet_flow_t flow = {
1109  .actions =
1110  VNET_FLOW_ACTION_REDIRECT_TO_NODE | VNET_FLOW_ACTION_MARK |
1111  VNET_FLOW_ACTION_BUFFER_ADVANCE,
1112  .mark_flow_id = t->dev_instance + vxm->flow_id_start,
1113  .redirect_node_index = vxlan4_flow_input_node.index,
1114  .buffer_advance = sizeof (ethernet_header_t),
1115  .type = VNET_FLOW_TYPE_IP4_VXLAN,
1116  .ip4_vxlan = {
1117  .protocol.prot = IP_PROTOCOL_UDP,
1118  .src_addr.addr = t->dst.ip4,
1119  .dst_addr.addr = t->src.ip4,
1120  .src_addr.mask.as_u32 = ~0,
1121  .dst_addr.mask.as_u32 = ~0,
1122  .dst_port.port = UDP_DST_PORT_vxlan,
1123  .dst_port.mask = 0xFF,
1124  .vni = t->vni,
1125  }
1126  ,
1127  };
1128  vnet_flow_add (vnm, &flow, &t->flow_index);
1129  }
1130  return vnet_flow_enable (vnm, t->flow_index, hw_if_index);
1131  }
1132  /* flow index is removed when the tunnel is deleted */
1133  return vnet_flow_disable (vnm, t->flow_index, hw_if_index);
1134 }
1135 
1136 u32
1138 {
1139  vxlan_main_t *vxm = &vxlan_main;
1140 
1141  if (sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index))
1142  return ~0;
1144 }
1145 
1146 static clib_error_t *
1148  unformat_input_t * input, vlib_cli_command_t * cmd)
1149 {
1150  unformat_input_t _line_input, *line_input = &_line_input;
1151 
1152  /* Get a line of input. */
1153  if (!unformat_user (input, unformat_line_input, line_input))
1154  return 0;
1155 
1156  vnet_main_t *vnm = vnet_get_main ();
1157  u32 rx_sw_if_index = ~0;
1158  u32 hw_if_index = ~0;
1159  int is_add = 1;
1160 
1161  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1162  {
1163  if (unformat (line_input, "hw %U", unformat_vnet_hw_interface, vnm,
1164  &hw_if_index))
1165  continue;
1166  if (unformat (line_input, "rx %U", unformat_vnet_sw_interface, vnm,
1167  &rx_sw_if_index))
1168  continue;
1169  if (unformat (line_input, "del"))
1170  {
1171  is_add = 0;
1172  continue;
1173  }
1174  return clib_error_return (0, "unknown input `%U'",
1175  format_unformat_error, line_input);
1176  }
1177 
1178  if (rx_sw_if_index == ~0)
1179  return clib_error_return (0, "missing rx interface");
1180  if (hw_if_index == ~0)
1181  return clib_error_return (0, "missing hw interface");
1182 
1183  u32 t_index = vnet_vxlan_get_tunnel_index (rx_sw_if_index);;
1184  if (t_index == ~0)
1185  return clib_error_return (0, "%U is not a vxlan tunnel",
1187  rx_sw_if_index);
1188 
1189  vxlan_main_t *vxm = &vxlan_main;
1190  vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
1191 
1192  if (!ip46_address_is_ip4 (&t->dst))
1193  return clib_error_return (0, "currently only IPV4 tunnels are supported");
1194 
1195  vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1196  ip4_main_t *im = &ip4_main;
1197  u32 rx_fib_index =
1199 
1200  if (t->encap_fib_index != rx_fib_index)
1201  return clib_error_return (0, "interface/tunnel fib mismatch");
1202 
1203  if (vnet_vxlan_add_del_rx_flow (hw_if_index, t_index, is_add))
1204  return clib_error_return (0, "error %s flow",
1205  is_add ? "enabling" : "disabling");
1206 
1207  return 0;
1208 }
1209 
1210 /* *INDENT-OFF* */
1211 VLIB_CLI_COMMAND (vxlan_offload_command, static) = {
1212  .path = "set flow-offload vxlan",
1213  .short_help =
1214  "set flow-offload vxlan hw <interface-name> rx <tunnel-name> [del]",
1215  .function = vxlan_offload_command_fn,
1216 };
1217 /* *INDENT-ON* */
1218 
1219 #define VXLAN_HASH_NUM_BUCKETS (2 * 1024)
1220 #define VXLAN_HASH_MEMORY_SIZE (1 << 20)
1221 
1222 clib_error_t *
1224 {
1225  vxlan_main_t *vxm = &vxlan_main;
1226 
1227  vxm->vnet_main = vnet_get_main ();
1228  vxm->vlib_main = vm;
1229 
1230  vnet_flow_get_range (vxm->vnet_main, "vxlan", 1024 * 1024,
1231  &vxm->flow_id_start);
1232 
1235 
1236  /* initialize the ip6 hash */
1237  clib_bihash_init_16_8 (&vxm->vxlan4_tunnel_by_key, "vxlan4",
1239  clib_bihash_init_24_8 (&vxm->vxlan6_tunnel_by_key, "vxlan6",
1241  vxm->vtep_table = vtep_table_create ();
1242  vxm->mcast_shared = hash_create_mem (0,
1243  sizeof (ip46_address_t),
1244  sizeof (mcast_shared_t));
1245 
1247 
1248  return 0;
1249 }
1250 
1252 
1253 /*
1254  * fd.io coding-style-patch-verification: ON
1255  *
1256  * Local Variables:
1257  * eval: (c-set-style "gnu")
1258  * End:
1259  */
unformat_function_t unformat_vnet_hw_interface
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
void vnet_set_interface_output_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Set interface output node - for interface registered without its output/tx nodes created because its ...
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:116
void dpo_stack_from_node(u32 child_node_index, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child parent relationship.
Definition: dpo.c:531
u32 user_instance
Definition: vxlan.h:131
u16 vni
Definition: flow_types.api:160
fib_node_index_t fib_entry_track(u32 fib_index, const fib_prefix_t *prefix, fib_node_type_t child_type, index_t child_index, u32 *sibling)
Trackers are used on FIB entries by objects that which to track the changing state of the entry...
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:113
#define hash_set(h, key, value)
Definition: hash.h:255
l2_input_config_t * configs
Definition: l2_input.h:62
uword vtep_addr_ref(vtep_table_t *t, u32 fib_index, ip46_address_t *ip)
Definition: vtep.c:19
u32 sibling_index
The tunnel is a child of the FIB entry for its destination.
Definition: vxlan.h:127
static uword ip46_address_is_multicast(const ip46_address_t *a)
Definition: ip46_address.h:154
int vnet_flow_get_range(vnet_main_t *vnm, char *owner, u32 count, u32 *start)
Definition: flow.c:24
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
clib_bihash_24_8_t vxlan6_tunnel_by_key
Definition: vxlan.h:163
A representation of a path as described by a route producer.
Definition: fib_types.h:490
ip4_address_t src_address
Definition: ip4_packet.h:125
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_interface_main_t interface_main
Definition: vnet.h:59
clib_error_t * vxlan_init(vlib_main_t *vm)
Definition: vxlan.c:1223
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
u64 as_u64
Definition: bihash_doc.h:63
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath)
Add n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:325
vlib_node_registration_t vxlan4_input_node
(constructor) VLIB_REGISTER_NODE (vxlan4_input_node)
Definition: decap.c:23
static clib_error_t * set_ip6_vxlan_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:1041
u32 frp_mitf_flags
MFIB interface flags.
Definition: fib_types.h:559
static mcast_shared_t mcast_shared_get(ip46_address_t *ip)
Definition: geneve.c:317
unsigned long u64
Definition: types.h:89
u32 flow_id_start
Definition: vxlan.h:185
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
typedef CLIB_PACKED(union { struct { fib_node_index_t mfib_entry_index;adj_index_t mcast_adj_index;};u64 as_u64;})
Definition: vxlan.c:295
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
void fib_entry_contribute_forwarding(fib_node_index_t fib_entry_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_entry.c:437
uword * mcast_shared
Definition: vxlan.h:170
ip46_address_t dst
Definition: vxlan.h:94
#define vnet_rewrite_set_data(rw, data, data_bytes)
Definition: rewrite.h:151
static void mcast_shared_remove(ip46_address_t *dst)
Definition: vxlan.c:328
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:262
vl_api_address_t src
Definition: gre.api:54
static clib_error_t * set_ip4_vxlan_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:984
vlib_node_registration_t vxlan4_flow_input_node
(constructor) VLIB_REGISTER_NODE (vxlan4_flow_input_node)
Definition: decap.c:1263
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:109
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:197
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_main_t * vm
Definition: in2out_ed.c:1582
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:122
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
vl_api_fib_path_t path
Definition: mfib_types.api:34
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
int vnet_flow_disable(vnet_main_t *vnm, u32 flow_index, u32 hw_if_index)
Definition: flow.c:135
static vxlan_tunnel_t * vxlan_tunnel_from_fib_node(fib_node_t *node)
Definition: vxlan.c:167
ip6_address_t src_address
Definition: ip6_packet.h:310
format_function_t format_vnet_sw_if_index_name
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1173
unsigned char u8
Definition: types.h:56
static clib_error_t * show_vxlan_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:843
static fib_node_back_walk_rc_t vxlan_tunnel_back_walk(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Function definition to backwalk a FIB node - Here we will restack the new dpo of VXLAN DIP to encap n...
Definition: vxlan.c:179
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:60
vnet_flood_class_t flood_class
Definition: interface.h:763
vnet_main_t * vnet_main
Definition: vxlan.h:181
VNET_DEVICE_CLASS(vxlan_device_class, static)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:530
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
void mfib_table_entry_delete_index(fib_node_index_t mfib_entry_index, mfib_source_t source)
Delete a FIB entry.
Definition: mfib_table.c:517
ip4_address_t dst_address
Definition: ip4_packet.h:125
static int ip46_address_cmp(const ip46_address_t *ip46_1, const ip46_address_t *ip46_2)
Definition: ip46_address.h:80
vl_api_interface_index_t mcast_sw_if_index
Definition: vxlan_gbp.api:41
Aggregate type for a prefix.
Definition: fib_types.h:203
static void vxlan_tunnel_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: vxlan.c:203
vlib_main_t * vlib_main
Definition: vxlan.h:180
#define clib_error_return(e, args...)
Definition: error.h:99
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:348
#define ALWAYS_ASSERT(truth)
unsigned int u32
Definition: types.h:88
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1097
static clib_error_t * vxlan_add_del_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:660
fib_node_t node
Linkage into the FIB object graph.
Definition: vxlan.h:112
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:768
bool is_ip6
Definition: ip.api:43
unformat_function_t unformat_line_input
Definition: format.h:283
vl_api_fib_path_type_t type
Definition: fib_types.api:123
int vnet_flow_del(vnet_main_t *vnm, u32 flow_index)
Definition: flow.c:67
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 pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
static clib_error_t * vxlan_offload_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:1147
uword * bm_ip6_bypass_enabled_by_sw_if
Definition: vxlan.h:177
static clib_error_t * vxlan_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: vxlan.c:104
uword vtep_addr_unref(vtep_table_t *t, u32 fib_index, ip46_address_t *ip)
Definition: vtep.c:34
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
dpo_type_t dpoi_type
the type
Definition: dpo.h:174
ip4_address_t local_ip
Definition: vxlan.h:75
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:229
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:102
vec_header_t h
Definition: buffer.c:322
void di(unformat_input_t *i)
Definition: unformat.c:163
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
The FIB DPO provieds;.
Definition: load_balance.h:106
vxlan_main_t vxlan_main
Definition: vxlan.c:44
#define PREDICT_FALSE(x)
Definition: clib.h:120
vnet_sw_interface_flags_t flags
Definition: interface.h:738
vlib_node_registration_t vxlan6_input_node
(constructor) VLIB_REGISTER_NODE (vxlan6_input_node)
Definition: decap.c:24
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
vl_api_address_t dst
Definition: gre.api:55
u8 * format_vxlan_encap_trace(u8 *s, va_list *args)
Definition: encap.c:58
u8 len
Definition: ip_types.api:92
format_function_t format_ip46_address
Definition: ip46_address.h:50
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:246
int vnet_vxlan_add_del_rx_flow(u32 hw_if_index, u32 t_index, int is_add)
Definition: vxlan.c:1098
int vnet_vxlan_add_del_tunnel(vnet_vxlan_add_del_tunnel_args_t *a, u32 *sw_if_indexp)
Definition: vxlan.c:339
vtep_table_t vtep_table
Definition: vxlan.h:167
u32 dev_instance
Definition: vxlan.h:130
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 mcast_sw_if_index
Definition: vxlan.h:97
vnet_flood_class_t
Definition: interface.h:679
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:115
fib_node_get_t fnv_get
Definition: fib_node.h:283
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
static void vnet_set_vni_and_flags(vxlan_header_t *h, u32 vni)
Definition: vxlan_packet.h:65
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
static uword unformat_decap_next(unformat_input_t *input, va_list *args)
Definition: vxlan.c:639
void fib_prefix_from_ip46_addr(const ip46_address_t *addr, fib_prefix_t *pfx)
Host prefix from ip.
Definition: fib_types.c:81
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
Aggregate type for a prefix.
Definition: mfib_types.h:24
u8 * default_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Return a complete, zero-length (aka placeholder) rewrite.
Definition: interface.c:1639
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
static u8 * format_vxlan_header_with_length(u8 *s, va_list *args)
Definition: vxlan.c:123
static void vxlan_tunnel_restack_dpo(vxlan_tunnel_t *t)
Definition: vxlan.c:139
#define ASSERT(truth)
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static void mcast_shared_add(ip46_address_t *dst, fib_node_index_t mfei, adj_index_t ai)
Definition: vxlan.c:317
static fib_node_t * vxlan_tunnel_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: vxlan.c:189
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
IPv4 main type.
Definition: ip4.h:106
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:600
format_function_t format_flow_enabled_hw
Definition: flow.h:289
static void hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
u32 sw_if_index
Definition: vxlan.h:106
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:324
static uword get_decap_next_for_node(u32 node_index, u32 ipv4_set)
Definition: vxlan.c:628
u32 hw_if_index
Definition: vxlan.h:107
u32 vnet_vxlan_get_tunnel_index(u32 sw_if_index)
Definition: vxlan.c:1137
unformat_function_t unformat_ip46_address
Definition: format.h:63
int vnet_flow_add(vnet_main_t *vnm, vnet_flow_t *flow, u32 *flow_index)
Definition: flow.c:43
static void vxlan_rewrite(vxlan_tunnel_t *t, bool is_ip6)
Definition: vxlan.c:232
static vtep_table_t vtep_table_create()
Definition: vtep.h:70
vl_api_ip4_address_t hi
Definition: arp.api:37
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:984
#define vec_elt(v, i)
Get vector value at index i.
#define foreach_copy_field
Definition: vxlan.c:223
#define unformat_parse_error(input)
Definition: format.h:269
uword * instance_used
Definition: vxlan.h:184
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
l2input_main_t l2input_main
Definition: l2_input.c:127
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
void vnet_int_vxlan_bypass_mode(u32 sw_if_index, u8 is_ip6, u8 is_enable)
Definition: vxlan.c:902
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:529
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 instance
Definition: gre.api:51
static fib_protocol_t fib_ip_proto(bool is_ip6)
Convert from boolean is_ip6 to FIB protocol.
Definition: fib_types.h:80
uword * bm_ip4_bypass_enabled_by_sw_if
Definition: vxlan.h:176
static clib_error_t * set_ip_vxlan_bypass(u32 is_ip6, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:940
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:498
fib_node_index_t fib_entry_index
Definition: vxlan.h:118
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:872
u32 encap_fib_index
Definition: vxlan.h:103
u32 table_id
Definition: wireguard.api:100
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
u32 index
Definition: flow_types.api:221
int vnet_flow_enable(vnet_main_t *vnm, u32 flow_index, u32 hw_if_index)
Definition: flow.c:91
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1228
u16 decap_next_index
Definition: vxlan.h:100
u32 * tunnel_index_by_sw_if_index
Definition: vxlan.h:173
#define hash_get_mem(h, key)
Definition: hash.h:269
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
static u8 * format_decap_next(u8 *s, va_list *args)
Definition: vxlan.c:47
vlib_node_registration_t vxlan4_encap_node
(constructor) VLIB_REGISTER_NODE (vxlan4_encap_node)
Definition: encap.c:538
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1144
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:507
clib_bihash_16_8_t vxlan4_tunnel_by_key
Definition: vxlan.h:162
adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto, vnet_link_t link_type, u32 sw_if_index)
Mcast Adjacency.
Definition: adj_mcast.c:51
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
vlib_node_registration_t vxlan6_encap_node
(constructor) VLIB_REGISTER_NODE (vxlan6_encap_node)
Definition: encap.c:551
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:358
dpo_id_t next_dpo
Definition: vxlan.h:87
static void hash_set_mem_alloc(uword **h, const void *key, uword v)
Definition: hash.h:279
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:468
u8 si
Definition: lisp_types.api:47
VNET_HW_INTERFACE_CLASS(vxlan_hw_class)
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
#define VXLAN_HASH_NUM_BUCKETS
Definition: vxlan.c:1219
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:556
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static bool vxlan_decap_next_is_valid(vxlan_main_t *vxm, u32 is_ip6, u32 decap_next_index)
Definition: vxlan.c:283
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
vxlan_tunnel_t * tunnels
Definition: vxlan.h:159
#define ip46_address_initializer
Definition: ip46_address.h:52
#define VXLAN_HASH_MEMORY_SIZE
Definition: vxlan.c:1220
const ip46_address_t zero_addr
Definition: lookup.c:181
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
ip46_address_t src
Definition: vxlan.h:93
u8 * format_vxlan_tunnel(u8 *s, va_list *args)
Definition: vxlan.c:59
static u8 * format_vxlan_name(u8 *s, va_list *args)
Definition: vxlan.c:86
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:303
ip6_address_t dst_address
Definition: ip6_packet.h:310
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
u32 flow_index
Definition: vxlan.h:129
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128