Skip to content

Commit

Permalink
add loopback
Browse files Browse the repository at this point in the history
  • Loading branch information
lhw2002426 committed Aug 21, 2024
1 parent 0d5ebe0 commit 5743f53
Show file tree
Hide file tree
Showing 20 changed files with 327 additions and 84 deletions.
7 changes: 6 additions & 1 deletion apps/c/httpclient/expect_info.out
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ Initialize platform devices...
Initialize device drivers...
registered a new Net device at .\+: "virtio-net"
Initialize network subsystem...
use NIC 0: "virtio-net"
net stack: smoltcp
use NIC: "loopback"
created net interface "loopback":
ether: 00-00-00-00-00-00
ip: 127.0.0.1/24
use NIC: "virtio-net"
created net interface "eth0":
ether: 52-54-00-12-34-56
ip: 10.0.2.15/24
Expand Down
1 change: 1 addition & 0 deletions crates/driver_net/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ documentation = "https://rcore-os.github.io/arceos/driver_net/index.html"

[features]
default = []
loopback = []
ixgbe = ["dep:ixgbe-driver"]

[dependencies]
Expand Down
3 changes: 3 additions & 0 deletions crates/driver_net/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ use alloc::sync::Arc;
#[cfg(feature = "ixgbe")]
/// ixgbe NIC device driver.
pub mod ixgbe;
#[cfg(feature = "loopback")]
/// loopback device driver
pub mod loopback;
mod net_buf;

use core::ptr::NonNull;
Expand Down
131 changes: 131 additions & 0 deletions crates/driver_net/src/loopback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Ruxos] is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
use crate::{EthernetAddress, NetBuf, NetBufBox, NetBufPool, NetBufPtr, NetDriverOps};
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use driver_common::{BaseDriverOps, DevError, DevResult, DeviceType};

extern crate alloc;

const NET_BUF_LEN: usize = 1526;

/// The VirtIO network device driver.
///
/// `QS` is the VirtIO queue size.
pub struct LoopbackDevice {
mac_address: EthernetAddress,
pub(crate) queue: VecDeque<NetBufBox>,
buf_pool: Arc<NetBufPool>,
}

unsafe impl Send for LoopbackDevice {}
unsafe impl Sync for LoopbackDevice {}

impl LoopbackDevice {
/// Creates a new driver instance and initializes the device
pub fn new(mac_address: Option<[u8; 6]>) -> Self {
let buf_pool = match NetBufPool::new(1024, NET_BUF_LEN) {
Ok(pool) => pool,
Err(_) => {
panic!("fail to create netbufpool");
}
};
Self {
mac_address: match mac_address {
Some(address) => EthernetAddress(address),
None => EthernetAddress([0; 6]),
},
queue: VecDeque::new(),
buf_pool: buf_pool,
}
}
}

impl BaseDriverOps for LoopbackDevice {
fn device_name(&self) -> &str {
"loopback"
}

fn device_type(&self) -> DeviceType {
DeviceType::Net
}
}

use log::info;

impl NetDriverOps for LoopbackDevice {
#[inline]
fn mac_address(&self) -> EthernetAddress {
EthernetAddress(self.mac_address.0)
}

#[inline]
fn can_transmit(&self) -> bool {
true
}

#[inline]
fn can_receive(&self) -> bool {
!self.queue.is_empty()
}

#[inline]
fn rx_queue_size(&self) -> usize {
self.queue.len()
}

#[inline]
fn tx_queue_size(&self) -> usize {
self.queue.len()
}

fn fill_rx_buffers(&mut self, buf_pool: &Arc<NetBufPool>) -> DevResult {
Ok(())
}

fn recycle_rx_buffer(&mut self, rx_buf: NetBufPtr) -> DevResult {
Ok(())
}

fn recycle_tx_buffers(&mut self) -> DevResult {
Ok(())
}

fn prepare_tx_buffer(&self, tx_buf: &mut NetBuf, pkt_len: usize) -> DevResult {
Ok(())
}

fn transmit(&mut self, tx_buf: NetBufPtr) -> DevResult {
unsafe { self.queue.push_back(NetBuf::from_buf_ptr(tx_buf)) }
Ok(())
}

fn receive(&mut self) -> DevResult<NetBufPtr> {
if let Some(token) = self.queue.pop_front() {
Ok(token.into_buf_ptr())
} else {
Err(DevError::Again)
}
}

fn alloc_tx_buffer(&mut self, size: usize) -> DevResult<NetBufPtr> {
let mut net_buf = self.buf_pool.alloc_boxed().ok_or(DevError::NoMemory)?;
let pkt_len = size;

// 1. Check if the buffer is large enough.
let hdr_len = net_buf.header_len();
if hdr_len + pkt_len > net_buf.capacity() {
return Err(DevError::InvalidParam);
}
net_buf.set_packet_len(pkt_len);

// 2. Return the buffer.
Ok(net_buf.into_buf_ptr())
}
}
5 changes: 1 addition & 4 deletions crates/lwip_rust/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::path::PathBuf;

