Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiprocess loopback #146

Merged
merged 5 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ multitask = ["ruxfeat/multitask", "ruxtask/multitask", "dep:ruxfutex"]
fd = ["alloc"]
fs = ["dep:ruxfs", "ruxfeat/fs", "fd"]
net = ["dep:ruxnet", "ruxfeat/net", "fd"]
signal = ["ruxruntime/signal"]
signal = ["ruxruntime/signal", "ruxhal/signal"]
pipe = ["fd"]
select = ["fd"]
epoll = ["fd"]
Expand Down
3 changes: 2 additions & 1 deletion api/ruxos_posix_api/src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub mod getrandom;
pub mod io;
pub mod prctl;
pub mod resources;
pub mod rt_sig;
pub mod stat;
pub mod sys;
pub mod task;
Expand All @@ -39,6 +38,8 @@ pub mod pipe;
#[cfg(feature = "multitask")]
pub mod pthread;
#[cfg(feature = "signal")]
pub mod rt_sig;
#[cfg(feature = "signal")]
pub mod signal;

/// Invalid syscall
Expand Down
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/src/imp/pipe.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.
*/

use alloc::sync::{Weak, Arc};
use alloc::sync::{Arc, Weak};
use core::ffi::c_int;

use axerrno::{LinuxError, LinuxResult};
Expand Down
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/src/imp/pthread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ pub fn sys_exit_group(status: c_int) -> ! {
debug!("sys_exit_group <= status: {:#?}", status);

// TODO: exit all threads, send signal to all threads

// drop all file opened by current task
current().fs.lock().as_mut().unwrap().close_all_files();

Expand Down
42 changes: 37 additions & 5 deletions api/ruxos_posix_api/src/imp/rt_sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

use axerrno::LinuxError;

use crate::ctypes;
use crate::{
ctypes::{self, k_sigaction},
sys_sigaction,
};
use core::{
ffi::c_int,
sync::atomic::{AtomicUsize, Ordering},
Expand Down Expand Up @@ -84,12 +87,41 @@ pub fn sys_rt_sigprocmask(
}

/// sigaction syscall for A64 musl
pub fn sys_rt_sigaction(
///
/// TODO: if sa is 0, return now action
pub unsafe fn sys_rt_sigaction(
sig: c_int,
_sa: *const ctypes::sigaction,
_old: *mut ctypes::sigaction,
sa: *const ctypes::sigaction,
old: *mut ctypes::sigaction,
_sigsetsize: ctypes::size_t,
) -> c_int {
debug!("sys_rt_sigaction <= sig: {}", sig);
syscall_body!(sys_rt_sigaction, Ok(0))
syscall_body!(sys_rt_sigaction, {
if sa as u64 == 0 || old as u64 == 0 {
Err(LinuxError::EFAULT)
} else {
let sa = unsafe { *sa };
let old = unsafe { *old };
let sa = k_sigaction::from(sa);
let mut old_sa = k_sigaction::from(old);
sys_sigaction(sig as _, Some(&sa), Some(&mut old_sa));
Ok(0)
}
})
}

impl From<ctypes::sigaction> for k_sigaction {
fn from(sa: ctypes::sigaction) -> Self {
let mut ret = Self {
..Default::default()
};
ret.flags = sa.sa_flags as _;
let mask = sa.sa_mask.__bits[0]; // only get the first 64 signals
ret.mask[0] = mask as _;
ret.mask[1] = (mask >> 32) as _;

ret.handler = unsafe { sa.__sa_handler.sa_handler };
ret.restorer = sa.sa_restorer;
ret
}
}
18 changes: 15 additions & 3 deletions api/ruxos_posix_api/src/imp/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,20 @@ pub unsafe fn sys_sigaltstack(
syscall_body!(sys_sigaltstack, Ok(0))
}

/// TODO: send a signal to a process
pub unsafe fn sys_kill(pid: pid_t, sig: c_int) -> c_int {
/// send a signal to a process
pub fn sys_kill(pid: pid_t, sig: c_int) -> c_int {
debug!("sys_kill <= pid {} sig {}", pid, sig);
syscall_body!(sys_kill, Ok(0))
syscall_body!(sys_kill, {
match Signal::signal(sig as _, true) {
None => Err(LinuxError::EINVAL),
Some(_) => Ok(0),
}
})
}

/// send a signal to a thread
/// TODO: send to the specified thread.
pub fn sys_tkill(tid: pid_t, sig: c_int) -> c_int {
debug!("sys_tkill <= tid {} sig {}", tid, sig);
sys_kill(tid, sig)
}
4 changes: 2 additions & 2 deletions api/ruxos_posix_api/src/imp/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub fn sys_wait4(
// lower 8 bits of exit_code is the signal number, while upper 8 bits of exit_code is the exit status
// according to "bits/waitstatus.h" in glibc source code.
// TODO: add signal number to wstatus
wstatus.write(task.exit_code()<<8);
wstatus.write(task.exit_code() << 8);
}
process_map.remove(&(pid as u64));
return pid;
Expand Down Expand Up @@ -108,7 +108,7 @@ pub fn sys_wait4(
// lower 8 bits of exit_code is the signal number, while upper 8 bits of exit_code is the exit status
// according to "bits/waitstatus.h" in glibc source code.
// TODO: add signal number to wstatus
wstatus.write(task.exit_code()<<8);
wstatus.write(task.exit_code() << 8);
}
let _ = to_remove.insert(*child_pid);
break;
Expand Down
11 changes: 8 additions & 3 deletions api/ruxos_posix_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ pub use imp::getrandom::{sys_getrandom, sys_rand, sys_random, sys_srand};
pub use imp::io::{sys_read, sys_readv, sys_write, sys_writev};
pub use imp::prctl::{sys_arch_prctl, sys_prctl};
pub use imp::resources::{sys_getrlimit, sys_prlimit64, sys_setrlimit};
pub use imp::rt_sig::{sys_rt_sigaction, sys_rt_sigprocmask};
pub use imp::stat::{
sys_getegid, sys_geteuid, sys_getgid, sys_getpgid, sys_getuid, sys_setgid, sys_setpgid,
sys_setuid, sys_umask,
Expand Down Expand Up @@ -108,7 +107,11 @@ pub use imp::pthread::{
sys_pthread_setspecific,
};
#[cfg(feature = "signal")]
pub use imp::signal::{sys_getitimer, sys_kill, sys_setitimer, sys_sigaction, sys_sigaltstack};
pub use imp::rt_sig::{sys_rt_sigaction, sys_rt_sigprocmask};
#[cfg(feature = "signal")]
pub use imp::signal::{
sys_getitimer, sys_kill, sys_setitimer, sys_sigaction, sys_sigaltstack, sys_tkill,
};

#[cfg(feature = "multitask")]
pub use imp::pthread::futex::sys_futex;
Expand All @@ -117,7 +120,9 @@ pub use imp::pthread::sys_clone;
#[cfg(all(feature = "multitask", feature = "musl"))]
pub use imp::pthread::sys_set_tid_address;
#[cfg(feature = "multitask")]
pub use imp::pthread::{sys_pthread_create, sys_pthread_exit, sys_exit_group, sys_pthread_join, sys_pthread_self};
pub use imp::pthread::{
sys_exit_group, sys_pthread_create, sys_pthread_exit, sys_pthread_join, sys_pthread_self,
};

#[cfg(feature = "fs")]
pub use imp::execve::sys_execve;
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
Loading
Loading