git: ff5ad900d2a0 - main - netlink: refactor control data generation for recvmsg(2)

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Tue, 02 Jan 2024 21:07:00 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=ff5ad900d2a0793659241eee96be53e6053b5081

commit ff5ad900d2a0793659241eee96be53e6053b5081
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-01-02 21:05:46 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-01-02 21:05:46 +0000

    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
---
 sys/netlink/netlink_domain.c | 64 +++++++++++++++++++++++---------------------
 sys/netlink/netlink_io.c     | 43 -----------------------------
 sys/netlink/netlink_var.h    |  2 --
 3 files changed, 34 insertions(+), 75 deletions(-)

diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index 94d8377b9e15..cc7018ed2582 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -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 @@ out:
 	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 @@ nospace:
 
 	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);
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
index 56e430cdcfa8..fb8e0a46e8dd 100644
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -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)
 {
diff --git a/sys/netlink/netlink_var.h b/sys/netlink/netlink_var.h
index 97532c31e54b..c8f0d02a0dab 100644
--- a/sys/netlink/netlink_var.h
+++ b/sys/netlink/netlink_var.h
@@ -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);