Skip to content

Commit 4077a95

Browse files
committed
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 <[email protected]>
1 parent e28a23f commit 4077a95

File tree

5 files changed

+120
-17
lines changed

5 files changed

+120
-17
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ fuse = ["pci", "dep:fuse-abi", "fuse-abi/num_enum"]
5656
gem-net = ["tcp", "dep:tock-registers"]
5757
idle-poll = []
5858
log-target = []
59+
loopback = []
5960
mmap = []
6061
newlib = []
6162
nostd = []

src/drivers/net/loopback.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use alloc::collections::vec_deque::VecDeque;
2+
use alloc::vec::Vec;
3+
4+
use hermit_sync::InterruptTicketMutex;
5+
6+
use crate::drivers::net::NetworkDriver;
7+
use crate::drivers::{Driver, InterruptLine};
8+
use crate::executor::device::{RxToken, TxToken};
9+
use crate::mm::device_alloc::DeviceAlloc;
10+
11+
pub(crate) struct LoopbackDriver(VecDeque<Vec<u8, DeviceAlloc>>);
12+
13+
impl LoopbackDriver {
14+
pub(crate) const fn new() -> Self {
15+
Self(VecDeque::new())
16+
}
17+
}
18+
19+
impl Driver for LoopbackDriver {
20+
fn get_interrupt_number(&self) -> InterruptLine {
21+
// This is called by mmio / pci specific code, this driver
22+
// is using neither.
23+
unimplemented!()
24+
}
25+
26+
fn get_name(&self) -> &'static str {
27+
"loopback"
28+
}
29+
}
30+
31+
impl NetworkDriver for LoopbackDriver {
32+
fn get_mac_address(&self) -> [u8; 6] {
33+
// This matches Linux' behaviour
34+
[0; 6]
35+
}
36+
37+
fn get_mtu(&self) -> u16 {
38+
// This matches Linux' behaviour
39+
u16::MAX
40+
}
41+
42+
fn receive_packet(
43+
&mut self,
44+
) -> Option<(
45+
crate::executor::device::RxToken,
46+
crate::executor::device::TxToken,
47+
)> {
48+
self.0
49+
.pop_front()
50+
.map(move |buffer| (RxToken::new(buffer), TxToken::new()))
51+
}
52+
53+
fn send_packet<R, F>(&mut self, len: usize, f: F) -> R
54+
where
55+
F: FnOnce(&mut [u8]) -> R,
56+
{
57+
let mut buffer = Vec::with_capacity_in(len, DeviceAlloc);
58+
buffer.resize(len, 0);
59+
let result = f(&mut buffer);
60+
self.0.push_back(buffer);
61+
result
62+
}
63+
64+
fn has_packet(&self) -> bool {
65+
!self.0.is_empty()
66+
}
67+
68+
fn set_polling_mode(&mut self, _value: bool) {
69+
// no-op
70+
}
71+
72+
fn handle_interrupt(&mut self) {
73+
// no-op
74+
}
75+
}
76+
77+
pub(crate) static LOOPBACK: InterruptTicketMutex<LoopbackDriver> =
78+
InterruptTicketMutex::new(LoopbackDriver::new());

src/drivers/net/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
#[cfg(all(target_arch = "riscv64", feature = "gem-net"))]
22
pub mod gem;
3+
#[cfg(all(
4+
not(any(
5+
all(target_arch = "riscv64", feature = "gem-net"),
6+
all(target_arch = "x86_64", feature = "rtl8139"),
7+
)),
8+
feature = "loopback"
9+
))]
10+
pub mod loopback;
311
#[cfg(all(target_arch = "x86_64", feature = "rtl8139"))]
412
pub mod rtl8139;
513
#[cfg(not(all(target_arch = "x86_64", feature = "rtl8139")))]
614
pub mod virtio;
715

816
use core::str::FromStr;
917

18+
use cfg_if::cfg_if;
1019
use smoltcp::phy::ChecksumCapabilities;
1120

1221
#[allow(unused_imports)]
@@ -56,3 +65,29 @@ pub(crate) fn mtu() -> u16 {
5665
DEFAULT_MTU
5766
}
5867
}
68+
69+
cfg_if! {
70+
if #[cfg(all(
71+
not(feature = "pci"),
72+
not(all(
73+
feature = "loopback",
74+
not(all(target_arch = "riscv64", feature = "gem-net"))
75+
))
76+
))] {
77+
pub(crate) use crate::arch::kernel::mmio::get_network_driver;
78+
} else if #[cfg(all(
79+
feature = "pci",
80+
not(all(
81+
feature = "loopback",
82+
not(all(target_arch = "x86_64", feature = "rtl8139"))
83+
))
84+
))] {
85+
pub(crate) use crate::drivers::pci::get_network_driver;
86+
} else {
87+
use hermit_sync::InterruptTicketMutex;
88+
89+
pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex<loopback::LoopbackDriver>> {
90+
Some(&loopback::LOOPBACK)
91+
}
92+
}
93+
}

src/executor/device.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ use smoltcp::wire::{IpCidr, Ipv4Address, Ipv4Cidr};
1818

1919
use super::network::{NetworkInterface, NetworkState};
2020
use crate::arch;
21-
#[cfg(not(feature = "pci"))]
22-
use crate::arch::kernel::mmio as hardware;
23-
use crate::drivers::net::NetworkDriver;
24-
#[cfg(feature = "pci")]
25-
use crate::drivers::pci as hardware;
21+
use crate::drivers::net::{NetworkDriver, get_network_driver};
2622
use crate::mm::device_alloc::DeviceAlloc;
2723

2824
/// Data type to determine the mac address
@@ -42,7 +38,7 @@ impl HermitNet {
4238
impl<'a> NetworkInterface<'a> {
4339
#[cfg(feature = "dhcpv4")]
4440
pub(crate) fn create() -> NetworkState<'a> {
45-
let (mtu, mac, checksums) = if let Some(driver) = hardware::get_network_driver() {
41+
let (mtu, mac, checksums) = if let Some(driver) = get_network_driver() {
4642
let guard = driver.lock();
4743
(
4844
guard.get_mtu(),
@@ -98,7 +94,7 @@ impl<'a> NetworkInterface<'a> {
9894

9995
#[cfg(not(feature = "dhcpv4"))]
10096
pub(crate) fn create() -> NetworkState<'a> {
101-
let (mtu, mac, checksums) = if let Some(driver) = hardware::get_network_driver() {
97+
let (mtu, mac, checksums) = if let Some(driver) = get_network_driver() {
10298
let guard = driver.lock();
10399
(
104100
guard.get_mtu(),
@@ -182,7 +178,7 @@ impl Device for HermitNet {
182178
}
183179

184180
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
185-
if let Some(driver) = hardware::get_network_driver() {
181+
if let Some(driver) = get_network_driver() {
186182
driver.lock().receive_packet()
187183
} else {
188184
None
@@ -231,9 +227,6 @@ impl phy::TxToken for TxToken {
231227
where
232228
F: FnOnce(&mut [u8]) -> R,
233229
{
234-
hardware::get_network_driver()
235-
.unwrap()
236-
.lock()
237-
.send_packet(len, f)
230+
get_network_driver().unwrap().lock().send_packet(len, f)
238231
}
239232
}

src/executor/mod.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,8 @@ use hermit_sync::without_interrupts;
2222
use smoltcp::time::Instant;
2323

2424
use crate::arch::core_local::*;
25-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
26-
use crate::drivers::mmio::get_network_driver;
2725
#[cfg(any(feature = "tcp", feature = "udp"))]
28-
use crate::drivers::net::NetworkDriver;
29-
#[cfg(all(any(feature = "tcp", feature = "udp"), feature = "pci"))]
30-
use crate::drivers::pci::get_network_driver;
26+
use crate::drivers::net::{NetworkDriver, get_network_driver};
3127
use crate::errno::Errno;
3228
use crate::executor::task::AsyncTask;
3329
use crate::io;

0 commit comments

Comments
 (0)