From 465a9fd754da7ba38f60bc9a296d88ecbe678623 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Wed, 23 Jul 2025 20:35:08 +0200 Subject: [PATCH 1/2] refactor(drivers/net): Move get_network_driver to drivers/net Signed-off-by: Jens Reidel --- src/drivers/net/mod.rs | 8 ++++++++ src/executor/device.rs | 17 +++++------------ src/executor/mod.rs | 6 +----- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/drivers/net/mod.rs b/src/drivers/net/mod.rs index b0b55276a1..c768634b6a 100644 --- a/src/drivers/net/mod.rs +++ b/src/drivers/net/mod.rs @@ -56,3 +56,11 @@ pub(crate) fn mtu() -> u16 { DEFAULT_MTU } } + +cfg_if::cfg_if! { + if #[cfg(not(feature = "pci"))] { + pub(crate) use crate::arch::kernel::mmio::get_network_driver; + } else { + pub(crate) use crate::drivers::pci::get_network_driver; + } +} diff --git a/src/executor/device.rs b/src/executor/device.rs index cfab994209..645d0fe9c6 100644 --- a/src/executor/device.rs +++ b/src/executor/device.rs @@ -18,11 +18,7 @@ use smoltcp::wire::{IpCidr, Ipv4Address, Ipv4Cidr}; use super::network::{NetworkInterface, NetworkState}; use crate::arch; -#[cfg(not(feature = "pci"))] -use crate::arch::kernel::mmio as hardware; -use crate::drivers::net::NetworkDriver; -#[cfg(feature = "pci")] -use crate::drivers::pci as hardware; +use crate::drivers::net::{NetworkDriver, get_network_driver}; use crate::mm::device_alloc::DeviceAlloc; /// Data type to determine the mac address @@ -42,7 +38,7 @@ impl HermitNet { impl<'a> NetworkInterface<'a> { #[cfg(feature = "dhcpv4")] pub(crate) fn create() -> NetworkState<'a> { - let (mtu, mac, checksums) = if let Some(driver) = hardware::get_network_driver() { + let (mtu, mac, checksums) = if let Some(driver) = get_network_driver() { let guard = driver.lock(); ( guard.get_mtu(), @@ -98,7 +94,7 @@ impl<'a> NetworkInterface<'a> { #[cfg(not(feature = "dhcpv4"))] pub(crate) fn create() -> NetworkState<'a> { - let (mtu, mac, checksums) = if let Some(driver) = hardware::get_network_driver() { + let (mtu, mac, checksums) = if let Some(driver) = get_network_driver() { let guard = driver.lock(); ( guard.get_mtu(), @@ -182,7 +178,7 @@ impl Device for HermitNet { } fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - if let Some(driver) = hardware::get_network_driver() { + if let Some(driver) = get_network_driver() { driver.lock().receive_packet() } else { None @@ -231,9 +227,6 @@ impl phy::TxToken for TxToken { where F: FnOnce(&mut [u8]) -> R, { - hardware::get_network_driver() - .unwrap() - .lock() - .send_packet(len, f) + get_network_driver().unwrap().lock().send_packet(len, f) } } diff --git a/src/executor/mod.rs b/src/executor/mod.rs index 95cb985c3a..c33a26b5e5 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -22,12 +22,8 @@ use hermit_sync::without_interrupts; use smoltcp::time::Instant; use crate::arch::core_local::*; -#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))] -use crate::drivers::mmio::get_network_driver; #[cfg(any(feature = "tcp", feature = "udp"))] -use crate::drivers::net::NetworkDriver; -#[cfg(all(any(feature = "tcp", feature = "udp"), feature = "pci"))] -use crate::drivers::pci::get_network_driver; +use crate::drivers::net::{NetworkDriver, get_network_driver}; use crate::errno::Errno; use crate::executor::task::AsyncTask; use crate::io; From 30da148977961e1080ed71382054ba795d55d4ec Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Tue, 15 Jul 2025 17:36:38 +0200 Subject: [PATCH 2/2] feat(drivers/net): Add loopback network driver The idea is that in the immediate future, this driver will be the fallback network driver. Once we support multiple interfaces, it should always be the driver for the loopback interface. Signed-off-by: Jens Reidel --- Cargo.toml | 1 + src/drivers/net/loopback.rs | 74 +++++++++++++++++++++++++++++++++++++ src/drivers/net/mod.rs | 30 ++++++++++++++- 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/drivers/net/loopback.rs diff --git a/Cargo.toml b/Cargo.toml index 09867f0fb7..88a0f8d665 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ fuse = ["pci", "dep:fuse-abi", "fuse-abi/num_enum"] gem-net = ["tcp", "dep:tock-registers"] idle-poll = [] log-target = [] +net = [] mmap = [] newlib = [] nostd = [] diff --git a/src/drivers/net/loopback.rs b/src/drivers/net/loopback.rs new file mode 100644 index 0000000000..6a03432f06 --- /dev/null +++ b/src/drivers/net/loopback.rs @@ -0,0 +1,74 @@ +use alloc::collections::vec_deque::VecDeque; +use alloc::vec::Vec; + +use hermit_sync::InterruptTicketMutex; + +use crate::drivers::net::NetworkDriver; +use crate::drivers::{Driver, InterruptLine}; +use crate::executor::device::{RxToken, TxToken}; +use crate::mm::device_alloc::DeviceAlloc; + +pub(crate) struct LoopbackDriver(VecDeque>); + +impl LoopbackDriver { + pub(crate) const fn new() -> Self { + Self(VecDeque::new()) + } +} + +impl Driver for LoopbackDriver { + fn get_interrupt_number(&self) -> InterruptLine { + // This is called by mmio / pci specific code, this driver + // is using neither. + unimplemented!() + } + + fn get_name(&self) -> &'static str { + "loopback" + } +} + +impl NetworkDriver for LoopbackDriver { + fn get_mac_address(&self) -> [u8; 6] { + // This matches Linux' behavior + [0; 6] + } + + fn get_mtu(&self) -> u16 { + // Technically Linux uses 2^16, which we cannot use until we switch + // to u32 for MTU + u16::MAX + } + + fn receive_packet(&mut self) -> Option<(RxToken, TxToken)> { + self.0 + .pop_front() + .map(move |buffer| (RxToken::new(buffer), TxToken::new())) + } + + fn send_packet(&mut self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + let mut buffer = Vec::with_capacity_in(len, DeviceAlloc); + buffer.resize(len, 0); + let result = f(&mut buffer); + self.0.push_back(buffer); + result + } + + fn has_packet(&self) -> bool { + !self.0.is_empty() + } + + fn set_polling_mode(&mut self, _value: bool) { + // no-op + } + + fn handle_interrupt(&mut self) { + // no-op + } +} + +pub(crate) static LOOPBACK: InterruptTicketMutex = + InterruptTicketMutex::new(LoopbackDriver::new()); diff --git a/src/drivers/net/mod.rs b/src/drivers/net/mod.rs index c768634b6a..8f50db2206 100644 --- a/src/drivers/net/mod.rs +++ b/src/drivers/net/mod.rs @@ -1,5 +1,13 @@ #[cfg(all(target_arch = "riscv64", feature = "gem-net"))] pub mod gem; +#[cfg(all( + not(any( + all(target_arch = "riscv64", feature = "gem-net", not(feature = "pci")), + all(target_arch = "x86_64", feature = "rtl8139"), + )), + feature = "net" +))] +pub mod loopback; #[cfg(all(target_arch = "x86_64", feature = "rtl8139"))] pub mod rtl8139; #[cfg(not(all(target_arch = "x86_64", feature = "rtl8139")))] @@ -58,9 +66,27 @@ pub(crate) fn mtu() -> u16 { } cfg_if::cfg_if! { - if #[cfg(not(feature = "pci"))] { + if #[cfg(all( + not(feature = "pci"), + not(all( + feature = "net", + not(all(target_arch = "riscv64", feature = "gem-net")) + )) + ))] { pub(crate) use crate::arch::kernel::mmio::get_network_driver; - } else { + } else if #[cfg(all( + feature = "pci", + not(all( + feature = "net", + not(all(target_arch = "x86_64", feature = "rtl8139")) + )) + ))] { pub(crate) use crate::drivers::pci::get_network_driver; + } else { + use hermit_sync::InterruptTicketMutex; + + pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex> { + Some(&loopback::LOOPBACK) + } } }