Skip to content

virtio/net: fix processing of merged RX buffers #2103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

francescolavra
Copy link
Member

When the virtio net feature that allows merging of RX buffers is enabled, buffers belonging to a merged set must be processed in strict sequential order; to achieve this, the seqno field of the vnet_rx structure is used to prevent different CPUS from processing RX buffers simultaneously.
This change set fixes a few flaws in the implementation of the critical section which can cause corruption of the pbuf structure holding received data, and can lead to failure to process incoming network traffic. The memory barriers needed to ensure correct synchronization between CPUs have been added via the newly defined smp_read_barrier() and smp_write_barrier() macros, which are more efficient than read_barrier() and write_barrier() on architectures (such as x86) with strong memory ordering. As part of the commit that introduces these new macros, existing calls to read_barrier() and write_barrier() have been replaced by calls to smp_read_barrier() and smp_write_barrier() where appropriate (i.e where memory is not used for device I/O).

Closes #2099.

Francesco Lavra added 3 commits May 29, 2025 12:06
When the virtio net feature that allows merging of RX buffers
is enabled, buffers belonging to a merged set must be processed in
strict sequential order; to achieve this, the seqno field of the
vnet_rx structure is used to prevent different CPUS from processing
RX buffers simultaneously. However, part of the code that processes
the first buffer of a merged set is being executed outside the
critical section, which can cause corruption of the relevant pbuf
struct. This issue can manifest itself as failure to process
incoming network traffic.
Fix the above issue by introducing the vnet_rx_hdr_remove() helper
function, which is called to process both the first buffer of a
merged set (inside the critical section), and the only buffer of a
received packet when merging is not being done.

Closes #2099.
These macros are used when memory read/write ordering needs to be
enforced in order for different CPUs to have a consistent view of
shared memory. They can expand to an actual memory fence (on
architectures with a weakly ordered memory model), or to a simple
compiler barrier (on architectures with strong memory ordering).
The use of these macros instead of read_barrier() and
write_barrier() (which always insert a memory fence) creates more
efficient code for architectures (such as x86) with strong memory
ordering.
Replace calls to read/write_barrier() with calls to
smp_read/write_barrier() when memory is not used for device I/O;
remove barriers when not needed; in spin_unlock(), replace compiler
barrier with SMP write barrier, otherwise code is not safe with
weakly ordered memory model.
When the virtio net feature that allows merging of RX buffers is
enabled, the seqno field of the vnet_rx structure is used to
prevent different CPUS from processing simultaneously RX buffers
belonging to the same merged set.
Add memory barriers at the beginning and end of the critical
section, in order to prevent memory read/write reordering from
causing different CPUs to run parts of the critical section at the
same time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

virtio network stop working nanos 0.1.49 - 0.1.53 (previous versions have not been tested)
1 participant