Skip to content

Commit 0bd935a

Browse files
sodarkevintraynor
authored andcommitted
net/mlx5: fix min and max MTU reporting
[ upstream commit 44d6571 ] mlx5 PMD used hardcoded and incorrect values when reporting maximum MTU and maximum Rx packet length through rte_eth_dev_info_get(). This patch adds support for querying OS for minimum and maximum allowed MTU values. Maximum Rx packet length is then calculated based on these values. On Linux, these values are queried through netlink, using IFLA_MIN_MTU and IFLA_MAX_MTU attributes added in Linux 4.18. Windows API unfortunately does not expose minimum and maximum allowed MTU values. In this case, fallback hardcoded values (working on currently supported HW) will be used. Bugzilla ID: 1719 Fixes: e60fbd5 ("mlx5: add device configure/start/stop") Signed-off-by: Dariusz Sosnowski <[email protected]> Acked-by: Viacheslav Ovsiienko <[email protected]>
1 parent f0c0a48 commit 0bd935a

File tree

9 files changed

+228
-1
lines changed

9 files changed

+228
-1
lines changed

drivers/common/mlx5/linux/mlx5_nl.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,3 +2033,111 @@ mlx5_nl_devlink_esw_multiport_get(int nlsk_fd, int family_id, const char *pci_ad
20332033
*enable ? "en" : "dis", pci_addr);
20342034
return ret;
20352035
}
2036+
2037+
struct mlx5_mtu {
2038+
uint32_t min_mtu;
2039+
bool min_mtu_set;
2040+
uint32_t max_mtu;
2041+
bool max_mtu_set;
2042+
};
2043+
2044+
static int
2045+
mlx5_nl_get_mtu_bounds_cb(struct nlmsghdr *nh, void *arg)
2046+
{
2047+
size_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2048+
struct mlx5_mtu *out = arg;
2049+
2050+
while (off < nh->nlmsg_len) {
2051+
struct rtattr *ra = RTE_PTR_ADD(nh, off);
2052+
uint32_t *payload;
2053+
2054+
switch (ra->rta_type) {
2055+
case IFLA_MIN_MTU:
2056+
payload = RTA_DATA(ra);
2057+
out->min_mtu = *payload;
2058+
out->min_mtu_set = true;
2059+
break;
2060+
case IFLA_MAX_MTU:
2061+
payload = RTA_DATA(ra);
2062+
out->max_mtu = *payload;
2063+
out->max_mtu_set = true;
2064+
break;
2065+
default:
2066+
/* Nothing to do for other attributes. */
2067+
break;
2068+
}
2069+
off += RTA_ALIGN(ra->rta_len);
2070+
}
2071+
2072+
return 0;
2073+
}
2074+
2075+
/**
2076+
* Query minimum and maximum allowed MTU values for given Linux network interface.
2077+
*
2078+
* This function queries the following interface attributes exposed in netlink since Linux 4.18:
2079+
*
2080+
* - IFLA_MIN_MTU - minimum allowed MTU
2081+
* - IFLA_MAX_MTU - maximum allowed MTU
2082+
*
2083+
* @param[in] nl
2084+
* Netlink socket of the ROUTE kind (NETLINK_ROUTE).
2085+
* @param[in] ifindex
2086+
* Linux network device index.
2087+
* @param[out] min_mtu
2088+
* Pointer to minimum allowed MTU. Populated only if both minimum and maximum MTU was queried.
2089+
* @param[out] max_mtu
2090+
* Pointer to maximum allowed MTU. Populated only if both minimum and maximum MTU was queried.
2091+
*
2092+
* @return
2093+
* 0 on success, negative on error and rte_errno is set.
2094+
*
2095+
* Known errors:
2096+
*
2097+
* - (-EINVAL) - either @p min_mtu or @p max_mtu is NULL.
2098+
* - (-ENOENT) - either minimum or maximum allowed MTU was not found in interface attributes.
2099+
*/
2100+
int
2101+
mlx5_nl_get_mtu_bounds(int nl, unsigned int ifindex, uint16_t *min_mtu, uint16_t *max_mtu)
2102+
{
2103+
struct mlx5_mtu out = { 0 };
2104+
struct {
2105+
struct nlmsghdr nh;
2106+
struct ifinfomsg info;
2107+
} req = {
2108+
.nh = {
2109+
.nlmsg_len = NLMSG_LENGTH(sizeof(req.info)),
2110+
.nlmsg_type = RTM_GETLINK,
2111+
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
2112+
},
2113+
.info = {
2114+
.ifi_family = AF_UNSPEC,
2115+
.ifi_index = ifindex,
2116+
},
2117+
};
2118+
uint32_t sn = MLX5_NL_SN_GENERATE;
2119+
int ret;
2120+
2121+
if (min_mtu == NULL || max_mtu == NULL) {
2122+
rte_errno = EINVAL;
2123+
return -rte_errno;
2124+
}
2125+
2126+
ret = mlx5_nl_send(nl, &req.nh, sn);
2127+
if (ret < 0)
2128+
return ret;
2129+
2130+
ret = mlx5_nl_recv(nl, sn, mlx5_nl_get_mtu_bounds_cb, &out);
2131+
if (ret < 0)
2132+
return ret;
2133+
2134+
if (!out.min_mtu_set || !out.max_mtu_set) {
2135+
rte_errno = ENOENT;
2136+
return -rte_errno;
2137+
}
2138+
2139+
*min_mtu = out.min_mtu;
2140+
*max_mtu = out.max_mtu;
2141+
2142+
return ret;
2143+
}

