tools: ynl: stop using mnl_cb_run2()

There's only one set of callbacks in YNL, for netlink control
messages, and most of them are trivial. So implement the message
walking directly without depending on mnl_cb_run2().

Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Link: https://lore.kernel.org/r/20240227223032.1835527-11-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2024-02-27 14:30:27 -08:00
parent 1621378aab
commit 766c4b5460
2 changed files with 45 additions and 19 deletions

View file

@ -255,10 +255,10 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
return MNL_CB_OK;
}
static int ynl_cb_error(const struct nlmsghdr *nlh, void *data)
static int
ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
const struct nlmsgerr *err = ynl_nlmsg_data(nlh);
struct ynl_parse_arg *yarg = data;
unsigned int hlen;
int code;
@ -275,9 +275,8 @@ static int ynl_cb_error(const struct nlmsghdr *nlh, void *data)
return code ? MNL_CB_ERROR : MNL_CB_STOP;
}
static int ynl_cb_done(const struct nlmsghdr *nlh, void *data)
static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
struct ynl_parse_arg *yarg = data;
int err;
err = *(int *)NLMSG_DATA(nlh);
@ -292,18 +291,6 @@ static int ynl_cb_done(const struct nlmsghdr *nlh, void *data)
return MNL_CB_STOP;
}
static int ynl_cb_noop(const struct nlmsghdr *nlh, void *data)
{
return MNL_CB_OK;
}
static mnl_cb_t ynl_cb_array[NLMSG_MIN_TYPE] = {
[NLMSG_NOOP] = ynl_cb_noop,
[NLMSG_ERROR] = ynl_cb_error,
[NLMSG_DONE] = ynl_cb_done,
[NLMSG_OVERRUN] = ynl_cb_noop,
};
/* Attribute validation */
int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
@ -475,14 +462,52 @@ static int ynl_cb_null(const struct nlmsghdr *nlh, void *data)
static int ynl_sock_read_msgs(struct ynl_parse_arg *yarg, mnl_cb_t cb)
{
struct ynl_sock *ys = yarg->ys;
ssize_t len;
const struct nlmsghdr *nlh;
ssize_t len, rem;
int ret;
len = mnl_socket_recvfrom(ys->sock, ys->rx_buf, MNL_SOCKET_BUFFER_SIZE);
if (len < 0)
return len;
return mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,
cb, yarg, ynl_cb_array, NLMSG_MIN_TYPE);
ret = MNL_CB_STOP;
for (rem = len; rem > 0; NLMSG_NEXT(nlh, rem)) {
nlh = (struct nlmsghdr *)&ys->rx_buf[len - rem];
if (!NLMSG_OK(nlh, rem)) {
yerr(yarg->ys, YNL_ERROR_INV_RESP,
"Invalid message or trailing data in the response.");
return MNL_CB_ERROR;
}
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
/* TODO: handle this better */
yerr(yarg->ys, YNL_ERROR_DUMP_INTER,
"Dump interrupted / inconsistent, please retry.");
return MNL_CB_ERROR;
}
switch (nlh->nlmsg_type) {
case 0:
yerr(yarg->ys, YNL_ERROR_INV_RESP,
"Invalid message type in the response.");
return MNL_CB_ERROR;
case NLMSG_NOOP:
case NLMSG_OVERRUN ... NLMSG_MIN_TYPE - 1:
ret = MNL_CB_OK;
break;
case NLMSG_ERROR:
ret = ynl_cb_error(nlh, yarg);
break;
case NLMSG_DONE:
ret = ynl_cb_done(nlh, yarg);
break;
default:
ret = cb(nlh, yarg);
break;
}
}
return ret;
}
static int ynl_recv_ack(struct ynl_sock *ys, int ret)

View file

@ -12,6 +12,7 @@ enum ynl_error_code {
YNL_ERROR_NONE = 0,
__YNL_ERRNO_END = 4096,
YNL_ERROR_INTERNAL,
YNL_ERROR_DUMP_INTER,
YNL_ERROR_EXPECT_ACK,
YNL_ERROR_EXPECT_MSG,
YNL_ERROR_UNEXPECT_MSG,