X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Flisp-gpe%2Finterface.c;h=1ccb53dda72d691cb32367cfdaa5df06f77db55d;hb=b474380f;hp=3288b2414b7f3a090b7782c311de3681f9c25d57;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c index 3288b2414b7..1ccb53dda72 100644 --- a/src/vnet/lisp-gpe/interface.c +++ b/src/vnet/lisp-gpe/interface.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -185,7 +185,8 @@ format_lisp_gpe_header_with_length (u8 * s, va_list * args) s = format (s, "\n ver_res %d res %d next_protocol %d iid %d(%x)", h->ver_res, h->res, h->next_protocol, - clib_net_to_host_u32 (h->iid), clib_net_to_host_u32 (h->iid)); + clib_net_to_host_u32 (h->iid << 8), + clib_net_to_host_u32 (h->iid << 8)); return s; } @@ -201,7 +202,7 @@ VNET_HW_INTERFACE_CLASS (lisp_gpe_hw_class) = { typedef struct { - u32 lb_index; + u32 dpo_index; } l2_lisp_gpe_tx_trace_t; static u8 * @@ -211,7 +212,7 @@ format_l2_lisp_gpe_tx_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); l2_lisp_gpe_tx_trace_t *t = va_arg (*args, l2_lisp_gpe_tx_trace_t *); - s = format (s, "L2-LISP-GPE-TX: load-balance %d", t->lb_index); + s = format (s, "L2-LISP-GPE-TX: load-balance %d", t->dpo_index); return s; } @@ -238,6 +239,8 @@ l2_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, { u32 n_left_from, next_index, *from, *to_next; lisp_gpe_main_t *lgm = &lisp_gpe_main; + u32 thread_index = vm->thread_index; + vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; @@ -273,12 +276,14 @@ l2_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, e0->src_address, e0->dst_address); vnet_buffer (b0)->ip.adj_index[VLIB_TX] = lbi0; - + vlib_increment_combined_counter (cm, thread_index, lbi0, 1, + vlib_buffer_length_in_chain (vm, + b0)); if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->lb_index = lbi0; + tr->dpo_index = lbi0; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, l2_arc_to_lb); @@ -306,6 +311,110 @@ VNET_DEVICE_CLASS (l2_lisp_gpe_device_class,static) = { }; /* *INDENT-ON* */ +typedef struct +{ + u32 dpo_index; +} nsh_lisp_gpe_tx_trace_t; + +u8 * +format_nsh_lisp_gpe_tx_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + nsh_lisp_gpe_tx_trace_t *t = va_arg (*args, nsh_lisp_gpe_tx_trace_t *); + + s = format (s, "NSH-GPE-TX: tunnel %d", t->dpo_index); + return s; +} + +/** + * @brief LISP-GPE interface TX for NSH overlays. + * @node nsh_lisp_gpe_interface_tx + * + * The NSH LISP-GPE interface TX function. + * + * @param[in] vm vlib_main_t corresponding to the current thread. + * @param[in] node vlib_node_runtime_t data for this node. + * @param[in] frame vlib_frame_t whose contents should be dispatched. + * + * @return number of vectors in frame. + */ +static uword +nsh_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, next_index, *from, *to_next; + lisp_gpe_main_t *lgm = &lisp_gpe_main; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u32 bi0; + u32 *nsh0, next0; + const dpo_id_t *dpo0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + nsh0 = vlib_buffer_get_current (b0); + + vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_LCAF; + + /* lookup SPI + SI (second word of the NSH header). + * NB: Load balancing was done by the control plane */ + dpo0 = lisp_nsh_fib_lookup (lgm, nsh0[1]); + + next0 = dpo0->dpoi_next_node; + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + nsh_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, + sizeof (*tr)); + tr->dpo_index = dpo0->dpoi_index; + } + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return from_frame->n_vectors; +} + +static u8 * +format_nsh_lisp_gpe_name (u8 * s, va_list * args) +{ + u32 dev_instance = va_arg (*args, u32); + return format (s, "nsh_lisp_gpe%d", dev_instance); +} + +/* *INDENT-OFF* */ +VNET_DEVICE_CLASS (nsh_lisp_gpe_device_class,static) = { + .name = "NSH_LISP_GPE", + .format_device_name = format_nsh_lisp_gpe_name, + .format_tx_trace = format_nsh_lisp_gpe_tx_trace, + .tx_function = nsh_lisp_gpe_interface_tx, +}; +/* *INDENT-ON* */ + static vnet_hw_interface_t * lisp_gpe_create_iface (lisp_gpe_main_t * lgm, u32 vni, u32 dp_table, vnet_device_class_t * dev_class, @@ -396,12 +505,14 @@ lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id) { fib_node_index_t fib_index; - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id); + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id, + FIB_SOURCE_LISP); vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; ip4_sw_interface_enable_disable (sw_if_index, 1); - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id); + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id, + FIB_SOURCE_LISP); vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; ip6_sw_interface_enable_disable (sw_if_index, 1); @@ -421,7 +532,7 @@ lisp_gpe_tenant_del_default_routes (u32 table_id) fib_index = fib_table_find (prefix.fp_proto, table_id); fib_table_entry_special_remove (fib_index, &prefix, FIB_SOURCE_LISP); - fib_table_unlock (fib_index, prefix.fp_proto); + fib_table_unlock (fib_index, prefix.fp_proto, FIB_SOURCE_LISP); } } @@ -440,7 +551,8 @@ lisp_gpe_tenant_add_default_routes (u32 table_id) /* * Add a deafult route that results in a control plane punt DPO */ - fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id); + fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id, + FIB_SOURCE_LISP); fib_table_entry_special_dpo_add (fib_index, &prefix, FIB_SOURCE_LISP, FIB_ENTRY_FLAG_EXCLUSIVE, lisp_cp_dpo_get (fib_proto_to_dpo @@ -463,7 +575,8 @@ lisp_gpe_tenant_add_default_routes (u32 table_id) * @return number of vectors in frame. */ u32 -lisp_gpe_add_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id) +lisp_gpe_add_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id, + u8 with_default_routes) { vnet_main_t *vnm = lgm->vnet_main; tunnel_lookup_t *l3_ifaces = &lgm->l3_ifaces; @@ -491,7 +604,8 @@ lisp_gpe_add_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id) /* insert default routes that point to lisp-cp lookup */ lisp_gpe_iface_set_table (hi->sw_if_index, table_id); - lisp_gpe_tenant_add_default_routes (table_id); + if (with_default_routes) + lisp_gpe_tenant_add_default_routes (table_id); /* enable interface */ vnet_sw_interface_set_flags (vnm, hi->sw_if_index, @@ -548,6 +662,12 @@ lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) uword *hip, *si; u16 bd_index; + if (bd_id > L2_BD_ID_MAX) + { + clib_warning ("bridge domain ID %d exceed 16M limit", bd_id); + return ~0; + } + bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); @@ -580,7 +700,7 @@ lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) /* we're ready. add iface to l2 bridge domain */ set_int_l2_mode (lgm->vlib_main, vnm, MODE_L2_BRIDGE, hi->sw_if_index, - bd_index, 0, 0, 0); + bd_index, L2_BD_PORT_TYPE_NORMAL, 0, 0); return (hi->sw_if_index); } @@ -600,11 +720,11 @@ void lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) { tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces; - u16 bd_index; - uword *hip; + vnet_hw_interface_t *hi; - bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); - hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); + u32 bd_index = bd_find_index (&bd_main, bd_id); + ASSERT (bd_index != ~0); + uword *hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); if (hip == 0) { @@ -612,9 +732,80 @@ lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) bd_id); return; } + + /* Remove interface from bridge .. by enabling L3 mode */ + hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]); + set_int_l2_mode (lgm->vlib_main, lgm->vnet_main, MODE_L3, hi->sw_if_index, + 0, L2_BD_PORT_TYPE_NORMAL, 0, 0); lisp_gpe_remove_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces); } +/** + * @brief Add LISP-GPE NSH interface. + * + * Creates LISP-GPE interface, sets it in L3 mode. + * + * @param[in] lgm Reference to @ref lisp_gpe_main_t. + * @param[in] a Parameters to create interface. + * + * @return sw_if_index. + */ +u32 +vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm) +{ + vnet_main_t *vnm = lgm->vnet_main; + tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; + vnet_hw_interface_t *hi; + uword *hip, *si; + + hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); + + if (hip) + { + clib_warning ("NSH interface 0 already exists"); + return ~0; + } + + si = hash_get (nsh_ifaces->sw_if_index_by_vni, 0); + if (si) + { + clib_warning ("NSH interface already exists"); + return ~0; + } + + /* create lisp iface and populate tunnel tables */ + hi = lisp_gpe_create_iface (lgm, 0, 0, + &nsh_lisp_gpe_device_class, &lgm->nsh_ifaces); + + /* enable interface */ + vnet_sw_interface_set_flags (vnm, hi->sw_if_index, + VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_hw_interface_set_flags (vnm, hi->hw_if_index, + VNET_HW_INTERFACE_FLAG_LINK_UP); + + return (hi->sw_if_index); +} + +/** + * @brief Del LISP-GPE NSH interface. + * + */ +void +vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm) +{ + tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; + uword *hip; + + hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); + + if (hip == 0) + { + clib_warning ("The NSH 0 interface doesn't exist"); + return; + } + lisp_gpe_remove_iface (lgm, hip[0], 0, &lgm->nsh_ifaces); +} + static clib_error_t * lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -623,6 +814,8 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 is_add = 1; u32 table_id, vni, bd_id; u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0; + u8 nsh_iface = 0; + clib_error_t *error = NULL; if (vnet_lisp_gpe_enable_disable_status () == 0) { @@ -651,29 +844,64 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, { bd_index_is_set = 1; } + else if (unformat (line_input, "nsh")) + { + nsh_iface = 1; + } + else + { + error = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + goto done; + } + } + + if (nsh_iface) + { + if (is_add) + { + if (~0 == vnet_lisp_gpe_add_nsh_iface (&lisp_gpe_main)) + { + error = clib_error_return (0, "NSH interface not created"); + goto done; + } + } else { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); + vnet_lisp_gpe_del_nsh_iface (&lisp_gpe_main); } + goto done; } if (vrf_is_set && bd_index_is_set) - return clib_error_return (0, - "Cannot set both vrf and brdige domain index!"); + { + error = clib_error_return + (0, "Cannot set both vrf and brdige domain index!"); + goto done; + } if (!vni_is_set) - return clib_error_return (0, "vni must be set!"); + { + error = clib_error_return (0, "vni must be set!"); + goto done; + } if (!vrf_is_set && !bd_index_is_set) - return clib_error_return (0, "vrf or bridge domain index must be set!"); + { + error = + clib_error_return (0, "vrf or bridge domain index must be set!"); + goto done; + } if (bd_index_is_set) { if (is_add) { if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, bd_id)) - return clib_error_return (0, "L2 interface not created"); + { + error = clib_error_return (0, "L2 interface not created"); + goto done; + } } else lisp_gpe_tenant_l2_iface_unlock (vni); @@ -682,20 +910,28 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, { if (is_add) { - if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, table_id)) - return clib_error_return (0, "L3 interface not created"); + if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, table_id, 1 + /* with_default_route */ + )) + { + error = clib_error_return (0, "L3 interface not created"); + goto done; + } } else lisp_gpe_tenant_l3_iface_unlock (vni); } - return (NULL); +done: + unformat_free (line_input); + + return error; } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (add_del_lisp_gpe_iface_command, static) = { - .path = "lisp gpe iface", - .short_help = "lisp gpe iface add/del vni vrf ", + .path = "gpe iface", + .short_help = "gpe iface add/del vni vrf ", .function = lisp_gpe_add_del_iface_command_fn, }; /* *INDENT-ON* */