drivers/common/mlx5/linux/mlx5_nl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,7 @@ __rte_internal
8787
int mlx5_nl_devlink_esw_multiport_get(int nlsk_fd, int family_id,
8888
const char *pci_addr, int *enable);
8989

90+
__rte_internal
91+
int mlx5_nl_get_mtu_bounds(int nl, unsigned int ifindex, uint16_t *min_mtu, uint16_t *max_mtu);
92+
9093
#endif /* RTE_PMD_MLX5_NL_H_ */

drivers/common/mlx5/version.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ INTERNAL {
146146
mlx5_nl_vf_mac_addr_modify; # WINDOWS_NO_EXPORT
147147
mlx5_nl_vlan_vmwa_create; # WINDOWS_NO_EXPORT
148148
mlx5_nl_vlan_vmwa_delete; # WINDOWS_NO_EXPORT
149+
mlx5_nl_get_mtu_bounds; # WINDOWS_NO_EXPORT
149150

150151
mlx5_os_get_physical_device_ctx;
151152
mlx5_os_umem_dereg;

drivers/net/mlx5/linux/mlx5_ethdev_os.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,36 @@ mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
157157
return mlx5_ifreq_by_ifname(ifname, req, ifr);
158158
}
159159

160+
/**
161+
* Get device minimum and maximum allowed MTU values.
162+
*
163+
* @param dev
164+
* Pointer to Ethernet device.
165+
* @param[out] min_mtu
166+
* Minimum MTU value output buffer.
167+
* @param[out] max_mtu
168+
* Maximum MTU value output buffer.
169+
*
170+
* @return
171+
* 0 on success, a negative errno value otherwise and rte_errno is set.
172+
*/
173+
int
174+
mlx5_os_get_mtu_bounds(struct rte_eth_dev *dev, uint16_t *min_mtu, uint16_t *max_mtu)
175+
{
176+
struct mlx5_priv *priv = dev->data->dev_private;
177+
int nl_route;
178+
int ret;
179+
180+
nl_route = mlx5_nl_init(NETLINK_ROUTE, 0);
181+
if (nl_route < 0)
182+
return nl_route;
183+
184+
ret = mlx5_nl_get_mtu_bounds(nl_route, priv->if_index, min_mtu, max_mtu);
185+
186+
close(nl_route);
187+
return ret;
188+
}
189+
160190
/**
161191
* Get device MTU.
162192
*

drivers/net/mlx5/linux/mlx5_os.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
15701570
eth_dev->data->mac_addrs = priv->mac;
15711571
eth_dev->device = dpdk_dev;
15721572
eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
1573+
/* Fetch minimum and maximum allowed MTU from the device. */
1574+
mlx5_get_mtu_bounds(eth_dev, &priv->min_mtu, &priv->max_mtu);
15731575
/* Configure the first MAC address by default. */
15741576
if (mlx5_get_mac(eth_dev, &mac.addr_bytes)) {
15751577
DRV_LOG(ERR,

drivers/net/mlx5/mlx5.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@
7474
/* Maximal number of field/field parts to map into sample registers .*/
7575
#define MLX5_FLEX_ITEM_MAPPING_NUM 32
7676

77+
/* Number of bytes not included in MTU. */
78+
#define MLX5_ETH_OVERHEAD (RTE_ETHER_HDR_LEN + RTE_VLAN_HLEN + RTE_ETHER_CRC_LEN)
79+
80+
/* Minimum allowed MTU to be reported whenever PMD cannot query it from OS. */
81+
#define MLX5_ETH_MIN_MTU (RTE_ETHER_MIN_MTU)
82+
83+
/* Maximum allowed MTU to be reported whenever PMD cannot query it from OS. */
84+
#define MLX5_ETH_MAX_MTU (9978)
85+
7786
enum mlx5_ipool_index {
7887
#if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
7988
MLX5_IPOOL_DECAP_ENCAP = 0, /* Pool for encap/decap resource. */
@@ -1957,6 +1966,8 @@ struct mlx5_priv {
19571966
unsigned int vlan_filter_n; /* Number of configured VLAN filters. */
19581967
/* Device properties. */
19591968
uint16_t mtu; /* Configured MTU. */
1969+
uint16_t min_mtu; /* Minimum MTU allowed on the NIC. */
1970+
uint16_t max_mtu; /* Maximum MTU allowed on the NIC. */
19601971
unsigned int isolated:1; /* Whether isolated mode is enabled. */
19611972
unsigned int representor:1; /* Device is a port representor. */
19621973
unsigned int master:1; /* Device is a E-Switch master. */
@@ -2286,6 +2297,7 @@ struct mlx5_priv *mlx5_dev_to_eswitch_info(struct rte_eth_dev *dev);
22862297
int mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev);
22872298
uint64_t mlx5_get_restore_flags(struct rte_eth_dev *dev,
22882299
enum rte_eth_dev_operation op);
2300+
void mlx5_get_mtu_bounds(struct rte_eth_dev *dev, uint16_t *min_mtu, uint16_t *max_mtu);
22892301

22902302
/* mlx5_ethdev_os.c */
22912303

@@ -2323,6 +2335,7 @@ int mlx5_os_get_stats_n(struct rte_eth_dev *dev, bool bond_master,
23232335
uint16_t *n_stats, uint16_t *n_stats_sec);
23242336
void mlx5_os_stats_init(struct rte_eth_dev *dev);
23252337
int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev);
2338+
int mlx5_os_get_mtu_bounds(struct rte_eth_dev *dev, uint16_t *min_mtu, uint16_t *max_mtu);
23262339

23272340
/* mlx5_mac.c */
23282341

drivers/net/mlx5/mlx5_ethdev.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,11 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
360360
unsigned int max;
361361
uint16_t max_wqe;
362362

363+
info->min_mtu = priv->min_mtu;
364+
info->max_mtu = priv->max_mtu;
365+
info->max_rx_pktlen = info->max_mtu + MLX5_ETH_OVERHEAD;
363366
/* FIXME: we should ask the device for these values. */
364367
info->min_rx_bufsize = 32;
365-
info->max_rx_pktlen = 65536;
366368
info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE;
367369
/*
368370
* Since we need one CQ per QP, the limit is the minimum number
@@ -863,3 +865,41 @@ mlx5_get_restore_flags(__rte_unused struct rte_eth_dev *dev,
863865
/* mlx5 PMD does not require any configuration restore. */
864866
return 0;
865867
}
868+
869+
/**
870+
* Query minimum and maximum allowed MTU value on the device.
871+
*
872+
* This functions will always return valid MTU bounds.
873+
* In case platform-specific implementation fails or current platform does not support it,
874+
* the fallback default values will be used.
875+
*
876+
* @param[in] dev
877+
* Pointer to Ethernet device
878+
* @param[out] min_mtu
879+
* Minimum MTU value output buffer.
880+
* @param[out] max_mtu
881+
* Maximum MTU value output buffer.
882+
*/
883+
void
884+
mlx5_get_mtu_bounds(struct rte_eth_dev *dev, uint16_t *min_mtu, uint16_t *max_mtu)
885+
{
886+
int ret;
887+
888+
MLX5_ASSERT(min_mtu != NULL);
889+
MLX5_ASSERT(max_mtu != NULL);
890+
891+
ret = mlx5_os_get_mtu_bounds(dev, min_mtu, max_mtu);
892+
if (ret < 0) {
893+
if (ret != -ENOTSUP)
894+
DRV_LOG(INFO, "port %u failed to query MTU bounds, using fallback values",
895+
dev->data->port_id);
896+
*min_mtu = MLX5_ETH_MIN_MTU;
897+
*max_mtu = MLX5_ETH_MAX_MTU;
898+
899+
/* This function does not fail. Clear rte_errno. */
900+
rte_errno = 0;
901+
}
902+
903+
DRV_LOG(INFO, "port %u minimum MTU is %u", dev->data->port_id, *min_mtu);
904+
DRV_LOG(INFO, "port %u maximum MTU is %u", dev->data->port_id, *max_mtu);
905+
}

drivers/net/mlx5/windows/mlx5_ethdev_os.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,34 @@ mlx5_get_ifname(const struct rte_eth_dev *dev, char ifname[MLX5_NAMESIZE])
7171
return 0;
7272
}
7373

