Skip to content

Commit f9cf228

Browse files
Jakub Kicinskidavem330
authored andcommitted
devlink: add device information API
ethtool -i has served us well for a long time, but its showing its limitations more and more. The device information should also be reported per device not per-netdev. Lay foundation for a simple devlink-based way of reading device info. Add driver name and device serial number as initial pieces of information exposed via this new API. v3: - rename helpers (Jiri); - rename driver name attr (Jiri); - remove double spacing in commit message (Jiri). RFC v2: - wrap the skb into an opaque structure (Jiri); - allow the serial number of be any length (Jiri & Andrew); - add driver name (Jonathan). Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 26281e2 commit f9cf228

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

include/net/devlink.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ enum devlink_param_wol_types {
429429
}
430430

431431
struct devlink_region;
432+
struct devlink_info_req;
432433

433434
typedef void devlink_snapshot_data_dest_t(const void *data);
434435

@@ -484,6 +485,8 @@ struct devlink_ops {
484485
int (*eswitch_encap_mode_get)(struct devlink *devlink, u8 *p_encap_mode);
485486
int (*eswitch_encap_mode_set)(struct devlink *devlink, u8 encap_mode,
486487
struct netlink_ext_ack *extack);
488+
int (*info_get)(struct devlink *devlink, struct devlink_info_req *req,
489+
struct netlink_ext_ack *extack);
487490
};
488491

489492
static inline void *devlink_priv(struct devlink *devlink)
@@ -607,6 +610,10 @@ u32 devlink_region_shapshot_id_get(struct devlink *devlink);
607610
int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
608611
u8 *data, u32 snapshot_id,
609612
devlink_snapshot_data_dest_t *data_destructor);
613+
int devlink_info_serial_number_put(struct devlink_info_req *req,
614+
const char *sn);
615+
int devlink_info_driver_name_put(struct devlink_info_req *req,
616+
const char *name);
610617

611618
#else
612619

@@ -905,6 +912,17 @@ devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
905912
return 0;
906913
}
907914

915+
static inline int
916+
devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
917+
{
918+
return 0;
919+
}
920+
921+
static inline int
922+
devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
923+
{
924+
return 0;
925+
}
908926
#endif
909927

910928
#endif /* _NET_DEVLINK_H_ */

include/uapi/linux/devlink.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ enum devlink_command {
9494
DEVLINK_CMD_PORT_PARAM_NEW,
9595
DEVLINK_CMD_PORT_PARAM_DEL,
9696

97+
DEVLINK_CMD_INFO_GET, /* can dump */
98+
9799
/* add new commands above here */
98100
__DEVLINK_CMD_MAX,
99101
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
@@ -290,6 +292,9 @@ enum devlink_attr {
290292
DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */
291293
DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */
292294

295+
DEVLINK_ATTR_INFO_DRIVER_NAME, /* string */
296+
DEVLINK_ATTR_INFO_SERIAL_NUMBER, /* string */
297+
293298
/* add new attributes above here, update the policy in devlink.c */
294299

295300
__DEVLINK_ATTR_MAX,

net/core/devlink.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,6 +3714,110 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
37143714
return 0;
37153715
}
37163716

3717+
struct devlink_info_req {
3718+
struct sk_buff *msg;
3719+
};
3720+
3721+
int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
3722+
{
3723+
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
3724+
}
3725+
EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
3726+
3727+
int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
3728+
{
3729+
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
3730+
}
3731+
EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
3732+
3733+
static int
3734+
devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
3735+
enum devlink_command cmd, u32 portid,
3736+
u32 seq, int flags, struct netlink_ext_ack *extack)
3737+
{
3738+
struct devlink_info_req req;
3739+
void *hdr;
3740+
int err;
3741+
3742+
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3743+
if (!hdr)
3744+
return -EMSGSIZE;
3745+
3746+
err = -EMSGSIZE;
3747+
if (devlink_nl_put_handle(msg, devlink))
3748+
goto err_cancel_msg;
3749+
3750+
req.msg = msg;
3751+
err = devlink->ops->info_get(devlink, &req, extack);
3752+
if (err)
3753+
goto err_cancel_msg;
3754+
3755+
genlmsg_end(msg, hdr);
3756+
return 0;
3757+
3758+
err_cancel_msg:
3759+
genlmsg_cancel(msg, hdr);
3760+
return err;
3761+
}
3762+
3763+
static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
3764+
struct genl_info *info)
3765+
{
3766+
struct devlink *devlink = info->user_ptr[0];
3767+
struct sk_buff *msg;
3768+
int err;
3769+
3770+
if (!devlink->ops || !devlink->ops->info_get)
3771+
return -EOPNOTSUPP;
3772+
3773+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3774+
if (!msg)
3775+
return -ENOMEM;
3776+
3777+
err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
3778+
info->snd_portid, info->snd_seq, 0,
3779+
info->extack);
3780+
if (err) {
3781+
nlmsg_free(msg);
3782+
return err;
3783+
}
3784+
3785+
return genlmsg_reply(msg, info);
3786+
}
3787+
3788+
static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
3789+
struct netlink_callback *cb)
3790+
{
3791+
struct devlink *devlink;
3792+
int start = cb->args[0];
3793+
int idx = 0;
3794+
int err;
3795+
3796+
mutex_lock(&devlink_mutex);
3797+
list_for_each_entry(devlink, &devlink_list, list) {
3798+
if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3799+
continue;
3800+
if (idx < start) {
3801+
idx++;
3802+
continue;
3803+
}
3804+
3805+
mutex_lock(&devlink->lock);
3806+
err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
3807+
NETLINK_CB(cb->skb).portid,
3808+
cb->nlh->nlmsg_seq, NLM_F_MULTI,
3809+
cb->extack);
3810+
mutex_unlock(&devlink->lock);
3811+
if (err)
3812+
break;
3813+
idx++;
3814+
}
3815+
mutex_unlock(&devlink_mutex);
3816+
3817+
cb->args[0] = idx;
3818+
return msg->len;
3819+
}
3820+
37173821
static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
37183822
[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
37193823
[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
@@ -3974,6 +4078,14 @@ static const struct genl_ops devlink_nl_ops[] = {
39744078
.flags = GENL_ADMIN_PERM,
39754079
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
39764080
},
4081+
{
4082+
.cmd = DEVLINK_CMD_INFO_GET,
4083+
.doit = devlink_nl_cmd_info_get_doit,
4084+
.dumpit = devlink_nl_cmd_info_get_dumpit,
4085+
.policy = devlink_nl_policy,
4086+
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
4087+
/* can be retrieved by unprivileged users */
4088+
},
39774089
};
39784090

39794091
static struct genl_family devlink_nl_family __ro_after_init = {

0 commit comments

Comments
 (0)