lib: Extract from devlink/mnlg a helper, mnlu_socket_recv_run()
Receiving a message in libmnl is a somewhat involved operation. Devlink's mnlg library has an implementation that is going to be handy for other tools as well. Extract it into a new helper. Signed-off-by: Petr Machata <me@pmachata.org> Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
parent
dd78dfc7be
commit
6dd778e837
|
|
@ -28,7 +28,6 @@ struct mnlg_socket {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
unsigned int portid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
||||||
|
|
@ -57,61 +56,10 @@ int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
|
||||||
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
|
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data)
|
|
||||||
{
|
|
||||||
return MNL_CB_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data)
|
|
||||||
{
|
|
||||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
|
||||||
|
|
||||||
/* Netlink subsystems returns the errno value with different signess */
|
|
||||||
if (err->error < 0)
|
|
||||||
errno = -err->error;
|
|
||||||
else
|
|
||||||
errno = err->error;
|
|
||||||
|
|
||||||
if (nl_dump_ext_ack(nlh, NULL))
|
|
||||||
return MNL_CB_ERROR;
|
|
||||||
|
|
||||||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data)
|
|
||||||
{
|
|
||||||
int len = *(int *)NLMSG_DATA(nlh);
|
|
||||||
|
|
||||||
if (len < 0) {
|
|
||||||
errno = -len;
|
|
||||||
nl_dump_ext_ack_done(nlh, len);
|
|
||||||
return MNL_CB_ERROR;
|
|
||||||
}
|
|
||||||
return MNL_CB_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static mnl_cb_t mnlg_cb_array[NLMSG_MIN_TYPE] = {
|
|
||||||
[NLMSG_NOOP] = mnlg_cb_noop,
|
|
||||||
[NLMSG_ERROR] = mnlg_cb_error,
|
|
||||||
[NLMSG_DONE] = mnlg_cb_stop,
|
|
||||||
[NLMSG_OVERRUN] = mnlg_cb_noop,
|
|
||||||
};
|
|
||||||
|
|
||||||
int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
|
int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
|
||||||
{
|
{
|
||||||
int err;
|
return mnlu_socket_recv_run(nlg->nl, nlg->seq, nlg->buf, MNL_SOCKET_BUFFER_SIZE,
|
||||||
|
data_cb, data);
|
||||||
do {
|
|
||||||
err = mnl_socket_recvfrom(nlg->nl, nlg->buf,
|
|
||||||
MNL_SOCKET_BUFFER_SIZE);
|
|
||||||
if (err <= 0)
|
|
||||||
break;
|
|
||||||
err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid,
|
|
||||||
data_cb, data, mnlg_cb_array,
|
|
||||||
ARRAY_SIZE(mnlg_cb_array));
|
|
||||||
} while (err > 0);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct group_info {
|
struct group_info {
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,7 @@
|
||||||
struct mnl_socket *mnlu_socket_open(int bus);
|
struct mnl_socket *mnlu_socket_open(int bus);
|
||||||
struct nlmsghdr *mnlu_msg_prepare(void *buf, uint32_t nlmsg_type, uint16_t flags,
|
struct nlmsghdr *mnlu_msg_prepare(void *buf, uint32_t nlmsg_type, uint16_t flags,
|
||||||
void *extra_header, size_t extra_header_size);
|
void *extra_header, size_t extra_header_size);
|
||||||
|
int mnlu_socket_recv_run(struct mnl_socket *nl, unsigned int seq, void *buf, size_t buf_size,
|
||||||
|
mnl_cb_t cb, void *data);
|
||||||
|
|
||||||
#endif /* __MNL_UTILS_H__ */
|
#endif /* __MNL_UTILS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,14 @@
|
||||||
* mnl_utils.c Helpers for working with libmnl.
|
* mnl_utils.c Helpers for working with libmnl.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <libmnl/libmnl.h>
|
#include <libmnl/libmnl.h>
|
||||||
|
|
||||||
|
#include "libnetlink.h"
|
||||||
#include "mnl_utils.h"
|
#include "mnl_utils.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
struct mnl_socket *mnlu_socket_open(int bus)
|
struct mnl_socket *mnlu_socket_open(int bus)
|
||||||
{
|
{
|
||||||
|
|
@ -47,3 +50,61 @@ struct nlmsghdr *mnlu_msg_prepare(void *buf, uint32_t nlmsg_type, uint16_t flags
|
||||||
|
|
||||||
return nlh;
|
return nlh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mnlu_cb_noop(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mnlu_cb_error(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
/* Netlink subsystems returns the errno value with different signess */
|
||||||
|
if (err->error < 0)
|
||||||
|
errno = -err->error;
|
||||||
|
else
|
||||||
|
errno = err->error;
|
||||||
|
|
||||||
|
if (nl_dump_ext_ack(nlh, NULL))
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
|
||||||
|
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mnlu_cb_stop(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
int len = *(int *)NLMSG_DATA(nlh);
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
errno = -len;
|
||||||
|
nl_dump_ext_ack_done(nlh, len);
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
return MNL_CB_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mnl_cb_t mnlu_cb_array[NLMSG_MIN_TYPE] = {
|
||||||
|
[NLMSG_NOOP] = mnlu_cb_noop,
|
||||||
|
[NLMSG_ERROR] = mnlu_cb_error,
|
||||||
|
[NLMSG_DONE] = mnlu_cb_stop,
|
||||||
|
[NLMSG_OVERRUN] = mnlu_cb_noop,
|
||||||
|
};
|
||||||
|
|
||||||
|
int mnlu_socket_recv_run(struct mnl_socket *nl, unsigned int seq, void *buf, size_t buf_size,
|
||||||
|
mnl_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
unsigned int portid = mnl_socket_get_portid(nl);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
do {
|
||||||
|
err = mnl_socket_recvfrom(nl, buf, buf_size);
|
||||||
|
if (err <= 0)
|
||||||
|
break;
|
||||||
|
err = mnl_cb_run2(buf, err, seq, portid,
|
||||||
|
cb, data, mnlu_cb_array,
|
||||||
|
ARRAY_SIZE(mnlu_cb_array));
|
||||||
|
} while (err > 0);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue