Skip to content

Commit

Permalink
network drivers create directly TxToken / RxToken for smoltcp
Browse files Browse the repository at this point in the history
For this purpose, it was necessary to avoid the creation of dynamic
objects of the driver. This means that during compilation it must
be defined which network interface is used. If the feature `rtl8139`
is activated, the driver for Realtek 8139 will be used. Otherwise the
Virtio network interface will be used.
  • Loading branch information
stlankes committed Jul 31, 2023
1 parent 42642ec commit 3c7299e
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 192 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ acpi = []
smp = ["include-transformed"]
fsgsbase = []
trace = []
rtl8139 = ["tcp", "pci"]
tcp = [
"smoltcp",
]
Expand Down
7 changes: 3 additions & 4 deletions src/arch/x86_64/kernel/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::arch::x86_64::mm::paging::{
};
use crate::arch::x86_64::mm::{paging, PhysAddr};
use crate::drivers::net::virtio_net::VirtioNetDriver;
use crate::drivers::net::NetworkInterface;
use crate::drivers::virtio::transport::mmio as mmio_virtio;
use crate::drivers::virtio::transport::mmio::{DevId, MmioRegisterLayout, VirtioDriver};

Expand All @@ -27,7 +26,7 @@ pub(crate) enum MmioDriver {

impl MmioDriver {
#[allow(unreachable_patterns)]
fn get_network_driver(&self) -> Option<&InterruptTicketMutex<dyn NetworkInterface>> {
fn get_network_driver(&self) -> Option<&InterruptTicketMutex<VirtioNetDriver>> {
match self {
Self::VirtioNet(drv) => Some(drv),
_ => None,
Expand Down Expand Up @@ -122,11 +121,11 @@ pub(crate) fn register_driver(drv: MmioDriver) {
}
}

pub fn get_network_driver() -> Option<&'static InterruptTicketMutex<dyn NetworkInterface>> {
pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex<VirtioNetDriver>> {
unsafe { MMIO_DRIVERS.iter().find_map(|drv| drv.get_network_driver()) }
}

pub fn init_drivers() {
pub(crate) fn init_drivers() {
// virtio: MMIO Device Discovery
without_interrupts(|| {
if let Ok(mmio) = detect_network() {
Expand Down
8 changes: 4 additions & 4 deletions src/drivers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ pub mod virtio;
pub mod error {
use core::fmt;

#[cfg(all(feature = "pci", not(target_arch = "aarch64")))]
#[cfg(feature = "rtl8139")]
use crate::drivers::net::rtl8139::RTL8139Error;
use crate::drivers::virtio::error::VirtioError;

#[derive(Debug)]
pub enum DriverError {
InitVirtioDevFail(VirtioError),
#[cfg(all(feature = "pci", not(target_arch = "aarch64")))]
#[cfg(feature = "rtl8139")]
InitRTL8139DevFail(RTL8139Error),
}

Expand All @@ -29,7 +29,7 @@ pub mod error {
}
}

#[cfg(all(feature = "pci", not(target_arch = "aarch64")))]
#[cfg(feature = "rtl8139")]
impl From<RTL8139Error> for DriverError {
fn from(err: RTL8139Error) -> Self {
DriverError::InitRTL8139DevFail(err)
Expand All @@ -42,7 +42,7 @@ pub mod error {
DriverError::InitVirtioDevFail(ref err) => {
write!(f, "Virtio driver failed: {err:?}")
}
#[cfg(all(feature = "pci", not(target_arch = "aarch64")))]
#[cfg(feature = "rtl8139")]
DriverError::InitRTL8139DevFail(ref err) => {
write!(f, "RTL8139 driver failed: {err:?}")
}
Expand Down
26 changes: 12 additions & 14 deletions src/drivers/net/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#[cfg(all(feature = "pci", not(target_arch = "aarch64")))]
#[cfg(feature = "rtl8139")]
pub mod rtl8139;
#[cfg(not(feature = "pci"))]
#[cfg(all(not(feature = "pci"), not(feature = "rtl8139")))]
pub mod virtio_mmio;
#[cfg(not(feature = "rtl8139"))]
pub mod virtio_net;
#[cfg(feature = "pci")]
#[cfg(all(feature = "pci", not(feature = "rtl8139")))]
pub mod virtio_pci;

#[cfg(target_arch = "x86_64")]
Expand All @@ -18,25 +19,22 @@ use crate::arch::kernel::mmio as hardware;
use crate::arch::scheduler::State;
#[cfg(feature = "pci")]
use crate::drivers::pci as hardware;
use crate::executor::device::{RxToken, TxToken};

/// A trait for accessing the network interface
pub trait NetworkInterface {
pub(crate) trait NetworkDriver {
/// Returns the mac address of the device.
fn get_mac_address(&self) -> [u8; 6];
/// Returns the current MTU of the device.
fn get_mtu(&self) -> u16;
/// Get buffer to create a TX packet
///
/// This returns ownership of the TX buffer.
fn get_tx_buffer(&mut self, len: usize) -> Result<(*mut u8, usize), ()>;
/// Frees the TX buffer (takes ownership)
fn free_tx_buffer(&self, token: usize);
/// Send TC packets (takes TX buffer ownership)
fn send_tx_buffer(&mut self, tkn_handle: usize, len: usize) -> Result<(), ()>;
/// Get buffer with the received packet
fn receive_packet(&mut self) -> Option<(RxToken, TxToken)>;
/// Send packet with the size `len`
fn send_packet<R, F>(&mut self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R;
/// Check if a packet is available
fn has_packet(&self) -> bool;
/// Get RX buffer with an received packet
fn receive_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<usize, ()>;
/// Enable / disable the polling mode of the network interface
fn set_polling_mode(&mut self, value: bool);
/// Handle interrupt and check if a packet is available
Expand Down
65 changes: 30 additions & 35 deletions src/drivers/net/rtl8139.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use crate::arch::mm::paging::virt_to_phys;
use crate::arch::mm::VirtAddr;
use crate::arch::pci::PciConfigRegion;
use crate::drivers::error::DriverError;
use crate::drivers::net::{network_irqhandler, NetworkInterface};
use crate::drivers::net::{network_irqhandler, NetworkDriver};
use crate::drivers::pci::{PciCommand, PciDevice};
use crate::executor::device::{RxToken, TxToken};

/// size of the receive buffer
const RX_BUF_LEN: usize = 8192;
Expand Down Expand Up @@ -213,7 +214,7 @@ pub(crate) struct RTL8139Driver {
polling_mode_counter: u32,
}

impl NetworkInterface for RTL8139Driver {
impl NetworkDriver for RTL8139Driver {
/// Returns the MAC address of the network interface
fn get_mac_address(&self) -> [u8; 6] {
self.mac
Expand All @@ -224,37 +225,32 @@ impl NetworkInterface for RTL8139Driver {
self.mtu
}

fn get_tx_buffer(&mut self, len: usize) -> Result<(*mut u8, usize), ()> {
/// Send packet with the size `len`
fn send_packet<R, F>(&mut self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let id = self.tx_counter % NO_TX_BUFFERS;

if self.tx_in_use[id] || len > TX_BUF_LEN {
trace!("Unable to get TX buffer");
Err(())
panic!("Unable to get TX buffer");
} else {
self.tx_in_use[id] = true;
self.tx_counter += 1;

Ok((
self.txbuffer[id * TX_BUF_LEN..][..TX_BUF_LEN].as_mut_ptr(),
id,
))
}
}
let buffer = &mut self.txbuffer[id * TX_BUF_LEN..][..len];
let result = f(buffer);

fn free_tx_buffer(&self, _token: usize) {
// get_tx_buffer did not allocate
}
// send the packet
unsafe {
outl(
self.iobase + TSD0 + (4 * id as u16),
len.try_into().unwrap(),
); //|0x3A0000);
}

fn send_tx_buffer(&mut self, id: usize, len: usize) -> Result<(), ()> {
// send the packet
unsafe {
outl(
self.iobase + TSD0 + (4 * id as u16),
len.try_into().unwrap(),
); //|0x3A0000);
result
}

Ok(())
}

fn has_packet(&self) -> bool {
Expand All @@ -271,7 +267,8 @@ impl NetworkInterface for RTL8139Driver {
false
}

fn receive_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<usize, ()> {
/// Get buffer with the received packet
fn receive_packet(&mut self) -> Option<(RxToken, TxToken)> {
let cmd = unsafe { inb(self.iobase + CR) };

if (cmd & CR_BUFE) != CR_BUFE {
Expand All @@ -284,29 +281,27 @@ impl NetworkInterface for RTL8139Driver {

// do we reach the end of the receive buffers?
// in this case, we conact the two slices to one vec
if pos + length as usize > RX_BUF_LEN {
buffer[..RX_BUF_LEN - pos].copy_from_slice(&self.rxbuffer[pos..RX_BUF_LEN]);
buffer[RX_BUF_LEN - pos..usize::from(length)].copy_from_slice(
&self.rxbuffer[0..usize::from(length) - (RX_BUF_LEN - pos)],
);
let vec_data = if pos + length as usize > RX_BUF_LEN {
let first = &self.rxbuffer[pos..RX_BUF_LEN];
let second = &self.rxbuffer[..length as usize - first.len()];
[first, second].concat()
} else {
buffer[..length.into()]
.copy_from_slice(&self.rxbuffer[pos..pos + usize::from(length)]);
(self.rxbuffer[pos..][..length.into()]).to_vec()
};

self.consume_current_buffer();

Ok(length.into())
Some((RxToken::new(vec_data), TxToken::new()))
} else {
error!(
warn!(
"RTL8192: invalid header {:#x}, rx_pos {}\n",
header, self.rxpos
);

Err(())
None
}
} else {
Err(())
None
}
}

Expand Down
Loading

0 comments on commit 3c7299e

Please sign in to comment.