Skip to content

Commit 7112a04

Browse files
msudheer337kuba-moo
authored andcommitted
ethtool: add netlink based get rss support
Add netlink based support for "ethtool -x <dev> [context x]" command by implementing ETHTOOL_MSG_RSS_GET netlink message. This is equivalent to functionality provided via ETHTOOL_GRSSH in ioctl path. It sends RSS table, hash key and hash function of an interface to user space. This patch implements existing functionality available in ioctl path and enables addition of new RSS context based parameters in future. Signed-off-by: Sudheer Mogilappagari <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 343a5d3 commit 7112a04

File tree

6 files changed

+207
-2
lines changed

6 files changed

+207
-2
lines changed

Documentation/networking/ethtool-netlink.rst

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ Userspace to kernel:
222222
``ETHTOOL_MSG_MODULE_GET`` get transceiver module parameters
223223
``ETHTOOL_MSG_PSE_SET`` set PSE parameters
224224
``ETHTOOL_MSG_PSE_GET`` get PSE parameters
225+
``ETHTOOL_MSG_RSS_GET`` get RSS settings
225226
===================================== =================================
226227

227228
Kernel to userspace:
@@ -263,6 +264,7 @@ Kernel to userspace:
263264
``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY`` PHC virtual clocks info
264265
``ETHTOOL_MSG_MODULE_GET_REPLY`` transceiver module parameters
265266
``ETHTOOL_MSG_PSE_GET_REPLY`` PSE parameters
267+
``ETHTOOL_MSG_RSS_GET_REPLY`` RSS settings
266268
======================================== =================================
267269