fn main() {
println!("cargo:rustc-link-lib=lwip");
println!("cargo:rerun-if-changed=custom");
Expand Down Expand Up @@ -28,9 +26,8 @@ fn generate_lwip_bindings() {
.generate()
.expect("Unable to generate bindings");

let out_path = PathBuf::from("src");
bindings
.write_to_file(out_path.join("bindings.rs"))
.write_to_file("src/bindings.rs")
.expect("Couldn't write bindings!");
}

Expand Down
4 changes: 2 additions & 2 deletions crates/lwip_rust/custom/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#define LWIP_TCP 1
#define LWIP_CALLBACK_API 1
#define LWIP_NETIF_API 0
#define LWIP_NETIF_LOOPBACK 0
#define LWIP_HAVE_LOOPIF 1
#define LWIP_NETIF_LOOPBACK 1
#define LWIP_HAVE_LOOPIF 0
#define LWIP_HAVE_SLIPIF 0
#define LWIP_NETCONN 0
#define LWIP_SOCKET 0
Expand Down
1 change: 1 addition & 0 deletions modules/ruxdriver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ virtio-9p = ["_9p","virtio", "driver_virtio/v9p"]
ramdisk = ["block", "driver_block/ramdisk"]
bcm2835-sdhci = ["block", "driver_block/bcm2835-sdhci"]
ixgbe = ["net", "driver_net/ixgbe", "dep:axalloc", "dep:ruxhal"]
loopback = ["driver_net/loopback", "dyn"]
# more devices example: e1000 = ["net", "driver_net/e1000"]

default = ["bus-mmio"]
Expand Down
2 changes: 1 addition & 1 deletion modules/ruxdriver/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* See the Mulan PSL v2 for more details.
*/

const NET_DEV_FEATURES: &[&str] = &["ixgbe", "virtio-net"];
const NET_DEV_FEATURES: &[&str] = &["ixgbe", "virtio-net", "loopback"];
const BLOCK_DEV_FEATURES: &[&str] = &["ramdisk", "bcm2835-sdhci", "virtio-blk"];
const DISPLAY_DEV_FEATURES: &[&str] = &["virtio-gpu"];
const _9P_DEV_FEATURES: &[&str] = &["virtio-9p"];
Expand Down
17 changes: 17 additions & 0 deletions modules/ruxdriver/src/drivers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@ pub trait DriverProbe {
}
}

cfg_if::cfg_if! {
if #[cfg(net_dev = "loopback")]
{
pub struct LoopbackDriver;
register_net_driver!(LoopbackDriver, driver_net::loopback::LoopbackDevice);

impl DriverProbe for LoopbackDriver {
fn probe_global() -> Option<AxDeviceEnum> {
debug!("mmc probe");
Some(AxDeviceEnum::from_net(
driver_net::loopback::LoopbackDevice::new(None),
))
}
}
}
}

#[cfg(net_dev = "virtio-net")]
register_net_driver!(
<virtio::VirtIoNet as VirtIoDevMeta>::Driver,
Expand Down
6 changes: 6 additions & 0 deletions modules/ruxdriver/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ macro_rules! for_each_drivers {
#[allow(unused_imports)]
use crate::virtio::{self, VirtIoDevMeta};

#[cfg(net_dev = "loopback")]
{
type $drv_type = crate::drivers::LoopbackDriver;
$code
}

#[cfg(net_dev = "virtio-net")]
{
type $drv_type = <virtio::VirtIoNet as VirtIoDevMeta>::Driver;
Expand Down
2 changes: 1 addition & 1 deletion modules/ruxfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ features = [ # no std
]

[dev-dependencies]
ruxdriver = { path = "../ruxdriver", features = ["block", "ramdisk"] }
ruxdriver = { path = "../ruxdriver", features = ["block", "ramdisk", "dyn"] }
driver_block = { path = "../../crates/driver_block", features = ["ramdisk"] }
axsync = { path = "../axsync", features = ["multitask"] }
ruxtask = { path = "../ruxtask", features = ["test"] }
4 changes: 3 additions & 1 deletion modules/ruxfs/tests/test_fatfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ fn test_fatfs() {
// By default, mount_points[0] will be rootfs
let mut mount_points: Vec<ruxfs::MountPoint> = Vec::new();
// setup and initialize blkfs as one mountpoint for rootfs
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(disk)));
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(Box::new(
disk,
))));
ruxfs::prepare_commonfs(&mut mount_points);

// setup and initialize rootfs
Expand Down
4 changes: 2 additions & 2 deletions modules/ruxfs/tests/test_ramfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ fn test_ramfs() {
// By default, mount_points[0] will be rootfs
let mut mount_points: Vec<ruxfs::MountPoint> = Vec::new();
// setup and initialize blkfs as one mountpoint for rootfs
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(Box::new(
RamDisk::default(),
)));
))));
ruxfs::prepare_commonfs(&mut mount_points);

// setup and initialize rootfs
Expand Down
3 changes: 2 additions & 1 deletion modules/ruxnet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ documentation = "https://rcore-os.github.io/arceos/ruxnet/index.html"

[features]
lwip = ["dep:lwip_rust"]
loopback = ["ruxdriver/loopback"]
smoltcp = []
default = ["smoltcp"]
default = ["smoltcp", "loopback"]

[dependencies]
log = "0.4"
Expand Down
9 changes: 6 additions & 3 deletions modules/ruxnet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ use ruxdriver::{prelude::*, AxDeviceContainer};
pub fn init_network(mut net_devs: AxDeviceContainer<AxNetDevice>) {
info!("Initialize network subsystem...");

let dev = net_devs.take_one().expect("No NIC device found!");
info!(" use NIC 0: {:?}", dev.device_name());
cfg_if::cfg_if! {
if #[cfg(feature = "lwip")] {
info!(" net stack: lwip");
Expand All @@ -74,5 +72,10 @@ pub fn init_network(mut net_devs: AxDeviceContainer<AxNetDevice>) {
compile_error!("No network stack is selected");
}
}
net_impl::init(dev);
net_impl::init();
while !net_devs.is_empty() {
let dev = net_devs.take_one().expect("No NIC device found!");
info!(" use NIC: {:?}", dev.device_name());
net_impl::init_netdev(dev);
}
}
Loading

0 comments on commit 5743f53

Please sign in to comment.