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>
next 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