Skip to content

Commit 11d55be

Browse files
kmaincentdavem330
authored andcommitted
net: ethtool: Add a command to expose current time stamping layer
Time stamping on network packets may happen either in the MAC or in the PHY, but not both. In preparation for making the choice selectable, expose both the current layers via ethtool. In accordance with the kernel implementation as it stands, the current layer will always read as "phy" when a PHY time stamping device is present. Future patches will allow changing the current layer administratively. Signed-off-by: Kory Maincent <kory.maincent@bootlin.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent acec05f commit 11d55be

File tree

8 files changed

+149
-1
lines changed

8 files changed

+149
-1
lines changed

Documentation/networking/ethtool-netlink.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ Userspace to kernel:
225225
``ETHTOOL_MSG_RSS_GET`` get RSS settings
226226
``ETHTOOL_MSG_MM_GET`` get MAC merge layer state
227227
``ETHTOOL_MSG_MM_SET`` set MAC merge layer parameters
228+
``ETHTOOL_MSG_TS_GET`` get current timestamping
228229
===================================== =================================
229230

230231
Kernel to userspace:
@@ -268,6 +269,7 @@ Kernel to userspace:
268269
``ETHTOOL_MSG_PSE_GET_REPLY`` PSE parameters
269270
``ETHTOOL_MSG_RSS_GET_REPLY`` RSS settings
270271
``ETHTOOL_MSG_MM_GET_REPLY`` MAC merge layer status
272+
``ETHTOOL_MSG_TS_GET_REPLY`` current timestamping
271273
======================================== =================================
272274

273275
``GET`` requests are sent by userspace applications to retrieve device
@@ -1994,6 +1996,26 @@ The attributes are propagated to the driver through the following structure:
19941996
.. kernel-doc:: include/linux/ethtool.h
19951997
:identifiers: ethtool_mm_cfg
19961998

1999+
TS_GET
2000+
======
2001+
2002+
Gets current timestamping.
2003+
2004+
Request contents:
2005+
2006+
================================= ====== ====================
2007+
``ETHTOOL_A_TS_HEADER`` nested request header
2008+
================================= ====== ====================
2009+
2010+
Kernel response contents:
2011+
2012+
======================= ====== ==============================
2013+
``ETHTOOL_A_TS_HEADER`` nested reply header
2014+
``ETHTOOL_A_TS_LAYER`` u32 current timestamping
2015+
======================= ====== ==============================
2016+
2017+
This command get the current timestamp layer.
2018+
19972019
Request translation
19982020
===================
19992021

@@ -2100,4 +2122,5 @@ are netlink only.
21002122
n/a ``ETHTOOL_MSG_PLCA_GET_STATUS``
21012123
n/a ``ETHTOOL_MSG_MM_GET``
21022124
n/a ``ETHTOOL_MSG_MM_SET``
2125+
n/a ``ETHTOOL_MSG_TS_GET``
21032126
=================================== =====================================

include/uapi/linux/ethtool_netlink.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ enum {
5757
ETHTOOL_MSG_PLCA_GET_STATUS,
5858
ETHTOOL_MSG_MM_GET,
5959
ETHTOOL_MSG_MM_SET,
60+
ETHTOOL_MSG_TS_GET,
6061

6162
/* add new constants above here */
6263
__ETHTOOL_MSG_USER_CNT,
@@ -109,6 +110,7 @@ enum {
109110
ETHTOOL_MSG_PLCA_NTF,
110111
ETHTOOL_MSG_MM_GET_REPLY,
111112
ETHTOOL_MSG_MM_NTF,
113+
ETHTOOL_MSG_TS_GET_REPLY,
112114

113115
/* add new constants above here */
114116
__ETHTOOL_MSG_KERNEL_CNT,
@@ -975,6 +977,18 @@ enum {
975977
ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
976978
};
977979

980+
/* TS LAYER */
981+
982+
enum {
983+
ETHTOOL_A_TS_UNSPEC,
984+
ETHTOOL_A_TS_HEADER, /* nest - _A_HEADER_* */
985+
ETHTOOL_A_TS_LAYER, /* u32 */
986+
987+
/* add new constants above here */
988+
__ETHTOOL_A_TS_CNT,
989+
ETHTOOL_A_TS_MAX = (__ETHTOOL_A_TS_CNT - 1)
990+
};
991+
978992
/* generic netlink info */
979993
#define ETHTOOL_GENL_NAME "ethtool"
980994
#define ETHTOOL_GENL_VERSION 1

include/uapi/linux/net_tstamp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@
1313
#include <linux/types.h>
1414
#include <linux/socket.h> /* for SO_TIMESTAMPING */
1515

16+
/* Layer of the TIMESTAMPING provider */
17+
enum timestamping_layer {
18+
NO_TIMESTAMPING,
19+
SOFTWARE_TIMESTAMPING,
20+
MAC_TIMESTAMPING,
21+
PHY_TIMESTAMPING,
22+
23+
__TIMESTAMPING_COUNT,
24+
};
25+
1626
/* SO_TIMESTAMPING flags */
1727
enum {
1828
SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),

net/ethtool/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o rss.o \
88
linkstate.o debug.o wol.o features.o privflags.o rings.o \
99
channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
1010
tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \
11-
module.o pse-pd.o plca.o mm.o
11+
module.o pse-pd.o plca.o mm.o ts.o

net/ethtool/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern const char wol_mode_names[][ETH_GSTRING_LEN];
3535
extern const char sof_timestamping_names[][ETH_GSTRING_LEN];
3636
extern const char ts_tx_type_names[][ETH_GSTRING_LEN];
3737
extern const char ts_rx_filter_names[][ETH_GSTRING_LEN];
38+
extern const char ts_layer_names[][ETH_GSTRING_LEN];
3839
extern const char udp_tunnel_type_names[][ETH_GSTRING_LEN];
3940

4041
int __ethtool_get_link(struct net_device *dev);

net/ethtool/netlink.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
306306
[ETHTOOL_MSG_PLCA_GET_STATUS] = &ethnl_plca_status_request_ops,
307307
[ETHTOOL_MSG_MM_GET] = &ethnl_mm_request_ops,
308308
[ETHTOOL_MSG_MM_SET] = &ethnl_mm_request_ops,
309+
[ETHTOOL_MSG_TS_GET] = &ethnl_ts_request_ops,
309310
};
310311

311312
static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1128,6 +1129,15 @@ static const struct genl_ops ethtool_genl_ops[] = {
11281129
.policy = ethnl_mm_set_policy,
11291130
.maxattr = ARRAY_SIZE(ethnl_mm_set_policy) - 1,
11301131
},
1132+
{
1133+
.cmd = ETHTOOL_MSG_TS_GET,
1134+
.doit = ethnl_default_doit,
1135+
.start = ethnl_default_start,
1136+
.dumpit = ethnl_default_dumpit,
1137+
.done = ethnl_default_done,
1138+
.policy = ethnl_ts_get_policy,
1139+
.maxattr = ARRAY_SIZE(ethnl_ts_get_policy) - 1,
1140+
},
11311141
};
11321142

11331143
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {

net/ethtool/netlink.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ extern const struct ethnl_request_ops ethnl_rss_request_ops;
395395
extern const struct ethnl_request_ops ethnl_plca_cfg_request_ops;
396396
extern const struct ethnl_request_ops ethnl_plca_status_request_ops;
397397
extern const struct ethnl_request_ops ethnl_mm_request_ops;
398+
extern const struct ethnl_request_ops ethnl_ts_request_ops;
398399

399400
extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
400401
extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
@@ -441,6 +442,7 @@ extern const struct nla_policy ethnl_plca_set_cfg_policy[ETHTOOL_A_PLCA_MAX + 1]
441442
extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADER + 1];
442443
extern const struct nla_policy ethnl_mm_get_policy[ETHTOOL_A_MM_HEADER + 1];
443444
extern const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1];
445+
extern const struct nla_policy ethnl_ts_get_policy[ETHTOOL_A_TS_HEADER + 1];
444446

