X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface.c;h=1cf63c75c67077a336b19777764e96def82a7801;hb=148c7b768;hp=dba5a667b22d69933b03d3f7aaa70f3066ab1ce8;hpb=b7b929931a07fbb27b43d5cd105f366c3e29807e;p=vpp.git diff --git a/src/vnet/interface.c b/src/vnet/interface.c index dba5a667b22..1cf63c75c67 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -42,20 +42,26 @@ #include #include #include -#include -#define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0) -#define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1) +typedef enum vnet_interface_helper_flags_t_ +{ + VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE = (1 << 0), + VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE = (1 << 1), +} vnet_interface_helper_flags_t; static clib_error_t *vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index, - u32 flags, - u32 helper_flags); + vnet_hw_interface_flags_t + flags, + vnet_interface_helper_flags_t + helper_flags); static clib_error_t *vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, - u32 flags, - u32 helper_flags); + vnet_sw_interface_flags_t + flags, + vnet_interface_helper_flags_t + helper_flags); static clib_error_t *vnet_hw_interface_set_class_helper (vnet_main_t * vnm, u32 hw_if_index, @@ -102,6 +108,17 @@ unserialize_vec_vnet_sw_hw_interface_state (serialize_main_t * m, } } +static vnet_sw_interface_flags_t +vnet_hw_interface_flags_to_sw (vnet_hw_interface_flags_t hwf) +{ + vnet_sw_interface_flags_t swf = VNET_SW_INTERFACE_FLAG_NONE; + + if (hwf & VNET_HW_INTERFACE_FLAG_LINK_UP) + swf |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; + + return (swf); +} + void serialize_vnet_interface_state (serialize_main_t * m, va_list * va) { @@ -143,7 +160,7 @@ serialize_vnet_interface_state (serialize_main_t * m, va_list * va) { vec_add2 (sts, st, 1); st->sw_hw_if_index = hif->hw_if_index; - st->flags = hif->flags; + st->flags = vnet_hw_interface_flags_to_sw(hif->flags); } })); /* *INDENT-ON* */ @@ -153,6 +170,17 @@ serialize_vnet_interface_state (serialize_main_t * m, va_list * va) vec_free (sts); } +static vnet_hw_interface_flags_t +vnet_sw_interface_flags_to_hw (vnet_sw_interface_flags_t swf) +{ + vnet_hw_interface_flags_t hwf = VNET_HW_INTERFACE_FLAG_NONE; + + if (swf & VNET_SW_INTERFACE_FLAG_ADMIN_UP) + hwf |= VNET_HW_INTERFACE_FLAG_LINK_UP; + + return (hwf); +} + void unserialize_vnet_interface_state (serialize_main_t * m, va_list * va) { @@ -171,8 +199,14 @@ unserialize_vnet_interface_state (serialize_main_t * m, va_list * va) pool_foreach (hif, im->hw_interfaces, ({ unserialize_cstring (m, &class_name); p = hash_get_mem (im->hw_interface_class_by_name, class_name); - ASSERT (p != 0); - error = vnet_hw_interface_set_class_helper (vnm, hif->hw_if_index, p[0], /* redistribute */ 0); + if (p) + { + error = vnet_hw_interface_set_class_helper + (vnm, hif->hw_if_index, p[0], /* redistribute */ 0); + } + else + error = clib_error_return (0, "hw class %s AWOL?", class_name); + if (error) clib_error_report (error); vec_free (class_name); @@ -188,8 +222,11 @@ unserialize_vnet_interface_state (serialize_main_t * m, va_list * va) vec_unserialize (m, &sts, unserialize_vec_vnet_sw_hw_interface_state); vec_foreach (st, sts) - vnet_hw_interface_set_flags_helper (vnm, st->sw_hw_if_index, st->flags, - /* no distribute */ 0); + { + vnet_hw_interface_set_flags_helper + (vnm, st->sw_hw_if_index, vnet_sw_interface_flags_to_hw (st->flags), + /* no distribute */ 0); + } vec_free (sts); } @@ -255,12 +292,11 @@ call_sw_interface_add_del_callbacks (vnet_main_t * vnm, u32 sw_if_index, (vnm, sw_if_index, is_create, vnm->sw_interface_add_del_functions); } -#define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0) -#define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1) - static clib_error_t * vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index, - u32 flags, u32 helper_flags) + vnet_hw_interface_flags_t flags, + vnet_interface_helper_flags_t + helper_flags) { vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); vnet_hw_interface_class_t *hw_class = @@ -271,8 +307,7 @@ vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index, (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0; mask = - (VNET_HW_INTERFACE_FLAG_LINK_UP | VNET_HW_INTERFACE_FLAG_DUPLEX_MASK | - VNET_HW_INTERFACE_FLAG_SPEED_MASK); + (VNET_HW_INTERFACE_FLAG_LINK_UP | VNET_HW_INTERFACE_FLAG_DUPLEX_MASK); flags &= mask; /* Call hardware interface add/del callbacks. */ @@ -308,7 +343,9 @@ done: static clib_error_t * vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, - u32 flags, u32 helper_flags) + vnet_sw_interface_flags_t flags, + vnet_interface_helper_flags_t + helper_flags) { vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); u32 mask; @@ -362,15 +399,6 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, } } - /* Do not change state for slave link of bonded interfaces */ - if (si->flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE) - { - error = clib_error_return - (0, "not allowed as %U belong to a BondEthernet interface", - format_vnet_sw_interface_name, vnm, si); - goto done; - } - /* Already in the desired state? */ if ((si->flags & mask) == flags) goto done; @@ -466,7 +494,8 @@ done: } clib_error_t * -vnet_hw_interface_set_flags (vnet_main_t * vnm, u32 hw_if_index, u32 flags) +vnet_hw_interface_set_flags (vnet_main_t * vnm, u32 hw_if_index, + vnet_hw_interface_flags_t flags) { return vnet_hw_interface_set_flags_helper (vnm, hw_if_index, flags, @@ -474,13 +503,38 @@ vnet_hw_interface_set_flags (vnet_main_t * vnm, u32 hw_if_index, u32 flags) } clib_error_t * -vnet_sw_interface_set_flags (vnet_main_t * vnm, u32 sw_if_index, u32 flags) +vnet_sw_interface_set_flags (vnet_main_t * vnm, u32 sw_if_index, + vnet_sw_interface_flags_t flags) { return vnet_sw_interface_set_flags_helper (vnm, sw_if_index, flags, VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE); } +void +vnet_sw_interface_admin_up (vnet_main_t * vnm, u32 sw_if_index) +{ + u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); + + if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) + { + flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); + } +} + +void +vnet_sw_interface_admin_down (vnet_main_t * vnm, u32 sw_if_index) +{ + u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index); + + if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) + { + flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP); + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); + } +} + static u32 vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm, vnet_sw_interface_t * template) @@ -533,6 +587,16 @@ vnet_create_sw_interface (vnet_main_t * vnm, vnet_sw_interface_t * template, vnet_hw_interface_t *hi; vnet_device_class_t *dev_class; + if (template->sub.eth.flags.two_tags == 1 + && template->sub.eth.flags.exact_match == 1 + && (template->sub.eth.flags.inner_vlan_id_any == 1 + || template->sub.eth.flags.outer_vlan_id_any == 1)) + { + error = clib_error_return (0, + "inner-dot1q any exact-match is unsupported"); + return error; + } + hi = vnet_get_sup_hw_interface (vnm, template->sup_sw_if_index); dev_class = vnet_get_device_class (vnm, hi->dev_class_index); @@ -571,18 +635,6 @@ vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index) pool_elt_at_index (im->sw_interfaces, sw_if_index); /* Check if the interface has config and is removed from L2 BD or XConnect */ - vlib_main_t *vm = vlib_get_main (); - l2_input_config_t *config; - if (sw_if_index < vec_len (l2input_main.configs)) - { - config = vec_elt_at_index (l2input_main.configs, sw_if_index); - if (config->xconnect) - set_int_l2_mode (vm, vnm, MODE_L3, config->output_sw_if_index, 0, - L2_BD_PORT_TYPE_NORMAL, 0, 0); - if (config->xconnect || config->bridge) - set_int_l2_mode (vm, vnm, MODE_L3, sw_if_index, 0, - L2_BD_PORT_TYPE_NORMAL, 0, 0); - } vnet_clear_sw_interface_tag (vnm, sw_if_index); /* Bring down interface in case it is up. */ @@ -684,9 +736,10 @@ setup_tx_node (vlib_main_t * vm, n->function = dev_class->tx_function; n->format_trace = dev_class->format_tx_trace; + /// XXX: Update this to use counter structure vlib_register_errors (vm, node_index, dev_class->tx_function_n_errors, - dev_class->tx_function_error_strings); + dev_class->tx_function_error_strings, 0); } static void @@ -719,10 +772,11 @@ vnet_register_interface (vnet_main_t * vnm, pool_get (im->hw_interfaces, hw); clib_memset (hw, 0, sizeof (*hw)); + hw->trace_classify_table_index = ~0; hw_index = hw - im->hw_interfaces; hw->hw_if_index = hw_index; - hw->default_rx_mode = VNET_HW_INTERFACE_RX_MODE_POLLING; + hw->default_rx_mode = VNET_HW_IF_RX_MODE_POLLING; if (dev_class->format_device_name) hw->name = format (0, "%U", dev_class->format_device_name, dev_instance); @@ -800,12 +854,14 @@ vnet_register_interface (vnet_main_t * vnm, /* The new class may differ from the old one. * Functions have to be updated. */ node = vlib_get_node (vm, hw->output_node_index); - node->function = vnet_interface_output_node_multiarch_select (); + node->function = vnet_interface_output_node; node->format_trace = format_vnet_interface_output_trace; /* *INDENT-OFF* */ foreach_vlib_main ({ nrt = vlib_node_get_runtime (this_vlib_main, hw->output_node_index); nrt->function = node->function; + vlib_node_runtime_perf_counter (this_vlib_main, nrt, 0, 0, 0, + VLIB_NODE_RUNTIME_PERF_RESET); }); /* *INDENT-ON* */ @@ -816,6 +872,8 @@ vnet_register_interface (vnet_main_t * vnm, foreach_vlib_main ({ nrt = vlib_node_get_runtime (this_vlib_main, hw->tx_node_index); nrt->function = node->function; + vlib_node_runtime_perf_counter (this_vlib_main, nrt, 0, 0, 0, + VLIB_NODE_RUNTIME_PERF_RESET); }); /* *INDENT-ON* */ @@ -850,13 +908,14 @@ vnet_register_interface (vnet_main_t * vnm, r.flags = 0; r.name = output_node_name; - r.function = vnet_interface_output_node_multiarch_select (); + r.function = vnet_interface_output_node; r.format_trace = format_vnet_interface_output_trace; { static char *e[] = { "interface is down", "interface is deleted", + "no buffers to segment GSO", }; r.n_errors = ARRAY_LEN (e); @@ -1184,6 +1243,16 @@ vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index) return (hc->flags & VNET_HW_INTERFACE_CLASS_FLAG_P2P); } +int +vnet_sw_interface_is_nbma (vnet_main_t * vnm, u32 sw_if_index) +{ + vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index); + vnet_hw_interface_class_t *hc = + vnet_get_hw_interface_class (vnm, hw->hw_class_index); + + return (hc->flags & VNET_HW_INTERFACE_CLASS_FLAG_NBMA); +} + clib_error_t * vnet_interface_init (vlib_main_t * vm) { @@ -1210,9 +1279,8 @@ vnet_interface_init (vlib_main_t * vm) sizeof (b->opaque), sizeof (vnet_buffer_opaque_t)); } - im->sw_if_counter_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, - CLIB_CACHE_LINE_BYTES); - im->sw_if_counter_lock[0] = 1; /* should be no need */ + clib_spinlock_init (&im->sw_if_counter_lock); + clib_spinlock_lock (&im->sw_if_counter_lock); /* should be no need */ vec_validate (im->sw_if_counters, VNET_N_SIMPLE_INTERFACE_COUNTER - 1); #define _(E,n,p) \ @@ -1227,7 +1295,7 @@ vnet_interface_init (vlib_main_t * vm) im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n; foreach_combined_interface_counter_name #undef _ - im->sw_if_counter_lock[0] = 0; + clib_spinlock_unlock (&im->sw_if_counter_lock); im->device_class_by_name = hash_create_string ( /* size */ 0, sizeof (uword)); @@ -1291,6 +1359,10 @@ vnet_interface_init (vlib_main_t * vm) } } + /* init per-thread data */ + vec_validate_aligned (im->per_thread_data, vlib_num_workers (), + CLIB_CACHE_LINE_BYTES); + if ((error = vlib_call_init_function (vm, vnet_interface_cli_init))) return error; @@ -1372,10 +1444,52 @@ vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index, char *new_name) return error; } +clib_error_t * +vnet_hw_interface_add_del_mac_address (vnet_main_t * vnm, + u32 hw_if_index, + const u8 * mac_address, u8 is_add) +{ + clib_error_t *error = 0; + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); + + vnet_device_class_t *dev_class = + vnet_get_device_class (vnm, hi->dev_class_index); + + if (!hi->hw_address) + { + error = + clib_error_return + (0, "Secondary MAC Addresses not supported for interface index %u", + hw_if_index); + goto done; + } + + if (dev_class->mac_addr_add_del_function) + error = dev_class->mac_addr_add_del_function (hi, mac_address, is_add); + + if (!error) + { + vnet_hw_interface_class_t *hw_class; + + hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); + + if (NULL != hw_class->mac_addr_add_del_function) + error = hw_class->mac_addr_add_del_function (hi, mac_address, is_add); + } + + /* If no errors, add to the list of secondary MACs on the ethernet intf */ + if (!error) + ethernet_interface_add_del_address (ðernet_main, hw_if_index, + mac_address, is_add); + +done: + return error; +} + static clib_error_t * vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, u32 hw_if_index, - u8 * mac_address) + const u8 * mac_address) { clib_error_t *error = 0; vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); @@ -1420,7 +1534,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, clib_error_t * vnet_hw_interface_change_mac_address (vnet_main_t * vnm, u32 hw_if_index, - u8 * mac_address) + const u8 * mac_address) { return vnet_hw_interface_change_mac_address_helper (vnm, hw_if_index, mac_address); @@ -1566,6 +1680,42 @@ default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) } } +clib_error_t * +vnet_hw_interface_set_rss_queues (vnet_main_t * vnm, + vnet_hw_interface_t * hi, + clib_bitmap_t * bitmap) +{ + clib_error_t *error = 0; + vnet_device_class_t *dev_class = + vnet_get_device_class (vnm, hi->dev_class_index); + + if (dev_class->set_rss_queues_function) + { + if (clib_bitmap_count_set_bits (bitmap) == 0) + { + error = clib_error_return (0, + "must assign at least one valid rss queue"); + goto done; + } + + error = dev_class->set_rss_queues_function (vnm, hi, bitmap); + } + else + { + error = clib_error_return (0, + "setting rss queues is not supported on this interface"); + } + + if (!error) + { + clib_bitmap_free (hi->rss_queues); + hi->rss_queues = clib_bitmap_dup (bitmap); + } + +done: + return error; +} + int collect_detailed_interface_stats_flag = 0; void