From 1cd0e5dd533f4209dde453eaa43215e52cd42985 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 17 Jan 2022 14:49:17 +0100 Subject: vnet: distinguish between max_frame_size and MTU Type: improvement Change-Id: I3659de6599f402c92e3855e3bf0e5e3388f2bea0 Signed-off-by: Damjan Marion --- src/vnet/devices/af_packet/af_packet.c | 10 ++++++---- src/vnet/devices/tap/tap.c | 10 ++++------ src/vnet/ethernet/ethernet.h | 6 ++++-- src/vnet/ethernet/interface.c | 26 +++++++++++++++++--------- src/vnet/gre/interface.c | 8 ++++---- src/vnet/interface.c | 34 ++++++++++++++++++++++------------ src/vnet/interface.h | 22 ++++++++++------------ src/vnet/interface_api.c | 2 +- src/vnet/interface_cli.c | 10 ---------- src/vnet/interface_funcs.h | 6 +++++- src/vnet/ipip/ipip.c | 10 ++++------ 11 files changed, 77 insertions(+), 67 deletions(-) (limited to 'src/vnet') diff --git a/src/vnet/devices/af_packet/af_packet.c b/src/vnet/devices/af_packet/af_packet.c index cf4f91e2fcd..208537996e3 100644 --- a/src/vnet/devices/af_packet/af_packet.c +++ b/src/vnet/devices/af_packet/af_packet.c @@ -57,13 +57,15 @@ unsigned int if_nametoindex (const char *ifname); typedef struct tpacket_req tpacket_req_t; static clib_error_t * -af_packet_eth_set_mtu (vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 mtu) +af_packet_eth_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi, + u32 frame_size) { clib_error_t *error, *rv; af_packet_main_t *apm = &af_packet_main; af_packet_if_t *apif = pool_elt_at_index (apm->interfaces, hi->dev_instance); - error = vnet_netlink_set_link_mtu (apif->host_if_index, mtu); + error = vnet_netlink_set_link_mtu (apif->host_if_index, + frame_size + hi->frame_overhead); if (error) { @@ -75,7 +77,7 @@ af_packet_eth_set_mtu (vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 mtu) return rv; } else - apif->host_mtu = mtu; + apif->host_mtu = frame_size + hi->frame_overhead; return 0; } @@ -398,7 +400,7 @@ af_packet_create_if (af_packet_create_if_arg_t *arg) eir.dev_class_index = af_packet_device_class.index; eir.dev_instance = if_index; eir.address = hw_addr; - eir.cb.set_mtu = af_packet_eth_set_mtu; + eir.cb.set_max_frame_size = af_packet_eth_set_max_frame_size; apif->hw_if_index = vnet_eth_register_interface (vnm, &eir); } else diff --git a/src/vnet/devices/tap/tap.c b/src/vnet/devices/tap/tap.c index 2e7ad39f3b4..f5ed30ad7b0 100644 --- a/src/vnet/devices/tap/tap.c +++ b/src/vnet/devices/tap/tap.c @@ -683,12 +683,10 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) } if (vif->type == VIRTIO_IF_TYPE_TUN) { - hw->max_supported_packet_bytes = TUN_MAX_PACKET_BYTES; - hw->min_packet_bytes = hw->min_supported_packet_bytes = - TUN_MIN_PACKET_BYTES; - hw->max_packet_bytes = - args->host_mtu_size ? args->host_mtu_size : TUN_DEFAULT_PACKET_BYTES; - vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, hw->max_packet_bytes); + hw->min_frame_size = TUN_MIN_PACKET_BYTES; + vnet_hw_interface_set_mtu ( + vnm, hw->sw_if_index, + args->host_mtu_size ? args->host_mtu_size : TUN_DEFAULT_PACKET_BYTES); } vnet_hw_if_change_caps (vnm, vif->hw_if_index, &cc); diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index b6adeb6f44d..858400d08d8 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -133,8 +133,8 @@ typedef struct /* ethernet interface flags change */ ethernet_flag_change_function_t *flag_change; - /* set MTU callback */ - vnet_interface_set_mtu_function_t *set_mtu; + /* set Max Frame Size callback */ + vnet_interface_set_max_frame_size_function_t *set_max_frame_size; } vnet_eth_if_callbacks_t; #define ETHERNET_MIN_PACKET_BYTES 64 @@ -576,6 +576,8 @@ typedef struct { u32 dev_class_index; u32 dev_instance; + u16 max_frame_size; + u16 frame_overhead; vnet_eth_if_callbacks_t cb; const u8 *address; } vnet_eth_interface_registration_t; diff --git a/src/vnet/ethernet/interface.c b/src/vnet/ethernet/interface.c index bac882228cb..a0ad7989867 100644 --- a/src/vnet/ethernet/interface.c +++ b/src/vnet/ethernet/interface.c @@ -311,15 +311,18 @@ ethernet_mac_change (vnet_hw_interface_t * hi, } static clib_error_t * -ethernet_set_mtu (vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 mtu) +ethernet_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi, + u32 frame_size) { ethernet_interface_t *ei = pool_elt_at_index (ethernet_main.interfaces, hi->hw_instance); - if (ei->cb.set_mtu) - return ei->cb.set_mtu (vnm, hi, mtu); + if (ei->cb.set_max_frame_size) + return ei->cb.set_max_frame_size (vnm, hi, frame_size); - return 0; + return vnet_error ( + VNET_ERR_UNSUPPORTED, + "underlying driver doesn't support changing Max Frame Size"); } /* *INDENT-OFF* */ @@ -333,7 +336,7 @@ VNET_HW_INTERFACE_CLASS (ethernet_hw_interface_class) = { .build_rewrite = ethernet_build_rewrite, .update_adjacency = ethernet_update_adjacency, .mac_addr_change_function = ethernet_mac_change, - .set_mtu = ethernet_set_mtu, + .set_max_frame_size = ethernet_set_max_frame_size, }; /* *INDENT-ON* */ @@ -378,10 +381,15 @@ vnet_eth_register_interface (vnet_main_t *vnm, ethernet_setup_node (vnm->vlib_main, hi->output_node_index); - hi->min_packet_bytes = hi->min_supported_packet_bytes = - ETHERNET_MIN_PACKET_BYTES; - hi->max_supported_packet_bytes = ETHERNET_MAX_PACKET_BYTES; - hi->max_packet_bytes = em->default_mtu; + hi->min_frame_size = ETHERNET_MIN_PACKET_BYTES; + hi->frame_overhead = + r->frame_overhead ? + r->max_frame_size : + sizeof (ethernet_header_t) + 2 * sizeof (ethernet_vlan_header_t); + hi->max_frame_size = r->max_frame_size ? + r->max_frame_size : + ethernet_main.default_mtu + hi->frame_overhead; + ; /* Default ethernet MTU, 9000 unless set by ethernet_config see below */ vnet_sw_interface_set_mtu (vnm, hi->sw_if_index, em->default_mtu); diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index bc78c605068..bb0be865664 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -447,13 +447,13 @@ vnet_gre_tunnel_add (vnet_gre_tunnel_add_del_args_t * a, if (!is_ipv6) { - hi->min_packet_bytes = - 64 + sizeof (gre_header_t) + sizeof (ip4_header_t); + hi->frame_overhead = sizeof (gre_header_t) + sizeof (ip4_header_t); + hi->min_frame_size = hi->frame_overhead + 64; } else { - hi->min_packet_bytes = - 64 + sizeof (gre_header_t) + sizeof (ip6_header_t); + hi->frame_overhead = sizeof (gre_header_t) + sizeof (ip6_header_t); + hi->min_frame_size = hi->frame_overhead + 64; } /* Standard default gre MTU. */ diff --git a/src/vnet/interface.c b/src/vnet/interface.c index a1493c66c23..412c6755ea8 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -769,30 +769,41 @@ sw_interface_walk_callback (vnet_main_t * vnm, u32 sw_if_index, void *ctx) } clib_error_t * -vnet_hw_interface_set_mtu (vnet_main_t *vnm, u32 hw_if_index, u32 mtu) +vnet_hw_interface_set_max_frame_size (vnet_main_t *vnm, u32 hw_if_index, + u32 fs) { vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); vnet_hw_interface_class_t *hw_if_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); clib_error_t *err = 0; - if (hi->max_packet_bytes != mtu) + log_debug ("set_max_frame_size: interface %s, max_frame_size %u -> %u", + hi->name, hi->max_frame_size, fs); + + if (hw_if_class->set_max_frame_size == 0) + return vnet_error (VNET_ERR_UNSUPPORTED, + "hw class doesn't support changing Max Frame Size"); + + if (hi->max_frame_size != fs) { - if (mtu > hi->max_supported_packet_bytes || - mtu < hi->min_supported_packet_bytes) - return vnet_error (VNET_ERR_INVALID_VALUE, - "requested mtu must be in the %u to %u range", - hi->min_supported_packet_bytes, - hi->max_supported_packet_bytes); - if (hw_if_class->set_mtu) - if ((err = hw_if_class->set_mtu (vnm, hi, mtu))) + u32 mtu; + if (hw_if_class->set_max_frame_size) + if ((err = hw_if_class->set_max_frame_size (vnm, hi, fs))) return err; - hi->max_packet_bytes = mtu; + hi->max_frame_size = fs; + mtu = fs - hi->frame_overhead; vnet_hw_interface_walk_sw (vnm, hw_if_index, sw_interface_walk_callback, &mtu); } return 0; } +clib_error_t * +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); + return vnet_hw_interface_set_max_frame_size (vnm, hw_if_index, + mtu + hi->frame_overhead); +} static void setup_tx_node (vlib_main_t * vm, @@ -910,7 +921,6 @@ vnet_register_interface (vnet_main_t * vnm, hw->hw_instance = hw_instance; hw->max_rate_bits_per_sec = 0; - hw->min_packet_bytes = 0; vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, 0); if (dev_class->tx_function == 0 && dev_class->tx_fn_registrations == 0) diff --git a/src/vnet/interface.h b/src/vnet/interface.h index 2eb50aed5e8..c8fbc61ec7b 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -71,7 +71,7 @@ typedef clib_error_t *(vnet_subif_add_del_function_t) struct vnet_sw_interface_t * template, int is_add); /* Interface set mtu callback. */ -typedef clib_error_t *(vnet_interface_set_mtu_function_t) ( +typedef clib_error_t *(vnet_interface_set_max_frame_size_function_t) ( struct vnet_main_t *vnm, struct vnet_hw_interface_t *hi, u32 mtu); /* Interface set mac address callback. */ @@ -432,8 +432,9 @@ typedef struct _vnet_hw_interface_class /* Function to add/delete additional MAC addresses */ vnet_interface_add_del_mac_address_function_t *mac_addr_add_del_function; - /* Function to set mtu. */ - vnet_interface_set_mtu_function_t *set_mtu; + + /* Function to set max frame size. */ + vnet_interface_set_max_frame_size_function_t *set_max_frame_size; /* Format function to display interface name. */ format_function_t *format_interface_name; @@ -701,17 +702,14 @@ typedef struct vnet_hw_interface_t /* Maximum transmit rate for this interface in bits/sec. */ f64 max_rate_bits_per_sec; - /* Smallest packet size supported by this interface. */ - u32 min_supported_packet_bytes; - - /* Largest packet size supported by this interface. */ - u32 max_supported_packet_bytes; - /* Smallest packet size for this interface. */ - u32 min_packet_bytes; + u32 min_frame_size; + + /* Largest frame size for this interface. */ + u32 max_frame_size; - /* Largest packet size for this interface. */ - u32 max_packet_bytes; + /* Layer 2 overhead */ + u16 frame_overhead; /* Hash table mapping sub interface id to sw_if_index. */ uword *sub_interface_sw_if_index_by_id; diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index d70cd1e42f8..938f3bb327e 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -258,7 +258,7 @@ send_sw_interface_details (vpe_api_main_t * am, mp->link_duplex = ntohl (((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >> VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT)); mp->link_speed = ntohl (hi->link_speed); - mp->link_mtu = ntohs (hi->max_packet_bytes); + mp->link_mtu = ntohs (hi->max_frame_size - hi->frame_overhead); mp->mtu[VNET_MTU_L3] = ntohl (swif->mtu[VNET_MTU_L3]); mp->mtu[VNET_MTU_IP4] = ntohl (swif->mtu[VNET_MTU_IP4]); mp->mtu[VNET_MTU_IP6] = ntohl (swif->mtu[VNET_MTU_IP6]); diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c index 740a8af78ec..b6d38578714 100644 --- a/src/vnet/interface_cli.c +++ b/src/vnet/interface_cli.c @@ -1167,21 +1167,11 @@ mtu_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) * Change physical MTU on interface. Only supported for Ethernet * interfaces */ - vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); ethernet_interface_t *eif = ethernet_get_interface (em, hw_if_index); if (!eif) return clib_error_return (0, "not supported"); - if (mtu < hi->min_supported_packet_bytes) - return clib_error_return (0, "Invalid mtu (%d): " - "must be >= min pkt bytes (%d)", mtu, - hi->min_supported_packet_bytes); - - if (mtu > hi->max_supported_packet_bytes) - return clib_error_return (0, "Invalid mtu (%d): must be <= (%d)", mtu, - hi->max_supported_packet_bytes); - err = vnet_hw_interface_set_mtu (vnm, hw_if_index, mtu); if (err) return err; diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h index 57e0d33b406..5434542cd7c 100644 --- a/src/vnet/interface_funcs.h +++ b/src/vnet/interface_funcs.h @@ -310,7 +310,7 @@ always_inline u32 vnet_hw_interface_get_mtu (vnet_main_t * vnm, u32 hw_if_index) { vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); - return hw->max_packet_bytes; + return hw->max_frame_size - hw->frame_overhead; } always_inline u32 @@ -430,6 +430,10 @@ clib_error_t *set_hw_interface_rx_placement (u32 hw_if_index, u32 queue_id, /* Set tx-queue placement on the interface */ int set_hw_interface_tx_queue (u32 hw_if_index, u32 queue_id, uword *bitmap); +/* Set the Max Frame Size on the HW interface */ +clib_error_t *vnet_hw_interface_set_max_frame_size (vnet_main_t *vnm, + u32 hw_if_index, + u32 max_frame_size); /* Set the MTU on the HW interface */ clib_error_t *vnet_hw_interface_set_mtu (vnet_main_t *vnm, u32 hw_if_index, u32 mtu); diff --git a/src/vnet/ipip/ipip.c b/src/vnet/ipip/ipip.c index 2ac234eb7ca..600f5421125 100644 --- a/src/vnet/ipip/ipip.c +++ b/src/vnet/ipip/ipip.c @@ -782,13 +782,11 @@ ipip_add_tunnel (ipip_transport_t transport, gm->tunnel_index_by_sw_if_index[sw_if_index] = t_idx; if (t->transport == IPIP_TRANSPORT_IP4) - { - hi->min_packet_bytes = 64 + sizeof (ip4_header_t); - } + hi->frame_overhead = sizeof (ip4_header_t); else - { - hi->min_packet_bytes = 64 + sizeof (ip6_header_t); - } + hi->frame_overhead = sizeof (ip6_header_t); + + hi->min_frame_size = hi->frame_overhead + 64; /* Standard default ipip MTU. */ vnet_sw_interface_set_mtu (vnm, sw_if_index, 9000); -- cgit 1.2.3-korg