74+
/**
75+
* Get device minimum and maximum allowed MTU.
76+
*
77+
* Windows API does not expose minimum and maximum allowed MTU.
78+
* In this case, this just returns (-ENOTSUP) to allow platform-independent code
79+
* to fallback to default values.
80+
*
81+
* @param dev
82+
* Pointer to Ethernet device.
83+
* @param[out] min_mtu
84+
* Minimum MTU value output buffer.
85+
* @param[out] max_mtu
86+
* Maximum MTU value output buffer.
87+
*
88+
* @return
89+
* (-ENOTSUP) - not supported on Windows
90+
*/
91+
int
92+
mlx5_os_get_mtu_bounds(struct rte_eth_dev *dev, uint16_t *min_mtu, uint16_t *max_mtu)
93+
{
94+
RTE_SET_USED(dev);
95+
RTE_SET_USED(min_mtu);
96+
RTE_SET_USED(max_mtu);
97+
98+
rte_errno = ENOTSUP;
99+
return -rte_errno;
100+
}
101+
74102
/**
75103
* Get device MTU.
76104
*

drivers/net/mlx5/windows/mlx5_os.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
478478
eth_dev->data->mac_addrs = priv->mac;
479479
eth_dev->device = dpdk_dev;
480480
eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
481+
/* Fetch minimum and maximum allowed MTU from the device. */
482+
mlx5_get_mtu_bounds(eth_dev, &priv->min_mtu, &priv->max_mtu);
481483
/* Configure the first MAC address by default. */
482484
if (mlx5_get_mac(eth_dev, &mac.addr_bytes)) {
483485
DRV_LOG(ERR,

0 commit comments

Comments
 (0)