Skip to content

Commit b71107d

Browse files
authored
Merge pull request #1268 from hermit-os/net-config
refactor(net/virtio): migrate `NetDevCfgRaw` to virtio-spec
2 parents 48645aa + 1323f2c commit b71107d

File tree

15 files changed

+255
-302
lines changed

15 files changed

+255
-302
lines changed

src/arch/aarch64/kernel/mmio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use hermit_sync::InterruptTicketMutex;
22

3-
use crate::drivers::net::virtio_net::VirtioNetDriver;
3+
use crate::drivers::net::virtio::VirtioNetDriver;
44

55
pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex<VirtioNetDriver>> {
66
None

src/arch/riscv64/kernel/mmio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use hermit_sync::InterruptSpinMutex;
55
#[cfg(feature = "gem-net")]
66
use crate::drivers::net::gem::GEMDriver;
77
#[cfg(not(feature = "gem-net"))]
8-
use crate::drivers::net::virtio_net::VirtioNetDriver;
8+
use crate::drivers::net::virtio::VirtioNetDriver;
99

1010
static mut MMIO_DRIVERS: Vec<MmioDriver> = Vec::new();
1111

src/arch/x86_64/kernel/mmio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::arch::x86_64::mm::paging::{
1212
BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt,
1313
};
1414
use crate::arch::x86_64::mm::{paging, PhysAddr};
15-
use crate::drivers::net::virtio_net::VirtioNetDriver;
15+
use crate::drivers::net::virtio::VirtioNetDriver;
1616
use crate::drivers::virtio::transport::mmio as mmio_virtio;
1717
use crate::drivers::virtio::transport::mmio::VirtioDriver;
1818
use crate::env;

src/drivers/net/mod.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22
pub mod gem;
33
#[cfg(feature = "rtl8139")]
44
pub mod rtl8139;
5-
#[cfg(all(not(feature = "pci"), not(feature = "rtl8139")))]
6-
pub mod virtio_mmio;
75
#[cfg(not(feature = "rtl8139"))]
8-
pub mod virtio_net;
9-
#[cfg(all(feature = "pci", not(feature = "rtl8139")))]
10-
pub mod virtio_pci;
6+
pub mod virtio;
117

128
use smoltcp::phy::ChecksumCapabilities;
139

src/drivers/net/virtio/mmio.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//! A module containing a virtio network driver.
2+
//!
3+
//! The module contains ...
4+
5+
use alloc::rc::Rc;
6+
use alloc::vec::Vec;
7+
use core::str::FromStr;
8+
9+
use smoltcp::phy::ChecksumCapabilities;
10+
use virtio_spec::mmio::{DeviceRegisterVolatileFieldAccess, DeviceRegisters};
11+
use volatile::VolatileRef;
12+
13+
use crate::drivers::net::virtio::{CtrlQueue, NetDevCfg, RxQueues, TxQueues, VirtioNetDriver};
14+
use crate::drivers::virtio::error::{VirtioError, VirtioNetError};
15+
use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
16+
use crate::drivers::virtio::virtqueue::Virtq;
17+
18+
// Backend-dependent interface for Virtio network driver
19+
impl VirtioNetDriver {
20+
pub fn new(
21+
dev_id: u16,
22+
mut registers: VolatileRef<'static, DeviceRegisters>,
23+
irq: u8,
24+
) -> Result<Self, VirtioNetError> {
25+
let dev_cfg_raw: &'static virtio_spec::net::Config = unsafe {
26+
&*registers
27+
.borrow_mut()
28+
.as_mut_ptr()
29+
.config()
30+
.as_raw_ptr()
31+
.cast::<virtio_spec::net::Config>()
32+
.as_ptr()
33+
};
34+
let dev_cfg_raw = VolatileRef::from_ref(dev_cfg_raw);
35+
let dev_cfg = NetDevCfg {
36+
raw: dev_cfg_raw,
37+
dev_id,
38+
features: virtio_spec::net::F::empty(),
39+
};
40+
let isr_stat = IsrStatus::new(registers.borrow_mut());
41+
let notif_cfg = NotifCfg::new(registers.borrow_mut());
42+
43+
let mtu = if let Some(my_mtu) = hermit_var!("HERMIT_MTU") {
44+
u16::from_str(&my_mtu).unwrap()
45+
} else {
46+
// fallback to the default MTU
47+
1514
48+
};
49+
50+
Ok(VirtioNetDriver {
51+
dev_cfg,
52+
com_cfg: ComCfg::new(registers, 1),
53+
isr_stat,
54+
notif_cfg,
55+
ctrl_vq: CtrlQueue::new(None),
56+
recv_vqs: RxQueues::new(Vec::<Rc<dyn Virtq>>::new(), false),
57+
send_vqs: TxQueues::new(Vec::<Rc<dyn Virtq>>::new(), Vec::new(), false),
58+
num_vqs: 0,
59+
irq,
60+
mtu,
61+
checksums: ChecksumCapabilities::default(),
62+
})
63+
}
64+
65+
pub fn print_information(&mut self) {
66+
self.com_cfg.print_information();
67+
if self.dev_status() == virtio_spec::net::S::LINK_UP {
68+
info!("The link of the network device is up!");
69+
}
70+
}
71+
72+
/// Initializes virtio network device by mapping configuration layout to
73+
/// respective structs (configuration structs are:
74+
///
75+
/// Returns a driver instance of
76+
/// [VirtioNetDriver](structs.virtionetdriver.html) or an [VirtioError](enums.virtioerror.html).
77+
pub fn init(
78+
dev_id: u16,
79+
registers: VolatileRef<'static, DeviceRegisters>,
80+
irq_no: u8,
81+
) -> Result<VirtioNetDriver, VirtioError> {
82+
if let Ok(mut drv) = VirtioNetDriver::new(dev_id, registers, irq_no) {
83+
match drv.init_dev() {
84+
Err(error_code) => Err(VirtioError::NetDriver(error_code)),
85+
_ => {
86+
drv.print_information();
87+
Ok(drv)
88+
}
89+
}
90+
} else {
91+
error!("Unable to create Driver. Aborting!");
92+
Err(VirtioError::Unknown)
93+
}
94+
}
95+
}

src/drivers/net/virtio_net.rs renamed to src/drivers/net/virtio/mod.rs

Lines changed: 63 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
//!
33
//! The module contains ...
44
5+
cfg_if::cfg_if! {
6+
if #[cfg(feature = "pci")] {
7+
mod pci;
8+
} else {
9+
mod mmio;
10+
}
11+
}
12+
513
use alloc::boxed::Box;
614
use alloc::rc::Rc;
715
use alloc::vec::Vec;
@@ -12,18 +20,16 @@ use align_address::Align;
1220
use pci_types::InterruptLine;
1321
use smoltcp::phy::{Checksum, ChecksumCapabilities};
1422
use smoltcp::wire::{EthernetFrame, Ipv4Packet, Ipv6Packet, ETHERNET_HEADER_LEN};
15-
use virtio_spec::net::{Hdr, HdrF};
23+
use virtio_spec::net::{ConfigVolatileFieldAccess, Hdr, HdrF};
1624
use virtio_spec::FeatureBits;
25+
use volatile::access::ReadOnly;
26+
use volatile::VolatileRef;
1727

18-
use self::constants::{Status, MAX_NUM_VQ};
28+
use self::constants::MAX_NUM_VQ;
1929
use self::error::VirtioNetError;
2030
#[cfg(not(target_arch = "riscv64"))]
2131
use crate::arch::kernel::core_local::increment_irq_counter;
2232
use crate::config::VIRTIO_MAX_QUEUE_SIZE;
23-
#[cfg(not(feature = "pci"))]
24-
use crate::drivers::net::virtio_mmio::NetDevCfgRaw;
25-
#[cfg(feature = "pci")]
26-
use crate::drivers::net::virtio_pci::NetDevCfgRaw;
2733
use crate::drivers::net::NetworkDriver;
2834
#[cfg(not(feature = "pci"))]
2935
use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
@@ -38,7 +44,7 @@ use crate::executor::device::{RxToken, TxToken};
3844
/// Handling the right access to fields, as some are read-only
3945
/// for the driver.
4046
pub(crate) struct NetDevCfg {
41-
pub raw: &'static NetDevCfgRaw,
47+
pub raw: VolatileRef<'static, virtio_spec::net::Config, ReadOnly>,
4248
pub dev_id: u16,
4349
pub features: virtio_spec::net::F,
4450
}
@@ -154,7 +160,7 @@ impl RxQueues {
154160
(1514 + mem::size_of::<Hdr>())
155161
.align_up(core::mem::size_of::<crossbeam_utils::CachePadded<u8>>())
156162
} else {
157-
dev_cfg.raw.get_mtu() as usize + mem::size_of::<Hdr>()
163+
dev_cfg.raw.as_ptr().mtu().read().to_ne() as usize + mem::size_of::<Hdr>()
158164
};
159165

