X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface.c;h=1d59a96219f13262e2cd8285358737935d189343;hb=f09d655101d2400df91d2a388168b925eea0dc01;hp=dbfe49694f53c2aaddbd1755dd3b6807b33dc670;hpb=6a7cff7ec234af8529ff72a530076e191cc8d759;p=vpp.git diff --git a/src/vnet/interface.c b/src/vnet/interface.c index dbfe49694f5..1d59a96219f 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -39,10 +39,19 @@ #include #include -#include #include #include -#include +#include +#include + +/* *INDENT-OFF* */ +VLIB_REGISTER_LOG_CLASS (if_default_log, static) = { + .class_name = "interface", +}; +/* *INDENT-ON* */ + +#define log_debug(fmt,...) vlib_log_debug(if_default_log.class, fmt, __VA_ARGS__) +#define log_err(fmt,...) vlib_log_err(if_default_log.class, fmt, __VA_ARGS__) typedef enum vnet_interface_helper_flags_t_ { @@ -132,22 +141,22 @@ serialize_vnet_interface_state (serialize_main_t * m, va_list * va) /* Serialize hardware interface classes since they may have changed. Must do this before sending up/down flags. */ /* *INDENT-OFF* */ - pool_foreach (hif, im->hw_interfaces, ({ + pool_foreach (hif, im->hw_interfaces) { vnet_hw_interface_class_t * hw_class = vnet_get_hw_interface_class (vnm, hif->hw_class_index); serialize_cstring (m, hw_class->name); - })); + } /* *INDENT-ON* */ /* Send sw/hw interface state when non-zero. */ /* *INDENT-OFF* */ - pool_foreach (sif, im->sw_interfaces, ({ + pool_foreach (sif, im->sw_interfaces) { if (sif->flags != 0) { vec_add2 (sts, st, 1); st->sw_hw_if_index = sif->sw_if_index; st->flags = sif->flags; } - })); + } /* *INDENT-ON* */ vec_serialize (m, sts, serialize_vec_vnet_sw_hw_interface_state); @@ -156,14 +165,14 @@ serialize_vnet_interface_state (serialize_main_t * m, va_list * va) _vec_len (sts) = 0; /* *INDENT-OFF* */ - pool_foreach (hif, im->hw_interfaces, ({ + pool_foreach (hif, im->hw_interfaces) { if (hif->flags != 0) { vec_add2 (sts, st, 1); st->sw_hw_if_index = hif->hw_if_index; st->flags = vnet_hw_interface_flags_to_sw(hif->flags); } - })); + } /* *INDENT-ON* */ vec_serialize (m, sts, serialize_vec_vnet_sw_hw_interface_state); @@ -197,15 +206,21 @@ unserialize_vnet_interface_state (serialize_main_t * m, va_list * va) clib_error_t *error; /* *INDENT-OFF* */ - pool_foreach (hif, im->hw_interfaces, ({ + 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); - })); + } /* *INDENT-ON* */ } @@ -287,9 +302,6 @@ 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, vnet_hw_interface_flags_t flags, @@ -336,6 +348,8 @@ vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index, hi->flags |= flags; done: + if (error) + log_err ("hw_set_flags_helper: %U", format_clib_error, error); return error; } @@ -397,15 +411,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; @@ -490,6 +495,7 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, hi->flags & ~VNET_HW_INTERFACE_FLAG_LINK_UP, helper_flags); + vnet_hw_if_update_runtime_data (vnm, si->hw_if_index); } } @@ -497,6 +503,8 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, si->flags |= flags; done: + if (error) + log_err ("sw_set_flags_helper: %U", format_clib_error, error); return error; } @@ -504,6 +512,7 @@ clib_error_t * vnet_hw_interface_set_flags (vnet_main_t * vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags) { + log_debug ("hw_set_flags: hw_if_index %u flags 0x%x", hw_if_index, flags); return vnet_hw_interface_set_flags_helper (vnm, hw_if_index, flags, VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE); @@ -513,11 +522,53 @@ clib_error_t * vnet_sw_interface_set_flags (vnet_main_t * vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags) { + log_debug ("sw_set_flags: sw_if_index %u flags 0x%x", sw_if_index, 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); + log_debug ("sw_admin_up: sw_if_index %u", 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); + log_debug ("sw_admin_down: sw_if_index %u", 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 void +vnet_if_update_lookup_tables (vnet_main_t *vnm, u32 sw_if_index) +{ + vnet_interface_main_t *im = &vnm->interface_main; + vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); + + vec_validate_init_empty (im->hw_if_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (im->if_out_arc_end_next_index_by_sw_if_index, + sw_if_index, ~0); + + im->hw_if_index_by_sw_if_index[sw_if_index] = hi->hw_if_index; + im->if_out_arc_end_next_index_by_sw_if_index[sw_if_index] = + hi->if_out_arc_end_node_next_index; +} + static u32 vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm, vnet_sw_interface_t * template) @@ -559,6 +610,7 @@ vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm, vnet_interface_counter_unlock (im); } + vnet_if_update_lookup_tables (vnm, sw_if_index); return sw_if_index; } @@ -566,10 +618,22 @@ clib_error_t * vnet_create_sw_interface (vnet_main_t * vnm, vnet_sw_interface_t * template, u32 * sw_if_index) { + vnet_interface_main_t *im = &vnm->interface_main; clib_error_t *error; 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)) + { + char *str = "inner-dot1q any exact-match is unsupported"; + error = clib_error_return (0, str); + log_err ("create_sw_interface: %s", str); + 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); @@ -591,11 +655,19 @@ vnet_create_sw_interface (vnet_main_t * vnm, vnet_sw_interface_t * template, if (error) { /* undo the work done by vnet_create_sw_interface_no_callbacks() */ - vnet_interface_main_t *im = &vnm->interface_main; + log_err ("create_sw_interface: set flags failed\n %U", + format_clib_error, error); vnet_sw_interface_t *sw = pool_elt_at_index (im->sw_interfaces, *sw_if_index); pool_put (im->sw_interfaces, sw); } + else + { + vnet_sw_interface_t *sw = + pool_elt_at_index (im->sw_interfaces, *sw_if_index); + log_debug ("create_sw_interface: interface %U (sw_if_index %u) created", + format_vnet_sw_interface_name, vnm, sw, *sw_if_index); + } return error; } @@ -607,19 +679,10 @@ vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index) vnet_sw_interface_t *sw = pool_elt_at_index (im->sw_interfaces, sw_if_index); + log_debug ("delete_sw_interface: sw_if_index %u, name '%U'", + sw_if_index, format_vnet_sw_if_index_name, vnm, 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. */ @@ -646,6 +709,9 @@ vnet_sw_interface_set_mtu (vnet_main_t * vnm, u32 sw_if_index, u32 mtu) if (si->mtu[VNET_MTU_L3] != mtu) { si->mtu[VNET_MTU_L3] = mtu; + log_debug ("set_mtu: interface %U, new mtu %u", + format_vnet_sw_if_index_name, vnm, sw_if_index, mtu); + call_sw_interface_mtu_change_callbacks (vnm, sw_if_index); } } @@ -668,7 +734,13 @@ vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index, } /* Notify interested parties */ if (changed) - call_sw_interface_mtu_change_callbacks (vnm, sw_if_index); + { + log_debug ("set_protocol_mtu: interface %U l3 %u ip4 %u ip6 %u mpls %u", + format_vnet_sw_if_index_name, vnm, sw_if_index, + mtu[VNET_MTU_L3], mtu[VNET_MTU_IP4], mtu[VNET_MTU_IP6], + mtu[VNET_MTU_MPLS]); + call_sw_interface_mtu_change_callbacks (vnm, sw_if_index); + } } void @@ -718,12 +790,11 @@ setup_tx_node (vlib_main_t * vm, { vlib_node_t *n = vlib_get_node (vm, node_index); - n->function = dev_class->tx_function; n->format_trace = dev_class->format_tx_trace; - vlib_register_errors (vm, node_index, - dev_class->tx_function_n_errors, - dev_class->tx_function_error_strings); + vlib_register_errors (vm, node_index, dev_class->tx_function_n_errors, + dev_class->tx_function_error_strings, + dev_class->tx_function_error_counters); } static void @@ -753,13 +824,16 @@ vnet_register_interface (vnet_main_t * vnm, vnet_config_main_t *cm; u32 hw_index, i; char *tx_node_name = NULL, *output_node_name = NULL; + vlib_node_t *if_out_node = + vlib_get_node (vm, vnet_interface_output_node.index); 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); @@ -795,7 +869,7 @@ vnet_register_interface (vnet_main_t * vnm, hw->min_packet_bytes = 0; vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, 0); - if (dev_class->tx_function == 0) + if (dev_class->tx_function == 0 && dev_class->tx_fn_registrations == 0) goto no_output_nodes; /* No output/tx nodes to create */ tx_node_name = (char *) format (0, "%v-tx", hw->name); @@ -816,45 +890,57 @@ vnet_register_interface (vnet_main_t * vnm, vlib_node_rename (vm, hw->tx_node_index, "%v", tx_node_name); vlib_node_rename (vm, hw->output_node_index, "%v", output_node_name); - /* *INDENT-OFF* */ - foreach_vlib_main ({ - vnet_interface_output_runtime_t *rt; - - rt = vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index); - ASSERT (rt->is_deleted == 1); - rt->is_deleted = 0; - rt->hw_if_index = hw_index; - rt->sw_if_index = hw->sw_if_index; - rt->dev_instance = hw->dev_instance; + foreach_vlib_main () + { + vnet_interface_output_runtime_t *rt; - rt = vlib_node_get_runtime_data (this_vlib_main, hw->tx_node_index); - rt->hw_if_index = hw_index; - rt->sw_if_index = hw->sw_if_index; - rt->dev_instance = hw->dev_instance; - }); - /* *INDENT-ON* */ + rt = + vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index); + ASSERT (rt->is_deleted == 1); + rt->is_deleted = 0; + rt->hw_if_index = hw_index; + rt->sw_if_index = hw->sw_if_index; + rt->dev_instance = hw->dev_instance; + + rt = vlib_node_get_runtime_data (this_vlib_main, hw->tx_node_index); + rt->hw_if_index = hw_index; + rt->sw_if_index = hw->sw_if_index; + rt->dev_instance = hw->dev_instance; + } /* 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; 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; - }); - /* *INDENT-ON* */ + node->node_fn_registrations = if_out_node->node_fn_registrations; + node->function = if_out_node->function; + + 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); + } node = vlib_get_node (vm, hw->tx_node_index); - node->function = dev_class->tx_function; + if (dev_class->tx_fn_registrations) + { + node->node_fn_registrations = dev_class->tx_fn_registrations; + node->function = vlib_node_get_preferred_node_fn_variant ( + vm, dev_class->tx_fn_registrations); + } + else + node->function = dev_class->tx_function; node->format_trace = dev_class->format_tx_trace; - /* *INDENT-OFF* */ - foreach_vlib_main ({ - nrt = vlib_node_get_runtime (this_vlib_main, hw->tx_node_index); - nrt->function = node->function; - }); - /* *INDENT-ON* */ + + 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); + } _vec_len (im->deleted_hw_interface_nodes) -= 1; } @@ -877,7 +963,13 @@ vnet_register_interface (vnet_main_t * vnm, r.flags = VLIB_NODE_FLAG_IS_OUTPUT; r.name = tx_node_name; - r.function = dev_class->tx_function; + if (dev_class->tx_fn_registrations) + { + r.function = 0; + r.node_fn_registrations = dev_class->tx_fn_registrations; + } + else + r.function = dev_class->tx_function; hw->tx_node_index = vlib_register_node (vm, &r); @@ -887,8 +979,14 @@ vnet_register_interface (vnet_main_t * vnm, r.flags = 0; r.name = output_node_name; - r.function = vnet_interface_output_node; r.format_trace = format_vnet_interface_output_trace; + if (if_out_node->node_fn_registrations) + { + r.function = 0; + r.node_fn_registrations = if_out_node->node_fn_registrations; + } + else + r.function = if_out_node->function; { static char *e[] = { @@ -908,7 +1006,6 @@ vnet_register_interface (vnet_main_t * vnm, vlib_node_add_next_with_slot (vm, hw->output_node_index, hw->tx_node_index, VNET_INTERFACE_OUTPUT_NEXT_TX); - /* add interface to the list of "output-interface" feature arc start nodes and clone nexts from 1st interface if it exists */ fcm = vnet_feature_get_config_main (im->output_feature_arc_index); @@ -932,6 +1029,9 @@ vnet_register_interface (vnet_main_t * vnm, } } + hw->if_out_arc_end_node_next_index = vlib_node_add_next ( + vm, vnet_interface_output_arc_end_node.index, hw->tx_node_index); + vnet_if_update_lookup_tables (vnm, hw->sw_if_index); setup_output_node (vm, hw->output_node_index, hw_class); setup_tx_node (vm, hw->tx_node_index, dev_class); @@ -962,6 +1062,10 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index) /* Call delete callbacks. */ call_hw_interface_add_del_callbacks (vnm, hw_if_index, /* is_create */ 0); + /* delete rx queues */ + vnet_hw_if_unregister_all_rx_queues (vnm, hw_if_index); + vnet_hw_if_update_runtime_data (vnm, hw_if_index); + /* Delete any sub-interfaces. */ { u32 id, sw_if_index; @@ -986,17 +1090,15 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index) /* Put output/tx nodes into recycle pool */ vnet_hw_interface_nodes_t *dn; - /* *INDENT-OFF* */ - foreach_vlib_main - ({ + foreach_vlib_main () + { vnet_interface_output_runtime_t *rt = vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index); /* Mark node runtime as deleted so output node (if called) * will drop packets. */ rt->is_deleted = 1; - }); - /* *INDENT-ON* */ + } vlib_node_rename (vm, hw->output_node_index, "interface-%d-output-deleted", hw_if_index); @@ -1011,8 +1113,7 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index) vec_free (hw->name); vec_free (hw->hw_address); vec_free (hw->input_node_thread_index_by_queue); - vec_free (hw->dq_runtime_index_by_queue); - + vec_free (hw->rx_queue_indices); pool_put (im->hw_interfaces, hw); } @@ -1049,11 +1150,11 @@ vnet_hw_interface_walk (vnet_main_t * vnm, im = &vnm->interface_main; /* *INDENT-OFF* */ - pool_foreach (hi, im->hw_interfaces, - ({ + pool_foreach (hi, im->hw_interfaces) + { if (WALK_STOP == fn(vnm, hi->hw_if_index, ctx)) break; - })); + } /* *INDENT-ON* */ } @@ -1067,11 +1168,11 @@ vnet_sw_interface_walk (vnet_main_t * vnm, im = &vnm->interface_main; /* *INDENT-OFF* */ - pool_foreach (si, im->sw_interfaces, + pool_foreach (si, im->sw_interfaces) { if (WALK_STOP == fn (vnm, si, ctx)) break; - }); + } /* *INDENT-ON* */ } @@ -1222,6 +1323,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) { @@ -1248,9 +1359,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) \ @@ -1265,7 +1375,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)); @@ -1279,25 +1389,13 @@ vnet_interface_init (vlib_main_t * vm) c->index = vec_len (im->device_classes); hash_set_mem (im->device_class_by_name, c->name, c->index); + /* to avoid confusion, please remove ".tx_function" statement + from VNET_DEVICE_CLASS() if using function candidates */ + ASSERT (c->tx_fn_registrations == 0 || c->tx_function == 0); + if (c->tx_fn_registrations) - { - vlib_node_fn_registration_t *fnr = c->tx_fn_registrations; - int priority = -1; - - /* to avoid confusion, please remove ".tx_function" statement - from VNET_DEVICE_CLASS() if using function candidates */ - ASSERT (c->tx_function == 0); - - while (fnr) - { - if (fnr->priority > priority) - { - priority = fnr->priority; - c->tx_function = fnr->function; - } - fnr = fnr->next_registration; - } - } + c->tx_function = vlib_node_get_preferred_node_fn_variant ( + vm, c->tx_fn_registrations); vec_add1 (im->device_classes, c[0]); c = c->next_class_registration; @@ -1307,6 +1405,8 @@ vnet_interface_init (vlib_main_t * vm) im->hw_interface_class_by_name = hash_create_string ( /* size */ 0, sizeof (uword)); + im->rxq_index_by_hw_if_index_and_queue_id = + hash_create_mem (0, sizeof (u64), sizeof (u32)); im->sw_if_index_by_sup_and_sub = hash_create_mem (0, sizeof (u64), sizeof (uword)); { @@ -1329,7 +1429,6 @@ vnet_interface_init (vlib_main_t * vm) } } - im->gso_interface_count = 0; /* init per-thread data */ vec_validate_aligned (im->per_thread_data, vlib_num_workers (), CLIB_CACHE_LINE_BYTES); @@ -1339,11 +1438,6 @@ vnet_interface_init (vlib_main_t * vm) vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword)); -#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 - if ((error = vlib_call_init_function (vm, trajectory_trace_init))) - return error; -#endif - return 0; } @@ -1415,6 +1509,50 @@ 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: + if (error) + log_err ("hw_add_del_mac_address: %U", format_clib_error, error); + return error; +} + static clib_error_t * vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, u32 hw_if_index, @@ -1609,6 +1747,44 @@ 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: + if (error) + log_err ("hw_set_rss_queues: %U", format_clib_error, error); + return error; +} + int collect_detailed_interface_stats_flag = 0; void