445447
int ethnl_set_features(struct sk_buff *skb, struct genl_info *info);
446448
int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info);

net/ethtool/ts.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include <linux/net_tstamp.h>
4+
#include <linux/phy.h>
5+
6+
#include "netlink.h"
7+
#include "common.h"
8+
#include "bitset.h"
9+
10+
struct ts_req_info {
11+
struct ethnl_req_info base;
12+
};
13+
14+
struct ts_reply_data {
15+
struct ethnl_reply_data base;
16+
enum timestamping_layer ts_layer;
17+
};
18+
19+
#define TS_REPDATA(__reply_base) \
20+
container_of(__reply_base, struct ts_reply_data, base)
21+
22+
/* TS_GET */
23+
const struct nla_policy ethnl_ts_get_policy[] = {
24+
[ETHTOOL_A_TS_HEADER] =
25+
NLA_POLICY_NESTED(ethnl_header_policy),
26+
};
27+
28+
static int ts_prepare_data(const struct ethnl_req_info *req_base,
29+
struct ethnl_reply_data *reply_base,
30+
const struct genl_info *info)
31+
{
32+
struct ts_reply_data *data = TS_REPDATA(reply_base);
33+
struct net_device *dev = reply_base->dev;
34+
const struct ethtool_ops *ops = dev->ethtool_ops;
35+
int ret;
36+
37+
ret = ethnl_ops_begin(dev);
38+
if (ret < 0)
39+
return ret;
40+
41+
if (phy_has_tsinfo(dev->phydev)) {
42+
data->ts_layer = PHY_TIMESTAMPING;
43+
} else if (ops->get_ts_info) {
44+
struct ethtool_ts_info ts_info = {0};
45+
46+
ops->get_ts_info(dev, &ts_info);
47+
if (ts_info.so_timestamping &
48+
SOF_TIMESTAMPING_HARDWARE_MASK)
49+
data->ts_layer = MAC_TIMESTAMPING;
50+
51+
if (ts_info.so_timestamping &
52+
SOF_TIMESTAMPING_SOFTWARE_MASK)
53+
data->ts_layer = SOFTWARE_TIMESTAMPING;
54+
} else {
55+
data->ts_layer = NO_TIMESTAMPING;
56+
}
57+
58+
ethnl_ops_complete(dev);
59+
60+
return ret;
61+
}
62+
63+
static int ts_reply_size(const struct ethnl_req_info *req_base,
64+
const struct ethnl_reply_data *reply_base)
65+
{
66+
return nla_total_size(sizeof(u32));
67+
}
68+
69+
static int ts_fill_reply(struct sk_buff *skb,
70+
const struct ethnl_req_info *req_base,
71+
const struct ethnl_reply_data *reply_base)
72+
{
73+
struct ts_reply_data *data = TS_REPDATA(reply_base);
74+
75+
return nla_put_u32(skb, ETHTOOL_A_TS_LAYER, data->ts_layer);
76+
}
77+
78+
const struct ethnl_request_ops ethnl_ts_request_ops = {
79+
.request_cmd = ETHTOOL_MSG_TS_GET,
80+
.reply_cmd = ETHTOOL_MSG_TS_GET_REPLY,
81+
.hdr_attr = ETHTOOL_A_TS_HEADER,
82+
.req_info_size = sizeof(struct ts_req_info),
83+
.reply_data_size = sizeof(struct ts_reply_data),
84+
85+
.prepare_data = ts_prepare_data,
86+
.reply_size = ts_reply_size,
87+
.fill_reply = ts_fill_reply,
88+
};

0 commit comments

Comments
 (0)