160166
// See Virtio specification v1.1 - 5.1.6.3.1
@@ -318,8 +324,10 @@ impl TxQueues {
318324
// Header and data are added as ONE output descriptor to the transmitvq.
319325
// Hence we are interpreting this, as the fact, that send packets must be inside a single descriptor.
320326
// As usize is currently safe as the minimal usize is defined as 16bit in rust.
321-
let buff_def =
322-
Bytes::new(mem::size_of::<Hdr>() + dev_cfg.raw.get_mtu() as usize).unwrap();
327+
let buff_def = Bytes::new(
328+
mem::size_of::<Hdr>() + dev_cfg.raw.as_ptr().mtu().read().to_ne() as usize,
329+
)
330+
.unwrap();
323331
let spec = BuffSpec::Single(buff_def);
324332

325333
let num_buff: u16 = vq.size().into();
@@ -421,7 +429,14 @@ impl NetworkDriver for VirtioNetDriver {
421429
/// If VIRTIO_NET_F_MAC is not set, the function panics currently!
422430
fn get_mac_address(&self) -> [u8; 6] {
423431
if self.dev_cfg.features.contains(virtio_spec::net::F::MAC) {
424-
self.dev_cfg.raw.get_mac()
432+
loop {
433+
let before = self.com_cfg.config_generation();
434+
let mac = self.dev_cfg.raw.as_ptr().mac().read();
435+
let after = self.com_cfg.config_generation();
436+
if before == after {
437+
break mac;
438+
}
439+
}
425440
} else {
426441
unreachable!("Currently VIRTIO_NET_F_MAC must be negotiated!")
427442
}
@@ -637,11 +652,11 @@ impl VirtioNetDriver {
637652
/// Returns the current status of the device, if VIRTIO_NET_F_STATUS
638653
/// has been negotiated. Otherwise assumes an active device.
639654
#[cfg(not(feature = "pci"))]
640-
pub fn dev_status(&self) -> u16 {
655+
pub fn dev_status(&self) -> virtio_spec::net::S {
641656
if self.dev_cfg.features.contains(virtio_spec::net::F::STATUS) {
642-
self.dev_cfg.raw.get_status()
657+
self.dev_cfg.raw.as_ptr().status().read()
643658
} else {
644-
u16::from(Status::VIRTIO_NET_S_LINK_UP)
659+
virtio_spec::net::S::LINK_UP
645660
}
646661
}
647662

@@ -650,8 +665,12 @@ impl VirtioNetDriver {
650665
#[cfg(feature = "pci")]
651666
pub fn is_link_up(&self) -> bool {
652667
if self.dev_cfg.features.contains(virtio_spec::net::F::STATUS) {
653-
self.dev_cfg.raw.get_status() & u16::from(Status::VIRTIO_NET_S_LINK_UP)
654-
== u16::from(Status::VIRTIO_NET_S_LINK_UP)
668+
self.dev_cfg
669+
.raw
670+
.as_ptr()
671+
.status()
672+
.read()
673+
.contains(virtio_spec::net::S::LINK_UP)
655674
} else {
656675
true
657676
}
@@ -660,8 +679,12 @@ impl VirtioNetDriver {
660679
#[allow(dead_code)]
661680
pub fn is_announce(&self) -> bool {
662681
if self.dev_cfg.features.contains(virtio_spec::net::F::STATUS) {
663-
self.dev_cfg.raw.get_status() & u16::from(Status::VIRTIO_NET_S_ANNOUNCE)
664-
== u16::from(Status::VIRTIO_NET_S_ANNOUNCE)
682+
self.dev_cfg
683+
.raw
684+
.as_ptr()
685+
.status()
686+
.read()
687+
.contains(virtio_spec::net::S::ANNOUNCE)
665688
} else {
666689
false
667690
}
@@ -675,7 +698,12 @@ impl VirtioNetDriver {
675698
#[allow(dead_code)]
676699
pub fn get_max_vq_pairs(&self) -> u16 {
677700
if self.dev_cfg.features.contains(virtio_spec::net::F::MQ) {
678-
self.dev_cfg.raw.get_max_virtqueue_pairs()
701+
self.dev_cfg
702+
.raw
703+
.as_ptr()
704+
.max_virtqueue_pairs()
705+
.read()
706+
.to_ne()
679707
} else {
680708
1
681709
}
@@ -838,7 +866,7 @@ impl VirtioNetDriver {
838866
debug!("{:?}", self.checksums);
839867

840868
if self.dev_cfg.features.contains(virtio_spec::net::F::MTU) {
841-
self.mtu = self.dev_cfg.raw.get_mtu();
869+
self.mtu = self.dev_cfg.raw.as_ptr().mtu().read().to_ne();
842870
}
843871

844872
Ok(())
@@ -924,10 +952,23 @@ impl VirtioNetDriver {
924952
// - the num_queues is found in the ComCfg struct of the device and defines the maximal number
925953
// of supported queues.
926954
if self.dev_cfg.features.contains(virtio_spec::net::F::MQ) {
927-
if self.dev_cfg.raw.get_max_virtqueue_pairs() * 2 >= MAX_NUM_VQ {
955+
if self
956+
.dev_cfg
957+
.raw
958+
.as_ptr()
959+
.max_virtqueue_pairs()
960+
.read()
961+
.to_ne() * 2 >= MAX_NUM_VQ
962+
{
928963
self.num_vqs = MAX_NUM_VQ;
929964
} else {
930-
self.num_vqs = self.dev_cfg.raw.get_max_virtqueue_pairs() * 2;
965+
self.num_vqs = self
966+
.dev_cfg
967+
.raw
968+
.as_ptr()
969+
.max_virtqueue_pairs()
970+
.read()
971+
.to_ne() * 2;
931972
}
932973
} else {
933974
// Minimal number of virtqueues defined in the standard v1.1. - 5.1.5 Step 1
@@ -1012,28 +1053,6 @@ impl VirtioNetDriver {
10121053
pub mod constants {
10131054
// Configuration constants
10141055
pub const MAX_NUM_VQ: u16 = 2;
1015-
1016-
/// Enum contains virtio's network device status
1017-
/// indiacted in the status field of the device's
1018-
/// configuration structure.
1019-
///
1020-
/// See Virtio specification v1.1. - 5.1.4
1021-
#[allow(dead_code, non_camel_case_types)]
1022-
#[derive(Copy, Clone, Debug)]
1023-
#[repr(u16)]
1024-
pub enum Status {
1025-
VIRTIO_NET_S_LINK_UP = 1 << 0,
1026-
VIRTIO_NET_S_ANNOUNCE = 1 << 1,
1027-
}
1028-
1029-
impl From<Status> for u16 {
1030-
fn from(stat: Status) -> Self {
1031-
match stat {
1032-
Status::VIRTIO_NET_S_LINK_UP => 1,
1033-
Status::VIRTIO_NET_S_ANNOUNCE => 2,
1034-
}
1035-
}
1036-
}
10371056
}
10381057

10391058
/// Error module of virtios network driver. Containing the (VirtioNetError)[VirtioNetError]

0 commit comments

Comments
 (0)