Add a new function to extract the CTRL_ATTR_MAXATTR attribute of the CTRL_CMD_GETFAMILY request. This will be used to allow reading the maximum supported devlink attribute of the running kernel in an upcoming change. Signed-off-by: Jacob Keller <jacob.e.keller@xxxxxxxxx> --- devlink/mnlg.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ devlink/mnlg.h | 1 + 2 files changed, 57 insertions(+) diff --git a/devlink/mnlg.c b/devlink/mnlg.c index e6d92742c150..348c3ff5c959 100644 --- a/devlink/mnlg.c +++ b/devlink/mnlg.c @@ -41,6 +41,10 @@ struct group_info { const char *name; }; +struct family_info { + uint32_t max_attr; +}; + static int parse_mc_grps_cb(const struct nlattr *attr, void *data) { const struct nlattr **tb = data; @@ -149,6 +153,58 @@ int mnlg_socket_group_add(struct mnlu_gen_socket *nlg, const char *group_name) return 0; } +static int get_family_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) + return MNL_CB_ERROR; + + tb[type] = attr; + return MNL_CB_OK; +} + +static int get_family_cb(const struct nlmsghdr *nlh, void *data) +{ + struct family_info *family = data; + struct nlattr *tb[CTRL_ATTR_MAX + 1] = {}; + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + + mnl_attr_parse(nlh, sizeof(*genl), get_family_attr_cb, tb); + if (!tb[CTRL_ATTR_MAXATTR]) + return MNL_CB_ERROR; + + family->max_attr = mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR]); + + return MNL_CB_OK; +} + +int mnlg_socket_get_max_attr(struct mnlu_gen_socket *nlg, uint32_t *max_attr) +{ + struct nlmsghdr *nlh; + struct family_info family; + int err; + + nlh = _mnlu_gen_socket_cmd_prepare(nlg, CTRL_CMD_GETFAMILY, + NLM_F_REQUEST | NLM_F_ACK, + GENL_ID_CTRL, 1); + + mnl_attr_put_u16(nlh, CTRL_ATTR_FAMILY_ID, nlg->family); + + err = mnlg_socket_send(nlg, nlh); + if (err < 0) + return err; + + err = mnlu_gen_socket_recv_run(nlg, get_family_cb, &family); + if (err < 0) + return err; + + *max_attr = family.max_attr; + + return 0; +} + int mnlg_socket_get_fd(struct mnlu_gen_socket *nlg) { return mnl_socket_get_fd(nlg->nl); diff --git a/devlink/mnlg.h b/devlink/mnlg.h index 24aa17566a9b..6348ad45ed26 100644 --- a/devlink/mnlg.h +++ b/devlink/mnlg.h @@ -18,6 +18,7 @@ struct mnlu_gen_socket; int mnlg_socket_send(struct mnlu_gen_socket *nlg, const struct nlmsghdr *nlh); int mnlg_socket_group_add(struct mnlu_gen_socket *nlg, const char *group_name); +int mnlg_socket_get_max_attr(struct mnlu_gen_socket *nlg, uint32_t *max_attr); int mnlg_socket_get_fd(struct mnlu_gen_socket *nlg); #endif /* _MNLG_H_ */ -- 2.35.1.456.ga9c7032d4631