X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface.c;h=36793f1177e5ec783bb0337aa2d16170d0d657f1;hb=0053de6;hp=1370d048b0bed348564f09cb78bcb3f146cf9b83;hpb=4e53a0d0f01c8c81842d1f50fb5cf0d26e0c1713;p=vpp.git diff --git a/src/vnet/interface.c b/src/vnet/interface.c index 1370d048b0b..36793f1177e 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -41,6 +41,7 @@ #include #include #include +#include #define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0) #define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1) @@ -121,6 +122,22 @@ unserialize_vnet_sw_interface_set_flags (serialize_main_t * m, va_list * va) /* helper_flags no redistribution */ 0); } +void +vnet_hw_interface_set_mtu (vnet_main_t * vnm, u32 hw_if_index, u32 mtu) +{ + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); + + if (hi->max_packet_bytes != mtu) + { + u16 l3_pad = hi->max_packet_bytes - hi->max_l3_packet_bytes[VLIB_TX]; + hi->max_packet_bytes = mtu; + hi->max_l3_packet_bytes[VLIB_TX] = + hi->max_l3_packet_bytes[VLIB_RX] = mtu - l3_pad; + ethernet_set_flags (vnm, hw_if_index, ETHERNET_INTERFACE_FLAG_MTU); + adj_mtu_update (hw_if_index); + } +} + static void unserialize_vnet_hw_interface_set_flags (serialize_main_t * m, va_list * va) { @@ -700,9 +717,10 @@ vnet_register_interface (vnet_main_t * vnm, vnet_feature_config_main_t *fcm; vnet_config_main_t *cm; u32 hw_index, i; - char *tx_node_name, *output_node_name; + char *tx_node_name = NULL, *output_node_name = NULL; pool_get (im->hw_interfaces, hw); + memset (hw, 0, sizeof (*hw)); hw_index = hw - im->hw_interfaces; hw->hw_if_index = hw_index; @@ -744,6 +762,9 @@ vnet_register_interface (vnet_main_t * vnm, hw->max_l3_packet_bytes[VLIB_RX] = ~0; hw->max_l3_packet_bytes[VLIB_TX] = ~0; + if (dev_class->tx_function == 0) + goto no_output_nodes; /* No output/tx nodes to create */ + tx_node_name = (char *) format (0, "%v-tx", hw->name); output_node_name = (char *) format (0, "%v-output", hw->name); @@ -783,18 +804,24 @@ 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 = dev_class->flatten_output_chains ? - vnet_interface_output_node_flatten_multiarch_select () : - vnet_interface_output_node_multiarch_select (); + node->function = vnet_interface_output_node_multiarch_select (); node->format_trace = format_vnet_interface_output_trace; - nrt = vlib_node_get_runtime (vm, hw->output_node_index); - nrt->function = node->function; + /* *INDENT-OFF* */ + foreach_vlib_main ({ + nrt = vlib_node_get_runtime (this_vlib_main, hw->output_node_index); + nrt->function = node->function; + }); + /* *INDENT-ON* */ node = vlib_get_node (vm, hw->tx_node_index); node->function = dev_class->tx_function; node->format_trace = dev_class->format_tx_trace; - nrt = vlib_node_get_runtime (vm, hw->tx_node_index); - nrt->function = node->function; + /* *INDENT-OFF* */ + foreach_vlib_main ({ + nrt = vlib_node_get_runtime (this_vlib_main, hw->tx_node_index); + nrt->function = node->function; + }); + /* *INDENT-ON* */ _vec_len (im->deleted_hw_interface_nodes) -= 1; } @@ -827,9 +854,7 @@ vnet_register_interface (vnet_main_t * vnm, r.flags = 0; r.name = output_node_name; - r.function = dev_class->flatten_output_chains ? - vnet_interface_output_node_flatten_multiarch_select () : - vnet_interface_output_node_multiarch_select (); + r.function = vnet_interface_output_node_multiarch_select (); r.format_trace = format_vnet_interface_output_trace; { @@ -876,11 +901,14 @@ vnet_register_interface (vnet_main_t * vnm, setup_output_node (vm, hw->output_node_index, hw_class); setup_tx_node (vm, hw->tx_node_index, dev_class); +no_output_nodes: /* Call all up/down callbacks with zero flags when interface is created. */ vnet_sw_interface_set_flags_helper (vnm, hw->sw_if_index, /* flags */ 0, VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE); vnet_hw_interface_set_flags_helper (vnm, hw_index, /* flags */ 0, VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE); + vec_free (tx_node_name); + vec_free (output_node_name); return hw_index; } @@ -891,7 +919,8 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index) vnet_interface_main_t *im = &vnm->interface_main; vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); vlib_main_t *vm = vnm->vlib_main; - + vnet_device_class_t *dev_class = vnet_get_device_class (vnm, + hw->dev_class_index); /* If it is up, mark it down. */ if (hw->flags != 0) vnet_hw_interface_set_flags (vnm, hw_if_index, /* flags */ 0); @@ -899,44 +928,54 @@ 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 software interface corresponding to hardware interface. */ - vnet_delete_sw_interface (vnm, hw->sw_if_index); - /* Delete any sub-interfaces. */ { u32 id, sw_if_index; /* *INDENT-OFF* */ - hash_foreach (id, sw_if_index, hw->sub_interface_sw_if_index_by_id, ({ + hash_foreach (id, sw_if_index, hw->sub_interface_sw_if_index_by_id, + ({ + vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); + u64 sup_and_sub_key = + ((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id; + hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key); vnet_delete_sw_interface (vnm, sw_if_index); })); + hash_free (hw->sub_interface_sw_if_index_by_id); /* *INDENT-ON* */ } - { - vnet_hw_interface_nodes_t *dn; + /* Delete software interface corresponding to hardware interface. */ + vnet_delete_sw_interface (vnm, hw->sw_if_index); - /* *INDENT-OFF* */ - 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* */ + if (dev_class->tx_function) + { + /* Put output/tx nodes into recycle pool */ + vnet_hw_interface_nodes_t *dn; - vlib_node_rename (vm, hw->output_node_index, - "interface-%d-output-deleted", hw_if_index); - vlib_node_rename (vm, hw->tx_node_index, "interface-%d-tx-deleted", - hw_if_index); - vec_add2 (im->deleted_hw_interface_nodes, dn, 1); - dn->tx_node_index = hw->tx_node_index; - dn->output_node_index = hw->output_node_index; - } + /* *INDENT-OFF* */ + 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); + vlib_node_rename (vm, hw->tx_node_index, "interface-%d-tx-deleted", + hw_if_index); + vec_add2 (im->deleted_hw_interface_nodes, dn, 1); + dn->tx_node_index = hw->tx_node_index; + dn->output_node_index = hw->output_node_index; + } hash_unset_mem (im->hw_interface_by_name, hw->name); 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); @@ -959,11 +998,30 @@ vnet_hw_interface_walk_sw (vnet_main_t * vnm, hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id, ({ - fn (vnm, sw_if_index, ctx); + if (WALK_STOP == fn (vnm, sw_if_index, ctx)) + break; })); /* *INDENT-ON* */ } +void +vnet_sw_interface_walk (vnet_main_t * vnm, + vnet_sw_interface_walk_t fn, void *ctx) +{ + vnet_interface_main_t *im; + vnet_sw_interface_t *si; + + im = &vnm->interface_main; + + /* *INDENT-OFF* */ + pool_foreach (si, im->sw_interfaces, + { + if (WALK_STOP == fn (vnm, si, ctx)) + break; + }); + /* *INDENT-ON* */ +} + static void serialize_vnet_hw_interface_set_class (serialize_main_t * m, va_list * va) { @@ -1147,6 +1205,10 @@ vnet_hw_interface_compare (vnet_main_t * vnm, int vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index) { + vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); + if (si->type == VNET_SW_INTERFACE_TYPE_P2P) + return 1; + 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); @@ -1161,6 +1223,7 @@ vnet_interface_init (vlib_main_t * vm) vnet_interface_main_t *im = &vnm->interface_main; vlib_buffer_t *b = 0; vnet_buffer_opaque_t *o = 0; + clib_error_t *error; /* * Keep people from shooting themselves in the foot. @@ -1196,7 +1259,19 @@ vnet_interface_init (vlib_main_t * vm) vec_validate (im->combined_sw_if_counters, VNET_N_COMBINED_INTERFACE_COUNTER - 1); im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX].name = "rx"; + im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_UNICAST].name = + "rx-unicast"; + im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_MULTICAST].name = + "rx-multicast"; + im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_BROADCAST].name = + "rx-broadcast"; im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX].name = "tx"; + im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_UNICAST].name = + "tx-unicast"; + im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_MULTICAST].name = + "tx-multicast"; + im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_BROADCAST].name = + "tx-broadcast"; im->sw_if_counter_lock[0] = 0; @@ -1241,15 +1316,17 @@ vnet_interface_init (vlib_main_t * vm) } } - { - clib_error_t *error; + if ((error = vlib_call_init_function (vm, vnet_interface_cli_init))) + return error; - if ((error = vlib_call_init_function (vm, vnet_interface_cli_init))) - return error; + 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; - } - vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword)); +#endif + + return 0; } VLIB_INIT_FUNCTION (vnet_interface_init); @@ -1322,7 +1399,8 @@ vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index, char *new_name) static clib_error_t * vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, - u32 hw_if_index, u64 mac_address) + u32 hw_if_index, + u8 * mac_address) { clib_error_t *error = 0; vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); @@ -1334,7 +1412,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, if (dev_class->mac_addr_change_function) { error = - dev_class->mac_addr_change_function (hi, (char *) &mac_address); + dev_class->mac_addr_change_function (hi, (char *) mac_address); } if (!error) { @@ -1343,7 +1421,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm, hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); if (NULL != hw_class->mac_addr_change_function) - hw_class->mac_addr_change_function (hi, (char *) &mac_address); + hw_class->mac_addr_change_function (hi, (char *) mac_address); } else { @@ -1364,12 +1442,57 @@ 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, - u64 mac_address) + u8 * mac_address) { return vnet_hw_interface_change_mac_address_helper (vnm, hw_if_index, mac_address); } +/* update the unnumbered state of an interface*/ +void +vnet_sw_interface_update_unnumbered (u32 unnumbered_sw_if_index, + u32 ip_sw_if_index, u8 enable) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_sw_interface_t *si; + u32 was_unnum; + + si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index); + was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED); + + if (enable) + { + si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; + si->unnumbered_sw_if_index = ip_sw_if_index; + + ip4_main.lookup_main.if_address_pool_index_by_sw_if_index + [unnumbered_sw_if_index] = + ip4_main. + lookup_main.if_address_pool_index_by_sw_if_index[ip_sw_if_index]; + ip6_main. + lookup_main.if_address_pool_index_by_sw_if_index + [unnumbered_sw_if_index] = + ip6_main. + lookup_main.if_address_pool_index_by_sw_if_index[ip_sw_if_index]; + } + else + { + si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); + si->unnumbered_sw_if_index = (u32) ~ 0; + + ip4_main.lookup_main.if_address_pool_index_by_sw_if_index + [unnumbered_sw_if_index] = ~0; + ip6_main.lookup_main.if_address_pool_index_by_sw_if_index + [unnumbered_sw_if_index] = ~0; + } + + if (was_unnum != (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)) + { + ip4_sw_interface_enable_disable (unnumbered_sw_if_index, enable); + ip6_sw_interface_enable_disable (unnumbered_sw_if_index, enable); + } +} + vnet_l3_packet_type_t vnet_link_to_l3_proto (vnet_link_t link) { @@ -1403,15 +1526,104 @@ default_build_rewrite (vnet_main_t * vnm, void default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) { - u8 *rewrite; + ip_adjacency_t *adj; + + adj = adj_get (ai); + + switch (adj->lookup_next_index) + { + case IP_LOOKUP_NEXT_GLEAN: + adj_glean_update_rewrite (ai); + break; + case IP_LOOKUP_NEXT_ARP: + /* + * default rewirte in neighbour adj + */ + adj_nbr_update_rewrite + (ai, + ADJ_NBR_REWRITE_FLAG_COMPLETE, + vnet_build_rewrite_for_sw_interface (vnm, + sw_if_index, + adj_get_link_type (ai), NULL)); + break; + case IP_LOOKUP_NEXT_MCAST: + /* + * mcast traffic also uses default rewrite string with no mcast + * switch time updates. + */ + adj_mcast_update_rewrite + (ai, + vnet_build_rewrite_for_sw_interface (vnm, + sw_if_index, + adj_get_link_type (ai), + NULL), 0); + break; + case IP_LOOKUP_NEXT_DROP: + case IP_LOOKUP_NEXT_PUNT: + case IP_LOOKUP_NEXT_LOCAL: + case IP_LOOKUP_NEXT_REWRITE: + case IP_LOOKUP_NEXT_MCAST_MIDCHAIN: + case IP_LOOKUP_NEXT_MIDCHAIN: + case IP_LOOKUP_NEXT_ICMP_ERROR: + case IP_LOOKUP_N_NEXT: + ASSERT (0); + break; + } +} + +int collect_detailed_interface_stats_flag = 0; + +void +collect_detailed_interface_stats_flag_set (void) +{ + collect_detailed_interface_stats_flag = 1; +} - rewrite = vnet_build_rewrite_for_sw_interface (vnm, sw_if_index, - adj_get_link_type (ai), - NULL); +void +collect_detailed_interface_stats_flag_clear (void) +{ + collect_detailed_interface_stats_flag = 0; +} - adj_nbr_update_rewrite (ai, ADJ_NBR_REWRITE_FLAG_COMPLETE, rewrite); +static clib_error_t * +collect_detailed_interface_stats_cli (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return clib_error_return (0, "expected enable | disable"); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "enable") || unformat (line_input, "on")) + collect_detailed_interface_stats_flag_set (); + else if (unformat (line_input, "disable") + || unformat (line_input, "off")) + collect_detailed_interface_stats_flag_clear (); + else + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + goto done; + } + } + +done: + unformat_free (line_input); + return error; } +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (collect_detailed_interface_stats_command, static) = { + .path = "interface collect detailed-stats", + .short_help = "interface collect detailed-stats ", + .function = collect_detailed_interface_stats_cli, +}; +/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON