<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel.git/kernel/bpf/cpumap.c, branch linux-6.19.y</title>
<subtitle>Hosts the 0x221E linux distro kernel.
</subtitle>
<id>https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-6.19.y</id>
<link rel='self' href='https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-6.19.y'/>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/'/>
<updated>2026-03-12T11:09:25Z</updated>
<entry>
<title>bpf: Fix race in cpumap on PREEMPT_RT</title>
<updated>2026-03-12T11:09:25Z</updated>
<author>
<name>Jiayuan Chen</name>
</author>
<published>2026-02-25T12:14:55Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=e67299e1044349ad0088d52c6bc5764cc1816c06'/>
<id>urn:sha1:e67299e1044349ad0088d52c6bc5764cc1816c06</id>
<content type='text'>
[ Upstream commit 869c63d5975d55e97f6b168e885452b3da20ea47 ]

On PREEMPT_RT kernels, the per-CPU xdp_bulk_queue (bq) can be accessed
concurrently by multiple preemptible tasks on the same CPU.

The original code assumes bq_enqueue() and __cpu_map_flush() run
atomically with respect to each other on the same CPU, relying on
local_bh_disable() to prevent preemption. However, on PREEMPT_RT,
local_bh_disable() only calls migrate_disable() (when
PREEMPT_RT_NEEDS_BH_LOCK is not set) and does not disable
preemption, which allows CFS scheduling to preempt a task during
bq_flush_to_queue(), enabling another task on the same CPU to enter
bq_enqueue() and operate on the same per-CPU bq concurrently.

This leads to several races:

1. Double __list_del_clearprev(): after bq-&gt;count is reset in
   bq_flush_to_queue(), a preempting task can call bq_enqueue() -&gt;
   bq_flush_to_queue() on the same bq when bq-&gt;count reaches
   CPU_MAP_BULK_SIZE. Both tasks then call __list_del_clearprev()
   on the same bq-&gt;flush_node, the second call dereferences the
   prev pointer that was already set to NULL by the first.

2. bq-&gt;count and bq-&gt;q[] races: concurrent bq_enqueue() can corrupt
   the packet queue while bq_flush_to_queue() is processing it.

The race between task A (__cpu_map_flush -&gt; bq_flush_to_queue) and
task B (bq_enqueue -&gt; bq_flush_to_queue) on the same CPU:

  Task A (xdp_do_flush)          Task B (cpu_map_enqueue)
  ----------------------         ------------------------
  bq_flush_to_queue(bq)
    spin_lock(&amp;q-&gt;producer_lock)
    /* flush bq-&gt;q[] to ptr_ring */
    bq-&gt;count = 0
    spin_unlock(&amp;q-&gt;producer_lock)
                                   bq_enqueue(rcpu, xdpf)
    &lt;-- CFS preempts Task A --&gt;      bq-&gt;q[bq-&gt;count++] = xdpf
                                     /* ... more enqueues until full ... */
                                     bq_flush_to_queue(bq)
                                       spin_lock(&amp;q-&gt;producer_lock)
                                       /* flush to ptr_ring */
                                       spin_unlock(&amp;q-&gt;producer_lock)
                                       __list_del_clearprev(flush_node)
                                         /* sets flush_node.prev = NULL */
    &lt;-- Task A resumes --&gt;
    __list_del_clearprev(flush_node)
      flush_node.prev-&gt;next = ...
      /* prev is NULL -&gt; kernel oops */

Fix this by adding a local_lock_t to xdp_bulk_queue and acquiring it
in bq_enqueue() and __cpu_map_flush(). These paths already run under
local_bh_disable(), so use local_lock_nested_bh() which on non-RT is
a pure annotation with no overhead, and on PREEMPT_RT provides a
per-CPU sleeping lock that serializes access to the bq.

To reproduce, insert an mdelay(100) between bq-&gt;count = 0 and
__list_del_clearprev() in bq_flush_to_queue(), then run reproducer
provided by syzkaller.

Fixes: 3253cb49cbad ("softirq: Allow to drop the softirq-BKL lock on PREEMPT_RT")
Reported-by: syzbot+2b3391f44313b3983e91@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/69369331.a70a0220.38f243.009d.GAE@google.com/T/
Reviewed-by: Sebastian Andrzej Siewior &lt;bigeasy@linutronix.de&gt;
Signed-off-by: Jiayuan Chen &lt;jiayuan.chen@shopee.com&gt;
Signed-off-by: Jiayuan Chen &lt;jiayuan.chen@linux.dev&gt;
Link: https://lore.kernel.org/r/20260225121459.183121-2-jiayuan.chen@linux.dev
Signed-off-by: Alexei Starovoitov &lt;ast@kernel.org&gt;
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</content>
</entry>
<entry>
<title>Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf after rc5</title>
<updated>2025-09-11T16:34:37Z</updated>
<author>
<name>Alexei Starovoitov</name>
</author>
<published>2025-09-11T16:34:37Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=5d87e96a4971760c83e554c1d3ca99986d4f9b47'/>
<id>urn:sha1:5d87e96a4971760c83e554c1d3ca99986d4f9b47</id>
<content type='text'>
Cross-merge BPF and other fixes after downstream PR.

No conflicts.

Signed-off-by: Alexei Starovoitov &lt;ast@kernel.org&gt;
</content>
</entry>
<entry>
<title>bpf: replace use of system_wq with system_percpu_wq</title>
<updated>2025-09-08T17:04:37Z</updated>
<author>
<name>Marco Crivellari</name>
</author>
<published>2025-09-05T08:53:07Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=34f86083a4e1887ada121d2b5c4f47cc038a3356'/>
<id>urn:sha1:34f86083a4e1887ada121d2b5c4f47cc038a3356</id>
<content type='text'>
Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.

This lack of consistentcy cannot be addressed without refactoring the API.

system_wq is a per-CPU worqueue, yet nothing in its name tells about that
CPU affinity constraint, which is very often not required by users. Make
it clear by adding a system_percpu_wq.

queue_work() / queue_delayed_work() mod_delayed_work() will now use the
new per-cpu wq: whether the user still stick on the old name a warn will
be printed along a wq redirect to the new one.

This patch add the new system_percpu_wq except for mm, fs and net
subsystem, whom are handled in separated patches.

The old wq will be kept for a few release cylces.

Suggested-by: Tejun Heo &lt;tj@kernel.org&gt;
Signed-off-by: Marco Crivellari &lt;marco.crivellari@suse.com&gt;
Link: https://lore.kernel.org/r/20250905085309.94596-2-marco.crivellari@suse.com
Signed-off-by: Alexei Starovoitov &lt;ast@kernel.org&gt;
</content>
</entry>
<entry>
<title>bpf, cpumap: Disable page_pool direct xdp_return need larger scope</title>
<updated>2025-08-15T09:08:08Z</updated>
<author>
<name>Jesper Dangaard Brouer</name>
</author>
<published>2025-08-14T18:24:37Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=2b986b9e917bc88f81aa1ed386af63b26c983f1d'/>
<id>urn:sha1:2b986b9e917bc88f81aa1ed386af63b26c983f1d</id>
<content type='text'>
When running an XDP bpf_prog on the remote CPU in cpumap code
then we must disable the direct return optimization that
xdp_return can perform for mem_type page_pool.  This optimization
assumes code is still executing under RX-NAPI of the original
receiving CPU, which isn't true on this remote CPU.

The cpumap code already disabled this via helpers
xdp_set_return_frame_no_direct() and xdp_clear_return_frame_no_direct(),
but the scope didn't include xdp_do_flush().

When doing XDP_REDIRECT towards e.g devmap this causes the
function bq_xmit_all() to run with direct return optimization
enabled. This can lead to hard to find bugs.  The issue
only happens when bq_xmit_all() cannot ndo_xdp_xmit all
frames and them frees them via xdp_return_frame_rx_napi().

Fix by expanding scope to include xdp_do_flush(). This was found
by Dragos Tatulea.

Fixes: 11941f8a8536 ("bpf: cpumap: Implement generic cpumap")
Reported-by: Dragos Tatulea &lt;dtatulea@nvidia.com&gt;
Reported-by: Chris Arges &lt;carges@cloudflare.com&gt;
Signed-off-by: Jesper Dangaard Brouer &lt;hawk@kernel.org&gt;
Signed-off-by: Martin KaFai Lau &lt;martin.lau@kernel.org&gt;
Signed-off-by: Daniel Borkmann &lt;daniel@iogearbox.net&gt;
Tested-by: Chris Arges &lt;carges@cloudflare.com&gt;
Link: https://patch.msgid.link/175519587755.3008742.1088294435150406835.stgit@firesoul
</content>
</entry>
<entry>
<title>net: Create separate gro_flush_normal function</title>
<updated>2025-07-25T01:34:55Z</updated>
<author>
<name>Samiullah Khawaja</name>
</author>
<published>2025-07-23T01:30:29Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=71c52411c51bf4f0869c572294ce8123b26528d5'/>
<id>urn:sha1:71c52411c51bf4f0869c572294ce8123b26528d5</id>
<content type='text'>
Move multiple copies of same code snippet doing `gro_flush` and
`gro_normal_list` into separate helper function.

Signed-off-by: Samiullah Khawaja &lt;skhawaja@google.com&gt;
Reviewed-by: Willem de Bruijn &lt;willemb@google.com&gt;
Link: https://patch.msgid.link/20250723013031.2911384-2-skhawaja@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>bpf: cpumap: switch to napi_skb_cache_get_bulk()</title>
<updated>2025-02-27T13:03:39Z</updated>
<author>
<name>Alexander Lobakin</name>
</author>
<published>2025-02-25T17:17:48Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=ed16b8a4d1ca901fc13ced042b76dde54738249a'/>
<id>urn:sha1:ed16b8a4d1ca901fc13ced042b76dde54738249a</id>
<content type='text'>
Now that cpumap uses GRO, which drops unused skb heads to the NAPI
cache, use napi_skb_cache_get_bulk() to try to reuse cached entries
and lower MM layer pressure. Always disable the BH before checking and
running the cpumap-pinned XDP prog and don't re-enable it in between
that and allocating an skb bulk, as we can access the NAPI caches only
from the BH context.
The better GRO aggregates packets, the less new skbs will be allocated.
If an aggregated skb contains 16 frags, this means 15 skbs were returned
to the cache, so next 15 skbs will be built without allocating anything.

The same trafficgen UDP GRO test now shows:

                GRO off   GRO on
threaded GRO    2.3       4         Mpps
thr bulk GRO    2.4       4.7       Mpps

diff            +4        +17       %

Comparing to the baseline cpumap:

baseline        2.7       N/A       Mpps
thr bulk GRO    2.4       4.7       Mpps
diff            -11       +74       %

Tested-by: Daniel Xu &lt;dxu@dxuuu.xyz&gt;
Reviewed-by: Toke Høiland-Jørgensen &lt;toke@redhat.com&gt;
Signed-off-by: Alexander Lobakin &lt;aleksander.lobakin@intel.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;
</content>
</entry>
<entry>
<title>bpf: cpumap: reuse skb array instead of a linked list to chain skbs</title>
<updated>2025-02-27T13:03:14Z</updated>
<author>
<name>Alexander Lobakin</name>
</author>
<published>2025-02-25T17:17:46Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=57efe762cd3c8796f8a4b410a578af8c8e99d22f'/>
<id>urn:sha1:57efe762cd3c8796f8a4b410a578af8c8e99d22f</id>
<content type='text'>
cpumap still uses linked lists to store a list of skbs to pass to the
stack. Now that we don't use listified Rx in favor of
napi_gro_receive(), linked list is now an unneeded overhead.
Inside the polling loop, we already have an array of skbs. Let's reuse
it for skbs passed to cpumap (generic XDP) and keep there in case of
XDP_PASS when a program is installed to the map itself. Don't list
regular xdp_frames after converting them to skbs as well; store them
in the mentioned array (but *before* generic skbs as the latters have
lower priority) and call gro_receive_skb() for each array element after
they're done.

