X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Finterface.c;h=7a2c3abd2d4fef338cb17add4b74ed25cad1b8f6;hb=d723161;hp=28c46110851aeaea9e5ba361cf016bbe6883f2b5;hpb=70083ee74c3141bbefb185525315f1b34497dcaa;p=vpp.git diff --git a/src/vnet/interface.c b/src/vnet/interface.c index 28c46110851..7a2c3abd2d4 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -122,57 +122,6 @@ unserialize_vnet_sw_interface_set_flags (serialize_main_t * m, va_list * va) /* helper_flags no redistribution */ 0); } -static void -vnet_sw_interface_set_mtu_cb (vnet_main_t * vnm, u32 sw_if_index, void *ctx) -{ - u32 *mtu = ctx; - vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); - ASSERT (si); - - si->max_l3_packet_bytes[VLIB_TX] = si->max_l3_packet_bytes[VLIB_RX] = *mtu; - adj_mtu_update (sw_if_index); -} - -/* - * MTU is set per software interface. Setting MTU on a parent - * interface will override the MTU setting on sub-interfaces. - * TODO: If sub-interface MTU is ~0 inherit from parent? - */ -int -vnet_sw_interface_set_mtu (vnet_main_t * vnm, u32 sw_if_index, u32 mtu) -{ - vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); - vnet_hw_interface_t *hi = vnet_get_sw_hw_interface (vnm, sw_if_index); - - if (mtu < hi->min_packet_bytes) - return VNET_API_ERROR_INVALID_VALUE; - if (mtu > hi->max_packet_bytes) - return VNET_API_ERROR_INVALID_VALUE; - - /* If done on a parent interface */ - if (si->sw_if_index == si->sup_sw_if_index) - { - if (hi->hw_class_index == ethernet_hw_interface_class.index) - { - ethernet_set_flags (vnm, hi->hw_if_index, - ETHERNET_INTERFACE_FLAG_MTU); - } - - /* Override MTU on any sub-interface */ - vnet_hw_interface_walk_sw (vnm, - hi->hw_if_index, - vnet_sw_interface_set_mtu_cb, &mtu); - } - else - { - si->max_l3_packet_bytes[VLIB_TX] = si->max_l3_packet_bytes[VLIB_RX] = - mtu; - adj_mtu_update (sw_if_index); - } - - return 0; -} - static void unserialize_vnet_hw_interface_set_flags (serialize_main_t * m, va_list * va) { @@ -520,10 +469,13 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, error = call_elf_section_interface_callbacks (vnm, sw_if_index, flags, vnm->sw_interface_admin_up_down_functions); - si->flags = old_flags; if (error) - goto done; + { + /* restore flags on error */ + si->flags = old_flags; + goto done; + } if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE) { @@ -619,9 +571,6 @@ vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm, if (sw->type == VNET_SW_INTERFACE_TYPE_HARDWARE) sw->sup_sw_if_index = sw->sw_if_index; - sw->max_l3_packet_bytes[VLIB_RX] = ~0; - sw->max_l3_packet_bytes[VLIB_TX] = ~0; - /* Allocate counters for this interface. */ { u32 i; @@ -705,6 +654,7 @@ vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index) if (config->xconnect || config->bridge) set_int_l2_mode (vm, vnm, MODE_L3, sw_if_index, 0, 0, 0, 0); } + vnet_clear_sw_interface_tag (vnm, sw_if_index); /* Bring down interface in case it is up. */ if (sw->flags != 0) @@ -715,6 +665,71 @@ vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index) pool_put (im->sw_interfaces, sw); } +static clib_error_t * +call_sw_interface_mtu_change_callbacks (vnet_main_t * vnm, u32 sw_if_index) +{ + return call_elf_section_interface_callbacks + (vnm, sw_if_index, 0, vnm->sw_interface_mtu_change_functions); +} + +void +vnet_sw_interface_set_mtu (vnet_main_t * vnm, u32 sw_if_index, u32 mtu) +{ + vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); + + if (si->mtu[VNET_MTU_L3] != mtu) + { + si->mtu[VNET_MTU_L3] = mtu; + call_sw_interface_mtu_change_callbacks (vnm, sw_if_index); + } +} + +void +vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index, + u32 mtu[]) +{ + vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index); + bool changed = false; + int i; + + for (i = 0; i < VNET_N_MTU; i++) + { + if (si->mtu[i] != mtu[i]) + { + si->mtu[i] = mtu[i]; + changed = true; + } + } + /* Notify interested parties */ + if (changed) + call_sw_interface_mtu_change_callbacks (vnm, sw_if_index); +} + +/* + * Reflect a change in hardware MTU on protocol MTUs + */ +static walk_rc_t +sw_interface_walk_callback (vnet_main_t * vnm, u32 sw_if_index, void *ctx) +{ + u32 *link_mtu = ctx; + vnet_sw_interface_set_mtu (vnm, sw_if_index, *link_mtu); + return WALK_CONTINUE; +} + +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) + { + hi->max_packet_bytes = mtu; + ethernet_set_flags (vnm, hw_if_index, ETHERNET_INTERFACE_FLAG_MTU); + vnet_hw_interface_walk_sw (vnm, hw_if_index, sw_interface_walk_callback, + &mtu); + } +} + static void setup_tx_node (vlib_main_t * vm, u32 node_index, vnet_device_class_t * dev_class) @@ -755,7 +770,7 @@ 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)); @@ -796,7 +811,7 @@ vnet_register_interface (vnet_main_t * vnm, hw->max_rate_bits_per_sec = 0; hw->min_packet_bytes = 0; - hw->max_packet_bytes = 9000; /* default */ + vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, 0); if (dev_class->tx_function == 0) goto no_output_nodes; /* No output/tx nodes to create */ @@ -943,6 +958,8 @@ no_output_nodes: 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; } @@ -1009,6 +1026,7 @@ vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_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); @@ -1031,11 +1049,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) { @@ -1260,6 +1297,10 @@ vnet_interface_init (vlib_main_t * vm) CLIB_CACHE_LINE_BYTES); im->sw_if_counter_lock[0] = 1; /* should be no need */ + /* + * $$$$ add stat segment name(s) if desired + * set xxx.stat_segment_name = "whatever"... + */ vec_validate (im->sw_if_counters, VNET_N_SIMPLE_INTERFACE_COUNTER - 1); im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP].name = "drops"; im->sw_if_counters[VNET_INTERFACE_COUNTER_PUNT].name = "punts"; @@ -1529,6 +1570,22 @@ vnet_link_to_l3_proto (vnet_link_t link) return (0); } +vnet_mtu_t +vnet_link_to_mtu (vnet_link_t link) +{ + switch (link) + { + case VNET_LINK_IP4: + return (VNET_MTU_IP4); + case VNET_LINK_IP6: + return (VNET_MTU_IP6); + case VNET_LINK_MPLS: + return (VNET_MTU_MPLS); + default: + return (VNET_MTU_L3); + } +} + u8 * default_build_rewrite (vnet_main_t * vnm, u32 sw_if_index, @@ -1570,7 +1627,7 @@ default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) vnet_build_rewrite_for_sw_interface (vnm, sw_if_index, adj_get_link_type (ai), - NULL), 0, 0); + NULL), 0); break; case IP_LOOKUP_NEXT_DROP: case IP_LOOKUP_NEXT_PUNT: