mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: net: report link up in config status
Expose `VIRTIO_NET_S_LINK_UP` through the virtio-net config status field when `VIRTIO_NET_F_STATUS` was negotiated. This makes the guest-visible status bits reflect the device runtime state and prepares the config status path used by later post-migration announce handling. On-behalf-of: SAP sebastian.eydam@sap.com Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
This commit is contained in:
committed by
Rob Bradford
parent
f5967cf287
commit
e17c0be127
@@ -487,6 +487,7 @@ impl Net {
|
||||
}
|
||||
|
||||
avail_features |= 1 << VIRTIO_NET_F_CTRL_VQ;
|
||||
avail_features |= 1 << VIRTIO_NET_F_STATUS;
|
||||
let queue_num = num_queues + 1;
|
||||
|
||||
let mut config = VirtioNetConfig::default();
|
||||
@@ -639,6 +640,17 @@ impl Net {
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the guest-visible virtio-net status field.
|
||||
fn guest_visible_status(&self) -> u16 {
|
||||
let mut status = 0;
|
||||
|
||||
if self.common.feature_acked(VIRTIO_NET_F_STATUS.into()) {
|
||||
status |= VIRTIO_NET_S_LINK_UP as u16;
|
||||
}
|
||||
|
||||
status
|
||||
}
|
||||
|
||||
#[cfg(fuzzing)]
|
||||
pub fn wait_for_epoll_threads(&mut self) {
|
||||
self.common.wait_for_epoll_threads();
|
||||
@@ -663,7 +675,9 @@ impl VirtioDevice for Net {
|
||||
}
|
||||
|
||||
fn read_config(&self, offset: u64, data: &mut [u8]) {
|
||||
self.read_config_from_slice(self.config.as_slice(), offset, data);
|
||||
let mut config = self.config;
|
||||
config.status = self.guest_visible_status();
|
||||
self.read_config_from_slice(config.as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(&mut self, context: ActivationContext) -> ActivateResult {
|
||||
@@ -857,3 +871,52 @@ impl Snapshottable for Net {
|
||||
}
|
||||
impl Transportable for Net {}
|
||||
impl Migratable for Net {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::mem::size_of;
|
||||
|
||||
use seccompiler::SeccompAction;
|
||||
use virtio_bindings::virtio_net::{VIRTIO_NET_F_STATUS, VIRTIO_NET_S_LINK_UP};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn test_net(acked_features: u64) -> Net {
|
||||
Net {
|
||||
common: VirtioCommon {
|
||||
acked_features,
|
||||
..Default::default()
|
||||
},
|
||||
id: "test-net".to_string(),
|
||||
taps: Vec::new(),
|
||||
config: VirtioNetConfig::default(),
|
||||
counters: NetCounters::default(),
|
||||
seccomp_action: SeccompAction::Allow,
|
||||
rate_limiter_config: None,
|
||||
exit_evt: EventFd::new(libc::EFD_NONBLOCK).unwrap(),
|
||||
device_status: Arc::new(AtomicU8::new(0)),
|
||||
}
|
||||
}
|
||||
|
||||
const STATUS_OFFSET: usize = std::mem::offset_of!(VirtioNetConfig, status);
|
||||
fn read_status(device: &Net) -> u16 {
|
||||
let mut data = vec![0; size_of::<VirtioNetConfig>()];
|
||||
device.read_config(0, &mut data);
|
||||
|
||||
u16::from_le_bytes(
|
||||
data[STATUS_OFFSET..STATUS_OFFSET + size_of::<u16>()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_status_feature_reports_link_up() {
|
||||
// The current implementation should always report "link up" if
|
||||
// VIRTIO_NET_F_STATUS has been negotiated.
|
||||
let net = test_net(1 << VIRTIO_NET_F_STATUS);
|
||||
|
||||
assert_eq!(read_status(&net), VIRTIO_NET_S_LINK_UP as u16);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user