Skip to content

Commit 0e9c127

Browse files
Binary-Eaterkuba-moo
authored andcommitted
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 <[email protected]> Reviewed-by: Dragos Tatulea <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4196aee commit 0e9c127

File tree

5 files changed

+117
-2
lines changed

5 files changed

+117
-2
lines changed

Documentation/netlink/specs/ethtool.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,18 @@ attribute-sets:
565565
-
566566
name: tx-lpi-timer
567567
type: u32
568+
-
569+
name: ts-stat
570+
attributes:
571+
-
572+
name: tx-pkts
573+
type: uint
574+
-
575+
name: tx-lost
576+
type: uint
577+
-
578+
name: tx-err
579+
type: uint
568580
-
569581
name: tsinfo
570582
attributes:
@@ -587,6 +599,10 @@ attribute-sets:
587599
-
588600
name: phc-index
589601
type: u32
602+
-
603+
name: stats
604+
type: nest
605+
nested-attributes: ts-stat
590606
-
591607
name: cable-result
592608
attributes:
@@ -1394,6 +1410,7 @@ operations:
13941410
- tx-types
13951411
- rx-filters
13961412
- phc-index
1413+
- stats
13971414
dump: *tsinfo-get-op
13981415
-
13991416
name: cable-test-act

Documentation/networking/ethtool-netlink.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,12 +1237,21 @@ Kernel response contents:
12371237
``ETHTOOL_A_TSINFO_TX_TYPES`` bitset supported Tx types
12381238
``ETHTOOL_A_TSINFO_RX_FILTERS`` bitset supported Rx filters
12391239
``ETHTOOL_A_TSINFO_PHC_INDEX`` u32 PTP hw clock index
1240+
``ETHTOOL_A_TSINFO_STATS`` nested HW timestamping statistics
12401241
===================================== ====== ==========================
12411242

12421243
``ETHTOOL_A_TSINFO_PHC_INDEX`` is absent if there is no associated PHC (there
12431244
is no special value for this case). The bitset attributes are omitted if they
12441245
would be empty (no bit set).
12451246

1247+
Additional hardware timestamping statistics response contents:
1248+
1249+
===================================== ====== ===================================
1250+
``ETHTOOL_A_TS_STAT_TX_PKTS`` u64 Packets with Tx HW timestamps
1251+
``ETHTOOL_A_TS_STAT_TX_LOST`` u64 Tx HW timestamp not arrived count
1252+
``ETHTOOL_A_TS_STAT_TX_ERR`` u64 HW error request Tx timestamp count
1253+
===================================== ====== ===================================
1254+
12461255
CABLE_TEST
12471256
==========
12481257

include/linux/ethtool.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,26 @@ struct ethtool_rmon_stats {
480480
);
481481
};
482482

483+
/**
484+
* struct ethtool_ts_stats - HW timestamping statistics
485+
* @pkts: Number of packets successfully timestamped by the hardware.
486+
* @lost: Number of hardware timestamping requests where the timestamping
487+
* information from the hardware never arrived for submission with
488+
* the skb.
489+
* @err: Number of arbitrary timestamp generation error events that the
490+
* hardware encountered, exclusive of @lost statistics. Cases such
491+
* as resource exhaustion, unavailability, firmware errors, and
492+
* detected illogical timestamp values not submitted with the skb
493+
* are inclusive to this counter.
494+
*/
495+
struct ethtool_ts_stats {
496+
struct_group(tx_stats,
497+
u64 pkts;
498+
u64 lost;
499+
u64 err;
500+
);
501+
};
502+
483503
#define ETH_MODULE_EEPROM_PAGE_LEN 128
484504
#define ETH_MODULE_MAX_I2C_ADDRESS 0x7f
485505

