Skip to content

Conversation

erfrimod
Copy link
Contributor

Linux netvsc sends an OID to stop receiving packets on vmbus channel close. Example scenarios: hibernation and MTU change. Prior to opening a new channel and processing the packets, netvsc checks that there are no pending packets. If there are, netvsc logs and error and is unable to recover. We observe the error: hv_netvsc eth0: Ring buffer not empty after closing rndis in the guest syslog.

Modifying netvsp to handle the OID and stop processing RX traffic. This will allow for netvsc to successfully close and re-open the vmbus channel, even under heavy incoming traffic.

@Copilot Copilot AI review requested due to automatic review settings August 15, 2025 22:50
@erfrimod erfrimod requested a review from a team as a code owner August 15, 2025 22:50
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements handling for RNDIS packet filter OID to stop receiving packets when the VMBus channel is being closed. This addresses an issue where Linux netvsc cannot successfully close and reopen channels under heavy traffic, leading to "Ring buffer not empty after closing rndis" errors.

Key changes:

  • Added stop_rx state tracking throughout the network stack
  • Implemented OID_GEN_CURRENT_PACKET_FILTER handling to set the stop_rx flag
  • Modified packet reception logic to respect the stop_rx flag

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
saved_state.rs Added stop_rx field to ReadyPrimary struct for state persistence
rndisprot.rs Added OID_REQUEST constant and RndisPacketFilterOidValue type for RNDIS protocol support
lib.rs Implemented stop_rx state management across channels, OID handling, and packet processing logic

@benhillis benhillis added backport_2411 Change should be backported to the release/2411 branch backport_2505 Change should be backported to the release/2505 branch labels Aug 15, 2025
Copy link

tracing::debug!(?oid, "oid set");

let mut restart_endpoint = false;
let mut stop_rx = false;
match oid {
rndisprot::Oid::OID_GEN_CURRENT_PACKET_FILTER => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we support reading the filter value back?

Copy link

Copy link

@erfrimod erfrimod force-pushed the erfrimod/netvsp_rndis_packet_filter branch from f6d5eb4 to 61c4cb6 Compare August 19, 2025 21:40
Brian-Perkins
Brian-Perkins previously approved these changes Aug 21, 2025
Copy link

data: ProcessingData::new(),
})
// Get the packet filter of the primary channel.
self.coordinator.state_mut().unwrap().workers[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of getting this out of the primary channel, can we have the primary channel report the new packet filter to the coordinator and so instead get it out of the coordinator?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a danger of losing the value since we could send the coordinator message and then get stopped / saved before actually processing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the filter from the primary channel. I store it in the worker[0] netchannel. And when readystate is saved, that's where it gets read from. And when the coordinator updates the subchannels, it also reads from worker[0].

UpdateGuestVfState,
guest_vf_state: bool,
/// Update the receive filter for all channels.
filter_state: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e., maybe this can be Option<u32> so that we can store the packet filter in the coordinator itself.

guest_vf_state: guest_vf,
filter_state: packet_filter,
}));
} else if let Some(CoordinatorMessage::Restart) = self.restart {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this would have to be updated, too, to store the new packet filter.

Copy link

self.stop_workers().await;
let worker_0_packet_filter =
self.workers[0].state().unwrap().channel.packet_filter;
self.workers.iter_mut().for_each(|worker| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: self.workers.iter_mut().skip(1).for_each(|worker| {

Brian-Perkins
Brian-Perkins previously approved these changes Aug 25, 2025
@erfrimod erfrimod merged commit 6f3ffb3 into microsoft:main Aug 27, 2025
29 checks passed
erfrimod added a commit to erfrimod/openvmm_fork2 that referenced this pull request Aug 27, 2025
Linux netvsc sends an OID to stop receiving packets on vmbus channel
close. Example scenarios: hibernation and MTU change. Prior to opening a
new channel and processing the packets, netvsc checks that there are no
pending packets. If there are, netvsc logs and error and is unable to
recover. We observe the error: `hv_netvsc eth0: Ring buffer not empty
after closing rndis` in the guest syslog.

Modifying netvsp to handle the OID and stop processing RX traffic. This
will allow for netvsc to successfully close and re-open the vmbus
channel, even under heavy incoming traffic.

---------

Co-authored-by: Sunil Muthuswamy <[email protected]>
erfrimod added a commit to erfrimod/openvmm_fork2 that referenced this pull request Aug 27, 2025
Linux netvsc sends an OID to stop receiving packets on vmbus channel
close. Example scenarios: hibernation and MTU change. Prior to opening a
new channel and processing the packets, netvsc checks that there are no
pending packets. If there are, netvsc logs and error and is unable to
recover. We observe the error: `hv_netvsc eth0: Ring buffer not empty
after closing rndis` in the guest syslog.

Modifying netvsp to handle the OID and stop processing RX traffic. This
will allow for netvsc to successfully close and re-open the vmbus
channel, even under heavy incoming traffic.

---------

Co-authored-by: Sunil Muthuswamy <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport_2411 Change should be backported to the release/2411 branch backport_2505 Change should be backported to the release/2505 branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants