vnet: add set_max_frame_size callbacks for several interfaces
[vpp.git] / src / vnet / vxlan / vxlan.c
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>
19 #include <vnet/fib/fib_entry_track.h>
20 #include <vnet/mfib/mfib_table.h>
21 #include <vnet/adj/adj_mcast.h>
22 #include <vnet/adj/rewrite.h>
23 #include <vnet/dpo/drop_dpo.h>
24 #include <vnet/interface.h>
25 #include <vnet/flow/flow.h>
26 #include <vnet/udp/udp_local.h>
27 #include <vlib/vlib.h>
28
29 /**
30  * @file
31  * @brief VXLAN.
32  *
33  * VXLAN provides the features needed to allow L2 bridge domains (BDs)
34  * to span multiple servers. This is done by building an L2 overlay on
35  * top of an L3 network underlay using VXLAN tunnels.
36  *
37  * This makes it possible for servers to be co-located in the same data
38  * center or be separated geographically as long as they are reachable
39  * through the underlay L3 network.
40  *
41  * You can refer to this kind of L2 overlay bridge domain as a VXLAN
42  * (Virtual eXtensible VLAN) segment.
43  */
44
45
46 vxlan_main_t vxlan_main;
47
48 static u32
49 vxlan_eth_flag_change (vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
50 {
51   /* nothing for now */
52   return 0;
53 }
54
55 static clib_error_t *
56 vxlan_eth_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hw,
57                               u32 frame_size)
58 {
59   /* nothing for now */
60   return 0;
61 }
62
63 static u8 *
64 format_decap_next (u8 * s, va_list * args)
65 {
66   u32 next_index = va_arg (*args, u32);
67
68   if (next_index == VXLAN_INPUT_NEXT_DROP)
69     return format (s, "drop");
70   else
71     return format (s, "index %d", next_index);
72   return s;
73 }
74
75 u8 *
76 format_vxlan_tunnel (u8 * s, va_list * args)
77 {
78   vxlan_tunnel_t *t = va_arg (*args, vxlan_tunnel_t *);
79
80   s = format (s,
81               "[%d] instance %d src %U dst %U src_port %d dst_port %d vni %d "
82               "fib-idx %d sw-if-idx %d ",
83               t->dev_instance, t->user_instance, format_ip46_address, &t->src,
84               IP46_TYPE_ANY, format_ip46_address, &t->dst, IP46_TYPE_ANY,
85               t->src_port, t->dst_port, t->vni, t->encap_fib_index,
86               t->sw_if_index);
87
88   s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
89
90   if (PREDICT_FALSE (t->decap_next_index != VXLAN_INPUT_NEXT_L2_INPUT))
91     s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index);
92
93   s = format (s, "l3 %u ", t->is_l3);
94
95   if (PREDICT_FALSE (ip46_address_is_multicast (&t->dst)))
96     s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index);
97
98   if (t->flow_index != ~0)
99     s = format (s, "flow-index %d [%U]", t->flow_index,
100                 format_flow_enabled_hw, t->flow_index);
101
102   return s;
103 }
104
105 static u8 *
106 format_vxlan_name (u8 * s, va_list * args)
107 {
108   u32 dev_instance = va_arg (*args, u32);
109   vxlan_main_t *vxm = &vxlan_main;
110   vxlan_tunnel_t *t;
111
112   if (dev_instance == ~0)
113     return format (s, "<cached-unused>");
114
115   if (dev_instance >= vec_len (vxm->tunnels))
116     return format (s, "<improperly-referenced>");
117
118   t = pool_elt_at_index (vxm->tunnels, dev_instance);
119
120   return format (s, "vxlan_tunnel%d", t->user_instance);
121 }
122
123 static clib_error_t *
124 vxlan_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
125 {
126   u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
127     VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
128   vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
129
130   return /* no error */ 0;
131 }
132
133 /* *INDENT-OFF* */
134 VNET_DEVICE_CLASS (vxlan_device_class, static) = {
135   .name = "VXLAN",
136   .format_device_name = format_vxlan_name,
137   .format_tx_trace = format_vxlan_encap_trace,
138   .admin_up_down_function = vxlan_interface_admin_up_down,
139 };
140 /* *INDENT-ON* */
141
142 static u8 *
143 format_vxlan_header_with_length (u8 * s, va_list * args)
144 {
145   u32 dev_instance = va_arg (*args, u32);
146   s = format (s, "unimplemented dev %u", dev_instance);
147   return s;
148 }
149
150 /* *INDENT-OFF* */
151 VNET_HW_INTERFACE_CLASS (vxlan_hw_class) = {
152   .name = "VXLAN",
153   .format_header = format_vxlan_header_with_length,
154   .build_rewrite = default_build_rewrite,
155 };
156 /* *INDENT-ON* */
157
158 static void
159 vxlan_tunnel_restack_dpo (vxlan_tunnel_t * t)
160 {
161   u8 is_ip4 = ip46_address_is_ip4 (&t->dst);
162   dpo_id_t dpo = DPO_INVALID;
163   fib_forward_chain_type_t forw_type = is_ip4 ?
164     FIB_FORW_CHAIN_TYPE_UNICAST_IP4 : FIB_FORW_CHAIN_TYPE_UNICAST_IP6;
165
166   fib_entry_contribute_forwarding (t->fib_entry_index, forw_type, &dpo);
167
168   /* vxlan uses the payload hash as the udp source port
169    * hence the packet's hash is unknown
170    * skip single bucket load balance dpo's */
171   while (DPO_LOAD_BALANCE == dpo.dpoi_type)
172     {
173       const load_balance_t *lb;
174       const dpo_id_t *choice;
175
176       lb = load_balance_get (dpo.dpoi_index);
177       if (lb->lb_n_buckets > 1)
178         break;
179
180       choice = load_balance_get_bucket_i (lb, 0);
181
182       if (DPO_RECEIVE == choice->dpoi_type)
183         dpo_copy (&dpo, drop_dpo_get (choice->dpoi_proto));
184       else
185         dpo_copy (&dpo, choice);
186     }
187
188   u32 encap_index = is_ip4 ?
189     vxlan4_encap_node.index : vxlan6_encap_node.index;
190   dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
191   dpo_reset (&dpo);
192 }
193
194 static vxlan_tunnel_t *
195 vxlan_tunnel_from_fib_node (fib_node_t * node)
196 {
197   ASSERT (FIB_NODE_TYPE_VXLAN_TUNNEL == node->fn_type);
198   return ((vxlan_tunnel_t *) (((char *) node) -
199                               STRUCT_OFFSET_OF (vxlan_tunnel_t, node)));
200 }
201
202 /**
203  * Function definition to backwalk a FIB node -
204  * Here we will restack the new dpo of VXLAN DIP to encap node.
205  */
206 static fib_node_back_walk_rc_t
207 vxlan_tunnel_back_walk (fib_node_t * node, fib_node_back_walk_ctx_t * ctx)
208 {
209   vxlan_tunnel_restack_dpo (vxlan_tunnel_from_fib_node (node));
210   return (FIB_NODE_BACK_WALK_CONTINUE);
211 }
212
213 /**
214  * Function definition to get a FIB node from its index
215  */
216 static fib_node_t *
217 vxlan_tunnel_fib_node_get (fib_node_index_t index)
218 {
219   vxlan_tunnel_t *t;
220   vxlan_main_t *vxm = &vxlan_main;
221
222   t = pool_elt_at_index (vxm->tunnels, index);
223
224   return (&t->node);
225 }
226
227 /**
228  * Function definition to inform the FIB node that its last lock has gone.
229  */
230 static void
231 vxlan_tunnel_last_lock_gone (fib_node_t * node)
232 {
233   /*
234    * The VXLAN tunnel is a root of the graph. As such
235    * it never has children and thus is never locked.
236    */
237   ASSERT (0);
238 }
239
240 /*
241  * Virtual function table registered by VXLAN tunnels
242  * for participation in the FIB object graph.
243  */
244 const static fib_node_vft_t vxlan_vft = {
245   .fnv_get = vxlan_tunnel_fib_node_get,
246   .fnv_last_lock = vxlan_tunnel_last_lock_gone,
247   .fnv_back_walk = vxlan_tunnel_back_walk,
248 };
249
250 #define foreach_copy_field                                                    \
251   _ (vni)                                                                     \
252   _ (mcast_sw_if_index)                                                       \
253   _ (encap_fib_index)                                                         \
254   _ (decap_next_index)                                                        \
255   _ (src)                                                                     \
256   _ (dst)                                                                     \
257   _ (src_port)                                                                \
258   _ (dst_port)                                                                \
259   _ (is_l3)
260
261 static void
262 vxlan_rewrite (vxlan_tunnel_t * t, bool is_ip6)
263 {
264   union
265   {
266     ip4_vxlan_header_t h4;
267     ip6_vxlan_header_t h6;
268   } h;
269   int len = is_ip6 ? sizeof h.h6 : sizeof h.h4;
270
271   udp_header_t *udp;
272   vxlan_header_t *vxlan;
273   /* Fixed portion of the (outer) ip header */
274
275   clib_memset (&h, 0, sizeof (h));
276   if (!is_ip6)
277     {
278       ip4_header_t *ip = &h.h4.ip4;
279       udp = &h.h4.udp, vxlan = &h.h4.vxlan;
280       ip->ip_version_and_header_length = 0x45;
281       ip->ttl = 254;
282       ip->protocol = IP_PROTOCOL_UDP;
283
284       ip->src_address = t->src.ip4;
285       ip->dst_address = t->dst.ip4;
286
287       /* we fix up the ip4 header length and checksum after-the-fact */
288       ip->checksum = ip4_header_checksum (ip);
289     }
290   else
291     {
292       ip6_header_t *ip = &h.h6.ip6;
293       udp = &h.h6.udp, vxlan = &h.h6.vxlan;
294       ip->ip_version_traffic_class_and_flow_label =
295         clib_host_to_net_u32 (6 << 28);
296       ip->hop_limit = 255;
297       ip->protocol = IP_PROTOCOL_UDP;
298
299       ip->src_address = t->src.ip6;
300       ip->dst_address = t->dst.ip6;
301     }
302
303   /* UDP header, randomize src port on something, maybe? */
304   udp->src_port = clib_host_to_net_u16 (t->src_port);
305   udp->dst_port = clib_host_to_net_u16 (t->dst_port);
306
307   /* VXLAN header */
308   vnet_set_vni_and_flags (vxlan, t->vni);
309   vnet_rewrite_set_data (*t, &h, len);
310 }
311
312 static bool
313 vxlan_decap_next_is_valid (vxlan_main_t * vxm, u32 is_ip6,
314                            u32 decap_next_index)
315 {
316   vlib_main_t *vm = vxm->vlib_main;
317   u32 input_idx = (!is_ip6) ?
318     vxlan4_input_node.index : vxlan6_input_node.index;
319   vlib_node_runtime_t *r = vlib_node_get_runtime (vm, input_idx);
320
321   return decap_next_index < r->n_next_nodes;
322 }
323
324 /* *INDENT-OFF* */
325 typedef CLIB_PACKED(union
326 {
327   struct
328   {
329     fib_node_index_t mfib_entry_index;
330     adj_index_t mcast_adj_index;
331   };
332   u64 as_u64;
333 }) mcast_shared_t;
334 /* *INDENT-ON* */
335
336 static inline mcast_shared_t
337 mcast_shared_get (ip46_address_t * ip)
338 {
339   ASSERT (ip46_address_is_multicast (ip));
340   uword *p = hash_get_mem (vxlan_main.mcast_shared, ip);
341   ALWAYS_ASSERT (p);
342   mcast_shared_t ret = {.as_u64 = *p };
343   return ret;
344 }
345
346 static inline void
347 mcast_shared_add (ip46_address_t * dst, fib_node_index_t mfei, adj_index_t ai)
348 {
349   mcast_shared_t new_ep = {
350     .mcast_adj_index = ai,
351     .mfib_entry_index = mfei,
352   };
353
354   hash_set_mem_alloc (&vxlan_main.mcast_shared, dst, new_ep.as_u64);
355 }
356
357 static inline void
358 mcast_shared_remove (ip46_address_t * dst)
359 {
360   mcast_shared_t ep = mcast_shared_get (dst);
361
362   adj_unlock (ep.mcast_adj_index);
363   mfib_table_entry_delete_index (ep.mfib_entry_index, MFIB_SOURCE_VXLAN);
364
365   hash_unset_mem_free (&vxlan_main.mcast_shared, dst);
366 }
367
368 int vnet_vxlan_add_del_tunnel
369   (vnet_vxlan_add_del_tunnel_args_t * a, u32 * sw_if_indexp)
370 {
371   vxlan_main_t *vxm = &vxlan_main;
372   vnet_main_t *vnm = vxm->vnet_main;
373   vxlan_decap_info_t *p;
374   u32 sw_if_index = ~0;
375   vxlan4_tunnel_key_t key4;
376   vxlan6_tunnel_key_t key6;
377   u32 is_ip6 = a->is_ip6;
378   vlib_main_t *vm = vlib_get_main ();
379   u8 hw_addr[6];
380
381   /* Set udp-ports */
382   if (a->src_port == 0)
383     a->src_port = is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan;
384
385   if (a->dst_port == 0)
386     a->dst_port = is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan;
387
388   int not_found;
389   if (!is_ip6)
390     {
391       /* ip4 mcast is indexed by mcast addr only */
392       key4.key[0] = ip46_address_is_multicast (&a->dst) ?
393                       a->dst.ip4.as_u32 :
394                       a->dst.ip4.as_u32 | (((u64) a->src.ip4.as_u32) << 32);
395       key4.key[1] = ((u64) clib_host_to_net_u16 (a->src_port) << 48) |
396                     (((u64) a->encap_fib_index) << 32) |
397                     clib_host_to_net_u32 (a->vni << 8);
398       not_found =
399         clib_bihash_search_inline_16_8 (&vxm->vxlan4_tunnel_by_key, &key4);
400       p = (void *) &key4.value;
401     }
402   else
403     {
404       key6.key[0] = a->dst.ip6.as_u64[0];
405       key6.key[1] = a->dst.ip6.as_u64[1];
406       key6.key[2] = (((u64) clib_host_to_net_u16 (a->src_port) << 48) |
407                      ((u64) a->encap_fib_index) << 32) |
408                     clib_host_to_net_u32 (a->vni << 8);
409       not_found =
410         clib_bihash_search_inline_24_8 (&vxm->vxlan6_tunnel_by_key, &key6);
411       p = (void *) &key6.value;
412     }
413
414   if (not_found)
415     p = 0;
416
417   if (a->is_add)
418     {
419       l2input_main_t *l2im = &l2input_main;
420       u32 dev_instance;         /* real dev instance tunnel index */
421       u32 user_instance;        /* request and actual instance number */
422
423       /* adding a tunnel: tunnel must not already exist */
424       if (p)
425         return VNET_API_ERROR_TUNNEL_EXIST;
426
427       /*if not set explicitly, default to l2 */
428       if (a->decap_next_index == ~0)
429         a->decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
430       if (!vxlan_decap_next_is_valid (vxm, is_ip6, a->decap_next_index))
431         return VNET_API_ERROR_INVALID_DECAP_NEXT;
432
433       vxlan_tunnel_t *t;
434       pool_get_aligned (vxm->tunnels, t, CLIB_CACHE_LINE_BYTES);
435       clib_memset (t, 0, sizeof (*t));
436       dev_instance = t - vxm->tunnels;
437
438       /* copy from arg structure */
439 #define _(x) t->x = a->x;
440       foreach_copy_field;
441 #undef _
442
443       vxlan_rewrite (t, is_ip6);
444       /*
445        * Reconcile the real dev_instance and a possible requested instance.
446        */
447       user_instance = a->instance;
448       if (user_instance == ~0)
449         user_instance = dev_instance;
450       if (hash_get (vxm->instance_used, user_instance))
451         {
452           pool_put (vxm->tunnels, t);
453           return VNET_API_ERROR_INSTANCE_IN_USE;
454         }
455
456       hash_set (vxm->instance_used, user_instance, 1);
457
458       t->dev_instance = dev_instance;   /* actual */
459       t->user_instance = user_instance; /* name */
460       t->flow_index = ~0;
461
462       if (a->is_l3 == 0)
463         t->hw_if_index =
464           vnet_register_interface (vnm, vxlan_device_class.index, dev_instance,
465                                    vxlan_hw_class.index, dev_instance);
466       else
467         {
468           vnet_eth_interface_registration_t eir = {};
469           f64 now = vlib_time_now (vm);
470           u32 rnd;
471           rnd = (u32) (now * 1e6);
472           rnd = random_u32 (&rnd);
473           memcpy (hw_addr + 2, &rnd, sizeof (rnd));
474           hw_addr[0] = 2;
475           hw_addr[1] = 0xfe;
476
477           eir.dev_class_index = vxlan_device_class.index;
478           eir.dev_instance = dev_instance;
479           eir.address = hw_addr;
480           eir.cb.flag_change = vxlan_eth_flag_change;
481           eir.cb.set_max_frame_size = vxlan_eth_set_max_frame_size;
482           t->hw_if_index = vnet_eth_register_interface (vnm, &eir);
483         }
484
485       vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, t->hw_if_index);
486
487       /* Set vxlan tunnel output node */
488       u32 encap_index = !is_ip6 ?
489         vxlan4_encap_node.index : vxlan6_encap_node.index;
490       vnet_set_interface_output_node (vnm, t->hw_if_index, encap_index);
491
492       t->sw_if_index = sw_if_index = hi->sw_if_index;
493
494       /* copy the key */
495       int add_failed;
496       if (is_ip6)
497         {
498           key6.value = (u64) dev_instance;
499           add_failed = clib_bihash_add_del_24_8 (&vxm->vxlan6_tunnel_by_key,
500                                                  &key6, 1 /*add */ );
501         }
502       else
503         {
504           vxlan_decap_info_t di = {.sw_if_index = t->sw_if_index, };
505           if (ip46_address_is_multicast (&t->dst))
506             di.local_ip = t->src.ip4;
507           else
508             di.next_index = t->decap_next_index;
509           key4.value = di.as_u64;
510           add_failed = clib_bihash_add_del_16_8 (&vxm->vxlan4_tunnel_by_key,
511                                                  &key4, 1 /*add */ );
512         }
513
514       if (add_failed)
515         {
516           if (a->is_l3 == 0)
517             vnet_delete_hw_interface (vnm, t->hw_if_index);
518           else
519             ethernet_delete_interface (vnm, t->hw_if_index);
520           hash_unset (vxm->instance_used, t->user_instance);
521           pool_put (vxm->tunnels, t);
522           return VNET_API_ERROR_INVALID_REGISTRATION;
523         }
524
525       vec_validate_init_empty (vxm->tunnel_index_by_sw_if_index, sw_if_index,
526                                ~0);
527       vxm->tunnel_index_by_sw_if_index[sw_if_index] = dev_instance;
528
529       /* setup l2 input config with l2 feature and bd 0 to drop packet */
530       vec_validate (l2im->configs, sw_if_index);
531       l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP;
532       l2im->configs[sw_if_index].bd_index = 0;
533
534       vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
535       si->flags &= ~VNET_SW_INTERFACE_FLAG_HIDDEN;
536       vnet_sw_interface_set_flags (vnm, sw_if_index,
537                                    VNET_SW_INTERFACE_FLAG_ADMIN_UP);
538
539       fib_node_init (&t->node, FIB_NODE_TYPE_VXLAN_TUNNEL);
540       fib_prefix_t tun_dst_pfx;
541       vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL;
542
543       fib_prefix_from_ip46_addr (&t->dst, &tun_dst_pfx);
544       if (!ip46_address_is_multicast (&t->dst))
545         {
546           /* Unicast tunnel -
547            * source the FIB entry for the tunnel's destination
548            * and become a child thereof. The tunnel will then get poked
549            * when the forwarding for the entry updates, and the tunnel can
550            * re-stack accordingly
551            */
552           vtep_addr_ref (&vxm->vtep_table, t->encap_fib_index, &t->src);
553           t->fib_entry_index = fib_entry_track (t->encap_fib_index,
554                                                 &tun_dst_pfx,
555                                                 FIB_NODE_TYPE_VXLAN_TUNNEL,
556                                                 dev_instance,
557                                                 &t->sibling_index);
558           vxlan_tunnel_restack_dpo (t);
559         }
560       else
561         {
562           /* Multicast tunnel -
563            * as the same mcast group can be used for multiple mcast tunnels
564            * with different VNIs, create the output fib adjacency only if
565            * it does not already exist
566            */
567           fib_protocol_t fp = fib_ip_proto (is_ip6);
568
569           if (vtep_addr_ref (&vxm->vtep_table,
570                              t->encap_fib_index, &t->dst) == 1)
571             {
572               fib_node_index_t mfei;
573               adj_index_t ai;
574               fib_route_path_t path = {
575                 .frp_proto = fib_proto_to_dpo (fp),
576                 .frp_addr = zero_addr,
577                 .frp_sw_if_index = 0xffffffff,
578                 .frp_fib_index = ~0,
579                 .frp_weight = 1,
580                 .frp_flags = FIB_ROUTE_PATH_LOCAL,
581                 .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
582               };
583               const mfib_prefix_t mpfx = {
584                 .fp_proto = fp,
585                 .fp_len = (is_ip6 ? 128 : 32),
586                 .fp_grp_addr = tun_dst_pfx.fp_addr,
587               };
588
589               /*
590                * Setup the (*,G) to receive traffic on the mcast group
591                *  - the forwarding interface is for-us
592                *  - the accepting interface is that from the API
593                */
594               mfib_table_entry_path_update (t->encap_fib_index, &mpfx,
595                                             MFIB_SOURCE_VXLAN,
596                                             MFIB_ENTRY_FLAG_NONE, &path);
597
598               path.frp_sw_if_index = a->mcast_sw_if_index;
599               path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE;
600               path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
601               mfei = mfib_table_entry_path_update (
602                 t->encap_fib_index, &mpfx, MFIB_SOURCE_VXLAN,
603                 MFIB_ENTRY_FLAG_NONE, &path);
604
605               /*
606                * Create the mcast adjacency to send traffic to the group
607                */
608               ai = adj_mcast_add_or_lock (fp,
609                                           fib_proto_to_link (fp),
610                                           a->mcast_sw_if_index);
611
612               /*
613                * create a new end-point
614                */
615               mcast_shared_add (&t->dst, mfei, ai);
616             }
617
618           dpo_id_t dpo = DPO_INVALID;
619           mcast_shared_t ep = mcast_shared_get (&t->dst);
620
621           /* Stack shared mcast dst mac addr rewrite on encap */
622           dpo_set (&dpo, DPO_ADJACENCY_MCAST,
623                    fib_proto_to_dpo (fp), ep.mcast_adj_index);
624
625           dpo_stack_from_node (encap_index, &t->next_dpo, &dpo);
626           dpo_reset (&dpo);
627           flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER;
628         }
629
630       vnet_get_sw_interface (vnet_get_main (), sw_if_index)->flood_class =
631         flood_class;
632     }
633   else
634     {
635       /* deleting a tunnel: tunnel must exist */
636       if (!p)
637         return VNET_API_ERROR_NO_SUCH_ENTRY;
638
639       u32 instance = is_ip6 ? key6.value :
640         vxm->tunnel_index_by_sw_if_index[p->sw_if_index];
641       vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, instance);
642
643       sw_if_index = t->sw_if_index;
644       vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */ );
645
646       vxm->tunnel_index_by_sw_if_index[sw_if_index] = ~0;
647
648       if (!is_ip6)
649         clib_bihash_add_del_16_8 (&vxm->vxlan4_tunnel_by_key, &key4,
650                                   0 /*del */ );
651       else
652         clib_bihash_add_del_24_8 (&vxm->vxlan6_tunnel_by_key, &key6,
653                                   0 /*del */ );
654
655       if (!ip46_address_is_multicast (&t->dst))
656         {
657           if (t->flow_index != ~0)
658             vnet_flow_del (vnm, t->flow_index);
659
660           vtep_addr_unref (&vxm->vtep_table, t->encap_fib_index, &t->src);
661           fib_entry_untrack (t->fib_entry_index, t->sibling_index);
662         }
663       else if (vtep_addr_unref (&vxm->vtep_table,
664                                 t->encap_fib_index, &t->dst) == 0)
665         {
666           mcast_shared_remove (&t->dst);
667         }
668
669       if (t->is_l3 == 0)
670         vnet_delete_hw_interface (vnm, t->hw_if_index);
671       else
672         ethernet_delete_interface (vnm, t->hw_if_index);
673       hash_unset (vxm->instance_used, t->user_instance);
674
675       fib_node_deinit (&t->node);
676       pool_put (vxm->tunnels, t);
677     }
678
679   if (sw_if_indexp)
680     *sw_if_indexp = sw_if_index;
681
682   if (a->is_add)
683     {
684       /* register udp ports */
685       if (!is_ip6 && !udp_is_valid_dst_port (a->src_port, 1))
686         udp_register_dst_port (vxm->vlib_main, a->src_port,
687                                vxlan4_input_node.index, 1);
688       if (is_ip6 && !udp_is_valid_dst_port (a->src_port, 0))
689         udp_register_dst_port (vxm->vlib_main, a->src_port,
690                                vxlan6_input_node.index, 0);
691     }
692
693   return 0;
694 }
695
696 static uword
697 get_decap_next_for_node (u32 node_index, u32 ipv4_set)
698 {
699   vxlan_main_t *vxm = &vxlan_main;
700   vlib_main_t *vm = vxm->vlib_main;
701   uword input_node = (ipv4_set) ? vxlan4_input_node.index :
702     vxlan6_input_node.index;
703
704   return vlib_node_add_next (vm, input_node, node_index);
705 }
706
707 static uword
708 unformat_decap_next (unformat_input_t * input, va_list * args)
709 {
710   u32 *result = va_arg (*args, u32 *);
711   u32 ipv4_set = va_arg (*args, int);
712   vxlan_main_t *vxm = &vxlan_main;
713   vlib_main_t *vm = vxm->vlib_main;
714   u32 node_index;
715   u32 tmp;
716
717   if (unformat (input, "l2"))
718     *result = VXLAN_INPUT_NEXT_L2_INPUT;
719   else if (unformat (input, "node %U", unformat_vlib_node, vm, &node_index))
720     *result = get_decap_next_for_node (node_index, ipv4_set);
721   else if (unformat (input, "%d", &tmp))
722     *result = tmp;
723   else
724     return 0;
725   return 1;
726 }
727
728 static clib_error_t *
729 vxlan_add_del_tunnel_command_fn (vlib_main_t * vm,
730                                  unformat_input_t * input,
731                                  vlib_cli_command_t * cmd)
732 {
733   unformat_input_t _line_input, *line_input = &_line_input;
734   ip46_address_t src = ip46_address_initializer, dst =
735     ip46_address_initializer;
736   u8 is_add = 1;
737   u8 src_set = 0;
738   u8 dst_set = 0;
739   u8 grp_set = 0;
740   u8 ipv4_set = 0;
741   u8 ipv6_set = 0;
742   u8 is_l3 = 0;
743   u32 instance = ~0;
744   u32 encap_fib_index = 0;
745   u32 mcast_sw_if_index = ~0;
746   u32 decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
747   u32 vni = 0;
748   u32 src_port = 0;
749   u32 dst_port = 0;
750   u32 table_id;
751   clib_error_t *parse_error = NULL;
752
753   /* Get a line of input. */
754   if (!unformat_user (input, unformat_line_input, line_input))
755     return 0;
756
757   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
758     {
759       if (unformat (line_input, "del"))
760         {
761           is_add = 0;
762         }
763       else if (unformat (line_input, "instance %d", &instance))
764         ;
765       else if (unformat (line_input, "src %U",
766                          unformat_ip46_address, &src, IP46_TYPE_ANY))
767         {
768           src_set = 1;
769           ip46_address_is_ip4 (&src) ? (ipv4_set = 1) : (ipv6_set = 1);
770         }
771       else if (unformat (line_input, "dst %U",
772                          unformat_ip46_address, &dst, IP46_TYPE_ANY))
773         {
774           dst_set = 1;
775           ip46_address_is_ip4 (&dst) ? (ipv4_set = 1) : (ipv6_set = 1);
776         }
777       else if (unformat (line_input, "group %U %U",
778                          unformat_ip46_address, &dst, IP46_TYPE_ANY,
779                          unformat_vnet_sw_interface,
780                          vnet_get_main (), &mcast_sw_if_index))
781         {
782           grp_set = dst_set = 1;
783           ip46_address_is_ip4 (&dst) ? (ipv4_set = 1) : (ipv6_set = 1);
784         }
785       else if (unformat (line_input, "encap-vrf-id %d", &table_id))
786         {
787           encap_fib_index =
788             fib_table_find (fib_ip_proto (ipv6_set), table_id);
789         }
790       else if (unformat (line_input, "l3"))
791         is_l3 = 1;
792       else if (unformat (line_input, "decap-next %U", unformat_decap_next,
793                          &decap_next_index, ipv4_set))
794         ;
795       else if (unformat (line_input, "vni %d", &vni))
796         ;
797       else if (unformat (line_input, "src_port %d", &src_port))
798         ;
799       else if (unformat (line_input, "dst_port %d", &dst_port))
800         ;
801       else
802         {
803           parse_error = clib_error_return (0, "parse error: '%U'",
804                                            format_unformat_error, line_input);
805           break;
806         }
807     }
808
809   unformat_free (line_input);
810
811   if (parse_error)
812     return parse_error;
813
814   if (is_l3 && decap_next_index == VXLAN_INPUT_NEXT_L2_INPUT)
815     {
816       vlib_node_t *node = vlib_get_node_by_name (
817         vm, (u8 *) (ipv4_set ? "ip4-input" : "ip6-input"));
818       decap_next_index = get_decap_next_for_node (node->index, ipv4_set);
819     }
820
821   if (encap_fib_index == ~0)
822     return clib_error_return (0, "nonexistent encap-vrf-id %d", table_id);
823
824   if (src_set == 0)
825     return clib_error_return (0, "tunnel src address not specified");
826
827   if (dst_set == 0)
828     return clib_error_return (0, "tunnel dst address not specified");
829
830   if (grp_set && !ip46_address_is_multicast (&dst))
831     return clib_error_return (0, "tunnel group address not multicast");
832
833   if (grp_set == 0 && ip46_address_is_multicast (&dst))
834     return clib_error_return (0, "dst address must be unicast");
835
836   if (grp_set && mcast_sw_if_index == ~0)
837     return clib_error_return (0, "tunnel nonexistent multicast device");
838
839   if (ipv4_set && ipv6_set)
840     return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
841
842   if (ip46_address_cmp (&src, &dst) == 0)
843     return clib_error_return (0, "src and dst addresses are identical");
844
845   if (decap_next_index == ~0)
846     return clib_error_return (0, "next node not found");
847
848   if (vni == 0)
849     return clib_error_return (0, "vni not specified");
850
851   if (vni >> 24)
852     return clib_error_return (0, "vni %d out of range", vni);
853
854   vnet_vxlan_add_del_tunnel_args_t a = { .is_add = is_add,
855                                          .is_ip6 = ipv6_set,
856                                          .instance = instance,
857 #define _(x) .x = x,
858                                          foreach_copy_field
859 #undef _
860   };
861
862   u32 tunnel_sw_if_index;
863   int rv = vnet_vxlan_add_del_tunnel (&a, &tunnel_sw_if_index);
864
865   switch (rv)
866     {
867     case 0:
868       if (is_add)
869         vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
870                          vnet_get_main (), tunnel_sw_if_index);
871       break;
872
873     case VNET_API_ERROR_TUNNEL_EXIST:
874       return clib_error_return (0, "tunnel already exists...");
875
876     case VNET_API_ERROR_NO_SUCH_ENTRY:
877       return clib_error_return (0, "tunnel does not exist...");
878
879     case VNET_API_ERROR_INSTANCE_IN_USE:
880       return clib_error_return (0, "Instance is in use");
881
882     default:
883       return clib_error_return
884         (0, "vnet_vxlan_add_del_tunnel returned %d", rv);
885     }
886
887   return 0;
888 }
889
890 /*?
891  * Add or delete a VXLAN Tunnel.
892  *
893  * VXLAN provides the features needed to allow L2 bridge domains (BDs)
894  * to span multiple servers. This is done by building an L2 overlay on
895  * top of an L3 network underlay using VXLAN tunnels.
896  *
897  * This makes it possible for servers to be co-located in the same data
898  * center or be separated geographically as long as they are reachable
899  * through the underlay L3 network.
900  *
901  * You can refer to this kind of L2 overlay bridge domain as a VXLAN
902  * (Virtual eXtensible VLAN) segment.
903  *
904  * @cliexpar
905  * Example of how to create a VXLAN Tunnel:
906  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 encap-vrf-id
907  7}
908  * Example of how to create a VXLAN Tunnel with a known name, vxlan_tunnel42:
909  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 instance 42}
910  * Example of how to create a multicast VXLAN Tunnel with a known name,
911  vxlan_tunnel23:
912  * @cliexcmd{create vxlan tunnel src 10.0.3.1 group 239.1.1.1
913  GigabitEthernet0/8/0 instance 23}
914  * Example of how to create a VXLAN Tunnel with custom udp-ports:
915  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 src_port
916  59000 dst_port 59001}
917  * Example of how to delete a VXLAN Tunnel:
918  * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 del}
919  ?*/
920 /* *INDENT-OFF* */
921 VLIB_CLI_COMMAND (create_vxlan_tunnel_command, static) = {
922   .path = "create vxlan tunnel",
923   .short_help =
924     "create vxlan tunnel src <local-vtep-addr>"
925     " {dst <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} vni <nn>"
926     " [instance <id>]"
927     " [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [del] [l3]"
928     " [src_port <local-vtep-udp-port>] [dst_port <remote-vtep-udp-port>]",
929   .function = vxlan_add_del_tunnel_command_fn,
930 };
931 /* *INDENT-ON* */
932
933 static clib_error_t *
934 show_vxlan_tunnel_command_fn (vlib_main_t * vm,
935                               unformat_input_t * input,
936                               vlib_cli_command_t * cmd)
937 {
938   vxlan_main_t *vxm = &vxlan_main;
939   vxlan_tunnel_t *t;
940   int raw = 0;
941
942   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
943     {
944       if (unformat (input, "raw"))
945         raw = 1;
946       else
947         return clib_error_return (0, "parse error: '%U'",
948                                   format_unformat_error, input);
949     }
950
951   if (pool_elts (vxm->tunnels) == 0)
952     vlib_cli_output (vm, "No vxlan tunnels configured...");
953
954 /* *INDENT-OFF* */
955   pool_foreach (t, vxm->tunnels)
956    {
957     vlib_cli_output (vm, "%U", format_vxlan_tunnel, t);
958   }
959 /* *INDENT-ON* */
960
961   if (raw)
962     {
963       vlib_cli_output (vm, "Raw IPv4 Hash Table:\n%U\n",
964                        format_bihash_16_8, &vxm->vxlan4_tunnel_by_key,
965                        1 /* verbose */ );
966       vlib_cli_output (vm, "Raw IPv6 Hash Table:\n%U\n",
967                        format_bihash_24_8, &vxm->vxlan6_tunnel_by_key,
968                        1 /* verbose */ );
969     }
970
971   return 0;
972 }
973
974 /*?
975  * Display all the VXLAN Tunnel entries.
976  *
977  * @cliexpar
978  * Example of how to display the VXLAN Tunnel entries:
979  * @cliexstart{show vxlan tunnel}
980  * [0] src 10.0.3.1 dst 10.0.3.3 src_port 4789 dst_port 4789 vni 13
981  encap_fib_index 0 sw_if_index 5 decap_next l2
982  * @cliexend
983  ?*/
984 /* *INDENT-OFF* */
985 VLIB_CLI_COMMAND (show_vxlan_tunnel_command, static) = {
986     .path = "show vxlan tunnel",
987     .short_help = "show vxlan tunnel [raw]",
988     .function = show_vxlan_tunnel_command_fn,
989 };
990 /* *INDENT-ON* */
991
992
993 void
994 vnet_int_vxlan_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable)
995 {
996   vxlan_main_t *vxm = &vxlan_main;
997
998   if (pool_is_free_index (vxm->vnet_main->interface_main.sw_interfaces,
999                           sw_if_index))
1000     return;
1001
1002   is_enable = ! !is_enable;
1003
1004   if (is_ip6)
1005     {
1006       if (clib_bitmap_get (vxm->bm_ip6_bypass_enabled_by_sw_if, sw_if_index)
1007           != is_enable)
1008         {
1009           vnet_feature_enable_disable ("ip6-unicast", "ip6-vxlan-bypass",
1010                                        sw_if_index, is_enable, 0, 0);
1011           vxm->bm_ip6_bypass_enabled_by_sw_if =
1012             clib_bitmap_set (vxm->bm_ip6_bypass_enabled_by_sw_if,
1013                              sw_if_index, is_enable);
1014         }
1015     }
1016   else
1017     {
1018       if (clib_bitmap_get (vxm->bm_ip4_bypass_enabled_by_sw_if, sw_if_index)
1019           != is_enable)
1020         {
1021           vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
1022                                        sw_if_index, is_enable, 0, 0);
1023           vxm->bm_ip4_bypass_enabled_by_sw_if =
1024             clib_bitmap_set (vxm->bm_ip4_bypass_enabled_by_sw_if,
1025                              sw_if_index, is_enable);
1026         }
1027     }
1028 }
1029
1030
1031 static clib_error_t *
1032 set_ip_vxlan_bypass (u32 is_ip6,
1033                      unformat_input_t * input, vlib_cli_command_t * cmd)
1034 {
1035   unformat_input_t _line_input, *line_input = &_line_input;
1036   vnet_main_t *vnm = vnet_get_main ();
1037   clib_error_t *error = 0;
1038   u32 sw_if_index, is_enable;
1039
1040   sw_if_index = ~0;
1041   is_enable = 1;
1042
1043   if (!unformat_user (input, unformat_line_input, line_input))
1044     return 0;
1045
1046   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1047     {
1048       if (unformat_user
1049           (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1050         ;
1051       else if (unformat (line_input, "del"))
1052         is_enable = 0;
1053       else
1054         {
1055           error = unformat_parse_error (line_input);
1056           goto done;
1057         }
1058     }
1059
1060   if (~0 == sw_if_index)
1061     {
1062       error = clib_error_return (0, "unknown interface `%U'",
1063                                  format_unformat_error, line_input);
1064       goto done;
1065     }
1066
1067   vnet_int_vxlan_bypass_mode (sw_if_index, is_ip6, is_enable);
1068
1069 done:
1070   unformat_free (line_input);
1071
1072   return error;
1073 }
1074
1075 static clib_error_t *
1076 set_ip4_vxlan_bypass (vlib_main_t * vm,
1077                       unformat_input_t * input, vlib_cli_command_t * cmd)
1078 {
1079   return set_ip_vxlan_bypass (0, input, cmd);
1080 }
1081
1082 /*?
1083  * This command adds the 'ip4-vxlan-bypass' graph node for a given interface.
1084  * By adding the IPv4 vxlan-bypass graph node to an interface, the node checks
1085  * for and validate input vxlan packet and bypass ip4-lookup, ip4-local,
1086  * ip4-udp-lookup nodes to speedup vxlan packet forwarding. This node will
1087  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
1088  *
1089  * @cliexpar
1090  * @parblock
1091  * Example of graph node before ip4-vxlan-bypass is enabled:
1092  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1093  *            Name                      Next                    Previous
1094  * ip4-vxlan-bypass                error-drop [0]
1095  *                                vxlan4-input [1]
1096  *                                 ip4-lookup [2]
1097  * @cliexend
1098  *
1099  * Example of how to enable ip4-vxlan-bypass on an interface:
1100  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0}
1101  *
1102  * Example of graph node after ip4-vxlan-bypass is enabled:
1103  * @cliexstart{show vlib graph ip4-vxlan-bypass}
1104  *            Name                      Next                    Previous
1105  * ip4-vxlan-bypass                error-drop [0]               ip4-input
1106  *                                vxlan4-input [1]        ip4-input-no-checksum
1107  *                                 ip4-lookup [2]
1108  * @cliexend
1109  *
1110  * Example of how to display the feature enabled on an interface:
1111  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1112  * IP feature paths configured on GigabitEthernet2/0/0...
1113  * ...
1114  * ipv4 unicast:
1115  *   ip4-vxlan-bypass
1116  *   ip4-lookup
1117  * ...
1118  * @cliexend
1119  *
1120  * Example of how to disable ip4-vxlan-bypass on an interface:
1121  * @cliexcmd{set interface ip vxlan-bypass GigabitEthernet2/0/0 del}
1122  * @endparblock
1123 ?*/
1124 /* *INDENT-OFF* */
1125 VLIB_CLI_COMMAND (set_interface_ip_vxlan_bypass_command, static) = {
1126   .path = "set interface ip vxlan-bypass",
1127   .function = set_ip4_vxlan_bypass,
1128   .short_help = "set interface ip vxlan-bypass <interface> [del]",
1129 };
1130 /* *INDENT-ON* */
1131
1132 static clib_error_t *
1133 set_ip6_vxlan_bypass (vlib_main_t * vm,
1134                       unformat_input_t * input, vlib_cli_command_t * cmd)
1135 {
1136   return set_ip_vxlan_bypass (1, input, cmd);
1137 }
1138
1139 /*?
1140  * This command adds the 'ip6-vxlan-bypass' graph node for a given interface.
1141  * By adding the IPv6 vxlan-bypass graph node to an interface, the node checks
1142  * for and validate input vxlan packet and bypass ip6-lookup, ip6-local,
1143  * ip6-udp-lookup nodes to speedup vxlan packet forwarding. This node will
1144  * cause extra overhead to for non-vxlan packets which is kept at a minimum.
1145  *
1146  * @cliexpar
1147  * @parblock
1148  * Example of graph node before ip6-vxlan-bypass is enabled:
1149  * @cliexstart{show vlib graph ip6-vxlan-bypass}
1150  *            Name                      Next                    Previous
1151  * ip6-vxlan-bypass                error-drop [0]
1152  *                                vxlan6-input [1]
1153  *                                 ip6-lookup [2]
1154  * @cliexend
1155  *
1156  * Example of how to enable ip6-vxlan-bypass on an interface:
1157  * @cliexcmd{set interface ip6 vxlan-bypass GigabitEthernet2/0/0}
1158  *
1159  * Example of graph node after ip6-vxlan-bypass is enabled:
1160  * @cliexstart{show vlib graph ip6-vxlan-bypass}
1161  *            Name                      Next                    Previous
1162  * ip6-vxlan-bypass                error-drop [0]               ip6-input
1163  *                                vxlan6-input [1]        ip4-input-no-checksum
1164  *                                 ip6-lookup [2]
1165  * @cliexend
1166  *
1167  * Example of how to display the feature enabled on an interface:
1168  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
1169  * IP feature paths configured on GigabitEthernet2/0/0...
1170  * ...
1171  * ipv6 unicast:
1172  *   ip6-vxlan-bypass
1173  *   ip6-lookup
1174  * ...
1175  * @cliexend
1176  *
1177  * Example of how to disable ip6-vxlan-bypass on an interface:
1178  * @cliexcmd{set interface ip6 vxlan-bypass GigabitEthernet2/0/0 del}
1179  * @endparblock
1180 ?*/
1181 /* *INDENT-OFF* */
1182 VLIB_CLI_COMMAND (set_interface_ip6_vxlan_bypass_command, static) = {
1183   .path = "set interface ip6 vxlan-bypass",
1184   .function = set_ip6_vxlan_bypass,
1185   .short_help = "set interface ip6 vxlan-bypass <interface> [del]",
1186 };
1187 /* *INDENT-ON* */
1188
1189 int
1190 vnet_vxlan_add_del_rx_flow (u32 hw_if_index, u32 t_index, int is_add)
1191 {
1192   vxlan_main_t *vxm = &vxlan_main;
1193   vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
1194   vnet_main_t *vnm = vnet_get_main ();
1195   if (is_add)
1196     {
1197       if (t->flow_index == ~0)
1198         {
1199           vxlan_main_t *vxm = &vxlan_main;
1200           vnet_flow_t flow = {
1201             .actions =
1202               VNET_FLOW_ACTION_REDIRECT_TO_NODE | VNET_FLOW_ACTION_MARK |
1203               VNET_FLOW_ACTION_BUFFER_ADVANCE,
1204             .mark_flow_id = t->dev_instance + vxm->flow_id_start,
1205             .redirect_node_index = vxlan4_flow_input_node.index,
1206             .buffer_advance = sizeof (ethernet_header_t),
1207             .type = VNET_FLOW_TYPE_IP4_VXLAN,
1208             .ip4_vxlan = {
1209                           .protocol.prot = IP_PROTOCOL_UDP,
1210                           .src_addr.addr = t->dst.ip4,
1211                           .dst_addr.addr = t->src.ip4,
1212                           .src_addr.mask.as_u32 = ~0,
1213                           .dst_addr.mask.as_u32 = ~0,
1214                           .dst_port.port = t->src_port,
1215                           .dst_port.mask = 0xFF,
1216                           .vni = t->vni,
1217                           }
1218             ,
1219           };
1220           vnet_flow_add (vnm, &flow, &t->flow_index);
1221         }
1222       return vnet_flow_enable (vnm, t->flow_index, hw_if_index);
1223     }
1224   /* flow index is removed when the tunnel is deleted */
1225   return vnet_flow_disable (vnm, t->flow_index, hw_if_index);
1226 }
1227
1228 u32
1229 vnet_vxlan_get_tunnel_index (u32 sw_if_index)
1230 {
1231   vxlan_main_t *vxm = &vxlan_main;
1232
1233   if (sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index))
1234     return ~0;
1235   return vxm->tunnel_index_by_sw_if_index[sw_if_index];
1236 }
1237
1238 static clib_error_t *
1239 vxlan_offload_command_fn (vlib_main_t * vm,
1240                           unformat_input_t * input, vlib_cli_command_t * cmd)
1241 {
1242   unformat_input_t _line_input, *line_input = &_line_input;
1243
1244   /* Get a line of input. */
1245   if (!unformat_user (input, unformat_line_input, line_input))
1246     return 0;
1247
1248   vnet_main_t *vnm = vnet_get_main ();
1249   u32 rx_sw_if_index = ~0;
1250   u32 hw_if_index = ~0;
1251   int is_add = 1;
1252
1253   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1254     {
1255       if (unformat (line_input, "hw %U", unformat_vnet_hw_interface, vnm,
1256                     &hw_if_index))
1257         continue;
1258       if (unformat (line_input, "rx %U", unformat_vnet_sw_interface, vnm,
1259                     &rx_sw_if_index))
1260         continue;
1261       if (unformat (line_input, "del"))
1262         {
1263           is_add = 0;
1264           continue;
1265         }
1266       return clib_error_return (0, "unknown input `%U'",
1267                                 format_unformat_error, line_input);
1268     }
1269
1270   if (rx_sw_if_index == ~0)
1271     return clib_error_return (0, "missing rx interface");
1272   if (hw_if_index == ~0)
1273     return clib_error_return (0, "missing hw interface");
1274
1275   u32 t_index = vnet_vxlan_get_tunnel_index (rx_sw_if_index);;
1276   if (t_index == ~0)
1277     return clib_error_return (0, "%U is not a vxlan tunnel",
1278                               format_vnet_sw_if_index_name, vnm,
1279                               rx_sw_if_index);
1280
1281   vxlan_main_t *vxm = &vxlan_main;
1282   vxlan_tunnel_t *t = pool_elt_at_index (vxm->tunnels, t_index);
1283
1284   if (!ip46_address_is_ip4 (&t->dst))
1285     return clib_error_return (0, "currently only IPV4 tunnels are supported");
1286
1287   vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1288   ip4_main_t *im = &ip4_main;
1289   u32 rx_fib_index =
1290     vec_elt (im->fib_index_by_sw_if_index, hw_if->sw_if_index);
1291
1292   if (t->encap_fib_index != rx_fib_index)
1293     return clib_error_return (0, "interface/tunnel fib mismatch");
1294
1295   if (vnet_vxlan_add_del_rx_flow (hw_if_index, t_index, is_add))
1296     return clib_error_return (0, "error %s flow",
1297                               is_add ? "enabling" : "disabling");
1298
1299   return 0;
1300 }
1301
1302 /* *INDENT-OFF* */
1303 VLIB_CLI_COMMAND (vxlan_offload_command, static) = {
1304     .path = "set flow-offload vxlan",
1305     .short_help =
1306     "set flow-offload vxlan hw <interface-name> rx <tunnel-name> [del]",
1307     .function = vxlan_offload_command_fn,
1308 };
1309 /* *INDENT-ON* */
1310
1311 #define VXLAN_HASH_NUM_BUCKETS (2 * 1024)
1312 #define VXLAN_HASH_MEMORY_SIZE (1 << 20)
1313
1314 clib_error_t *
1315 vxlan_init (vlib_main_t * vm)
1316 {
1317   vxlan_main_t *vxm = &vxlan_main;
1318
1319   vxm->vnet_main = vnet_get_main ();
1320   vxm->vlib_main = vm;
1321
1322   vnet_flow_get_range (vxm->vnet_main, "vxlan", 1024 * 1024,
1323                        &vxm->flow_id_start);
1324
1325   vxm->bm_ip4_bypass_enabled_by_sw_if = 0;
1326   vxm->bm_ip6_bypass_enabled_by_sw_if = 0;
1327
1328   /* initialize the ip6 hash */
1329   clib_bihash_init_16_8 (&vxm->vxlan4_tunnel_by_key, "vxlan4",
1330                          VXLAN_HASH_NUM_BUCKETS, VXLAN_HASH_MEMORY_SIZE);
1331   clib_bihash_init_24_8 (&vxm->vxlan6_tunnel_by_key, "vxlan6",
1332                          VXLAN_HASH_NUM_BUCKETS, VXLAN_HASH_MEMORY_SIZE);
1333   vxm->vtep_table = vtep_table_create ();
1334   vxm->mcast_shared = hash_create_mem (0,
1335                                        sizeof (ip46_address_t),
1336                                        sizeof (mcast_shared_t));
1337
1338   fib_node_register_type (FIB_NODE_TYPE_VXLAN_TUNNEL, &vxlan_vft);
1339
1340   return 0;
1341 }
1342
1343 VLIB_INIT_FUNCTION (vxlan_init);
1344
1345 /*
1346  * fd.io coding-style-patch-verification: ON
1347  *
1348  * Local Variables:
1349  * eval: (c-set-style "gnu")
1350  * End:
1351  */