Tested-by: Daniel Xu &lt;dxu@dxuuu.xyz&gt;
Reviewed-by: Toke Høiland-Jørgensen &lt;toke@redhat.com&gt;
Signed-off-by: Alexander Lobakin &lt;aleksander.lobakin@intel.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
<entry>
<title>bpf: cpumap: switch to GRO from netif_receive_skb_list()</title>
<updated>2025-02-27T13:03:14Z</updated>
<author>
<name>Alexander Lobakin</name>
</author>
<published>2025-02-25T17:17:45Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=4f8ab26a034f04f918c8d36c051ec84e4082eed5'/>
<id>urn:sha1:4f8ab26a034f04f918c8d36c051ec84e4082eed5</id>
<content type='text'>
cpumap has its own BH context based on kthread. It has a sane batch
size of 8 frames per one cycle.
GRO can be used here on its own. Adjust cpumap calls to the upper stack
to use GRO API instead of netif_receive_skb_list() which processes skbs
by batches, but doesn't involve GRO layer at all.
In plenty of tests, GRO performs better than listed receiving even
given that it has to calculate full frame checksums on the CPU.
As GRO passes the skbs to the upper stack in the batches of
@gro_normal_batch, i.e. 8 by default, and skb-&gt;dev points to the
device where the frame comes from, it is enough to disable GRO
netdev feature on it to completely restore the original behaviour:
untouched frames will be being bulked and passed to the upper stack
by 8, as it was with netif_receive_skb_list().

Tested-by: Daniel Xu &lt;dxu@dxuuu.xyz&gt;
Reviewed-by: Toke Høiland-Jørgensen &lt;toke@redhat.com&gt;
Signed-off-by: Alexander Lobakin &lt;aleksander.lobakin@intel.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
<entry>
<title>xdp: get rid of xdp_frame::mem.id</title>
<updated>2024-12-13T02:22:52Z</updated>
<author>
<name>Alexander Lobakin</name>
</author>
<published>2024-12-11T17:26:39Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=56d95b0adfa224bb1c67733dbcad30dd8debd39e'/>
<id>urn:sha1:56d95b0adfa224bb1c67733dbcad30dd8debd39e</id>
<content type='text'>
Initially, xdp_frame::mem.id was used to search for the corresponding
&amp;page_pool to return the page correctly.
However, after that struct page was extended to have a direct pointer
to its PP (netmem has it as well), further keeping of this field makes
no sense. xdp_return_frame_bulk() still used it to do a lookup, and
this leftover is now removed.
Remove xdp_frame::mem and replace it with ::mem_type, as only memory
type still matters and we need to know it to be able to free the frame
correctly.
As a cute side effect, we can now make every scalar field in &amp;xdp_frame
of 4 byte width, speeding up accesses to them.

Reviewed-by: Toke Høiland-Jørgensen &lt;toke@redhat.com&gt;
Signed-off-by: Alexander Lobakin &lt;aleksander.lobakin@intel.com&gt;
Link: https://patch.msgid.link/20241211172649.761483-3-aleksander.lobakin@intel.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>bpf, cpumap: Move xdp:xdp_cpumap_kthread tracepoint before rcv</title>
<updated>2024-09-11T14:32:11Z</updated>
<author>
<name>Daniel Xu</name>
</author>
<published>2024-09-06T01:22:44Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=23dc9867329c72b48e5039ac93fbf50d9099cdb3'/>
<id>urn:sha1:23dc9867329c72b48e5039ac93fbf50d9099cdb3</id>
<content type='text'>
cpumap takes RX processing out of softirq and onto a separate kthread.
Since the kthread needs to be scheduled in order to run (versus softirq
which does not), we can theoretically experience extra latency if the
system is under load and the scheduler is being unfair to us.

Moving the tracepoint to before passing the skb list up the stack allows
users to more accurately measure enqueue/dequeue latency introduced by
cpumap via xdp:xdp_cpumap_enqueue and xdp:xdp_cpumap_kthread tracepoints.

f9419f7bd7a5 ("bpf: cpumap add tracepoints") which added the tracepoints
states that the intent behind them was for general observability and for
a feedback loop to see if the queues are being overwhelmed. This change
does not mess with either of those use cases but rather adds a third
one.

Signed-off-by: Daniel Xu &lt;dxu@dxuuu.xyz&gt;
Signed-off-by: Daniel Borkmann &lt;daniel@iogearbox.net&gt;
Acked-by: Jesper Dangaard Brouer &lt;hawk@kernel.org&gt;
Link: https://lore.kernel.org/bpf/47615d5b5e302e4bd30220473779e98b492d47cd.1725585718.git.dxu@dxuuu.xyz
</content>
</entry>
</feed>
