[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240223192658.45893-2-rrameshbabu@nvidia.com>
Date: Fri, 23 Feb 2024 11:24:45 -0800
From: Rahul Rameshbabu <rrameshbabu@...dia.com>
To: Saeed Mahameed <saeed@...nel.org>,
Leon Romanovsky <leon@...nel.org>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Jonathan Corbet <corbet@....net>,
Richard Cochran <richardcochran@...il.com>,
Tariq Toukan <tariqt@...dia.com>,
Gal Pressman <gal@...dia.com>,
Vadim Fedorenko <vadim.fedorenko@...ux.dev>,
Andrew Lunn <andrew@...n.ch>,
Heiner Kallweit <hkallweit1@...il.com>,
Przemek Kitszel <przemyslaw.kitszel@...el.com>,
Ahmed Zaki <ahmed.zaki@...el.com>,
Alexander Lobakin <aleksander.lobakin@...el.com>,
Hangbin Liu <liuhangbin@...il.com>,
Paul Greenwalt <paul.greenwalt@...el.com>,
Justin Stitt <justinstitt@...gle.com>,
Randy Dunlap <rdunlap@...radead.org>,
Maxime Chevallier <maxime.chevallier@...tlin.com>,
Kory Maincent <kory.maincent@...tlin.com>,
Wojciech Drewek <wojciech.drewek@...el.com>,
Vladimir Oltean <vladimir.oltean@....com>,
Jiri Pirko <jiri@...nulli.us>,
Jacob Keller <jacob.e.keller@...el.com>,
Alexandre Torgue <alexandre.torgue@...s.st.com>,
Jose Abreu <joabreu@...opsys.com>,
Dragos Tatulea <dtatulea@...dia.com>
Cc: netdev@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux-doc@...r.kernel.org,
Rahul Rameshbabu <rrameshbabu@...dia.com>
Subject: [PATCH RFC net-next v1 1/6] ethtool: add interface to read Tx hardware timestamping statistics
Multiple network devices that support hardware timestamping appear to have
common behavior with regards to timestamp handling. Implement common Tx
hardware timestamping statistics in a tx_stats struct_group. Common Rx
hardware timestamping statistics can subsequently be implemented in a
rx_stats struct_group for ethtool_ts_stats.
Signed-off-by: Rahul Rameshbabu <rrameshbabu@...dia.com>
Reviewed-by: Dragos Tatulea <dtatulea@...dia.com>
---
include/linux/ethtool.h | 28 +++++++++++++++
include/uapi/linux/ethtool.h | 20 +++++++++++
include/uapi/linux/ethtool_netlink.h | 17 +++++++++
net/ethtool/netlink.h | 3 +-
net/ethtool/stats.c | 53 +++++++++++++++++++++++++---
net/ethtool/strset.c | 5 +++
6 files changed, 120 insertions(+), 6 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index b90c33607594..1cc1010afaca 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -483,6 +483,31 @@ struct ethtool_rmon_stats {
);
};
+/**
+ * struct ethtool_ts_stats - HW timestamping statistics
+ * @layer: input field denoting whether stats should be queried from the DMA or
+ * PHY timestamping layer. Defaults to the active layer for packet
+ * timestamping.
+ * @tx_stats: struct group for TX HW timestamping
+ * @pkts: Number of packets successfully timestamped by the queried
+ * layer.
+ * @lost: Number of packet timestamps that failed to get applied on a
+ * packet by the queried layer.
+ * @late: Number of packet timestamps that were delivered by the
+ * hardware but were lost due to arriving too late.
+ * @err: Number of timestamping errors that occurred on the queried
+ * layer.
+ */
+struct ethtool_ts_stats {
+ enum ethtool_ts_stats_layer layer;
+ struct_group(tx_stats,
+ u64 pkts;
+ u64 lost;
+ u64 late;
+ u64 err;
+ );
+};
+
#define ETH_MODULE_EEPROM_PAGE_LEN 128
#define ETH_MODULE_MAX_I2C_ADDRESS 0x7f
@@ -807,6 +832,7 @@ struct ethtool_rxfh_param {
* @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics.
* @get_rmon_stats: Query some of the RMON (RFC 2819) statistics.
* Set %ranges to a pointer to zero-terminated array of byte ranges.
+ * @get_eth_ts_stats: Query the device hardware timestamping statistics.
* @get_module_power_mode: Get the power mode policy for the plug-in module
* used by the network device and its operational power mode, if
* plugged-in.
@@ -943,6 +969,8 @@ struct ethtool_ops {
void (*get_rmon_stats)(struct net_device *dev,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges);
+ void (*get_ts_stats)(struct net_device *dev,
+ struct ethtool_ts_stats *ts_stats);
int (*get_module_power_mode)(struct net_device *dev,
struct ethtool_module_power_mode_params *params,
struct netlink_ext_ack *extack);
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 06ef6b78b7de..39edae554fc5 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -681,6 +681,7 @@ enum ethtool_link_ext_substate_module {
* @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics
* @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics
* @ETH_SS_STATS_RMON: names of RMON statistics
+ * @ETH_SS_STATS_TS: names of hardware timestamping statistics
*
* @ETH_SS_COUNT: number of defined string sets
*/
@@ -706,6 +707,7 @@ enum ethtool_stringset {
ETH_SS_STATS_ETH_MAC,
ETH_SS_STATS_ETH_CTRL,
ETH_SS_STATS_RMON,
+ ETH_SS_STATS_TS,
/* add new constants above here */
ETH_SS_COUNT
@@ -1462,6 +1464,24 @@ struct ethtool_ts_info {
__u32 rx_reserved[3];
};
+/**
+ * enum ethtool_ts_stats_layer - layer to query hardware timestamping statistics
+ * @ETHTOOL_TS_STATS_LAYER_ACTIVE:
+ * retrieve the statistics from the layer that is currently feeding
+ * hardware timestamps for packets.
+ * @ETHTOOL_TS_STATS_LAYER_DMA:
+ * retrieve the statistics from the DMA hardware timestamping layer of the
+ * device.
+ * @ETHTOOL_TS_STATS_PHY:
+ * retrieve the statistics from the PHY hardware timestamping layer of the
+ * device.
+ */
+enum ethtool_ts_stats_layer {
+ ETHTOOL_TS_STATS_LAYER_ACTIVE,
+ ETHTOOL_TS_STATS_LAYER_DMA,
+ ETHTOOL_TS_STATS_LAYER_PHY,
+};
+
/*
* %ETHTOOL_SFEATURES changes features present in features[].valid to the
* values of corresponding bits in features[].requested. Bits in .requested
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 3f89074aa06c..55f2a3c8caa0 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -749,6 +749,7 @@ enum {
ETHTOOL_A_STATS_GRP, /* nest - _A_STATS_GRP_* */
ETHTOOL_A_STATS_SRC, /* u32 */
+ ETHTOOL_A_STATS_LAYER, /* u32 */
/* add new constants above here */
__ETHTOOL_A_STATS_CNT,
@@ -760,6 +761,7 @@ enum {
ETHTOOL_STATS_ETH_MAC,
ETHTOOL_STATS_ETH_CTRL,
ETHTOOL_STATS_RMON,
+ ETHTOOL_STATS_TS,
/* add new constants above here */
__ETHTOOL_STATS_CNT
@@ -875,6 +877,21 @@ enum {
ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1)
};
+enum {
+ /* hwTimestampingTxPkts */
+ ETHTOOL_A_STATS_TS_TX_PKT,
+ /* hwTimestampingTxLost */
+ ETHTOOL_A_STATS_TS_TX_LOST,
+ /* hwTimestampingTxLate */
+ ETHTOOL_A_STATS_TS_TX_LATE,
+ /* hwTimestampingTxErrors */
+ ETHTOOL_A_STATS_TS_TX_ERRORS,
+
+ /* add new constants above here */
+ __ETHTOOL_A_STATS_TS_CNT,
+ ETHTOOL_A_STATS_TS_MAX = (__ETHTOOL_A_STATS_TS_CNT - 1)
+};
+
/* MODULE */
enum {
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 9a333a8d04c1..962ecd62aeea 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -429,7 +429,7 @@ extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INF
extern const struct nla_policy ethnl_fec_get_policy[ETHTOOL_A_FEC_HEADER + 1];
extern const struct nla_policy ethnl_fec_set_policy[ETHTOOL_A_FEC_AUTO + 1];
extern const struct nla_policy ethnl_module_eeprom_get_policy[ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS + 1];
-extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC + 1];
+extern const struct nla_policy ethnl_stats_get_policy[__ETHTOOL_A_STATS_CNT];
extern const struct nla_policy ethnl_phc_vclocks_get_policy[ETHTOOL_A_PHC_VCLOCKS_HEADER + 1];
extern const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HEADER + 1];
extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MODE_POLICY + 1];
@@ -454,5 +454,6 @@ extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING
extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN];
extern const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN];
extern const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN];
+extern const char stats_ts_names[__ETHTOOL_A_STATS_TS_CNT][ETH_GSTRING_LEN];
#endif /* _NET_ETHTOOL_NETLINK_H */
diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c
index 912f0c4fff2f..e4333d77fb31 100644
--- a/net/ethtool/stats.c
+++ b/net/ethtool/stats.c
@@ -8,6 +8,7 @@ struct stats_req_info {
struct ethnl_req_info base;
DECLARE_BITMAP(stat_mask, __ETHTOOL_STATS_CNT);
enum ethtool_mac_stats_src src;
+ enum ethtool_ts_stats_layer layer;
};
#define STATS_REQINFO(__req_base) \
@@ -20,6 +21,7 @@ struct stats_reply_data {
struct ethtool_eth_mac_stats mac_stats;
struct ethtool_eth_ctrl_stats ctrl_stats;
struct ethtool_rmon_stats rmon_stats;
+ struct ethtool_ts_stats ts_stats;
);
const struct ethtool_rmon_hist_range *rmon_ranges;
};
@@ -32,6 +34,7 @@ const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {
[ETHTOOL_STATS_ETH_MAC] = "eth-mac",
[ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl",
[ETHTOOL_STATS_RMON] = "rmon",
+ [ETHTOOL_STATS_TS] = "ts",
};
const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = {
@@ -76,18 +79,27 @@ const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN] = {
[ETHTOOL_A_STATS_RMON_JABBER] = "etherStatsJabbers",
};
-const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_SRC + 1] = {
- [ETHTOOL_A_STATS_HEADER] =
- NLA_POLICY_NESTED(ethnl_header_policy),
- [ETHTOOL_A_STATS_GROUPS] = { .type = NLA_NESTED },
- [ETHTOOL_A_STATS_SRC] =
+const char stats_ts_names[__ETHTOOL_A_STATS_TS_CNT][ETH_GSTRING_LEN] = {
+ [ETHTOOL_A_STATS_TS_TX_PKT] = "hwTimestampingTxPkts",
+ [ETHTOOL_A_STATS_TS_TX_LOST] = "hwTimestampingTxLost",
+ [ETHTOOL_A_STATS_TS_TX_LATE] = "hwTimestampingTxLate",
+ [ETHTOOL_A_STATS_TS_TX_ERRORS] = "hwTimestampingTxErrors",
+};
+
+const struct nla_policy ethnl_stats_get_policy[__ETHTOOL_A_STATS_CNT] = {
+ [ETHTOOL_A_STATS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
+ [ETHTOOL_A_STATS_GROUPS] = { .type = NLA_NESTED },
+ [ETHTOOL_A_STATS_SRC] =
NLA_POLICY_MAX(NLA_U32, ETHTOOL_MAC_STATS_SRC_PMAC),
+ [ETHTOOL_A_STATS_LAYER] =
+ NLA_POLICY_MAX(NLA_U32, ETHTOOL_TS_STATS_LAYER_PHY),
};
static int stats_parse_request(struct ethnl_req_info *req_base,
struct nlattr **tb,
struct netlink_ext_ack *extack)
{
+ enum ethtool_ts_stats_layer layer = ETHTOOL_TS_STATS_LAYER_ACTIVE;
enum ethtool_mac_stats_src src = ETHTOOL_MAC_STATS_SRC_AGGREGATE;
struct stats_req_info *req_info = STATS_REQINFO(req_base);
bool mod = false;
@@ -104,9 +116,12 @@ static int stats_parse_request(struct ethnl_req_info *req_base,
return -EINVAL;
}
+ if (tb[ETHTOOL_A_STATS_LAYER])
+ layer = nla_get_u32(tb[ETHTOOL_A_STATS_LAYER]);
if (tb[ETHTOOL_A_STATS_SRC])
src = nla_get_u32(tb[ETHTOOL_A_STATS_SRC]);
+ req_info->layer = layer;
req_info->src = src;
return 0;
@@ -118,6 +133,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
{
const struct stats_req_info *req_info = STATS_REQINFO(req_base);
struct stats_reply_data *data = STATS_REPDATA(reply_base);
+ enum ethtool_ts_stats_layer layer = req_info->layer;
enum ethtool_mac_stats_src src = req_info->src;
struct net_device *dev = reply_base->dev;
int ret;
@@ -144,6 +160,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
data->mac_stats.src = src;
data->ctrl_stats.src = src;
data->rmon_stats.src = src;
+ data->ts_stats.layer = layer;
if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
dev->ethtool_ops->get_eth_phy_stats)
@@ -158,6 +175,9 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
dev->ethtool_ops->get_rmon_stats)
dev->ethtool_ops->get_rmon_stats(dev, &data->rmon_stats,
&data->rmon_ranges);
+ if (test_bit(ETHTOOL_STATS_TS, req_info->stat_mask) &&
+ dev->ethtool_ops->get_ts_stats)
+ dev->ethtool_ops->get_ts_stats(dev, &data->ts_stats);
ethnl_ops_complete(dev);
return 0;
@@ -194,6 +214,10 @@ static int stats_reply_size(const struct ethnl_req_info *req_base,
nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */
ETHTOOL_RMON_HIST_MAX * 2;
}
+ if (test_bit(ETHTOOL_STATS_TS, req_info->stat_mask)) {
+ n_stats += sizeof(struct ethtool_ts_stats) / sizeof(u64);
+ n_grps++;
+ }
len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */
nla_total_size(4) + /* _A_STATS_GRP_ID */
@@ -370,6 +394,22 @@ static int stats_put_rmon_stats(struct sk_buff *skb,
return 0;
}
+static int stats_put_ts_stats(struct sk_buff *skb,
+ const struct stats_reply_data *data)
+{
+ if (stat_put(skb, ETHTOOL_A_STATS_TS_TX_PKT,
+ data->ts_stats.pkts) ||
+ stat_put(skb, ETHTOOL_A_STATS_TS_TX_LOST,
+ data->ts_stats.lost) ||
+ stat_put(skb, ETHTOOL_A_STATS_TS_TX_LATE,
+ data->ts_stats.late) ||
+ stat_put(skb, ETHTOOL_A_STATS_TS_TX_ERRORS,
+ data->ts_stats.err))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
static int stats_put_stats(struct sk_buff *skb,
const struct stats_reply_data *data,
u32 id, u32 ss_id,
@@ -423,6 +463,9 @@ static int stats_fill_reply(struct sk_buff *skb,
if (!ret && test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask))
ret = stats_put_stats(skb, data, ETHTOOL_STATS_RMON,
ETH_SS_STATS_RMON, stats_put_rmon_stats);
+ if (!ret && test_bit(ETHTOOL_STATS_TS, req_info->stat_mask))
+ ret = stats_put_stats(skb, data, ETHTOOL_STATS_TS,
+ ETH_SS_STATS_TS, stats_put_ts_stats);
return ret;
}
diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c
index c678b484a079..ce1e193076c3 100644
--- a/net/ethtool/strset.c
+++ b/net/ethtool/strset.c
@@ -105,6 +105,11 @@ static const struct strset_info info_template[] = {
.count = __ETHTOOL_A_STATS_RMON_CNT,
.strings = stats_rmon_names,
},
+ [ETH_SS_STATS_TS] = {
+ .per_dev = false,
+ .count = __ETHTOOL_A_STATS_TS_CNT,
+ .strings = stats_ts_names,
+ },
};
struct strset_req_info {
--
2.42.0
Powered by blists - more mailing lists