268270
``GET`` requests are sent by userspace applications to retrieve device
@@ -1687,6 +1689,33 @@ to control PoDL PSE Admin functions. This option is implementing
16871689
``IEEE 802.3-2018`` 30.15.1.2.1 acPoDLPSEAdminControl. See
16881690
``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` for supported values.
16891691

1692+
RSS_GET
1693+
=======
1694+
1695+
Get indirection table, hash key and hash function info associated with a
1696+
RSS context of an interface similar to ``ETHTOOL_GRSSH`` ioctl request.
1697+
1698+
Request contents:
1699+
1700+
===================================== ====== ==========================
1701+
``ETHTOOL_A_RSS_HEADER`` nested request header
1702+
``ETHTOOL_A_RSS_CONTEXT`` u32 context number
1703+
===================================== ====== ==========================
1704+
1705+
Kernel response contents:
1706+
1707+
===================================== ====== ==========================
1708+
``ETHTOOL_A_RSS_HEADER`` nested reply header
1709+
``ETHTOOL_A_RSS_HFUNC`` u32 RSS hash func
1710+
``ETHTOOL_A_RSS_INDIR`` binary Indir table bytes
1711+
``ETHTOOL_A_RSS_HKEY`` binary Hash key bytes
1712+
===================================== ====== ==========================
1713+
1714+
ETHTOOL_A_RSS_HFUNC attribute is bitmap indicating the hash function
1715+
being used. Current supported options are toeplitz, xor or crc32.
1716+
ETHTOOL_A_RSS_INDIR attribute returns RSS indrection table where each byte
1717+
indicates queue number.
1718+
16901719
Request translation
16911720
===================
16921721

@@ -1768,7 +1797,7 @@ are netlink only.
17681797
``ETHTOOL_GMODULEEEPROM`` ``ETHTOOL_MSG_MODULE_EEPROM_GET``
17691798
``ETHTOOL_GEEE`` ``ETHTOOL_MSG_EEE_GET``
17701799
``ETHTOOL_SEEE`` ``ETHTOOL_MSG_EEE_SET``
1771-
``ETHTOOL_GRSSH`` n/a
1800+
``ETHTOOL_GRSSH`` ``ETHTOOL_MSG_RSS_GET``
17721801
``ETHTOOL_SRSSH`` n/a
17731802
``ETHTOOL_GTUNABLE`` n/a
17741803
``ETHTOOL_STUNABLE`` n/a

include/uapi/linux/ethtool_netlink.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ enum {
5151
ETHTOOL_MSG_MODULE_SET,
5252
ETHTOOL_MSG_PSE_GET,
5353
ETHTOOL_MSG_PSE_SET,
54+
ETHTOOL_MSG_RSS_GET,
5455

5556
/* add new constants above here */
5657
__ETHTOOL_MSG_USER_CNT,
@@ -97,6 +98,7 @@ enum {
9798
ETHTOOL_MSG_MODULE_GET_REPLY,
9899
ETHTOOL_MSG_MODULE_NTF,
99100
ETHTOOL_MSG_PSE_GET_REPLY,
101+
ETHTOOL_MSG_RSS_GET_REPLY,
100102

101103
/* add new constants above here */
102104
__ETHTOOL_MSG_KERNEL_CNT,
@@ -880,6 +882,18 @@ enum {
880882
ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
881883
};
882884

885+
enum {
886+
ETHTOOL_A_RSS_UNSPEC,
887+
ETHTOOL_A_RSS_HEADER,
888+
ETHTOOL_A_RSS_CONTEXT, /* u32 */
889+
ETHTOOL_A_RSS_HFUNC, /* u32 */
890+
ETHTOOL_A_RSS_INDIR, /* binary */
891+
ETHTOOL_A_RSS_HKEY, /* binary */
892+
893+
__ETHTOOL_A_RSS_CNT,
894+
ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1),
895+
};
896+
883897
/* generic netlink info */
884898
#define ETHTOOL_GENL_NAME "ethtool"
885899
#define ETHTOOL_GENL_VERSION 1

net/ethtool/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ obj-y += ioctl.o common.o
44

55
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
66

7-
ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
7+
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 module.o \

net/ethtool/netlink.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
287287
[ETHTOOL_MSG_PHC_VCLOCKS_GET] = &ethnl_phc_vclocks_request_ops,
288288
[ETHTOOL_MSG_MODULE_GET] = &ethnl_module_request_ops,
289289
[ETHTOOL_MSG_PSE_GET] = &ethnl_pse_request_ops,
290+
[ETHTOOL_MSG_RSS_GET] = &ethnl_rss_request_ops,
290291
};
291292

292293
static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1040,6 +1041,12 @@ static const struct genl_ops ethtool_genl_ops[] = {
10401041
.policy = ethnl_pse_set_policy,
10411042
.maxattr = ARRAY_SIZE(ethnl_pse_set_policy) - 1,
10421043
},
1044+
{
1045+
.cmd = ETHTOOL_MSG_RSS_GET,
1046+
.doit = ethnl_default_doit,
1047+
.policy = ethnl_rss_get_policy,
1048+
.maxattr = ARRAY_SIZE(ethnl_rss_get_policy) - 1,
1049+
},
10431050
};
10441051

10451052
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
@@ -346,6 +346,7 @@ extern const struct ethnl_request_ops ethnl_stats_request_ops;
346346
extern const struct ethnl_request_ops ethnl_phc_vclocks_request_ops;
347347
extern const struct ethnl_request_ops ethnl_module_request_ops;
348348
extern const struct ethnl_request_ops ethnl_pse_request_ops;
349+
extern const struct ethnl_request_ops ethnl_rss_request_ops;
349350

350351
extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
351352
extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
@@ -386,6 +387,7 @@ extern const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HEADER +
386387
extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MODE_POLICY + 1];
387388
extern const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER + 1];
388389
extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1];
390+
extern const struct nla_policy ethnl_rss_get_policy[ETHTOOL_A_RSS_CONTEXT + 1];
389391

390392
int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
391393
int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);

net/ethtool/rss.c

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include "netlink.h"
4+
#include "common.h"
5+
6+
struct rss_req_info {
7+
struct ethnl_req_info base;
8+
u32 rss_context;
9+
};
10+
11+
struct rss_reply_data {
12+
struct ethnl_reply_data base;
13+
u32 indir_size;
14+
u32 hkey_size;
15+
u32 hfunc;
16+
u32 *indir_table;
17+
u8 *hkey;
18+
};
19+
20+
#define RSS_REQINFO(__req_base) \
21+
container_of(__req_base, struct rss_req_info, base)
22+
23+
#define RSS_REPDATA(__reply_base) \
24+
container_of(__reply_base, struct rss_reply_data, base)
25+
26+
const struct nla_policy ethnl_rss_get_policy[] = {
27+
[ETHTOOL_A_RSS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
28+
[ETHTOOL_A_RSS_CONTEXT] = { .type = NLA_U32 },
29+
};
30+
31+
static int
32+
rss_parse_request(struct ethnl_req_info *req_info, struct nlattr **tb,
33+
struct netlink_ext_ack *extack)
34+
{
35+
struct rss_req_info *request = RSS_REQINFO(req_info);
36+
37+
if (tb[ETHTOOL_A_RSS_CONTEXT])
38+
request->rss_context = nla_get_u32(tb[ETHTOOL_A_RSS_CONTEXT]);
39+
40+
return 0;
41+
}
42+
43+
static int
44+
rss_prepare_data(const struct ethnl_req_info *req_base,
45+
struct ethnl_reply_data *reply_base, struct genl_info *info)
46+
{
47+
struct rss_reply_data *data = RSS_REPDATA(reply_base);
48+
struct rss_req_info *request = RSS_REQINFO(req_base);
49+
struct net_device *dev = reply_base->dev;
50+
const struct ethtool_ops *ops;
51+
u32 total_size, indir_bytes;
52+
u8 dev_hfunc = 0;
53+
u8 *rss_config;
54+
int ret;
55+
56+
ops = dev->ethtool_ops;
57+
if (!ops->get_rxfh)
58+
return -EOPNOTSUPP;
59+
60+
/* Some drivers don't handle rss_context */
61+
if (request->rss_context && !ops->get_rxfh_context)
62+
return -EOPNOTSUPP;
63+
64+
ret = ethnl_ops_begin(dev);
65+
if (ret < 0)
66+
return ret;
67+
68+
data->indir_size = 0;
69+
data->hkey_size = 0;
70+
if (ops->get_rxfh_indir_size)
71+
data->indir_size = ops->get_rxfh_indir_size(dev);
72+
if (ops->get_rxfh_key_size)
73+
data->hkey_size = ops->get_rxfh_key_size(dev);
74+
75+
indir_bytes = data->indir_size * sizeof(u32);
76+
total_size = indir_bytes + data->hkey_size;
77+
rss_config = kzalloc(total_size, GFP_KERNEL);
78+
if (!rss_config) {
79+
ret = -ENOMEM;
80+
goto out_ops;
81+
}
82+
83+
if (data->indir_size)
84+
data->indir_table = (u32 *)rss_config;
85+
86+
if (data->hkey_size)
87+
data->hkey = rss_config + indir_bytes;
88+
89+
if (request->rss_context)
90+
ret = ops->get_rxfh_context(dev, data->indir_table, data->hkey,
91+
&dev_hfunc, request->rss_context);
92+
else
93+
ret = ops->get_rxfh(dev, data->indir_table, data->hkey,
94+
&dev_hfunc);
95+
96+
if (ret)
97+
goto out_ops;
98+
99+
data->hfunc = dev_hfunc;
100+
out_ops:
101+
ethnl_ops_complete(dev);
102+
return ret;
103+
}
104+
105+
static int
106+
rss_reply_size(const struct ethnl_req_info *req_base,
107+
const struct ethnl_reply_data *reply_base)
108+
{
109+
const struct rss_reply_data *data = RSS_REPDATA(reply_base);
110+
int len;
111+
112+
len = nla_total_size(sizeof(u32)) + /* _RSS_HFUNC */
113+
nla_total_size(sizeof(u32) * data->indir_size) + /* _RSS_INDIR */
114+
nla_total_size(data->hkey_size); /* _RSS_HKEY */
115+
116+
return len;
117+
}
118+
119+
static int
120+
rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base,
121+
const struct ethnl_reply_data *reply_base)
122+
{
123+
const struct rss_reply_data *data = RSS_REPDATA(reply_base);
124+
125+
if (nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc) ||
126+
nla_put(skb, ETHTOOL_A_RSS_INDIR,
127+
sizeof(u32) * data->indir_size, data->indir_table) ||
128+
nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey))
129+
return -EMSGSIZE;
130+
131+
return 0;
132+
}
133+
134+
static void rss_cleanup_data(struct ethnl_reply_data *reply_base)
135+
{
136+
const struct rss_reply_data *data = RSS_REPDATA(reply_base);
137+
138+
kfree(data->indir_table);
139+
}
140+
141+
const struct ethnl_request_ops ethnl_rss_request_ops = {
142+
.request_cmd = ETHTOOL_MSG_RSS_GET,
143+
.reply_cmd = ETHTOOL_MSG_RSS_GET_REPLY,
144+
.hdr_attr = ETHTOOL_A_RSS_HEADER,
145+
.req_info_size = sizeof(struct rss_req_info),
146+
.reply_data_size = sizeof(struct rss_reply_data),
147+
148+
.parse_request = rss_parse_request,
149+
.prepare_data = rss_prepare_data,
150+
.reply_size = rss_reply_size,
151+
.fill_reply = rss_fill_reply,
152+
.cleanup_data = rss_cleanup_data,
153+
};

0 commit comments

Comments
 (0)