FD.io VPP  v20.01-48-g3e0dafb74
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 {
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 static uword
295 vtep_addr_ref (ip46_address_t * ip)
296 {
297  uword *vtep = ip46_address_is_ip4 (ip) ?
298  hash_get (vxlan_main.vtep4, ip->ip4.as_u32) :
299  hash_get_mem (vxlan_main.vtep6, &ip->ip6);
300  if (vtep)
301  return ++(*vtep);
302  ip46_address_is_ip4 (ip) ?
303  hash_set (vxlan_main.vtep4, ip->ip4.as_u32, 1) :
304  hash_set_mem_alloc (&vxlan_main.vtep6, &ip->ip6, 1);
305  return 1;
306 }
307 
308 static uword
309 vtep_addr_unref (ip46_address_t * ip)
310 {
311  uword *vtep = ip46_address_is_ip4 (ip) ?
312  hash_get (vxlan_main.vtep4, ip->ip4.as_u32) :
313  hash_get_mem (vxlan_main.vtep6, &ip->ip6);
314  ASSERT (vtep);
315  if (--(*vtep) != 0)
316  return *vtep;
317  ip46_address_is_ip4 (ip) ?
318  hash_unset (vxlan_main.vtep4, ip->ip4.as_u32) :
319  hash_unset_mem_free (&vxlan_main.vtep6, &ip->ip6);
320  return 0;
321 }
322 
323 /* *INDENT-OFF* */
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  };
331  u64 as_u64;
332 }) mcast_shared_t;
333 /* *INDENT-ON* */
334 
335 static inline mcast_shared_t
336 mcast_shared_get (ip46_address_t * ip)
337 {
339  uword *p = hash_get_mem (vxlan_main.mcast_shared, ip);
340  ASSERT (p);
341  mcast_shared_t ret = {.as_u64 = *p };
342  return ret;
343 }
344 
345 static inline void
346 mcast_shared_add (ip46_address_t * dst, 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 (&vxlan_main.mcast_shared, dst, new_ep.as_u64);
354 }
355 
356 static inline void
357 mcast_shared_remove (ip46_address_t * dst)
358 {
359  mcast_shared_t ep = mcast_shared_get (dst);
360 
361  adj_unlock (ep.mcast_adj_index);
362  mfib_table_entry_delete_index (ep.mfib_entry_index, MFIB_SOURCE_VXLAN);
363 
364  hash_unset_mem_free (&vxlan_main.mcast_shared, dst);
365 }
366 
368  (vnet_vxlan_add_del_tunnel_args_t * a, u32 * sw_if_indexp)
369 {
370  vxlan_main_t *vxm = &vxlan_main;
371  vnet_main_t *vnm = vxm->vnet_main;
373  u32 sw_if_index = ~0;
374  vxlan4_tunnel_key_t key4;
375  vxlan6_tunnel_key_t key6;
376  u32 is_ip6 = a->is_ip6;
377 
378  int not_found;
379  if (!is_ip6)
380  {
381  /* ip4 mcast is indexed by mcast addr only */
382  key4.key[0] = ip46_address_is_multicast (&a->dst) ?
383  a->dst.ip4.as_u32 :
384  a->dst.ip4.as_u32 | (((u64) a->src.ip4.as_u32) << 32);
385  key4.key[1] = (((u64) a->encap_fib_index) << 32)
386  | clib_host_to_net_u32 (a->vni << 8);
387  not_found =
388  clib_bihash_search_inline_16_8 (&vxm->vxlan4_tunnel_by_key, &key4);
389  p = (void *) &key4.value;
390  }
391  else
392  {
393  key6.key[0] = a->dst.ip6.as_u64[0];
394  key6.key[1] = a->dst.ip6.as_u64[1];
395  key6.key[2] = (((u64) a->encap_fib_index) << 32)
396  | clib_host_to_net_u32 (a->vni << 8);
397  not_found =
398  clib_bihash_search_inline_24_8 (&vxm->vxlan6_tunnel_by_key, &key6);
399  p = (void *) &key6.value;
400  }
401 
402  if (not_found)
403  p = 0;
404 
405  if (a->is_add)
406  {
407  l2input_main_t *l2im = &l2input_main;
408  u32 dev_instance; /* real dev instance tunnel index */
409  u32 user_instance; /* request and actual instance number */
410 
411  /* adding a tunnel: tunnel must not already exist */
412  if (p)
413  return VNET_API_ERROR_TUNNEL_EXIST;
414 
415  /*if not set explicitly, default to l2 */
416  if (a->decap_next_index == ~0)
417  a->decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
418  if (!vxlan_decap_next_is_valid (vxm, is_ip6, a->decap_next_index))
419  return VNET_API_ERROR_INVALID_DECAP_NEXT;
420 
421  vxlan_tunnel_t *t;
423  clib_memset (t, 0, sizeof (*t));
424  dev_instance = t - vxm->tunnels;
425 
426  /* copy from arg structure */
427 #define _(x) t->x = a->x;
429 #undef _
430 
431  vxlan_rewrite (t, is_ip6);
432  /*
433  * Reconcile the real dev_instance and a possible requested instance.
434  */
435  user_instance = a->instance;
436  if (user_instance == ~0)
437  user_instance = dev_instance;
438  if (hash_get (vxm->instance_used, user_instance))
439  {
440  pool_put (vxm->tunnels, t);
441  return VNET_API_ERROR_INSTANCE_IN_USE;
442  }
443  hash_set (vxm->instance_used, user_instance, 1);
444 
445  t->dev_instance = dev_instance; /* actual */
446  t->user_instance = user_instance; /* name */
447  t->flow_index = ~0;
448 
450  (vnm, vxlan_device_class.index, dev_instance,
451  vxlan_hw_class.index, dev_instance);
453 
454  /* Set vxlan tunnel output node */
455  u32 encap_index = !is_ip6 ?
456  vxlan4_encap_node.index : vxlan6_encap_node.index;
457  vnet_set_interface_output_node (vnm, t->hw_if_index, encap_index);
458 
459  t->sw_if_index = sw_if_index = hi->sw_if_index;
460 
461  /* copy the key */
462  int add_failed;
463  if (is_ip6)
464  {
465  key6.value = (u64) dev_instance;
466  add_failed = clib_bihash_add_del_24_8 (&vxm->vxlan6_tunnel_by_key,
467  &key6, 1 /*add */ );
468  }
469  else
470  {
471  vxlan_decap_info_t di = {.sw_if_index = t->sw_if_index, };
472  if (ip46_address_is_multicast (&t->dst))
473  di.local_ip = t->src.ip4;
474  else
476  key4.value = di.as_u64;
477  add_failed = clib_bihash_add_del_16_8 (&vxm->vxlan4_tunnel_by_key,
478  &key4, 1 /*add */ );
479  }
480 
481  if (add_failed)
482  {
485  pool_put (vxm->tunnels, t);
486  return VNET_API_ERROR_INVALID_REGISTRATION;
487  }
488 
490  ~0);
491  vxm->tunnel_index_by_sw_if_index[sw_if_index] = dev_instance;
492 
493  /* setup l2 input config with l2 feature and bd 0 to drop packet */
494  vec_validate (l2im->configs, sw_if_index);
495  l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
496  l2im->configs[sw_if_index].bd_index = 0;
497 
498  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
500  vnet_sw_interface_set_flags (vnm, sw_if_index,
502 
504  fib_prefix_t tun_dst_pfx;
506 
507  fib_prefix_from_ip46_addr (&t->dst, &tun_dst_pfx);
508  if (!ip46_address_is_multicast (&t->dst))
509  {
510  /* Unicast tunnel -
511  * source the FIB entry for the tunnel's destination
512  * and become a child thereof. The tunnel will then get poked
513  * when the forwarding for the entry updates, and the tunnel can
514  * re-stack accordingly
515  */
516  vtep_addr_ref (&t->src);
518  &tun_dst_pfx,
520  dev_instance,
521  &t->sibling_index);
523  }
524  else
525  {
526  /* Multicast tunnel -
527  * as the same mcast group can be used for multiple mcast tunnels
528  * with different VNIs, create the output fib adjacency only if
529  * it does not already exist
530  */
531  fib_protocol_t fp = fib_ip_proto (is_ip6);
532 
533  if (vtep_addr_ref (&t->dst) == 1)
534  {
535  fib_node_index_t mfei;
536  adj_index_t ai;
538  .frp_proto = fib_proto_to_dpo (fp),
539  .frp_addr = zero_addr,
540  .frp_sw_if_index = 0xffffffff,
541  .frp_fib_index = ~0,
542  .frp_weight = 1,
543  .frp_flags = FIB_ROUTE_PATH_LOCAL,
544  .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
545  };
546  const mfib_prefix_t mpfx = {
547  .fp_proto = fp,
548  .fp_len = (is_ip6 ? 128 : 32),
549  .fp_grp_addr = tun_dst_pfx.fp_addr,
550  };
551 
552  /*
553  * Setup the (*,G) to receive traffic on the mcast group
554  * - the forwarding interface is for-us
555  * - the accepting interface is that from the API
556  */
558  &mpfx, MFIB_SOURCE_VXLAN, &path);
559 
564  &mpfx,
565  MFIB_SOURCE_VXLAN, &path);
566 
567  /*
568  * Create the mcast adjacency to send traffic to the group
569  */
570  ai = adj_mcast_add_or_lock (fp,
571  fib_proto_to_link (fp),
572  a->mcast_sw_if_index);
573 
574  /*
575  * create a new end-point
576  */
577  mcast_shared_add (&t->dst, mfei, ai);
578  }
579 
580  dpo_id_t dpo = DPO_INVALID;
581  mcast_shared_t ep = mcast_shared_get (&t->dst);
582 
583  /* Stack shared mcast dst mac addr rewrite on encap */
585  fib_proto_to_dpo (fp), ep.mcast_adj_index);
586 
587  dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
588  dpo_reset (&dpo);
589  flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
590  }
591 
592  vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
593  flood_class;
594  }
595  else
596  {
597  /* deleting a tunnel: tunnel must exist */
598  if (!p)
599  return VNET_API_ERROR_NO_SUCH_ENTRY;
600 
601  u32 instance = is_ip6 ? key6.value :
603  vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, instance);
604 
605  sw_if_index = t->sw_if_index;
606  vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */ );
607 
609 
610  if (!is_ip6)
611  clib_bihash_add_del_16_8 (&vxm->vxlan4_tunnel_by_key, &key4,
612  0 /*del */ );
613  else
614  clib_bihash_add_del_24_8 (&vxm->vxlan6_tunnel_by_key, &key6,
615  0 /*del */ );
616 
617  if (!ip46_address_is_multicast (&t->dst))
618  {
619  if (t->flow_index != ~0)
620  vnet_flow_del (vnm, t->flow_index);
621 
622  vtep_addr_unref (&t->src);
624  }
625  else if (vtep_addr_unref (&t->dst) == 0)
626  {
627  mcast_shared_remove (&t->dst);
628  }
629 
632 
633  fib_node_deinit (&t->node);
634  pool_put (vxm->tunnels, t);
635  }
636 
637  if (sw_if_indexp)
638  *sw_if_indexp = sw_if_index;
639 
640  if (a->is_add)
641  {
642  /* register udp ports */
643  if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_vxlan, 1))
644  udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_vxlan,
645  vxlan4_input_node.index, 1);
646  if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_vxlan6, 0))
647  udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_vxlan6,
648  vxlan6_input_node.index, 0);
649  }
650 
651  return 0;
652 }
653 
654 static uword
655 get_decap_next_for_node (u32 node_index, u32 ipv4_set)
656 {
657  vxlan_main_t *vxm = &vxlan_main;
658  vlib_main_t *vm = vxm->vlib_main;
659  uword input_node = (ipv4_set) ? vxlan4_input_node.index :
660  vxlan6_input_node.index;
661 
662  return vlib_node_add_next (vm, input_node, node_index);
663 }
664 
665 static uword
666 unformat_decap_next (unformat_input_t * input, va_list * args)
667 {
668  u32 *result = va_arg (*args, u32 *);
669  u32 ipv4_set = va_arg (*args, int);
670  vxlan_main_t *vxm = &vxlan_main;
671  vlib_main_t *vm = vxm->vlib_main;
672  u32 node_index;
673  u32 tmp;
674 
675  if (unformat (input, "l2"))
676  *result = VXLAN_INPUT_NEXT_L2_INPUT;
677  else if (unformat (input, "node %U", unformat_vlib_node, vm, &node_index))
678  *result = get_decap_next_for_node (node_index, ipv4_set);
679  else if (unformat (input, "%d", &tmp))
680  *result = tmp;
681  else
682  return 0;
683  return 1;
684 }
685 
686 static clib_error_t *
688  unformat_input_t * input,
689  vlib_cli_command_t * cmd)
690 {
691  unformat_input_t _line_input, *line_input = &_line_input;
692  ip46_address_t src = ip46_address_initializer, dst =
694  u8 is_add = 1;
695  u8 src_set = 0;
696  u8 dst_set = 0;
697  u8 grp_set = 0;
698  u8 ipv4_set = 0;
699  u8 ipv6_set = 0;
700  u32 instance = ~0;
701  u32 encap_fib_index = 0;
702  u32 mcast_sw_if_index = ~0;
703  u32 decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
704  u32 vni = 0;
705  u32 table_id;
706  clib_error_t *parse_error = NULL;
707 
708  /* Get a line of input. */
709  if (!unformat_user (input, unformat_line_input, line_input))
710  return 0;
711 
712  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
713  {
714  if (unformat (line_input, "del"))
715  {
716  is_add = 0;
717  }
718  else if (unformat (line_input, "instance %d", &instance))
719  ;
720  else if (unformat (line_input, "src %U",
722  {
723  src_set = 1;
724  ip46_address_is_ip4 (&src) ? (ipv4_set = 1) : (ipv6_set = 1);
725  }
726  else if (unformat (line_input, "dst %U",
728  {
729  dst_set = 1;
730  ip46_address_is_ip4 (&dst) ? (ipv4_set = 1) : (ipv6_set = 1);
731  }
732  else if (unformat (line_input, "group %U %U",
735  vnet_get_main (), &mcast_sw_if_index))
736  {
737  grp_set = dst_set = 1;
738  ip46_address_is_ip4 (&dst) ? (ipv4_set = 1) : (ipv6_set = 1);
739  }
740  else if (unformat (line_input, "encap-vrf-id %d", &table_id))
741  {
742  encap_fib_index =
743  fib_table_find (fib_ip_proto (ipv6_set), table_id);
744  }
745  else if (unformat (line_input, "decap-next %U", unformat_decap_next,
746  &decap_next_index, ipv4_set))
747  ;
748  else if (unformat (line_input, "vni %d", &vni))
749  ;
750  else
751  {
752  parse_error = clib_error_return (0, "parse error: '%U'",
753  format_unformat_error, line_input);
754  break;
755  }
756  }
757 
758  unformat_free (line_input);
759 
760  if (parse_error)
761  return parse_error;
762 
763  if (encap_fib_index == ~0)
764  return clib_error_return (0, "nonexistent encap-vrf-id %d", table_id);
765 
766  if (src_set == 0)
767  return clib_error_return (0, "tunnel src address not specified");
768 
769  if (dst_set == 0)
770  return clib_error_return (0, "tunnel dst address not specified");
771 
772  if (grp_set && !ip46_address_is_multicast (&dst))
773  return clib_error_return (0, "tunnel group address not multicast");
774 
775  if (grp_set == 0 && ip46_address_is_multicast (&dst))
776  return clib_error_return (0, "dst address must be unicast");
777 
778  if (grp_set && mcast_sw_if_index == ~0)
779  return clib_error_return (0, "tunnel nonexistent multicast device");
780 
781  if (ipv4_set && ipv6_set)
782  return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
783 
784  if (ip46_address_cmp (&src, &dst) == 0)
785  return clib_error_return (0, "src and dst addresses are identical");
786 
787  if (decap_next_index == ~0)
788  return clib_error_return (0, "next node not found");
789 
790  if (vni == 0)
791  return clib_error_return (0, "vni not specified");
792 
793  if (vni >> 24)
794  return clib_error_return (0, "vni %d out of range", vni);
795 
797  .is_add = is_add,
798  .is_ip6 = ipv6_set,
799  .instance = instance,
800 #define _(x) .x = x,
802 #undef _
803  };
804 
805  u32 tunnel_sw_if_index;
806  int rv = vnet_vxlan_add_del_tunnel (&a, &tunnel_sw_if_index);
807 
808  switch (rv)
809  {
810  case 0:
811  if (is_add)
813  vnet_get_main (), tunnel_sw_if_index);
814  break;
815 
816  case VNET_API_ERROR_TUNNEL_EXIST:
817  return clib_error_return (0, "tunnel already exists...");
818 
819  case VNET_API_ERROR_NO_SUCH_ENTRY:
820  return clib_error_return (0, "tunnel does not exist...");
821 
822  case VNET_API_ERROR_INSTANCE_IN_USE:
823  return clib_error_return (0, "Instance is in use");
824 
825  default:
826  return clib_error_return
827  (0, "vnet_vxlan_add_del_tunnel returned %d", rv);
828  }
829 
830  return 0;
831 }
832 
833 /*?
834  * Add or delete a VXLAN Tunnel.
835  *
836  * VXLAN provides the features needed to allow L2 bridge domains (BDs)
837  * to span multiple servers. This is done by building an L2 overlay on
838  * top of an L3 network underlay using VXLAN tunnels.
839  *
840  * This makes it possible for servers to be co-located in the same data
841  * center or be separated geographically as long as they are reachable
842  * through the underlay L3 network.
843  *
844  * You can refer to this kind of L2 overlay bridge domain as a VXLAN
845  * (Virtual eXtensible VLAN) segment.
846  *
847  * @cliexpar
848  * Example of how to create a VXLAN Tunnel:
849  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 encap-vrf-id 7}
850  * Example of how to create a VXLAN Tunnel with a known name, vxlan_tunnel42:
851  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 instance 42}
852  * Example of how to create a multicast VXLAN Tunnel with a known name, vxlan_tunnel23:
853  * @cliexcmd{create vxlan tunnel src 10.0.3.1 group 239.1.1.1 GigabitEthernet0/8/0 instance 23}
854  * Example of how to delete a VXLAN Tunnel:
855  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 del}
856  ?*/
857 /* *INDENT-OFF* */
858 VLIB_CLI_COMMAND (create_vxlan_tunnel_command, static) = {
859  .path = "create vxlan tunnel",
860  .short_help =
861  "create vxlan tunnel src <local-vtep-addr>"
862  " {dst <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} vni <nn>"
863  " [instance <id>]"
864  " [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [del]",
866 };
867 /* *INDENT-ON* */
868 
869 static clib_error_t *
871  unformat_input_t * input,
872  vlib_cli_command_t * cmd)
873 {
874  vxlan_main_t *vxm = &vxlan_main;
875  vxlan_tunnel_t *t;
876  int raw = 0;
877 
879  {
880  if (unformat (input, "raw"))
881  raw = 1;
882  else
883  return clib_error_return (0, "parse error: '%U'",
884  format_unformat_error, input);
885  }
886 
887  if (pool_elts (vxm->tunnels) == 0)
888  vlib_cli_output (vm, "No vxlan tunnels configured...");
889 
890 /* *INDENT-OFF* */
891  pool_foreach (t, vxm->tunnels,
892  ({
893  vlib_cli_output (vm, "%U", format_vxlan_tunnel, t);
894  }));
895 /* *INDENT-ON* */
896 
897  if (raw)
898  {
899  vlib_cli_output (vm, "Raw IPv4 Hash Table:\n%U\n",
900  format_bihash_16_8, &vxm->vxlan4_tunnel_by_key,
901  1 /* verbose */ );
902  vlib_cli_output (vm, "Raw IPv6 Hash Table:\n%U\n",
903  format_bihash_24_8, &vxm->vxlan6_tunnel_by_key,
904  1 /* verbose */ );
905  }
906 
907  return 0;
908 }
909 
910 /*?
911  * Display all the VXLAN Tunnel entries.
912  *
913  * @cliexpar
914  * Example of how to display the VXLAN Tunnel entries:
915  * @cliexstart{show vxlan tunnel}
916  * [0] src 10.0.3.1 dst 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
917  * @cliexend
918  ?*/
919 /* *INDENT-OFF* */
920 VLIB_CLI_COMMAND (show_vxlan_tunnel_command, static) = {
921  .path = "show vxlan tunnel",
922  .short_help = "show vxlan tunnel [raw]",
923  .function = show_vxlan_tunnel_command_fn,
924 };
925 /* *INDENT-ON* */
926 
927 
928 void
930 {
931  vxlan_main_t *vxm = &vxlan_main;
932 
934  sw_if_index))
935  return;
936 
937  is_enable = ! !is_enable;
938 
939  if (is_ip6)
940  {
941  if (clib_bitmap_get (vxm->bm_ip6_bypass_enabled_by_sw_if, sw_if_index)
942  != is_enable)
943  {
944  vnet_feature_enable_disable ("ip6-unicast", "ip6-vxlan-bypass",
945  sw_if_index, is_enable, 0, 0);
948  sw_if_index, is_enable);
949  }
950  }
951  else
952  {
953  if (clib_bitmap_get (vxm->bm_ip4_bypass_enabled_by_sw_if, sw_if_index)
954  != is_enable)
955  {
956  vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
957  sw_if_index, is_enable, 0, 0);
960  sw_if_index, is_enable);
961  }
962  }
963 }
964 
965 
966 static clib_error_t *
968  unformat_input_t * input, vlib_cli_command_t * cmd)
969 {
970  unformat_input_t _line_input, *line_input = &_line_input;
971  vnet_main_t *vnm = vnet_get_main ();
972  clib_error_t *error = 0;
973  u32 sw_if_index, is_enable;
974 
975  sw_if_index = ~0;
976  is_enable = 1;
977 
978  if (!unformat_user (input, unformat_line_input, line_input))
979  return 0;
980 
981  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
982  {
983  if (unformat_user
984  (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
985  ;
986  else if (unformat (line_input, "del"))
987  is_enable = 0;
988  else
989  {
990  error = unformat_parse_error (line_input);
991  goto done;
992  }
993  }
994 
995  if (~0 == sw_if_index)
996  {
997  error = clib_error_return (0, "unknown interface `%U'",
998  format_unformat_error, line_input);
999  goto done;
1000  }
1001 
1002  vnet_int_vxlan_bypass_mode (sw_if_index, is_ip6, is_enable);
1003 
1004 done:
1005  unformat_free (line_input);
1006 
1007  return error;
1008 }
1009 
1010 static clib_error_t *
1012  unformat_input_t * input, vlib_cli_command_t * cmd)
1013 {
1014  return set_ip_vxlan_bypass (0, input, cmd);
1015 }
1016 
1017 /*?
1018  * This command adds the 'ip4-vxlan-bypass' graph node for a given interface.
1019  * By adding the IPv4 vxlan-bypass graph node to an interface, the node checks
1020  * for and validate input vxlan packet and bypass ip4-lookup, ip4-local,
1021  * ip4-udp-lookup nodes to speedup vxlan packet forwarding. This node will
1022  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
1023  *
1024  * @cliexpar
1025  * @parblock
1026  * Example of graph node before ip4-vxlan-bypass is enabled:
1027  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1028  * Name Next Previous
1029  * ip4-vxlan-bypass error-drop [0]
1030  * vxlan4-input [1]
1031  * ip4-lookup [2]
1032  * @cliexend
1033  *
1034  * Example of how to enable ip4-vxlan-bypass on an interface:
1035  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0}
1036  *
1037  * Example of graph node after ip4-vxlan-bypass is enabled:
1038  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1039  * Name Next Previous
1040  * ip4-vxlan-bypass error-drop [0] ip4-input
1041  * vxlan4-input [1] ip4-input-no-checksum
1042  * ip4-lookup [2]
1043  * @cliexend
1044  *
1045  * Example of how to display the feature enabled on an interface:
1046  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1047  * IP feature paths configured on GigabitEthernet2/0/0...
1048  * ...
1049  * ipv4 unicast:
1050  * ip4-vxlan-bypass
1051  * ip4-lookup
1052  * ...
1053  * @cliexend
1054  *
1055  * Example of how to disable ip4-vxlan-bypass on an interface:
1056  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0 del}
1057  * @endparblock
1058 ?*/
1059 /* *INDENT-OFF* */
1060 VLIB_CLI_COMMAND (set_interface_ip_vxlan_bypass_command, static) = {
1061  .path = "set interface ip vxlan-bypass",
1062  .function = set_ip4_vxlan_bypass,
1063  .short_help = "set interface ip vxlan-bypass <interface> [del]",
1064 };
1065 /* *INDENT-ON* */
1066 
1067 static clib_error_t *
1069  unformat_input_t * input, vlib_cli_command_t * cmd)
1070 {
1071  return set_ip_vxlan_bypass (1, input, cmd);
1072 }
1073 
1074 /*?
1075  * This command adds the 'ip6-vxlan-bypass' graph node for a given interface.
1076  * By adding the IPv6 vxlan-bypass graph node to an interface, the node checks
1077  * for and validate input vxlan packet and bypass ip6-lookup, ip6-local,
1078  * ip6-udp-lookup nodes to speedup vxlan packet forwarding. This node will
1079  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
1080  *
1081  * @cliexpar
1082  * @parblock
1083  * Example of graph node before ip6-vxlan-bypass is enabled:
1084  * @cliexstart{show vlib graph ip6-vxlan-bypass}
1085  * Name Next Previous
1086  * ip6-vxlan-bypass error-drop [0]
1087  * vxlan6-input [1]
1088  * ip6-lookup [2]
1089  * @cliexend
1090  *
1091  * Example of how to enable ip6-vxlan-bypass on an interface:
1092  * @cliexcmd{set interface ip6 vxlan-bypass GigabitEthernet2/0/0}
1093  *
1094  * Example of graph node after ip6-vxlan-bypass is enabled:
1095  * @cliexstart{show vlib graph ip6-vxlan-bypass}
1096  * Name Next Previous
1097  * ip6-vxlan-bypass error-drop [0] ip6-input
1098  * vxlan6-input [1] ip4-input-no-checksum
1099  * ip6-lookup [2]
1100  * @cliexend
1101  *
1102  * Example of how to display the feature enabled on an interface:
1103  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1104  * IP feature paths configured on GigabitEthernet2/0/0...
1105  * ...
1106  * ipv6 unicast:
1107  * ip6-vxlan-bypass
1108  * ip6-lookup
1109  * ...
1110  * @cliexend
1111  *
1112  * Example of how to disable ip6-vxlan-bypass on an interface:
1113  * @cliexcmd{set interface ip6 vxlan-bypass GigabitEthernet2/0/0 del}
1114  * @endparblock
1115 ?*/
1116 /* *INDENT-OFF* */
1117 VLIB_CLI_COMMAND (set_interface_ip6_vxlan_bypass_command, static) = {
1118  .path = "set interface ip6 vxlan-bypass",
1119  .function = set_ip6_vxlan_bypass,
1120  .short_help = "set interface ip6 vxlan-bypass <interface> [del]",
1121 };
1122 /* *INDENT-ON* */
1123 
1124 int
1125 vnet_vxlan_add_del_rx_flow (u32 hw_if_index, u32 t_index, int is_add)
1126 {
1127  vxlan_main_t *vxm = &vxlan_main;
1128  vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
1129  vnet_main_t *vnm = vnet_get_main ();
1130  if (is_add)
1131  {
1132  if (t->flow_index == ~0)
1133  {
1134  vxlan_main_t *vxm = &vxlan_main;
1135  vnet_flow_t flow = {
1136  .actions =
1137  VNET_FLOW_ACTION_REDIRECT_TO_NODE | VNET_FLOW_ACTION_MARK |
1138  VNET_FLOW_ACTION_BUFFER_ADVANCE,
1139  .mark_flow_id = t->dev_instance + vxm->flow_id_start,
1140  .redirect_node_index = vxlan4_flow_input_node.index,
1141  .buffer_advance = sizeof (ethernet_header_t),
1142  .type = VNET_FLOW_TYPE_IP4_VXLAN,
1143  .ip4_vxlan = {
1144  .src_addr = t->dst.ip4,
1145  .dst_addr = t->src.ip4,
1146  .dst_port = UDP_DST_PORT_vxlan,
1147  .vni = t->vni,
1148  }
1149  ,
1150  };
1151  vnet_flow_add (vnm, &flow, &t->flow_index);
1152  }
1153  return vnet_flow_enable (vnm, t->flow_index, hw_if_index);
1154  }
1155  /* flow index is removed when the tunnel is deleted */
1156  return vnet_flow_disable (vnm, t->flow_index, hw_if_index);
1157 }
1158 
1159 u32
1161 {
1162  vxlan_main_t *vxm = &vxlan_main;
1163 
1164  if (sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index))
1165  return ~0;
1167 }
1168 
1169 static clib_error_t *
1171  unformat_input_t * input, vlib_cli_command_t * cmd)
1172 {
1173  unformat_input_t _line_input, *line_input = &_line_input;
1174 
1175  /* Get a line of input. */
1176  if (!unformat_user (input, unformat_line_input, line_input))
1177  return 0;
1178 
1179  vnet_main_t *vnm = vnet_get_main ();
1180  u32 rx_sw_if_index = ~0;
1181  u32 hw_if_index = ~0;
1182  int is_add = 1;
1183 
1184  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1185  {
1186  if (unformat (line_input, "hw %U", unformat_vnet_hw_interface, vnm,
1187  &hw_if_index))
1188  continue;
1189  if (unformat (line_input, "rx %U", unformat_vnet_sw_interface, vnm,
1190  &rx_sw_if_index))
1191  continue;
1192  if (unformat (line_input, "del"))
1193  {
1194  is_add = 0;
1195  continue;
1196  }
1197  return clib_error_return (0, "unknown input `%U'",
1198  format_unformat_error, line_input);
1199  }
1200 
1201  if (rx_sw_if_index == ~0)
1202  return clib_error_return (0, "missing rx interface");
1203  if (hw_if_index == ~0)
1204  return clib_error_return (0, "missing hw interface");
1205 
1206  u32 t_index = vnet_vxlan_get_tunnel_index (rx_sw_if_index);;
1207  if (t_index == ~0)
1208  return clib_error_return (0, "%U is not a vxlan tunnel",
1210  rx_sw_if_index);
1211 
1212  vxlan_main_t *vxm = &vxlan_main;
1213  vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
1214 
1215  if (!ip46_address_is_ip4 (&t->dst))
1216  return clib_error_return (0, "currently only IPV4 tunnels are supported");
1217 
1218  vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1219  ip4_main_t *im = &ip4_main;
1220  u32 rx_fib_index =
1222 
1223  if (t->encap_fib_index != rx_fib_index)
1224  return clib_error_return (0, "interface/tunnel fib mismatch");
1225 
1226  if (vnet_vxlan_add_del_rx_flow (hw_if_index, t_index, is_add))
1227  return clib_error_return (0, "error %s flow",
1228  is_add ? "enabling" : "disabling");
1229 
1230  return 0;
1231 }
1232 
1233 /* *INDENT-OFF* */
1234 VLIB_CLI_COMMAND (vxlan_offload_command, static) = {
1235  .path = "set flow-offload vxlan",
1236  .short_help =
1237  "set flow-offload vxlan hw <interface-name> rx <tunnel-name> [del]",
1238  .function = vxlan_offload_command_fn,
1239 };
1240 /* *INDENT-ON* */
1241 
1242 #define VXLAN_HASH_NUM_BUCKETS (2 * 1024)
1243 #define VXLAN_HASH_MEMORY_SIZE (1 << 20)
1244 
1245 clib_error_t *
1247 {
1248  vxlan_main_t *vxm = &vxlan_main;
1249 
1250  vxm->vnet_main = vnet_get_main ();
1251  vxm->vlib_main = vm;
1252 
1253  vnet_flow_get_range (vxm->vnet_main, "vxlan", 1024 * 1024,
1254  &vxm->flow_id_start);
1255 
1258 
1259  /* initialize the ip6 hash */
1260  clib_bihash_init_16_8 (&vxm->vxlan4_tunnel_by_key, "vxlan4",
1262  clib_bihash_init_24_8 (&vxm->vxlan6_tunnel_by_key, "vxlan6",
1264  vxm->vtep6 = hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword));
1265  vxm->mcast_shared = hash_create_mem (0,
1266  sizeof (ip46_address_t),
1267  sizeof (mcast_shared_t));
1268 
1270 
1271  return 0;
1272 }
1273 
1275 
1276 /*
1277  * fd.io coding-style-patch-verification: ON
1278  *
1279  * Local Variables:
1280  * eval: (c-set-style "gnu")
1281  * End:
1282  */
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:440
void vnet_set_interface_output_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Set interface output node - for interface registered without its output/tx nodes created because its ...
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:130
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 sibling_index
The tunnel is a child of the FIB entry for its destination.
Definition: vxlan.h:126
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
clib_bihash_24_8_t vxlan6_tunnel_by_key
Definition: vxlan.h:162
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
uword * vtep6
Definition: vxlan.h:167
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_interface_main_t interface_main
Definition: vnet.h:56
clib_error_t * vxlan_init(vlib_main_t *vm)
Definition: vxlan.c:1246
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:1068
u32 frp_mitf_flags
MFIB interface flags.
Definition: fib_types.h:554
static mcast_shared_t mcast_shared_get(ip46_address_t *ip)
Definition: geneve.c:335
unsigned long u64
Definition: types.h:89
u32 flow_id_start
Definition: vxlan.h:185
#define NULL
Definition: clib.h:58
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:324
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:93
#define vnet_rewrite_set_data(rw, data, data_bytes)
Definition: rewrite.h:140
static void mcast_shared_remove(ip46_address_t *dst)
Definition: vxlan.c:357
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:60
static clib_error_t * set_ip4_vxlan_bypass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:1011
vlib_node_registration_t vxlan4_flow_input_node
(constructor) VLIB_REGISTER_NODE (vxlan4_flow_input_node)
Definition: decap.c:1291
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: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)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:121
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:307
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
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:870
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:745
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:498
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:525
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
void mfib_table_entry_delete_index(fib_node_index_t mfib_entry_index, mfib_source_t source)
Delete a FIB entry.
Definition: mfib_table.c:517
ip4_address_t dst_address
Definition: ip4_packet.h:170
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:324
unsigned int u32
Definition: types.h:88
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1097
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:687
fib_node_t node
Linkage into the FIB object graph.
Definition: vxlan.h:111
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:762
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:519
static clib_error_t * vxlan_offload_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vxlan.c:1170
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
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:74
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
u32 vni
Definition: lisp_gpe.api:129
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:102
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:287
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:111
vnet_sw_interface_flags_t flags
Definition: interface.h:720
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:61
vlib_main_t * vm
Definition: in2out_ed.c:1810
u8 * format_vxlan_encap_trace(u8 *s, va_list *args)
Definition: encap.c:53
u8 len
Definition: ip_types.api:91
static uword vtep_addr_unref(ip46_address_t *ip)
Definition: vxlan.c:309
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:231
int vnet_vxlan_add_del_rx_flow(u32 hw_if_index, u32 t_index, int is_add)
Definition: vxlan.c:1125
int vnet_vxlan_add_del_tunnel(vnet_vxlan_add_del_tunnel_args_t *a, u32 *sw_if_indexp)
Definition: vxlan.c:368
u8 is_ip4
Definition: lisp_gpe.api:232
u32 dev_instance
Definition: vxlan.h:129
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:141
u32 mcast_sw_if_index
Definition: vxlan.h:96
vnet_flood_class_t
Definition: interface.h:661
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
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:284
static void vnet_set_vni_and_flags(vxlan_header_t *h, u32 vni)
Definition: vxlan_packet.h:62
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:666
void fib_prefix_from_ip46_addr(const ip46_address_t *addr, fib_prefix_t *pfx)
Host prefix from ip.
Definition: fib_types.c:81
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
Aggregate type for a prefix.
Definition: mfib_types.h:24
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
u8 * default_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Return a complete, zero-length (aka dummy) rewrite.
Definition: interface.c:1629
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
static 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.
static void mcast_shared_add(ip46_address_t *dst, fib_node_index_t mfei, adj_index_t ai)
Definition: vxlan.c:346
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:105
uword * vtep4
Definition: vxlan.h:166
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:595
format_function_t format_flow_enabled_hw
Definition: flow.h:236
static void hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
u32 sw_if_index
Definition: vxlan.h:105
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:260
static uword get_decap_next_for_node(u32 node_index, u32 ipv4_set)
Definition: vxlan.c:655
u32 hw_if_index
Definition: vxlan.h:106
u32 vnet_vxlan_get_tunnel_index(u32 sw_if_index)
Definition: vxlan.c:1160
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
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:974
static uword vtep_addr_ref(ip46_address_t *ip)
Definition: vxlan.c:295
#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:294
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
l2input_main_t l2input_main
Definition: l2_input.c:128
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:929
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)
u32 instance
Definition: gre.api:57
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:967
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
fib_node_index_t fib_entry_index
Definition: vxlan.h:117
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:854
u32 encap_fib_index
Definition: vxlan.h:102
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
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:1147
u16 decap_next_index
Definition: vxlan.h:99
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:480
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:1079
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
clib_bihash_16_8_t vxlan4_tunnel_by_key
Definition: vxlan.h:161
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:493
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:294
dpo_id_t next_dpo
Definition: vxlan.h:86
static void hash_set_mem_alloc(uword **h, const void *key, uword v)
Definition: hash.h:279
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:471
VNET_HW_INTERFACE_CLASS(vxlan_hw_class)
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
#define VXLAN_HASH_NUM_BUCKETS
Definition: vxlan.c:1242
u32 table_id
Definition: fib_types.api:118
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:487
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static bool vxlan_decap_next_is_valid(vxlan_main_t *vxm, u32 is_ip6, u32 decap_next_index)
Definition: vxlan.c:283
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
vxlan_tunnel_t * tunnels
Definition: vxlan.h:158
#define ip46_address_initializer
Definition: ip46_address.h:52
#define VXLAN_HASH_MEMORY_SIZE
Definition: vxlan.c:1243
icmpr_flow_t * flow
Definition: main.c:123
const ip46_address_t zero_addr
Definition: lookup.c:307
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
ip46_address_t src
Definition: vxlan.h:92
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:304
ip6_address_t dst_address
Definition: ip6_packet.h:307
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
u32 flow_index
Definition: vxlan.h:128
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128