@@ -755,7 +775,10 @@ struct ethtool_rxfh_param {
755775
* @get_ts_info: Get the time stamping and PTP hardware clock capabilities.
756776
* It may be called with RCU, or rtnl or reference on the device.
757777
* Drivers supporting transmit time stamps in software should set this to
758-
* ethtool_op_get_ts_info().
778+
* ethtool_op_get_ts_info(). Drivers must not zero statistics which they
779+
* don't report. The stats structure is initialized to ETHTOOL_STAT_NOT_SET
780+
* indicating driver does not report statistics.
781+
* @get_ts_stats: Query the device hardware timestamping statistics.
759782
* @get_module_info: Get the size and type of the eeprom contained within
760783
* a plug-in module.
761784
* @get_module_eeprom: Get the eeprom information from the plug-in module
@@ -898,6 +921,8 @@ struct ethtool_ops {
898921
struct ethtool_dump *, void *);
899922
int (*set_dump)(struct net_device *, struct ethtool_dump *);
900923
int (*get_ts_info)(struct net_device *, struct ethtool_ts_info *);
924+
void (*get_ts_stats)(struct net_device *dev,
925+
struct ethtool_ts_stats *ts_stats);
901926
int (*get_module_info)(struct net_device *,
902927
struct ethtool_modinfo *);
903928
int (*get_module_eeprom)(struct net_device *,

include/uapi/linux/ethtool_netlink.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,12 +478,26 @@ enum {
478478
ETHTOOL_A_TSINFO_TX_TYPES, /* bitset */
479479
ETHTOOL_A_TSINFO_RX_FILTERS, /* bitset */
480480
ETHTOOL_A_TSINFO_PHC_INDEX, /* u32 */
481+
ETHTOOL_A_TSINFO_STATS, /* nest - _A_TSINFO_STAT */
481482

482483
/* add new constants above here */
483484
__ETHTOOL_A_TSINFO_CNT,
484485
ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
485486
};
486487

488+
enum {
489+
ETHTOOL_A_TS_STAT_UNSPEC,
490+
491+
ETHTOOL_A_TS_STAT_TX_PKTS, /* u64 */
492+
ETHTOOL_A_TS_STAT_TX_LOST, /* u64 */
493+
ETHTOOL_A_TS_STAT_TX_ERR, /* u64 */
494+
495+
/* add new constants above here */
496+
__ETHTOOL_A_TS_STAT_CNT,
497+
ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
498+
499+
};
500+
487501
/* PHC VCLOCKS */
488502

489503
enum {

net/ethtool/tsinfo.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,18 @@ struct tsinfo_req_info {
1313
struct tsinfo_reply_data {
1414
struct ethnl_reply_data base;
1515
struct ethtool_ts_info ts_info;
16+
struct ethtool_ts_stats stats;
1617
};
1718

1819
#define TSINFO_REPDATA(__reply_base) \
1920
container_of(__reply_base, struct tsinfo_reply_data, base)
2021

22+
#define ETHTOOL_TS_STAT_CNT \
23+
(__ETHTOOL_A_TS_STAT_CNT - (ETHTOOL_A_TS_STAT_UNSPEC + 1))
24+
2125
const struct nla_policy ethnl_tsinfo_get_policy[] = {
2226
[ETHTOOL_A_TSINFO_HEADER] =
23-
NLA_POLICY_NESTED(ethnl_header_policy),
27+
NLA_POLICY_NESTED(ethnl_header_policy_stats),
2428
};
2529

2630
static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
@@ -34,6 +38,12 @@ static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
3438
ret = ethnl_ops_begin(dev);
3539
if (ret < 0)
3640
return ret;
41+
if (req_base->flags & ETHTOOL_FLAG_STATS &&
42+
dev->ethtool_ops->get_ts_stats) {
43+
ethtool_stats_init((u64 *)&data->stats,
44+
sizeof(data->stats) / sizeof(u64));
45+
dev->ethtool_ops->get_ts_stats(dev, &data->stats);
46+
}
3747
ret = __ethtool_get_ts_info(dev, &data->ts_info);
3848
ethnl_ops_complete(dev);
3949

@@ -79,10 +89,47 @@ static int tsinfo_reply_size(const struct ethnl_req_info *req_base,
7989
}
8090
if (ts_info->phc_index >= 0)
8191
len += nla_total_size(sizeof(u32)); /* _TSINFO_PHC_INDEX */
92+
if (req_base->flags & ETHTOOL_FLAG_STATS)
93+
len += nla_total_size(0) + /* _TSINFO_STATS */
94+
nla_total_size_64bit(sizeof(u64)) * ETHTOOL_TS_STAT_CNT;
8295

8396
return len;
8497
}
8598

99+
static int tsinfo_put_stat(struct sk_buff *skb, u64 val, u16 attrtype)
100+
{
101+
if (val == ETHTOOL_STAT_NOT_SET)
102+
return 0;
103+
if (nla_put_uint(skb, attrtype, val))
104+
return -EMSGSIZE;
105+
return 0;
106+
}
107+
108+
static int tsinfo_put_stats(struct sk_buff *skb,
109+
const struct ethtool_ts_stats *stats)
110+
{
111+
struct nlattr *nest;
112+
113+
nest = nla_nest_start(skb, ETHTOOL_A_TSINFO_STATS);
114+
if (!nest)
115+
return -EMSGSIZE;
116+
117+
if (tsinfo_put_stat(skb, stats->tx_stats.pkts,
118+
ETHTOOL_A_TS_STAT_TX_PKTS) ||
119+
tsinfo_put_stat(skb, stats->tx_stats.lost,
120+
ETHTOOL_A_TS_STAT_TX_LOST) ||
121+
tsinfo_put_stat(skb, stats->tx_stats.err,
122+
ETHTOOL_A_TS_STAT_TX_ERR))
123+
goto err_cancel;
124+
125+
nla_nest_end(skb, nest);
126+
return 0;
127+
128+
err_cancel:
129+
nla_nest_cancel(skb, nest);
130+
return -EMSGSIZE;
131+
}
132+
86133
static int tsinfo_fill_reply(struct sk_buff *skb,
87134
const struct ethnl_req_info *req_base,
88135
const struct ethnl_reply_data *reply_base)
@@ -119,6 +166,9 @@ static int tsinfo_fill_reply(struct sk_buff *skb,
119166
if (ts_info->phc_index >= 0 &&
120167
nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, ts_info->phc_index))
121168
return -EMSGSIZE;
169+
if (req_base->flags & ETHTOOL_FLAG_STATS &&
170+
tsinfo_put_stats(skb, &data->stats))
171+
return -EMSGSIZE;
122172

123173
return 0;
124174
}

0 commit comments

Comments
 (0)