ethtool: add support to set/get rx buf len via ethtool

Add support to set rx buf len via ethtool -G parameter and get
rx buf len via ethtool -g parameter.

Signed-off-by: Hao Chen <chenhao288@hisilicon.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>

 Conflicts:
	net/ethtool/netlink.h
	net/ethtool/rings.c
This commit is contained in:
Hao Chen 2021-11-18 20:12:42 +08:00 committed by Jianping Liu
parent ea084da501
commit 32d15e73d2
4 changed files with 46 additions and 6 deletions

View File

@ -806,7 +806,7 @@ Request contents:
Kernel response contents: Kernel response contents:
==================================== ====== ========================== ==================================== ====== ===========================
``ETHTOOL_A_RINGS_HEADER`` nested reply header ``ETHTOOL_A_RINGS_HEADER`` nested reply header
``ETHTOOL_A_RINGS_RX_MAX`` u32 max size of RX ring ``ETHTOOL_A_RINGS_RX_MAX`` u32 max size of RX ring
``ETHTOOL_A_RINGS_RX_MINI_MAX`` u32 max size of RX mini ring ``ETHTOOL_A_RINGS_RX_MINI_MAX`` u32 max size of RX mini ring
@ -816,7 +816,8 @@ Kernel response contents:
``ETHTOOL_A_RINGS_RX_MINI`` u32 size of RX mini ring ``ETHTOOL_A_RINGS_RX_MINI`` u32 size of RX mini ring
``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring ``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring
``ETHTOOL_A_RINGS_TX`` u32 size of TX ring ``ETHTOOL_A_RINGS_TX`` u32 size of TX ring
==================================== ====== ========================== ``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
==================================== ====== ===========================
RINGS_SET RINGS_SET
@ -826,13 +827,14 @@ Sets ring sizes like ``ETHTOOL_SRINGPARAM`` ioctl request.
Request contents: Request contents:
==================================== ====== ========================== ==================================== ====== ===========================
``ETHTOOL_A_RINGS_HEADER`` nested reply header ``ETHTOOL_A_RINGS_HEADER`` nested reply header
``ETHTOOL_A_RINGS_RX`` u32 size of RX ring ``ETHTOOL_A_RINGS_RX`` u32 size of RX ring
``ETHTOOL_A_RINGS_RX_MINI`` u32 size of RX mini ring ``ETHTOOL_A_RINGS_RX_MINI`` u32 size of RX mini ring
``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring ``ETHTOOL_A_RINGS_RX_JUMBO`` u32 size of RX jumbo ring
``ETHTOOL_A_RINGS_TX`` u32 size of TX ring ``ETHTOOL_A_RINGS_TX`` u32 size of TX ring
==================================== ====== ========================== ``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
==================================== ====== ===========================
Kernel checks that requested ring sizes do not exceed limits reported by Kernel checks that requested ring sizes do not exceed limits reported by
driver. Driver may impose additional constraints and may not suspport all driver. Driver may impose additional constraints and may not suspport all

View File

@ -72,6 +72,22 @@ enum {
ETH_RSS_HASH_FUNCS_COUNT ETH_RSS_HASH_FUNCS_COUNT
}; };
/**
* struct kernel_ethtool_ringparam - RX/TX ring configuration
* @rx_buf_len: Current length of buffers on the rx ring.
*/
struct kernel_ethtool_ringparam {
u32 rx_buf_len;
};
/**
* enum ethtool_supported_ring_param - indicator caps for setting ring params
* @ETHTOOL_RING_USE_RX_BUF_LEN: capture for setting rx_buf_len
*/
enum ethtool_supported_ring_param {
ETHTOOL_RING_USE_RX_BUF_LEN = BIT(0),
};
#define __ETH_RSS_HASH_BIT(bit) ((u32)1 << (bit)) #define __ETH_RSS_HASH_BIT(bit) ((u32)1 << (bit))
#define __ETH_RSS_HASH(name) __ETH_RSS_HASH_BIT(ETH_RSS_HASH_##name##_BIT) #define __ETH_RSS_HASH(name) __ETH_RSS_HASH_BIT(ETH_RSS_HASH_##name##_BIT)
@ -264,6 +280,7 @@ struct ethtool_pause_stats {
/** /**
* struct ethtool_ops - optional netdev operations * struct ethtool_ops - optional netdev operations
* @supported_coalesce_params: supported types of interrupt coalescing. * @supported_coalesce_params: supported types of interrupt coalescing.
* @supported_ring_params: supported ring params.
* @get_drvinfo: Report driver/device information. Should only set the * @get_drvinfo: Report driver/device information. Should only set the
* @driver, @version, @fw_version and @bus_info fields. If not * @driver, @version, @fw_version and @bus_info fields. If not
* implemented, the @driver and @bus_info fields will be filled in * implemented, the @driver and @bus_info fields will be filled in
@ -419,6 +436,7 @@ struct ethtool_pause_stats {
*/ */
struct ethtool_ops { struct ethtool_ops {
u32 supported_coalesce_params; u32 supported_coalesce_params;
u32 supported_ring_params;
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
int (*get_regs_len)(struct net_device *); int (*get_regs_len)(struct net_device *);
void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);

View File

@ -308,6 +308,7 @@ enum {
ETHTOOL_A_RINGS_RX_MINI, /* u32 */ ETHTOOL_A_RINGS_RX_MINI, /* u32 */
ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */ ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */
ETHTOOL_A_RINGS_TX, /* u32 */ ETHTOOL_A_RINGS_TX, /* u32 */
ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
/* add new constants above here */ /* add new constants above here */
__ETHTOOL_A_RINGS_CNT, __ETHTOOL_A_RINGS_CNT,

View File

@ -10,6 +10,7 @@ struct rings_req_info {
struct rings_reply_data { struct rings_reply_data {
struct ethnl_reply_data base; struct ethnl_reply_data base;
struct ethtool_ringparam ringparam; struct ethtool_ringparam ringparam;
struct kernel_ethtool_ringparam kernel_ringparam;
}; };
#define RINGS_REPDATA(__reply_base) \ #define RINGS_REPDATA(__reply_base) \
@ -58,7 +59,8 @@ static int rings_reply_size(const struct ethnl_req_info *req_base,
nla_total_size(sizeof(u32)) + /* _RINGS_RX */ nla_total_size(sizeof(u32)) + /* _RINGS_RX */
nla_total_size(sizeof(u32)) + /* _RINGS_RX_MINI */ nla_total_size(sizeof(u32)) + /* _RINGS_RX_MINI */
nla_total_size(sizeof(u32)) + /* _RINGS_RX_JUMBO */ nla_total_size(sizeof(u32)) + /* _RINGS_RX_JUMBO */
nla_total_size(sizeof(u32)); /* _RINGS_TX */ nla_total_size(sizeof(u32)) + /* _RINGS_TX */
nla_total_size(sizeof(u32)); /* _RINGS_RX_BUF_LEN */
} }
static int rings_fill_reply(struct sk_buff *skb, static int rings_fill_reply(struct sk_buff *skb,
@ -66,6 +68,7 @@ static int rings_fill_reply(struct sk_buff *skb,
const struct ethnl_reply_data *reply_base) const struct ethnl_reply_data *reply_base)
{ {
const struct rings_reply_data *data = RINGS_REPDATA(reply_base); const struct rings_reply_data *data = RINGS_REPDATA(reply_base);
const struct kernel_ethtool_ringparam *kernel_ringparam = &data->kernel_ringparam;
const struct ethtool_ringparam *ringparam = &data->ringparam; const struct ethtool_ringparam *ringparam = &data->ringparam;
if ((ringparam->rx_max_pending && if ((ringparam->rx_max_pending &&
@ -87,7 +90,10 @@ static int rings_fill_reply(struct sk_buff *skb,
(nla_put_u32(skb, ETHTOOL_A_RINGS_TX_MAX, (nla_put_u32(skb, ETHTOOL_A_RINGS_TX_MAX,
ringparam->tx_max_pending) || ringparam->tx_max_pending) ||
nla_put_u32(skb, ETHTOOL_A_RINGS_TX, nla_put_u32(skb, ETHTOOL_A_RINGS_TX,
ringparam->tx_pending)))) ringparam->tx_pending))) ||
(kernel_ringparam->rx_buf_len &&
(nla_put_u32(skb, ETHTOOL_A_RINGS_RX_BUF_LEN,
kernel_ringparam->rx_buf_len))))
return -EMSGSIZE; return -EMSGSIZE;
return 0; return 0;
@ -121,11 +127,13 @@ rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = {
[ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 }, [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 },
[ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 }, [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 },
[ETHTOOL_A_RINGS_TX] = { .type = NLA_U32 }, [ETHTOOL_A_RINGS_TX] = { .type = NLA_U32 },
[ETHTOOL_A_RINGS_RX_BUF_LEN] = NLA_POLICY_MIN(NLA_U32, 1),
}; };
int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info) int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
{ {
struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1]; struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1];
struct kernel_ethtool_ringparam kernel_ringparam = {};
struct ethtool_ringparam ringparam = {}; struct ethtool_ringparam ringparam = {};
struct ethnl_req_info req_info = {}; struct ethnl_req_info req_info = {};
const struct nlattr *err_attr; const struct nlattr *err_attr;
@ -163,6 +171,8 @@ int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
ethnl_update_u32(&ringparam.rx_jumbo_pending, ethnl_update_u32(&ringparam.rx_jumbo_pending,
tb[ETHTOOL_A_RINGS_RX_JUMBO], &mod); tb[ETHTOOL_A_RINGS_RX_JUMBO], &mod);
ethnl_update_u32(&ringparam.tx_pending, tb[ETHTOOL_A_RINGS_TX], &mod); ethnl_update_u32(&ringparam.tx_pending, tb[ETHTOOL_A_RINGS_TX], &mod);
ethnl_update_u32(&kernel_ringparam.rx_buf_len,
tb[ETHTOOL_A_RINGS_RX_BUF_LEN], &mod);
ret = 0; ret = 0;
if (!mod) if (!mod)
goto out_ops; goto out_ops;
@ -185,6 +195,15 @@ int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
goto out_ops; goto out_ops;
} }
if (kernel_ringparam.rx_buf_len != 0 &&
!(ops->supported_ring_params & ETHTOOL_RING_USE_RX_BUF_LEN)) {
ret = -EOPNOTSUPP;
NL_SET_ERR_MSG_ATTR(info->extack,
tb[ETHTOOL_A_RINGS_RX_BUF_LEN],
"setting rx buf len not supported");
goto out_ops;
}
ret = dev->ethtool_ops->set_ringparam(dev, &ringparam); ret = dev->ethtool_ops->set_ringparam(dev, &ringparam);
if (ret < 0) if (ret < 0)
goto out_ops; goto out_ops;