mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
netlink: refactor control data generation for recvmsg(2)
Netlink should return a very simple control data on every recvmsg(2) syscall. This data is associated with a syscall, not with an nlmsg, neither with internal our internal representation (nl_bufs). There is no need to pre-allocate it in non-sleepable context and attach to nl_buf. Allocate right in the syscall with M_WAITOK. This also shaves lots of code and simplifies things. Reviewed by: melifaro Differential Revision: https://reviews.freebsd.org/D42989
This commit is contained in:
parent
7e19c0186f
commit
ff5ad900d2
|
@ -179,15 +179,6 @@ nl_get_groups_compat(struct nlpcb *nlp)
|
|||
return (groups_mask);
|
||||
}
|
||||
|
||||
static void
|
||||
nl_send_one_group(struct nl_writer *nw, struct nl_buf *nb, struct nlpcb *nlp)
|
||||
{
|
||||
if (__predict_false(nlp->nl_flags & NLF_MSG_INFO))
|
||||
nl_add_msg_info(nb);
|
||||
nw->buf = nb;
|
||||
(void)nl_send_one(nw);
|
||||
}
|
||||
|
||||
static struct nl_buf *
|
||||
nl_buf_copy(struct nl_buf *nb)
|
||||
{
|
||||
|
@ -197,13 +188,6 @@ nl_buf_copy(struct nl_buf *nb)
|
|||
if (__predict_false(copy == NULL))
|
||||
return (NULL);
|
||||
memcpy(copy, nb, sizeof(*nb) + nb->buflen);
|
||||
if (nb->control != NULL) {
|
||||
copy->control = m_copym(nb->control, 0, M_COPYALL, M_NOWAIT);
|
||||
if (__predict_false(copy->control == NULL)) {
|
||||
nl_buf_free(copy);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (copy);
|
||||
}
|
||||
|
@ -248,7 +232,8 @@ nl_send_group(struct nl_writer *nw)
|
|||
|
||||
copy = nl_buf_copy(nb);
|
||||
if (copy != NULL) {
|
||||
nl_send_one_group(nw, copy, nlp_last);
|
||||
nw->buf = copy;
|
||||
(void)nl_send_one(nw);
|
||||
} else {
|
||||
NLP_LOCK(nlp_last);
|
||||
if (nlp_last->nl_socket != NULL)
|
||||
|
@ -259,9 +244,10 @@ nl_send_group(struct nl_writer *nw)
|
|||
nlp_last = nlp;
|
||||
}
|
||||
}
|
||||
if (nlp_last != NULL)
|
||||
nl_send_one_group(nw, nb, nlp_last);
|
||||
else
|
||||
if (nlp_last != NULL) {
|
||||
nw->buf = nb;
|
||||
(void)nl_send_one(nw);
|
||||
} else
|
||||
nl_buf_free(nb);
|
||||
|
||||
NLCTL_RUNLOCK(ctl);
|
||||
|
@ -657,6 +643,30 @@ nl_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
|
|||
return (error);
|
||||
}
|
||||
|
||||
/* Create control data for recvmsg(2) on Netlink socket. */
|
||||
static struct mbuf *
|
||||
nl_createcontrol(struct nlpcb *nlp)
|
||||
{
|
||||
struct {
|
||||
struct nlattr nla;
|
||||
uint32_t val;
|
||||
} data[] = {
|
||||
{
|
||||
.nla.nla_len = sizeof(struct nlattr) + sizeof(uint32_t),
|
||||
.nla.nla_type = NLMSGINFO_ATTR_PROCESS_ID,
|
||||
.val = nlp->nl_process_id,
|
||||
},
|
||||
{
|
||||
.nla.nla_len = sizeof(struct nlattr) + sizeof(uint32_t),
|
||||
.nla.nla_type = NLMSGINFO_ATTR_PORT_ID,
|
||||
.val = nlp->nl_port,
|
||||
},
|
||||
};
|
||||
|
||||
return (sbcreatecontrol(data, sizeof(data), NETLINK_MSG_INFO,
|
||||
SOL_NETLINK, M_WAITOK));
|
||||
}
|
||||
|
||||
static int
|
||||
nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
|
||||
struct mbuf **mp, struct mbuf **controlp, int *flagsp)
|
||||
|
@ -667,6 +677,7 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
|
|||
.nl_pid = 0 /* comes from the kernel */
|
||||
};
|
||||
struct sockbuf *sb = &so->so_rcv;
|
||||
struct nlpcb *nlp = sotonlpcb(so);
|
||||
struct nl_buf *first, *last, *nb, *next;
|
||||
struct nlmsghdr *hdr;
|
||||
int flags, error;
|
||||
|
@ -681,6 +692,9 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
|
|||
*psa = sodupsockaddr((const struct sockaddr *)&nl_empty_src,
|
||||
M_WAITOK);
|
||||
|
||||
if (controlp != NULL && (nlp->nl_flags & NLF_MSG_INFO))
|
||||
*controlp = nl_createcontrol(nlp);
|
||||
|
||||
flags = flagsp != NULL ? *flagsp & ~MSG_TRUNC : 0;
|
||||
trunc = flagsp != NULL ? *flagsp & MSG_TRUNC : false;
|
||||
nonblock = (so->so_state & SS_NBIO) ||
|
||||
|
@ -691,9 +705,6 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
|
|||
if (__predict_false(error))
|
||||
return (error);
|
||||
|
||||
if (controlp != NULL)
|
||||
*controlp = NULL;
|
||||
|
||||
len = 0;
|
||||
overflow = 0;
|
||||
msgrcv = 0;
|
||||
|
@ -798,13 +809,6 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
|
|||
|
||||
for (nb = first; nb != last; nb = next) {
|
||||
next = TAILQ_NEXT(nb, tailq);
|
||||
|
||||
/* XXXGL multiple controls??? */
|
||||
if (controlp != NULL && *controlp == NULL &&
|
||||
nb->control != NULL && !peek) {
|
||||
*controlp = nb->control;
|
||||
nb->control = NULL;
|
||||
}
|
||||
if (__predict_true(error == 0))
|
||||
error = uiomove(&nb->data[nb->offset],
|
||||
(int)(nb->datalen - nb->offset), uio);
|
||||
|
|
|
@ -62,7 +62,6 @@ nl_buf_alloc(size_t len, int mflag)
|
|||
if (__predict_true(nb != NULL)) {
|
||||
nb->buflen = len;
|
||||
nb->datalen = nb->offset = 0;
|
||||
nb->control = NULL;
|
||||
}
|
||||
|
||||
return (nb);
|
||||
|
@ -72,51 +71,9 @@ void
|
|||
nl_buf_free(struct nl_buf *nb)
|
||||
{
|
||||
|
||||
if (nb->control)
|
||||
m_freem(nb->control);
|
||||
free(nb, M_NETLINK);
|
||||
}
|
||||
|
||||
void
|
||||
nl_add_msg_info(struct nl_buf *nb)
|
||||
{
|
||||
/* XXXGL pass nlp as arg? */
|
||||
struct nlpcb *nlp = nl_get_thread_nlp(curthread);
|
||||
NL_LOG(LOG_DEBUG2, "Trying to recover nlp from thread %p: %p",
|
||||
curthread, nlp);
|
||||
|
||||
if (nlp == NULL)
|
||||
return;
|
||||
|
||||
/* Prepare what we want to encode - PID, socket PID & msg seq */
|
||||
struct {
|
||||
struct nlattr nla;
|
||||
uint32_t val;
|
||||
} data[] = {
|
||||
{
|
||||
.nla.nla_len = sizeof(struct nlattr) + sizeof(uint32_t),
|
||||
.nla.nla_type = NLMSGINFO_ATTR_PROCESS_ID,
|
||||
.val = nlp->nl_process_id,
|
||||
},
|
||||
{
|
||||
.nla.nla_len = sizeof(struct nlattr) + sizeof(uint32_t),
|
||||
.nla.nla_type = NLMSGINFO_ATTR_PORT_ID,
|
||||
.val = nlp->nl_port,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
nb->control = sbcreatecontrol(data, sizeof(data),
|
||||
NETLINK_MSG_INFO, SOL_NETLINK, M_NOWAIT);
|
||||
|
||||
if (__predict_true(nb->control != NULL))
|
||||
NL_LOG(LOG_DEBUG2, "Storing %u bytes of control data, ctl: %p",
|
||||
(unsigned)sizeof(data), nb->control);
|
||||
else
|
||||
NL_LOG(LOG_DEBUG2, "Failed to allocate %u bytes of control",
|
||||
(unsigned)sizeof(data));
|
||||
}
|
||||
|
||||
void
|
||||
nl_schedule_taskqueue(struct nlpcb *nlp)
|
||||
{
|
||||
|
|
|
@ -45,7 +45,6 @@ struct ucred;
|
|||
|
||||
struct nl_buf {
|
||||
TAILQ_ENTRY(nl_buf) tailq;
|
||||
struct mbuf *control;
|
||||
u_int buflen;
|
||||
u_int datalen;
|
||||
u_int offset;
|
||||
|
@ -142,7 +141,6 @@ void nl_taskqueue_handler(void *_arg, int pending);
|
|||
void nl_schedule_taskqueue(struct nlpcb *nlp);
|
||||
void nl_process_receive_locked(struct nlpcb *nlp);
|
||||
void nl_set_source_metadata(struct mbuf *m, int num_messages);
|
||||
void nl_add_msg_info(struct nl_buf *nb);
|
||||
struct nl_buf *nl_buf_alloc(size_t len, int mflag);
|
||||
void nl_buf_free(struct nl_buf *nb);
|
||||
|
||||
|
|
Loading…
Reference in a new issue