git: f75d7fac109b - main - netlink: avoid putting empty mbufs on the socket queue

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Thu, 11 Jan 2024 04:52:13 UTC
The branch main has been updated by glebius:

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

commit f75d7fac109bf8e322b07456c5361ee62f5635c2
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-01-11 04:51:53 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-01-11 04:51:53 +0000

    netlink: avoid putting empty mbufs on the socket queue
    
    When processing incoming Netlink messages in nl_process_nbuf() kernel
    always allocates a writer with a buffer to put generated reply to.
    However, certain messages aren't replied.  That makes nlmsg_flush()
    to put an empty buffer to the socket.  Avoid doing that because avoiding
    is much easier than dealing with empty buffers on the receiver side.
---
 sys/netlink/netlink_domain.c         |  7 +------
 sys/netlink/netlink_io.c             |  2 ++
 sys/netlink/netlink_message_writer.c | 11 +++++++++--
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index 94989af73dfe..7ecafbf99d26 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -740,12 +740,7 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
 	TAILQ_FOREACH(nb, &sb->nl_queue, tailq) {
 		u_int offset;
 
-		/*
-		 * XXXGL: zero length buffer may be at the tail of a queue
-		 * when a writer overflows socket buffer.  When this is
-		 * improved, use MPASS(nb->offset < nb->datalen).
-		 */
-		MPASS(nb->offset <= nb->datalen);
+		MPASS(nb->offset < nb->datalen);
 		offset = nb->offset;
 		while (offset < nb->datalen) {
 			hdr = (struct nlmsghdr *)&nb->data[offset];
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
index 5f50c40f71d8..61d9d657556a 100644
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -201,6 +201,8 @@ nl_send(struct nl_writer *nw, struct nlpcb *nlp)
 	struct nl_buf *nb;
 
 	MPASS(nw->hdr == NULL);
+	MPASS(nw->buf != NULL);
+	MPASS(nw->buf->datalen > 0);
 
 	IF_DEBUG_LEVEL(LOG_DEBUG2) {
 		struct nlmsghdr *hdr = (struct nlmsghdr *)nw->buf->data;
diff --git a/sys/netlink/netlink_message_writer.c b/sys/netlink/netlink_message_writer.c
index 50305e3d9d80..59bc6aabaa3f 100644
--- a/sys/netlink/netlink_message_writer.c
+++ b/sys/netlink/netlink_message_writer.c
@@ -100,6 +100,7 @@ _nlmsg_ignore_limit(struct nl_writer *nw)
 bool
 _nlmsg_flush(struct nl_writer *nw)
 {
+	bool result;
 
 	if (__predict_false(nw->hdr != NULL)) {
 		/* Last message has not been completed, skip it. */
@@ -109,8 +110,14 @@ _nlmsg_flush(struct nl_writer *nw)
 		nw->hdr = NULL;
         }
 
-	NL_LOG(LOG_DEBUG2, "OUT");
-	bool result = nw->cb(nw);
+	if (nw->buf->datalen == 0) {
+		MPASS(nw->num_messages == 0);
+		nl_buf_free(nw->buf);
+		nw->buf = NULL;
+		return (true);
+	}
+
+	result = nw->cb(nw);
 	nw->num_messages = 0;
 
 	if (!result) {