All of lore.kernel.org
 help / color / mirror / Atom feed
From: xiaoshoukui@gmail.com
To: tung.quang.nguyen@est.tech
Cc: edumazet@google.com, jmaloy@redhat.com, netdev@vger.kernel.org,
	w@1wt.eu, tung.quang.nguyen@dektech.com.au,
	xiaoshoukui@ruijie.com.cn
Subject: Re: [PATCH net] tipc: fix memory leaks in bundle and fragment paths
Date: Fri, 25 Sep 2026 13:43:41 +0000	[thread overview]
Message-ID: <20260925134341.11418-1-xiaoshoukui@gmail.com> (raw)
In-Reply-To: <DU4P189MB37506A937448D1ED977C7BFCC6842@DU4P189MB3750.EURP189.PROD.OUTLOOK.COM>

Hi Tung,

Thanks for bringing this performance concern to our attention and
sharing your benchmark results.

> This patch tries to address an unreal use case. I am waiting for
> your real reproducer and explanation on how data part of bundling
> and fragmented messages can contain invalid types/users.
> Of course, tipc_data_input() drops invalid types/users as designed.
> The check is redundant because tipc_data_input() never returns false
> after calling tipc_msg_extract() or tipc_buf_append().
> This is not correct. If tipc_data_input() returns false, the skb
> will be dropped.
> tipc_data_input() releases invalid skbs as expected.

Your observation regarding truly illegal message users is correct. In
the default case, tipc_data_input() drops the skb with kfree_skb() and
returns true. However, this issue concerns the recognized internal
control users. For these users, tipc_data_input() returns false without
freeing the skb:

static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
			    struct sk_buff_head *inputq)
{
	...
	switch (msg_user(hdr)) {
	case TIPC_LOW_IMPORTANCE:
	...
	case NAME_DISTRIBUTOR:
		...
		return true;
	case MSG_BUNDLER:
	case TUNNEL_PROTOCOL:
	case MSG_FRAGMENTER:
	case BCAST_PROTOCOL:
		return false; /* <--- Returns false WITHOUT kfree_skb() */
	...
	default:
		pr_warn("Dropping received illegal msg type\n");
		kfree_skb(skb);
		return true;
	}
}

The two receive paths where this occurs are:

1. Nested Bundle Path
   crafted packet
     -> outer msg_user = MSG_BUNDLER
     -> payload contains a structurally valid inner MSG_BUNDLER
     -> tipc_msg_extract() allocates and extracts the inner skb
     -> tipc_data_input() sees MSG_BUNDLER and returns false
        without consuming the skb
     -> the bundle extraction loop ignores the return value
     -> the extracted inner skb is leaked

2. Fragment Reassembly Path
   crafted fragment sequence
     -> reassembly completes in tipc_buf_append()
     -> the complete reassembled skb has msg_user = MSG_FRAGMENTER
     -> tipc_data_input() sees MSG_FRAGMENTER and returns false
        without consuming the skb
     -> the fragment completion path ignores the return value
     -> the reassembled skb is leaked

The reproducer source code and instructions have been sent to you
separately.


> Note that we do not want to add check for unreal cases because it
> causes performance regression.
> I tested your patch and it showed regression as below:
...

Regarding the reported performance regression, We conducted two
investigations: an assembly-level analysis of the hot path,
and a clean-environment performance benchmark with strict
CPU affinity.

1. Assembly & Hot-Path Analysis
--------------------------------
We compared the generated disassembly of baseline, patched, and
unlikely()-annotated builds using identical compiler toolchains and
optimization flags.

For the bundled-message receive path:

Baseline:
	call	tipc_data_input
	...
	call	tipc_msg_extract
	test	%al, %al
	jne	<next_extracted_message>

Patched:
	call	tipc_data_input
	test	%al, %al
	je	<drop_reason_path>
	...
	call	tipc_msg_extract
	test	%al, %al
	jne	<next_extracted_message>

The disassembly confirms that adding a single `test` + conditional
branch on a register cannot account for a 10%--15% throughput drop.

Adding unlikely() shifts the basic-block layout and branch direction
as expected:

	call	tipc_data_input
	test	%al, %al
	jne	<next_extracted_message>

Nevertheless, using unlikely() makes the exceptional path explicit,
improves readability, and is consistent with kernel coding
conventions. The fragment-reassembly path is similar.

2. Benchmark Methodology & Results
----------------------------------
We re-evaluated the patch series in a high-throughput, CPU-isolated
network namespace environment (`netns` + `veth`) to eliminate
external hardware I/O bottlenecks and measure pure kernel hot-path
overhead.

To eliminate thread contention and CPU migration jitter---which
previously caused bimodal performance drops (fluctuating between
~32 Gbps and ~48 Gbps when threads floated across cores)---we strictly
isolated CPU cores via taskset:
  - Client side (netperf): Pinned to CPU 0 and CPU 1
  - Server side (netserver): Pinned to CPU 2 and CPU 3
    (taskset -c 2,3)

Under identical hardware and isolation conditions, we ran 10-iteration
benchmarks comparing unpatched vs. patched kernels with NAGLE disabled.

The average throughput was:
+----------------+----------------+---------------+------------------+
| Message Size   | Unpatched      | Patched       | Delta (%)        |
+----------------+----------------+---------------+------------------+
| 64B (Small)    | 69.80 Mbps     | 68.58 Mbps    | -1.22M (-1.75%)  |
| 65,536B (Large)| 46,992.62 Mbps | 45,834.77 Mbps| -1.16G (-2.46%)  |
+----------------+----------------+---------------+------------------+

The results show NO statistically significant performance regression
(< 2.5% variation, falling entirely within standard measurement noise
and thermal throttling).


3. Explanation for the Previously Reported Degradation
------------------------------------------------------
During troubleshooting, we observed that if `netserver` (or softirq
handling) is not pinned to dedicated cores separate from `netperf`,
the Linux CFS scheduler frequently migrates `netserver` worker threads
onto the core running `netperf`.

When client and server threads contend for the same core, cache
bouncing and time-slice preemption can reduce throughput by 25%--30%
in 40Gbps+ testing.

To help align our benchmark methodologies, could you share a few
details about your test setup?
- The exact netperf repository version/commit used;
- Whether `netserver` and softirq handling were CPU-pinned;
- Whether node1 and node2 were physical hosts or virtual machines;
- NIC / link speed and CPU model;
- The exact method used to disable TIPC Nagle.

Thanks,
Xiaoshoukui

      reply	other threads:[~2026-09-25 13:45 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16  6:12 [PATCH net] tipc: fix memory leaks in bundle and fragment paths xiaoshoukui
2026-09-17  3:51 ` Tung Quang Nguyen
2026-09-21  3:47   ` xiaoshoukui
2026-09-21  9:28     ` Tung Quang Nguyen
2026-09-25 13:43       ` xiaoshoukui [this message]

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=20260925134341.11418-1-xiaoshoukui@gmail.com \
    --to=xiaoshoukui@gmail.com \
    --cc=edumazet@google.com \
    --cc=jmaloy@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=tung.quang.nguyen@dektech.com.au \
    --cc=tung.quang.nguyen@est.tech \
    --cc=w@1wt.eu \
    --cc=xiaoshoukui@ruijie.com.cn \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.