349 lines
14 KiB
Diff
349 lines
14 KiB
Diff
From adc45e25377473ec6b3303fbe15bb63e29f4b9c8 Mon Sep 17 00:00:00 2001
|
|
From: Hao Chen <chenhao288@hisilicon.com>
|
|
Date: Mon, 27 Dec 2021 19:41:40 +0800
|
|
Subject: [PATCH 167/283] ethtool: add support to set/get rx buf len via
|
|
ethtool
|
|
|
|
mainline inclusion
|
|
from mainline-v5.17-rc1
|
|
commit 0b70c256eba8448b072d25c95ee65e59da8970de
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EN3D
|
|
CVE: NA
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0b70c256eba8448b072d25c95ee65e59da8970de
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
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>
|
|
Reviewed-by: Yongxin Li <liyongxin1@huawei.com>
|
|
Signed-off-by: Junxin Chen <chenjunxin1@huawei.com>
|
|
(fix conflicts: remove extend link modes)
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
|
|
Conflicts:
|
|
include/linux/ethtool.h
|
|
net/ethtool/netlink.h
|
|
net/ethtool/rings.c
|
|
---
|
|
Documentation/networking/ethtool-netlink.rst | 10 ++--
|
|
include/linux/ethtool.h | 26 ++++++----
|
|
include/net/netlink.h | 50 +++++++++++++++++++-
|
|
include/uapi/linux/ethtool_netlink.h | 1 +
|
|
net/ethtool/netlink.c | 2 +-
|
|
net/ethtool/netlink.h | 23 +++++++++
|
|
net/ethtool/rings.c | 24 +++++++++-
|
|
7 files changed, 120 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
|
|
index 6ed5a806054a..1cf07b28382d 100644
|
|
--- a/Documentation/networking/ethtool-netlink.rst
|
|
+++ b/Documentation/networking/ethtool-netlink.rst
|
|
@@ -231,7 +231,7 @@ Request contents:
|
|
|
|
Kernel response contents:
|
|
|
|
- ==================================== ====== ==========================
|
|
+ ==================================== ====== ===========================
|
|
``ETHTOOL_A_RINGS_HEADER`` nested reply header
|
|
``ETHTOOL_A_RINGS_RX_MAX`` u32 max size of RX ring
|
|
``ETHTOOL_A_RINGS_RX_MINI_MAX`` u32 max size of RX mini ring
|
|
@@ -241,7 +241,8 @@ Kernel response contents:
|
|
``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_TX`` u32 size of TX ring
|
|
- ==================================== ====== ==========================
|
|
+ ``ETHTOOL_A_RINGS_RX_BUF_LEN`` u32 size of buffers on the ring
|
|
+ ==================================== ====== ===========================
|
|
|
|
|
|
RINGS_SET
|
|
@@ -251,13 +252,14 @@ Sets ring sizes like ``ETHTOOL_SRINGPARAM`` ioctl request.
|
|
|
|
Request contents:
|
|
|
|
- ==================================== ====== ==========================
|
|
+ ==================================== ====== ===========================
|
|
``ETHTOOL_A_RINGS_HEADER`` nested reply header
|
|
``ETHTOOL_A_RINGS_RX`` u32 size of RX 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_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
|
|
driver. Driver may impose additional constraints and may not suspport all
|
|
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
|
|
index 4154522d8497..812026982640 100644
|
|
--- a/include/linux/ethtool.h
|
|
+++ b/include/linux/ethtool.h
|
|
@@ -71,6 +71,22 @@ enum {
|
|
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(name) __ETH_RSS_HASH_BIT(ETH_RSS_HASH_##name##_BIT)
|
|
|
|
@@ -234,14 +250,7 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
|
|
/**
|
|
* struct ethtool_ops - optional netdev operations
|
|
* @supported_coalesce_params: supported types of interrupt coalescing.
|
|
- * @get_settings: DEPRECATED, use %get_link_ksettings/%set_link_ksettings
|
|
- * API. Get various device settings including Ethernet link
|
|
- * settings. The @cmd parameter is expected to have been cleared
|
|
- * before get_settings is called. Returns a negative error code
|
|
- * or zero.
|
|
- * @set_settings: DEPRECATED, use %get_link_ksettings/%set_link_ksettings
|
|
- * API. Set various device settings including Ethernet link
|
|
- * settings. Returns a negative error code or zero.
|
|
+ * @supported_ring_params: supported ring params.
|
|
* @get_drvinfo: Report driver/device information. Should only set the
|
|
* @driver, @version, @fw_version and @bus_info fields. If not
|
|
* implemented, the @driver and @bus_info fields will be filled in
|
|
@@ -384,6 +393,7 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
|
|
struct ethtool_ops {
|
|
#ifndef __GENKSYMS__
|
|
u32 supported_coalesce_params;
|
|
+ u32 supported_ring_params;
|
|
#endif
|
|
int (*get_settings)(struct net_device *, struct ethtool_cmd *);
|
|
int (*set_settings)(struct net_device *, struct ethtool_cmd *);
|
|
diff --git a/include/net/netlink.h b/include/net/netlink.h
|
|
index d6e48d6ad67d..f30598d66eec 100644
|
|
--- a/include/net/netlink.h
|
|
+++ b/include/net/netlink.h
|
|
@@ -191,6 +191,17 @@ enum {
|
|
|
|
#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
|
|
|
|
+enum nla_policy_validation {
|
|
+ NLA_VALIDATE_NONE,
|
|
+ NLA_VALIDATE_RANGE,
|
|
+ NLA_VALIDATE_RANGE_WARN_TOO_LONG,
|
|
+ NLA_VALIDATE_MIN,
|
|
+ NLA_VALIDATE_MAX,
|
|
+ NLA_VALIDATE_MASK,
|
|
+ NLA_VALIDATE_RANGE_PTR,
|
|
+ NLA_VALIDATE_FUNCTION,
|
|
+};
|
|
+
|
|
/**
|
|
* struct nla_policy - attribute validation policy
|
|
* @type: Type of attribute or NLA_UNSPEC
|
|
@@ -228,9 +239,46 @@ enum {
|
|
struct nla_policy {
|
|
u16 type;
|
|
u16 len;
|
|
- void *validation_data;
|
|
+ void *validation_data;
|
|
+#ifndef __GENKSYMS__
|
|
+ u8 validation_type;
|
|
+ union {
|
|
+ const u32 bitfield32_valid;
|
|
+ const u32 mask;
|
|
+ const char *reject_message;
|
|
+ const struct nla_policy *nested_policy;
|
|
+ struct netlink_range_validation *range;
|
|
+ struct netlink_range_validation_signed *range_signed;
|
|
+ struct {
|
|
+ s16 min, max;
|
|
+ };
|
|
+ int (*validate)(const struct nlattr *attr,
|
|
+ struct netlink_ext_ack *extack);
|
|
+ u16 strict_start_type;
|
|
+ };
|
|
+#endif
|
|
};
|
|
|
|
+#define __NLA_IS_UINT_TYPE(tp) \
|
|
+ (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64)
|
|
+#define __NLA_IS_SINT_TYPE(tp) \
|
|
+ (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64)
|
|
+
|
|
+#define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
|
|
+
|
|
+#define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \
|
|
+ (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \
|
|
+ __NLA_IS_SINT_TYPE(tp) || \
|
|
+ tp == NLA_MSECS || \
|
|
+ tp == NLA_BINARY) + tp)
|
|
+
|
|
+
|
|
+#define NLA_POLICY_MIN(tp, _min) { \
|
|
+ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
|
|
+ .validation_type = NLA_VALIDATE_MIN, \
|
|
+ .min = _min, \
|
|
+}
|
|
+
|
|
/**
|
|
* struct nl_info - netlink source information
|
|
* @nlh: Netlink message header of original request
|
|
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
|
|
index aa543c783529..4eed3507a005 100644
|
|
--- a/include/uapi/linux/ethtool_netlink.h
|
|
+++ b/include/uapi/linux/ethtool_netlink.h
|
|
@@ -280,6 +280,7 @@ enum {
|
|
ETHTOOL_A_RINGS_RX_MINI, /* u32 */
|
|
ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */
|
|
ETHTOOL_A_RINGS_TX, /* u32 */
|
|
+ ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
|
|
|
|
/* add new constants above here */
|
|
__ETHTOOL_A_RINGS_CNT,
|
|
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
|
|
index 7ac8a4524376..d86613309591 100644
|
|
--- a/net/ethtool/netlink.c
|
|
+++ b/net/ethtool/netlink.c
|
|
@@ -9,7 +9,7 @@ static struct genl_family ethtool_genl_family;
|
|
static bool ethnl_ok __read_mostly;
|
|
static u32 ethnl_bcast_seq;
|
|
|
|
-static const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_MAX + 1] = {
|
|
+const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_MAX + 1] = {
|
|
[ETHTOOL_A_HEADER_UNSPEC] = { .type = NLA_REJECT },
|
|
[ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
|
|
[ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
|
|
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
|
|
index a862bad9dd06..bc2b83877e01 100644
|
|
--- a/net/ethtool/netlink.h
|
|
+++ b/net/ethtool/netlink.h
|
|
@@ -326,6 +326,29 @@ extern const struct ethnl_request_ops ethnl_wol_request_ops;
|
|
extern const struct ethnl_request_ops ethnl_features_request_ops;
|
|
extern const struct ethnl_request_ops ethnl_privflags_request_ops;
|
|
extern const struct ethnl_request_ops ethnl_rings_request_ops;
|
|
+extern const struct ethnl_request_ops ethnl_channels_request_ops;
|
|
+extern const struct ethnl_request_ops ethnl_coalesce_request_ops;
|
|
+extern const struct ethnl_request_ops ethnl_pause_request_ops;
|
|
+extern const struct ethnl_request_ops ethnl_eee_request_ops;
|
|
+extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
|
|
+
|
|
+extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
|
|
+extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
|
|
+extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_COUNTS_ONLY + 1];
|
|
+extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1];
|
|
+extern const struct nla_policy ethnl_linkmodes_get_policy[ETHTOOL_A_LINKMODES_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_linkstate_get_policy[ETHTOOL_A_LINKSTATE_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_debug_get_policy[ETHTOOL_A_DEBUG_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_debug_set_policy[ETHTOOL_A_DEBUG_MSGMASK + 1];
|
|
+extern const struct nla_policy ethnl_wol_get_policy[ETHTOOL_A_WOL_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_wol_set_policy[ETHTOOL_A_WOL_SOPASS + 1];
|
|
+extern const struct nla_policy ethnl_features_get_policy[ETHTOOL_A_FEATURES_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_features_set_policy[ETHTOOL_A_FEATURES_WANTED + 1];
|
|
+extern const struct nla_policy ethnl_privflags_get_policy[ETHTOOL_A_PRIVFLAGS_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_privflags_set_policy[ETHTOOL_A_PRIVFLAGS_FLAGS + 1];
|
|
+extern const struct nla_policy ethnl_rings_get_policy[ETHTOOL_A_RINGS_HEADER + 1];
|
|
+extern const struct nla_policy ethnl_rings_set_policy[ETHTOOL_A_RINGS_RX_BUF_LEN + 1];
|
|
|
|
int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
|
|
int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
|
|
diff --git a/net/ethtool/rings.c b/net/ethtool/rings.c
|
|
index 93f428e9a6c2..128e15b10883 100644
|
|
--- a/net/ethtool/rings.c
|
|
+++ b/net/ethtool/rings.c
|
|
@@ -10,6 +10,7 @@ struct rings_req_info {
|
|
struct rings_reply_data {
|
|
struct ethnl_reply_data base;
|
|
struct ethtool_ringparam ringparam;
|
|
+ struct kernel_ethtool_ringparam kernel_ringparam;
|
|
};
|
|
|
|
#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_MINI */
|
|
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,
|
|
@@ -66,6 +68,8 @@ static int rings_fill_reply(struct sk_buff *skb,
|
|
const struct ethnl_reply_data *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;
|
|
|
|
if ((ringparam->rx_max_pending &&
|
|
@@ -87,7 +91,10 @@ static int rings_fill_reply(struct sk_buff *skb,
|
|
(nla_put_u32(skb, ETHTOOL_A_RINGS_TX_MAX,
|
|
ringparam->tx_max_pending) ||
|
|
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 0;
|
|
@@ -121,11 +128,13 @@ rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = {
|
|
[ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 },
|
|
[ETHTOOL_A_RINGS_RX_JUMBO] = { .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)
|
|
{
|
|
struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1];
|
|
+ struct kernel_ethtool_ringparam kernel_ringparam = {};
|
|
struct ethtool_ringparam ringparam = {};
|
|
struct ethnl_req_info req_info = {};
|
|
const struct nlattr *err_attr;
|
|
@@ -163,6 +172,8 @@ int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
|
|
ethnl_update_u32(&ringparam.rx_jumbo_pending,
|
|
tb[ETHTOOL_A_RINGS_RX_JUMBO], &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;
|
|
if (!mod)
|
|
goto out_ops;
|
|
@@ -185,6 +196,15 @@ int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info)
|
|
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);
|
|
|
|
out_ops:
|
|
--
|
|
2.34.1
|
|
|