X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fvxlan%2Fvxlan.c;h=26844623edd53a20319a61ed026512683fdc4c94;hb=3d460bd;hp=28fde51cc23bc57e4c9cedf84c3e8145e5c9c6a3;hpb=0765c6e18b2f684686cc2c20b4c8484a57981655;p=vpp.git diff --git a/src/vnet/vxlan/vxlan.c b/src/vnet/vxlan/vxlan.c index 28fde51cc23..26844623edd 100644 --- a/src/vnet/vxlan/vxlan.c +++ b/src/vnet/vxlan/vxlan.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /** @@ -43,15 +44,10 @@ static u8 * format_decap_next (u8 * s, va_list * args) { u32 next_index = va_arg (*args, u32); - switch (next_index) - { - case VXLAN_INPUT_NEXT_DROP: - return format (s, "drop"); - case VXLAN_INPUT_NEXT_L2_INPUT: - return format (s, "l2"); - default: - return format (s, "index %d", next_index); - } + if (next_index == VXLAN_INPUT_NEXT_DROP) + return format (s, "drop"); + else + return format (s, "index %d", next_index); return s; } @@ -59,52 +55,69 @@ u8 * format_vxlan_tunnel (u8 * s, va_list * args) { vxlan_tunnel_t * t = va_arg (*args, vxlan_tunnel_t *); vxlan_main_t * ngm = &vxlan_main; + u32 dev_instance; + u32 user_instance; + + dev_instance = t - ngm->tunnels; + user_instance = t->user_instance; - s = format (s, "[%d] src %U dst %U vni %d sw_if_index %d ", - t - ngm->tunnels, + s = format (s, + "[%d] instance %d src %U dst %U vni %d fib-idx %d sw-if-idx %d ", + dev_instance, + user_instance, format_ip46_address, &t->src, IP46_TYPE_ANY, format_ip46_address, &t->dst, IP46_TYPE_ANY, - t->vni, t->sw_if_index); + t->vni, t->encap_fib_index, t->sw_if_index); - if (ip46_address_is_multicast (&t->dst)) - s = format (s, "mcast_sw_if_index %d ", t->mcast_sw_if_index); + s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index); + + if (PREDICT_FALSE (t->decap_next_index != VXLAN_INPUT_NEXT_L2_INPUT)) + s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index); + + if (PREDICT_FALSE (ip46_address_is_multicast (&t->dst))) + s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index); - s = format (s, "encap_fib_index %d fib_entry_index %d decap_next %U\n", - t->encap_fib_index, t->fib_entry_index, - format_decap_next, t->decap_next_index); return s; } static u8 * format_vxlan_name (u8 * s, va_list * args) { u32 dev_instance = va_arg (*args, u32); - return format (s, "vxlan_tunnel%d", dev_instance); -} + vxlan_main_t * vxm = &vxlan_main; + vxlan_tunnel_t *t; -static uword dummy_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - clib_warning ("you shouldn't be here, leaking buffers..."); - return frame->n_vectors; + if (dev_instance == ~0) + return format(s, ""); + + if (dev_instance >= vec_len(vxm->tunnels)) + return format(s, ""); + + t = pool_elt_at_index(vxm->tunnels, dev_instance); + + return format (s, "vxlan_tunnel%d", t->user_instance); } static clib_error_t * vxlan_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) { - if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) - vnet_hw_interface_set_flags (vnm, hw_if_index, VNET_HW_INTERFACE_FLAG_LINK_UP); - else - vnet_hw_interface_set_flags (vnm, hw_if_index, 0); + u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? + VNET_HW_INTERFACE_FLAG_LINK_UP : 0; + vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags); return /* no error */ 0; } +static int +vxlan_name_renumber (vnet_hw_interface_t *hi, u32 new_dev_instance) +{ + return 0; +} + VNET_DEVICE_CLASS (vxlan_device_class,static) = { .name = "VXLAN", .format_device_name = format_vxlan_name, + .name_renumber = vxlan_name_renumber, .format_tx_trace = format_vxlan_encap_trace, - .tx_function = dummy_interface_tx, .admin_up_down_function = vxlan_interface_admin_up_down, }; @@ -138,9 +151,7 @@ vxlan_tunnel_restack_dpo(vxlan_tunnel_t * t) static vxlan_tunnel_t * vxlan_tunnel_from_fib_node (fib_node_t *node) { -#if (CLIB_DEBUG > 0) ASSERT(FIB_NODE_TYPE_VXLAN_TUNNEL == node->fn_type); -#endif return ((vxlan_tunnel_t*) (((char*)node) - STRUCT_OFFSET_OF(vxlan_tunnel_t, node))); } @@ -203,106 +214,66 @@ _(decap_next_index) \ _(src) \ _(dst) -static int vxlan4_rewrite (vxlan_tunnel_t * t) +static int +vxlan_rewrite (vxlan_tunnel_t * t, bool is_ip6) { - u8 *rw = 0; - ip4_header_t * ip0; - ip4_vxlan_header_t * h0; - int len = sizeof (*h0); - - vec_validate_aligned (rw, len-1, CLIB_CACHE_LINE_BYTES); - - h0 = (ip4_vxlan_header_t *) rw; - - /* Fixed portion of the (outer) ip4 header */ - ip0 = &h0->ip4; - ip0->ip_version_and_header_length = 0x45; - ip0->ttl = 254; - ip0->protocol = IP_PROTOCOL_UDP; - - /* we fix up the ip4 header length and checksum after-the-fact */ - ip0->src_address.as_u32 = t->src.ip4.as_u32; - ip0->dst_address.as_u32 = t->dst.ip4.as_u32; - ip0->checksum = ip4_header_checksum (ip0); - - /* UDP header, randomize src port on something, maybe? */ - h0->udp.src_port = clib_host_to_net_u16 (4789); - h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_vxlan); - - /* VXLAN header */ - vnet_set_vni_and_flags(&h0->vxlan, t->vni); - - t->rewrite = rw; - return (0); -} - -static int vxlan6_rewrite (vxlan_tunnel_t * t) -{ - u8 *rw = 0; - ip6_header_t * ip0; - ip6_vxlan_header_t * h0; - int len = sizeof (*h0); - - vec_validate_aligned (rw, len-1, CLIB_CACHE_LINE_BYTES); - - h0 = (ip6_vxlan_header_t *) rw; - - /* Fixed portion of the (outer) ip6 header */ - ip0 = &h0->ip6; - ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32(6 << 28); - ip0->hop_limit = 255; - ip0->protocol = IP_PROTOCOL_UDP; - - ip0->src_address = t->src.ip6; - ip0->dst_address = t->dst.ip6; + union { + ip4_vxlan_header_t * h4; + ip6_vxlan_header_t * h6; + u8 *rw; + } r = { .rw = 0 }; + int len = is_ip6 ? sizeof *r.h6 : sizeof *r.h4; + + vec_validate_aligned (r.rw, len-1, CLIB_CACHE_LINE_BYTES); + + udp_header_t * udp; + vxlan_header_t * vxlan; + /* Fixed portion of the (outer) ip header */ + if (!is_ip6) + { + ip4_header_t * ip = &r.h4->ip4; + udp = &r.h4->udp, vxlan = &r.h4->vxlan; + ip->ip_version_and_header_length = 0x45; + ip->ttl = 254; + ip->protocol = IP_PROTOCOL_UDP; + + ip->src_address = t->src.ip4; + ip->dst_address = t->dst.ip4; + + /* we fix up the ip4 header length and checksum after-the-fact */ + ip->checksum = ip4_header_checksum (ip); + } + else + { + ip6_header_t * ip = &r.h6->ip6; + udp = &r.h6->udp, vxlan = &r.h6->vxlan; + ip->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32(6 << 28); + ip->hop_limit = 255; + ip->protocol = IP_PROTOCOL_UDP; + + ip->src_address = t->src.ip6; + ip->dst_address = t->dst.ip6; + } /* UDP header, randomize src port on something, maybe? */ - h0->udp.src_port = clib_host_to_net_u16 (4789); - h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_vxlan); + udp->src_port = clib_host_to_net_u16 (4789); + udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_vxlan); /* VXLAN header */ - vnet_set_vni_and_flags(&h0->vxlan, t->vni); + vnet_set_vni_and_flags(vxlan, t->vni); - t->rewrite = rw; + t->rewrite = r.rw; return (0); } -static int vxlan_check_decap_next(vxlan_main_t * vxm, u32 is_ip6, u32 decap_next_index) +static bool +vxlan_decap_next_is_valid (vxlan_main_t * vxm, u32 is_ip6, u32 decap_next_index) { vlib_main_t * vm = vxm->vlib_main; - vlib_node_runtime_t *r; - - if(!is_ip6) - { - r = vlib_node_get_runtime (vm, vxlan4_input_node.index); - if(decap_next_index >= r->n_next_nodes) - return 1; - } - else - { - r = vlib_node_get_runtime (vm, vxlan6_input_node.index); - if(decap_next_index >= r->n_next_nodes) - return 1; - } - - return 0; -} - -static void -hash_set_key_copy (uword ** h, void * key, uword v) { - size_t ksz = hash_header(*h)->user; - void * copy = clib_mem_alloc (ksz); - clib_memcpy (copy, key, ksz); - hash_set_mem (*h, copy, v); -} + u32 input_idx = (!is_ip6) ? vxlan4_input_node.index : vxlan6_input_node.index; + vlib_node_runtime_t *r = vlib_node_get_runtime (vm, input_idx); -static void -hash_unset_key_free (uword ** h, void * key) { - hash_pair_t * hp = hash_get_pair_mem (*h, key); - ASSERT (hp); - key = uword_to_pointer (hp->key, void *); - hash_unset_mem (*h, key); - clib_mem_free (key); + return decap_next_index < r->n_next_nodes; } static uword @@ -315,7 +286,7 @@ vtep_addr_ref(ip46_address_t *ip) return ++(*vtep); ip46_address_is_ip4(ip) ? hash_set (vxlan_main.vtep4, ip->ip4.as_u32, 1) : - hash_set_key_copy (&vxlan_main.vtep6, &ip->ip6, 1); + hash_set_mem_alloc (&vxlan_main.vtep6, &ip->ip6, 1); return 1; } @@ -330,7 +301,7 @@ vtep_addr_unref(ip46_address_t *ip) return *vtep; ip46_address_is_ip4(ip) ? hash_unset (vxlan_main.vtep4, ip->ip4.as_u32) : - hash_unset_key_free (&vxlan_main.vtep6, &ip->ip6); + hash_unset_mem_free (&vxlan_main.vtep6, &ip->ip6); return 0; } @@ -361,7 +332,7 @@ mcast_shared_add(ip46_address_t *dst, .mfib_entry_index = mfei, }; - hash_set_key_copy (&vxlan_main.mcast_shared, dst, new_ep.as_u64); + hash_set_mem_alloc (&vxlan_main.mcast_shared, dst, new_ep.as_u64); } static inline void @@ -373,13 +344,7 @@ mcast_shared_remove(ip46_address_t *dst) mfib_table_entry_delete_index(ep.mfib_entry_index, MFIB_SOURCE_VXLAN); - hash_unset_key_free (&vxlan_main.mcast_shared, dst); -} - -static inline fib_protocol_t -fib_ip_proto(bool is_ip6) -{ - return (is_ip6) ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4; + hash_unset_mem_free (&vxlan_main.mcast_shared, dst); } int vnet_vxlan_add_del_tunnel @@ -408,10 +373,12 @@ int vnet_vxlan_add_del_tunnel key6.vni = clib_host_to_net_u32 (a->vni << 8); p = hash_get_mem (vxm->vxlan6_tunnel_by_key, &key6); } - + if (a->is_add) { l2input_main_t * l2im = &l2input_main; + u32 dev_instance; /* real dev instance tunnel index */ + u32 user_instance; /* request and actual instance number */ /* adding a tunnel: tunnel must not already exist */ if (p) @@ -420,31 +387,45 @@ int vnet_vxlan_add_del_tunnel /*if not set explicitly, default to l2 */ if(a->decap_next_index == ~0) a->decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT; - if (vxlan_check_decap_next(vxm, is_ip6, a->decap_next_index)) + if (!vxlan_decap_next_is_valid(vxm, is_ip6, a->decap_next_index)) return VNET_API_ERROR_INVALID_DECAP_NEXT; pool_get_aligned (vxm->tunnels, t, CLIB_CACHE_LINE_BYTES); memset (t, 0, sizeof (*t)); - + dev_instance = t - vxm->tunnels; + /* copy from arg structure */ #define _(x) t->x = a->x; foreach_copy_field; #undef _ - if (!is_ip6) - rv = vxlan4_rewrite (t); - else - rv = vxlan6_rewrite (t); - + rv = vxlan_rewrite (t, is_ip6); if (rv) { pool_put (vxm->tunnels, t); return rv; } + /* + * Reconcile the real dev_instance and a possible requested instance. + */ + user_instance = a->instance; + if (user_instance == ~0) + user_instance = dev_instance; + if (hash_get (vxm->instance_used, user_instance)) + { + pool_put (vxm->tunnels, t); + return VNET_API_ERROR_INSTANCE_IN_USE; + } + hash_set (vxm->instance_used, user_instance, 1); + + t->dev_instance = dev_instance; /* actual */ + t->user_instance = user_instance; /* name */ + /* copy the key */ if (is_ip6) - hash_set_key_copy (&vxm->vxlan6_tunnel_by_key, &key6, t - vxm->tunnels); + hash_set_mem_alloc (&vxm->vxlan6_tunnel_by_key, &key6, + t - vxm->tunnels); else hash_set (vxm->vxlan4_tunnel_by_key, key4.as_u64, t - vxm->tunnels); @@ -457,11 +438,13 @@ int vnet_vxlan_add_del_tunnel _vec_len (vxm->free_vxlan_tunnel_hw_if_indices) -= 1; hi = vnet_get_hw_interface (vnm, hw_if_index); - hi->dev_instance = t - vxm->tunnels; - hi->hw_instance = hi->dev_instance; + hi->dev_instance = dev_instance; + hi->hw_instance = dev_instance; - /* clear old stats of freed tunnel before reuse */ sw_if_index = hi->sw_if_index; + vnet_interface_name_renumber(sw_if_index, user_instance); + + /* clear old stats of freed tunnel before reuse */ vnet_interface_counter_lock(im); vlib_zero_combined_counter (&im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX], sw_if_index); @@ -471,31 +454,37 @@ int vnet_vxlan_add_del_tunnel (&im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP], sw_if_index); vnet_interface_counter_unlock(im); } - else + else { hw_if_index = vnet_register_interface (vnm, vxlan_device_class.index, t - vxm->tunnels, vxlan_hw_class.index, t - vxm->tunnels); hi = vnet_get_hw_interface (vnm, hw_if_index); } - + + /* Set vxlan tunnel output node */ + u32 encap_index = !is_ip6 ? + vxlan4_encap_node.index : vxlan6_encap_node.index; + vnet_set_interface_output_node (vnm, hw_if_index, encap_index); + t->hw_if_index = hw_if_index; t->sw_if_index = sw_if_index = hi->sw_if_index; - + vec_validate_init_empty (vxm->tunnel_index_by_sw_if_index, sw_if_index, ~0); - vxm->tunnel_index_by_sw_if_index[sw_if_index] = t - vxm->tunnels; + vxm->tunnel_index_by_sw_if_index[sw_if_index] = dev_instance; /* setup l2 input config with l2 feature and bd 0 to drop packet */ vec_validate (l2im->configs, sw_if_index); l2im->configs[sw_if_index].feature_bitmap = L2INPUT_FEAT_DROP; l2im->configs[sw_if_index].bd_index = 0; - - vnet_sw_interface_set_flags (vnm, sw_if_index, + + vnet_sw_interface_t * si = vnet_get_sw_interface (vnm, sw_if_index); + si->flags &= ~VNET_SW_INTERFACE_FLAG_HIDDEN; + vnet_sw_interface_set_flags (vnm, sw_if_index, VNET_SW_INTERFACE_FLAG_ADMIN_UP); + fib_node_init(&t->node, FIB_NODE_TYPE_VXLAN_TUNNEL); fib_prefix_t tun_dst_pfx; - u32 encap_index = !is_ip6 ? - vxlan4_encap_node.index : vxlan6_encap_node.index; vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL; fib_prefix_from_ip46_addr(&t->dst, &tun_dst_pfx); @@ -510,9 +499,9 @@ int vnet_vxlan_add_del_tunnel vtep_addr_ref(&t->src); t->fib_entry_index = fib_table_entry_special_add (t->encap_fib_index, &tun_dst_pfx, FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE, ADJ_INDEX_INVALID); + FIB_ENTRY_FLAG_NONE); t->sibling_index = fib_entry_child_add - (t->fib_entry_index, FIB_NODE_TYPE_VXLAN_TUNNEL, t - vxm->tunnels); + (t->fib_entry_index, FIB_NODE_TYPE_VXLAN_TUNNEL, dev_instance); vxlan_tunnel_restack_dpo(t); } else @@ -529,7 +518,7 @@ int vnet_vxlan_add_del_tunnel fib_node_index_t mfei; adj_index_t ai; fib_route_path_t path = { - .frp_proto = fp, + .frp_proto = fib_proto_to_dpo(fp), .frp_addr = zero_addr, .frp_sw_if_index = 0xffffffff, .frp_fib_index = ~0, @@ -578,7 +567,7 @@ int vnet_vxlan_add_del_tunnel mcast_shared_t ep = mcast_shared_get(&t->dst); /* Stack shared mcast dst mac addr rewrite on encap */ - dpo_set (&dpo, DPO_ADJACENCY, + dpo_set (&dpo, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(fp), ep.mcast_adj_index); @@ -587,9 +576,6 @@ int vnet_vxlan_add_del_tunnel flood_class = VNET_FLOOD_CLASS_TUNNEL_MASTER; } - /* Set vxlan tunnel output node */ - hi->output_node_index = encap_index; - vnet_get_sw_interface (vnet_get_main(), sw_if_index)->flood_class = flood_class; } else @@ -598,19 +584,24 @@ int vnet_vxlan_add_del_tunnel if (!p) return VNET_API_ERROR_NO_SUCH_ENTRY; - t = pool_elt_at_index (vxm->tunnels, p[0]); + u32 instance = p[0]; + t = pool_elt_at_index (vxm->tunnels, instance); + + sw_if_index = t->sw_if_index; + vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */); + vnet_sw_interface_t * si = vnet_get_sw_interface (vnm, sw_if_index); + si->flags |= VNET_SW_INTERFACE_FLAG_HIDDEN; - vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */); /* make sure tunnel is removed from l2 bd or xconnect */ - set_int_l2_mode(vxm->vlib_main, vnm, MODE_L3, t->sw_if_index, 0, 0, 0, 0); + set_int_l2_mode(vxm->vlib_main, vnm, MODE_L3, sw_if_index, 0, 0, 0, 0); vec_add1 (vxm->free_vxlan_tunnel_hw_if_indices, t->hw_if_index); - vxm->tunnel_index_by_sw_if_index[t->sw_if_index] = ~0; + vxm->tunnel_index_by_sw_if_index[sw_if_index] = ~0; if (!is_ip6) hash_unset (vxm->vxlan4_tunnel_by_key, key4.as_u64); else - hash_unset_key_free (&vxm->vxlan6_tunnel_by_key, &key6); + hash_unset_mem_free (&vxm->vxlan6_tunnel_by_key, &key6); if (!ip46_address_is_multicast(&t->dst)) { @@ -623,6 +614,12 @@ int vnet_vxlan_add_del_tunnel mcast_shared_remove(&t->dst); } + vnet_hw_interface_t *hi; + hi = vnet_get_hw_interface (vnm, t->hw_if_index); + hi->dev_instance = ~0; + + hash_unset (vxlan_main.instance_used, instance); + fib_node_deinit(&t->node); vec_free (t->rewrite); pool_put (vxm->tunnels, t); @@ -677,6 +674,7 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, u8 grp_set = 0; u8 ipv4_set = 0; u8 ipv6_set = 0; + u32 instance = ~0; u32 encap_fib_index = 0; u32 mcast_sw_if_index = ~0; u32 decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT; @@ -685,6 +683,7 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, int rv; vnet_vxlan_add_del_tunnel_args_t _a, * a = &_a; u32 tunnel_sw_if_index; + clib_error_t *error = NULL; /* Cant "universally zero init" (={0}) due to GCC bug 53119 */ memset(&src, 0, sizeof src); @@ -699,6 +698,8 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, { is_add = 0; } + else if (unformat (line_input, "instance %d", &instance)) + ; else if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4)) { @@ -743,7 +744,10 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, { encap_fib_index = fib_table_find (fib_ip_proto (ipv6_set), tmp); if (encap_fib_index == ~0) - return clib_error_return (0, "nonexistent encap-vrf-id %d", tmp); + { + error = clib_error_return (0, "nonexistent encap-vrf-id %d", tmp); + goto done; + } } else if (unformat (line_input, "decap-next %U", unformat_decap_next, &decap_next_index, ipv4_set)) @@ -751,51 +755,83 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, else if (unformat (line_input, "vni %d", &vni)) { if (vni >> 24) - return clib_error_return (0, "vni %d out of range", vni); + { + error = clib_error_return (0, "vni %d out of range", vni); + goto done; + } } else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } } - unformat_free (line_input); - if (src_set == 0) - return clib_error_return (0, "tunnel src address not specified"); + { + error = clib_error_return (0, "tunnel src address not specified"); + goto done; + } if (dst_set == 0) - return clib_error_return (0, "tunnel dst address not specified"); + { + error = clib_error_return (0, "tunnel dst address not specified"); + goto done; + } if (grp_set && !ip46_address_is_multicast(&dst)) - return clib_error_return (0, "tunnel group address not multicast"); + { + error = clib_error_return (0, "tunnel group address not multicast"); + goto done; + } if (grp_set == 0 && ip46_address_is_multicast(&dst)) - return clib_error_return (0, "dst address must be unicast"); + { + error = clib_error_return (0, "dst address must be unicast"); + goto done; + } if (grp_set && mcast_sw_if_index == ~0) - return clib_error_return (0, "tunnel nonexistent multicast device"); + { + error = clib_error_return (0, "tunnel nonexistent multicast device"); + goto done; + } if (ipv4_set && ipv6_set) - return clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + { + error = clib_error_return (0, "both IPv4 and IPv6 addresses specified"); + goto done; + } if (ip46_address_cmp(&src, &dst) == 0) - return clib_error_return (0, "src and dst addresses are identical"); + { + error = clib_error_return (0, "src and dst addresses are identical"); + goto done; + } if (decap_next_index == ~0) - return clib_error_return (0, "next node not found"); + { + error = clib_error_return (0, "next node not found"); + goto done; + } if (vni == 0) - return clib_error_return (0, "vni not specified"); + { + error = clib_error_return (0, "vni not specified"); + goto done; + } memset (a, 0, sizeof (*a)); a->is_add = is_add; a->is_ip6 = ipv6_set; + a->instance = instance; #define _(x) a->x = x; foreach_copy_field; #undef _ - + rv = vnet_vxlan_add_del_tunnel (a, &tunnel_sw_if_index); switch(rv) @@ -807,17 +843,31 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, break; case VNET_API_ERROR_TUNNEL_EXIST: - return clib_error_return (0, "tunnel already exists..."); + error = clib_error_return (0, "tunnel already exists..."); + goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: - return clib_error_return (0, "tunnel does not exist..."); + error = clib_error_return (0, "tunnel does not exist..."); + goto done; + + case VNET_API_ERROR_INVALID_ARGUMENT: + error = clib_error_return (0, "Invalid argument"); + goto done; + + case VNET_API_ERROR_INSTANCE_IN_USE: + error = clib_error_return (0, "Instance is in use"); + goto done; default: - return clib_error_return + error = clib_error_return (0, "vnet_vxlan_add_del_tunnel returned %d", rv); + goto done; } - return 0; +done: + unformat_free (line_input); + + return error; } /*? @@ -837,6 +887,8 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm, * @cliexpar * Example of how to create a VXLAN Tunnel: * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 encap-vrf-id 7} + * Example of how to create a VXLAN Tunnel with a known name, vxlan_tunnel42: + * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 instance 42} * Example of how to delete a VXLAN Tunnel: * @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 del} ?*/ @@ -846,6 +898,7 @@ VLIB_CLI_COMMAND (create_vxlan_tunnel_command, static) = { .short_help = "create vxlan tunnel src " " {dst |group } vni " + " [instance ]" " [encap-vrf-id ] [decap-next [l2|node ]] [del]", .function = vxlan_add_del_tunnel_command_fn, }; @@ -940,6 +993,8 @@ set_ip_vxlan_bypass (u32 is_ip6, vnet_int_vxlan_bypass_mode (sw_if_index, is_ip6, is_enable); done: + unformat_free (line_input); + return error; } @@ -1088,3 +1143,9 @@ clib_error_t *vxlan_init (vlib_main_t *vm) } VLIB_INIT_FUNCTION(vxlan_init); + +/* + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */