public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Jeremy Kerr <jk@codeconstruct.com.au>
To: Matt Johnston <matt@codeconstruct.com.au>,
	 "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	 Jakub Kicinski <kuba@kernel.org>,
	Paolo Abeni <pabeni@redhat.com>,  Simon Horman <horms@kernel.org>
Cc: netdev@vger.kernel.org, yuanzhaoming <yuanzm2@lenovo.com>
Subject: [PATCH net-next] net: mctp: avoid copy in fragmentation loop for near-MTU messages
Date: Tue, 24 Mar 2026 15:19:56 +0800	[thread overview]
Message-ID: <20260324-dev-mtu-copy-v1-1-7af6bd7027d3@codeconstruct.com.au> (raw)

Currently, we incorrectly send messages that are within 4 bytes (a
struct mctp_hdr) smaller than the MTU through mctp_do_fragment_route().
This has no effect on the actual fragmentation, as we will still send as
one packet, but unnecessarily copies the original skb into a new
single-fragment skb.

Instead of having the MTU comparisons in both mctp_local_output() and
mctp_do_fragment_route(), feed all local messages through the latter,
and add the single-packet optimisation there.

This means we can coalesce the routing path of mctp_local_output, so our
out_release path is now solely for errors, so rename the label
accordingly.

Include a check in the route tests for the single-packet case too.

Reported-by: yuanzhaoming <yuanzm2@lenovo.com>
Closes: https://github.com/openbmc/linux/commit/269936db5eb3962fe290b1dc4dbf1859cd5a04dd#r175836230
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/mctp/route.c           | 26 +++++++++++---------------
 net/mctp/test/route-test.c |  4 ++++
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/net/mctp/route.c b/net/mctp/route.c
index 59ad60b885631c4de4f859284bc8c0f71201f8f8..021e04f1ea7c950af4c4e21d7afbc8c98d093186 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -1037,6 +1037,13 @@ static int mctp_do_fragment_route(struct mctp_dst *dst, struct sk_buff *skb,
 		return -EMSGSIZE;
 	}
 
+	/* within MTU? avoid the copy, send original skb */
+	if (skb->len <= mtu) {
+		hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM |
+			MCTP_HDR_FLAG_EOM | tag;
+		return dst->output(dst, skb);
+	}
+
 	/* keep same headroom as the original skb */
 	headroom = skb_headroom(skb);
 
@@ -1111,7 +1118,6 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 	struct mctp_hdr *hdr;
 	unsigned long flags;
 	unsigned int netid;
-	unsigned int mtu;
 	mctp_eid_t saddr;
 	int rc;
 	u8 tag;
@@ -1133,7 +1139,7 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 	netid = READ_ONCE(dst->dev->net);
 
 	if (rc)
-		goto out_release;
+		goto err_free;
 
 	if (req_tag & MCTP_TAG_OWNER) {
 		if (req_tag & MCTP_TAG_PREALLOC)
@@ -1145,7 +1151,7 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 
 		if (IS_ERR(key)) {
 			rc = PTR_ERR(key);
-			goto out_release;
+			goto err_free;
 		}
 		mctp_skb_set_flow(skb, key);
 		/* done with the key in this scope */
@@ -1170,20 +1176,10 @@ int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
 	hdr->dest = daddr;
 	hdr->src = saddr;
 
-	mtu = dst->mtu;
-
-	if (skb->len + sizeof(struct mctp_hdr) <= mtu) {
-		hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM |
-			MCTP_HDR_FLAG_EOM | tag;
-		rc = dst->output(dst, skb);
-	} else {
-		rc = mctp_do_fragment_route(dst, skb, mtu, tag);
-	}
-
 	/* route output functions consume the skb, even on error */
-	skb = NULL;
+	return mctp_do_fragment_route(dst, skb, dst->mtu, tag);
 
-out_release:
+err_free:
 	kfree_skb(skb);
 	return rc;
 }
diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index 75ea96c10e497e73b55e20a30934679b7e24fdeb..61c989c43ec09c9e105de4e51b295d07bb93d6da 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -63,6 +63,10 @@ static void mctp_test_fragment(struct kunit *test)
 		if (!skb2)
 			break;
 
+		/* avoid copying single-skb messages */
+		if (first && last)
+			KUNIT_EXPECT_PTR_EQ(test, skb, skb2);
+
 		hdr2 = mctp_hdr(skb2);
 
 		tag_mask = MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO;

---
base-commit: 2d1373e4246da3b58e1df058374ed6b101804e07
change-id: 20260324-dev-mtu-copy-0515711235ee

Best regards,
-- 
Jeremy Kerr <jk@codeconstruct.com.au>


             reply	other threads:[~2026-03-24  7:20 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-24  7:19 Jeremy Kerr [this message]
2026-03-25 17:50 ` [PATCH net-next] net: mctp: avoid copy in fragmentation loop for near-MTU messages Simon Horman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260324-dev-mtu-copy-v1-1-7af6bd7027d3@codeconstruct.com.au \
    --to=jk@codeconstruct.com.au \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=matt@codeconstruct.com.au \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=yuanzm2@lenovo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox