From fa957142beae75e4cf881f7e861cefd97f034a83 Mon Sep 17 00:00:00 2001 From: Nitin Saxena Date: Fri, 16 Feb 2018 11:21:38 +0000 Subject: [PATCH] dpdk: Fix MTU calc for NICs that support mtu<9216 Problem: rte_eth_dev_set_mtu() returns with failure from ThunderX NICVF DPDK PMD driver which supports MTU less than ETHERNET_MAX_PACKET_BYTES. rte_eth_dev_set_mtu() being called twice from dpdk_lib_init(): one via dpdk_device_setup() and second in dpdk_lib_init() itself. Currently dpdk_lib_init() passes vnet_hardware_interface->max_packet_bytes as an argument to rte_eth_dev_set_mtu() without consulting dev_info.max_rx_pktlen. NICs like i4oe, ixgbe can support MTU much greater than 9216 hence its not a problem for those NICS. Fix: This patch calculates dpdk_device->port_conf.rxmode.max_rx_pkt_len, vnet_hardware_interface->max_packet_bytes and MTU by consulting dev_info.max_rx_pktlen. Change-Id: If04bbfae49ee971dac0063ff1835e4a9c3087865 Signed-off-by: Nitin Saxena --- src/plugins/dpdk/device/init.c | 100 +++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 34 deletions(-) diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c index cc30c8dcca1..d719d4b7153 100755 --- a/src/plugins/dpdk/device/init.c +++ b/src/plugins/dpdk/device/init.c @@ -180,6 +180,7 @@ static clib_error_t * dpdk_lib_init (dpdk_main_t * dm) { u32 nports; + u32 mtu, max_rx_frame; u32 nb_desc = 0; int i; clib_error_t *error; @@ -466,39 +467,6 @@ dpdk_lib_init (dpdk_main_t * dm) xd->nb_tx_desc = devconf->num_tx_desc; } - /* - * Ensure default mtu is not > the mtu read from the hardware. - * Otherwise rte_eth_dev_configure() will fail and the port will - * not be available. - */ - if (ETHERNET_MAX_PACKET_BYTES > dev_info.max_rx_pktlen) - { - /* - * This device does not support the platforms's max frame - * size. Use it's advertised mru instead. - */ - xd->port_conf.rxmode.max_rx_pkt_len = dev_info.max_rx_pktlen; - } - else - { - xd->port_conf.rxmode.max_rx_pkt_len = ETHERNET_MAX_PACKET_BYTES; - - /* - * Some platforms do not account for Ethernet FCS (4 bytes) in - * MTU calculations. To interop with them increase mru but only - * if the device's settings can support it. - */ - if ((dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + 4)) && - xd->port_conf.rxmode.hw_strip_crc) - { - /* - * Allow additional 4 bytes (for Ethernet FCS). These bytes are - * stripped by h/w and so will not consume any buffer memory. - */ - xd->port_conf.rxmode.max_rx_pkt_len += 4; - } - } - if (xd->pmd == VNET_DPDK_PMD_AF_PACKET) { f64 now = vlib_time_now (vm); @@ -583,6 +551,61 @@ dpdk_lib_init (dpdk_main_t * dm) if (error) return error; + /* + * Ensure default mtu is not > the mtu read from the hardware. + * Otherwise rte_eth_dev_configure() will fail and the port will + * not be available. + * Calculate max_frame_size and mtu supported by NIC + */ + if (ETHERNET_MAX_PACKET_BYTES > dev_info.max_rx_pktlen) + { + /* + * This device does not support the platforms's max frame + * size. Use it's advertised mru instead. + */ + max_rx_frame = dev_info.max_rx_pktlen; + mtu = dev_info.max_rx_pktlen - sizeof (ethernet_header_t); + } + else + { + /* VPP treats MTU and max_rx_pktlen both equal to + * ETHERNET_MAX_PACKET_BYTES, if dev_info.max_rx_pktlen >= + * ETHERNET_MAX_PACKET_BYTES + sizeof(ethernet_header_t) + */ + if (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + + sizeof (ethernet_header_t))) + { + mtu = ETHERNET_MAX_PACKET_BYTES; + max_rx_frame = ETHERNET_MAX_PACKET_BYTES; + + /* + * Some platforms do not account for Ethernet FCS (4 bytes) in + * MTU calculations. To interop with them increase mru but only + * if the device's settings can support it. + */ + if (xd->port_conf.rxmode.hw_strip_crc && + (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + + sizeof (ethernet_header_t) + + 4))) + { + max_rx_frame += 4; + } + } + else + { + max_rx_frame = ETHERNET_MAX_PACKET_BYTES; + mtu = ETHERNET_MAX_PACKET_BYTES - sizeof (ethernet_header_t); + + if (xd->port_conf.rxmode.hw_strip_crc && + (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + 4))) + { + max_rx_frame += 4; + } + } + } + /*Set port rxmode config */ + xd->port_conf.rxmode.max_rx_pkt_len = max_rx_frame; + sw = vnet_get_hw_sw_interface (dm->vnet_main, xd->hw_if_index); xd->vlib_sw_if_index = sw->sw_if_index; vnet_hw_interface_set_input_node (dm->vnet_main, xd->hw_if_index, @@ -606,8 +629,17 @@ dpdk_lib_init (dpdk_main_t * dm) ~1); } + /*Get vnet hardware interface */ hi = vnet_get_hw_interface (dm->vnet_main, xd->hw_if_index); + /*Override default max_packet_bytes and max_supported_bytes set in + * ethernet_register_interface() above*/ + if (hi) + { + hi->max_packet_bytes = max_rx_frame; + hi->max_supported_packet_bytes = max_rx_frame; + } + if (dm->conf->no_tx_checksum_offload == 0) if (xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD) hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD; @@ -658,7 +690,7 @@ dpdk_lib_init (dpdk_main_t * dm) hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = xd->port_conf.rxmode.max_rx_pkt_len - sizeof (ethernet_header_t); - rte_eth_dev_set_mtu (xd->device_index, hi->max_packet_bytes); + rte_eth_dev_set_mtu (xd->device_index, mtu); } if (nb_desc > dm->conf->num_mbufs) -- 2.16.6