Compare commits

...

27 Commits

Author SHA1 Message Date
Luoyuan Xiao 2c903512c8 network functions testing 2022-05-20 00:12:42 +08:00
Luoyuan Xiao ae8450f87c
Merge pull request #244 from shzhxh/net-testing
update test scripts
2021-12-06 16:45:58 +08:00
shzhxh ec695dcac8 update test scripts 2021-12-06 16:42:38 +08:00
GCYY 59181a89f0 add loopback net function 2021-11-02 12:31:58 +08:00
GCYY 475a335d7b fmt 2021-10-31 12:41:58 +08:00
GCYY a7a26829ac Modify ip addr 2021-10-31 00:45:48 +08:00
GCYY 6ea8243554 Merge branch 'net-testing' of https://github.com/rcore-os/zCore into net-testing 2021-10-28 20:23:28 +08:00
Luoyuan Xiao fb13d4078f
Update rtl8211f.rs 2021-10-28 14:39:16 +08:00
elliott10 5d8ce43ca1 Add all network testing threads into future-executor 2021-10-22 21:04:24 +08:00
Luoyuan Xiao 348094a644
Merge pull request #235 from rcore-os/net-testing-pr
add kernel-state network verification function
2021-10-22 18:28:38 +08:00
GCYY c7a4652230 add kernel-state network verification function 2021-10-22 16:26:21 +08:00
Luoyuan Xiao bb99eefe7e
Merge pull request #234 from rcore-os/net-testing-pr
enable user state tcp and udp
2021-10-21 11:26:01 +08:00
GCYY 133e2c75ef modify some net display info 2021-10-20 21:06:30 +08:00
GCYY 4b1123686a modify some net display info 2021-10-20 20:58:33 +08:00
GCYY 953b8d58f4 Merge branch 'net-testing' of https://github.com/rcore-os/zCore into net-testing 2021-10-20 20:12:05 +08:00
GCYY 67b6796757 fmt code 2021-10-20 20:11:31 +08:00
GCYY 535b41e70a modify udp and icmp 2021-10-20 20:10:38 +08:00
GCYY 1110f894a1 modify to make tcp work 2021-10-19 18:25:47 +08:00
GCYY 011a87a003 modify code to adapt socket object 2021-10-19 15:07:43 +08:00
GCYY 99980683e0 add socket object and update smoltcp dependencies 2021-10-19 14:41:53 +08:00
GCYY a3df5ddb69 add socket syscall interface and fmt code 2021-10-19 14:28:01 +08:00
Luoyuan Xiao c5d829bc32
Merge pull request #232 from shzhxh/net-testing
add testcase
2021-10-19 14:23:51 +08:00
shzhxh 1990915537 add testcase 2021-10-19 12:09:51 +08:00
elliott10 a9d85db871 Enable PLIC Irq Manager 2021-10-15 19:57:49 +08:00
elliott10 1ba370de72 D1 board support network: ping, udp, tcp 2021-10-09 16:38:48 +08:00
elliott10 9d0fb90eb9 Virtio Network response PING by smoltcp 2021-10-03 21:24:44 +08:00
elliott10 9757df80ae Add virtio network driver 2021-09-26 22:24:40 +08:00
70 changed files with 10055 additions and 261 deletions

1
.gitignore vendored
View File

@ -17,4 +17,5 @@ stdout-zcore
scripts/script.sh
stdout-baremetal-test-rv64
stdout-rv64
zCore/fw-zCore.bin

View File

@ -99,3 +99,48 @@ Hello world from user mode program!
```
## 网络测试时的网桥
```
# 创建网桥
ip link add name br0 type bridge
ip link set br0 up
# 添加ip地址 (addr当前网卡地址)
ip addr add [addr] brd + dev br0
# 创建tuntap
ip tuntap add dev tap0 mode tap user own
ip link set dev tap0 up
# 添加进网桥
ip link set tap0 master br0
ip link set eth0 master br0
# 刷掉eth0的数据
ip addr flush dev eth0
# 把br0变成默认网关
ip route add default via [route] dev br0
```
## 执行测例
```
# zCore在D1上运行起来后测试主机上退出串口连接程序
cd scripts
# 运行第一部分的测例
cp linux/baremetal-test-ones.txt.1 linux/baremetal-test-ones.txt
sudo python3 baremetal-libc-test-d1.py
# 运行第二部分的测例
cp linux/baremetal-test-ones.txt.2 linux/baremetal-test-ones.txt
sudo python3 baremetal-libc-test-d1.py
# 运行第三部分的测例
cp linux/baremetal-test-ones.txt.3 linux/baremetal-test-ones.txt
sudo python3 baremetal-libc-test-d1.py
# 运行第四部分的测例
cp linux/baremetal-test-ones.txt.4 linux/baremetal-test-ones.txt
sudo python3 baremetal-libc-test-d1.py
# 运行网络的测例
sudo python3 baremetal-net-test-d1.py
```

View File

@ -10,6 +10,8 @@ description = "Kernel HAL implementation for bare metal environment."
[features]
board_qemu = []
board_d1 = []
loopback = []
rtl8x = []
[dependencies]
log = "0.4"
@ -20,13 +22,15 @@ trapframe = "0.8.0"
kernel-hal = { path = "../kernel-hal" }
naive-timer = "0.1.0"
lazy_static = { version = "1.4", features = ["spin_no_std"] }
uart_16550 = "=0.2.15"
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
device_tree = { git = "https://github.com/rcore-os/device_tree-rs" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "568276" }
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", rev = "fcf694d2", features = ["log"] }
#isomorphic_drivers = { path = "/home/xly/rust/arch-lib/isomorphic_drivers", features = ["log"] }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = "0.14"
uart_16550 = "=0.2.15"
raw-cpuid = "9.0"
pc-keyboard = "0.5"
apic = { git = "https://github.com/rcore-os/apic-rs", rev = "fb86bd7" }

View File

@ -23,32 +23,31 @@ pub const MMIO_MTIMECMP0: *mut u64 = 0x0200_4000usize as *mut u64;
pub const MMIO_MTIME: *const u64 = 0x0200_BFF8 as *const u64;
#[cfg(feature = "board_qemu")]
pub const UART_BASE: usize = 0x10000000;
pub const UART_BASE: usize = 0x10000000;
#[cfg(feature = "board_qemu")]
pub const UART0_INT_NUM: u32 = 10;
pub const UART0_INT_NUM: u32 = 10;
#[cfg(feature = "board_qemu")]
pub const PLIC_PRIORITY: usize = 0x0c000000;
pub const PLIC_PRIORITY: usize = 0x0c000000;
#[cfg(feature = "board_qemu")]
pub const PLIC_PENDING: usize = 0x0c001000;
pub const PLIC_PENDING: usize = 0x0c001000;
#[cfg(feature = "board_qemu")]
pub const PLIC_INT_ENABLE: usize = 0x0c002080;
#[cfg(feature = "board_qemu")]
pub const PLIC_THRESHOLD: usize = 0x0c201000;
pub const PLIC_THRESHOLD: usize = 0x0c201000;
#[cfg(feature = "board_qemu")]
pub const PLIC_CLAIM: usize = 0x0c201004;
pub const PLIC_CLAIM: usize = 0x0c201004;
#[cfg(feature = "board_d1")]
pub const UART_BASE: usize = 0x02500000;
pub const UART_BASE: usize = 0x02500000;
#[cfg(feature = "board_d1")]
pub const UART0_INT_NUM: u32 = 18;
pub const UART0_INT_NUM: u32 = 18;
#[cfg(feature = "board_d1")]
pub const PLIC_PRIORITY: usize = 0x1000_0000;
pub const PLIC_PRIORITY: usize = 0x1000_0000;
#[cfg(feature = "board_d1")]
pub const PLIC_PENDING: usize = 0x1000_1000;
pub const PLIC_PENDING: usize = 0x1000_1000;
#[cfg(feature = "board_d1")]
pub const PLIC_INT_ENABLE: usize = 0x1000_2080;
#[cfg(feature = "board_d1")]
pub const PLIC_THRESHOLD: usize = 0x1020_1000;
pub const PLIC_THRESHOLD: usize = 0x1020_1000;
#[cfg(feature = "board_d1")]
pub const PLIC_CLAIM: usize = 0x1020_1004;
pub const PLIC_CLAIM: usize = 0x1020_1004;

View File

@ -0,0 +1,63 @@
// c906
const L1_CACHE_BYTES: u64 = 64;
const CACHE_LINE_SIZE: u64 = 64;
pub fn flush_cache(addr: u64, size: u64) {
flush_dcache_range(addr, addr + size);
}
pub fn invalidate_dcache(addr: u64, size: u64) {
invalidate_dcache_range(addr, addr + size);
}
// 注意start输入物理地址
pub fn flush_dcache_range(start: u64, end: u64) {
// CACHE_LINE 64对齐
let end = (end + (CACHE_LINE_SIZE - 1)) & !(CACHE_LINE_SIZE - 1);
// 地址对齐到L1 Cache的节
let mut i: u64 = start & !(L1_CACHE_BYTES - 1);
while i < end {
unsafe {
// 老风格的llvm asm
// DCACHE 指定物理地址清脏表项
// llvm_asm!("dcache.cpa $0"::"r"(i));
// 新asm
asm!(".long 0x0295000b", in("a0") i); // dcache.cpa a0, 因编译器无法识别该指令
}
i += L1_CACHE_BYTES;
}
unsafe {
//llvm_asm!("sync.is");
asm!(".long 0x01b0000b"); // sync.is
}
}
// start 物理地址
pub fn invalidate_dcache_range(start: u64, end: u64) {
let end = (end + (CACHE_LINE_SIZE - 1)) & !(CACHE_LINE_SIZE - 1);
let mut i: u64 = start & !(L1_CACHE_BYTES - 1);
while i < end {
unsafe {
//llvm_asm!("dcache.ipa $0"::"r"(i)); // DCACHE 指定物理地址无效表项
asm!(".long 0x02a5000b", in("a0") i); // dcache.ipa a0
}
i += L1_CACHE_BYTES;
}
unsafe {
//llvm_asm!("sync.is");
asm!(".long 0x01b0000b"); // sync.is
}
}
pub fn fence_w() {
unsafe {
llvm_asm!("fence ow, ow" ::: "memory");
}
}

View File

@ -8,8 +8,9 @@ use riscv::register::{
use spin::Mutex;
use trapframe::{TrapFrame, UserContext};
use super::{plic, uart, sbi, timer_set_next};
use super::consts::{PHYSICAL_MEMORY_OFFSET, UART_BASE, UART0_INT_NUM};
use super::consts::{PHYSICAL_MEMORY_OFFSET, UART0_INT_NUM, UART_BASE};
use super::{plic, sbi, timer_set_next, uart};
use crate::drivers::IRQ_MANAGER;
use crate::{map_range, phys_to_virt, putfmt};
const TABLE_SIZE: usize = 256;
@ -20,19 +21,21 @@ lazy_static! {
fn init_irq() {
init_irq_table();
irq_add_handle(Timer, Box::new(super_timer)); //模拟参照了x86_64,把timer处理函数也放进去了
//irq_add_handle(Keyboard, Box::new(keyboard));
irq_add_handle(S_PLIC, Box::new(plic::handle_interrupt));
irq_add_handle(Timer, Box::new(super_timer));
//模拟参照了x86_64,把timer处理函数也放进去了
//irq_add_handle(Keyboard, Box::new(keyboard));
irq_add_handle(S_PLIC, Box::new(external));
}
pub fn init() {
unsafe {
sstatus::set_sie();
init_uart();
//init_uart();
sie::set_sext();
init_ext();
//init_ext();
}
init_irq();
@ -64,7 +67,7 @@ pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
Trap::Exception(Exception::InstructionPageFault) => page_fault(stval, tf),
Trap::Interrupt(Interrupt::SupervisorTimer) => super_timer(),
Trap::Interrupt(Interrupt::SupervisorSoft) => super_soft(),
Trap::Interrupt(Interrupt::SupervisorExternal) => plic::handle_interrupt(),
Trap::Interrupt(Interrupt::SupervisorExternal) => external(),
//Trap::Interrupt(Interrupt::SupervisorExternal) => irq_handle(code as u8),
_ => panic!("Undefined Trap: {:#x} {:#x}", is_int, code),
}
@ -77,9 +80,20 @@ fn init_irq_table() {
}
}
// Drivers IrqManager
pub fn enable_irq(irq: usize) {
// Handled in PLIC driver
}
fn external() {
IRQ_MANAGER
.read()
.try_handle_interrupt(Some(SupervisorExternal));
}
#[export_name = "hal_irq_handle"]
pub fn irq_handle(irq: u8) {
debug!("PLIC handle: {:#x}", irq);
trace!("hal_irq_handle: {:#x}", irq);
let table = IRQ_TABLE.lock();
match &table[irq as usize] {
Some(f) => f(),
@ -226,6 +240,8 @@ fn page_fault(stval: usize, tf: &mut TrapFrame) {
root_paddr: satp::read().frame().start_address().as_usize(),
};
// 这个pagefault handler还有些问题噢
let page = Page::of_addr(VirtAddr::new(vaddr));
if let Ok(pte) = pti.get().ref_entry(page) {
let pte = unsafe { &mut *(pte as *mut PageTableEntry) };
@ -347,6 +363,8 @@ fn keyboard() {
}
*/
const SupervisorExternal: usize = usize::MAX / 2 + 1 + 8;
// IRQ
const Timer: u8 = 5;
const U_PLIC: u8 = 8;

View File

@ -1,4 +1,6 @@
use super::super::*;
use alloc::{collections::VecDeque, string::String, vec, vec::Vec};
use core::fmt::{self, Write};
use kernel_hal::{
ColorDepth, ColorFormat, FramebufferInfo, HalError, PageTableTrait, PhysAddr, VirtAddr,
FRAME_BUFFER,
@ -7,13 +9,15 @@ use riscv::addr::Page;
use riscv::asm::sfence_vma_all;
use riscv::paging::{PageTableFlags as PTF, *};
use riscv::register::{satp, sie, stval, time};
//use crate::sbi;
use alloc::{collections::VecDeque, vec::Vec};
use core::fmt::{self, Write};
mod sbi;
use crate::drivers::{
device_tree::{self, Node},
irq, net, serial, virtio,
};
mod consts;
pub mod cpu_C906;
mod sbi;
use consts::*;
@ -98,6 +102,39 @@ pub fn remap_the_kernel(dtb: usize) {
)
.unwrap();
// GPIO/CCU
#[cfg(feature = "board_d1")]
map_range(
&mut pt,
phys_to_virt(0x0200_0000),
phys_to_virt(0x0200_0000) + PAGE_SIZE,
linear_offset,
PTF::VALID | PTF::READABLE | PTF::WRITABLE,
)
.unwrap();
//SYS_CFG
#[cfg(feature = "board_d1")]
map_range(
&mut pt,
phys_to_virt(0x0300_0000),
phys_to_virt(0x0300_0000) + PAGE_SIZE,
linear_offset,
PTF::VALID | PTF::READABLE | PTF::WRITABLE,
)
.unwrap();
//GMAC
#[cfg(feature = "board_d1")]
map_range(
&mut pt,
phys_to_virt(0x0450_0000),
phys_to_virt(0x0450_0000) + PAGE_SIZE,
linear_offset,
PTF::VALID | PTF::READABLE | PTF::WRITABLE,
)
.unwrap();
// PLIC
map_range(
&mut pt,
@ -222,7 +259,7 @@ impl PageTableImpl {
let current =
phys_to_virt(satp::read().frame().start_address().as_usize()) as *const PageTable;
map_kernel(root_vaddr as _, current as _);
trace!("create page table @ {:#x}", root_frame.paddr);
info!("create page table @ {:#x}", root_frame.paddr);
PageTableImpl {
root_paddr: root_frame.paddr,
}
@ -332,7 +369,7 @@ pub unsafe fn set_page_table(vmtoken: usize) {
let mode = satp::Mode::Sv32;
#[cfg(target_arch = "riscv64")]
let mode = satp::Mode::Sv39;
debug!("set user table: {:#x?}", vmtoken);
trace!("set user table: {:#x?}", vmtoken);
satp::set(mode, 0, vmtoken >> 12);
//刷TLB好像很重要
sfence_vma_all();
@ -389,11 +426,11 @@ lazy_static! {
//调用这里
/// Put a char by serial interrupt handler.
fn serial_put(mut x: u8) {
pub fn serial_put(mut x: u8) {
if (x == b'\r') || (x == b'\n') {
STDIN.lock().push_back(b'\n');
STDIN.lock().push_back(b'\r');
}else{
} else {
STDIN.lock().push_back(x);
}
STDIN_CALLBACK.lock().retain(|f| !f());
@ -474,10 +511,7 @@ struct Stdout1;
impl fmt::Write for Stdout1 {
fn write_str(&mut self, s: &str) -> fmt::Result {
//每次都创建一个新的Uart ? 内存位置始终相同
write!(
uart::Uart::new(phys_to_virt(UART_BASE)),
"{}", s
).unwrap();
write!(uart::Uart::new(phys_to_virt(UART_BASE)), "{}", s).unwrap();
Ok(())
}
@ -501,7 +535,7 @@ macro_rules! bare_println {
($($arg:tt)*) => (bare_print!("{}\n", format_args!($($arg)*)));
}
fn get_cycle() -> u64 {
pub fn get_cycle() -> u64 {
time::read() as u64
/*
unsafe {
@ -512,16 +546,19 @@ fn get_cycle() -> u64 {
#[export_name = "hal_timer_now"]
pub fn timer_now() -> Duration {
const FREQUENCY: u64 = 10_000_000; // ???
const FREQUENCY: u64 = 24_000_000; // ???
// 1_000_000_000
// clock / 频率 /
let time = get_cycle();
//bare_println!("timer_now(): {:?}", time);
Duration::from_nanos(time * 1_000_000_000 / FREQUENCY as u64)
Duration::from_nanos(((time / FREQUENCY) * 1_000_000_000) as u64)
// Duration::from_nanos(time / as u64)
}
#[export_name = "hal_timer_set_next"]
fn timer_set_next() {
//let TIMEBASE: u64 = 100000;
let TIMEBASE: u64 = 10_000_000;
let TIMEBASE: u64 = 240_000;
// let TIMEBASE: u64 = 25_000_000;
sbi::set_timer(get_cycle() + TIMEBASE);
}
@ -533,23 +570,72 @@ fn timer_init() {
}
pub fn init(config: Config) {
interrupt::init();
//interrupt::init();
timer_init();
/*
interrupt::init_soft();
sbi::send_ipi(0);
*/
unsafe {
llvm_asm!("ebreak"::::"volatile");
}
*/
#[cfg(feature = "board_qemu")]
{
bare_println!("Setup virtio @devicetree {:#x}", config.dtb);
drivers::virtio::device_tree::init(config.dtb);
irq::plic::driver_init();
//serial::uart16550::driver_init();
serial::uart::driver_init();
virtio::virtio::driver_init();
device_tree::init(config.dtb);
}
#[cfg(feature = "board_d1")]
{
let plic_node = Node {
name: String::from("plic"),
props: vec![
(
String::from("reg"),
vec![00, 00, 00, 00, 0x10, 0x00, 0x00, 0x00],
),
(String::from("phandle"), vec![00, 00, 00, 0x03]),
],
children: Vec::new(),
};
let uart_node = Node {
name: String::from("uart"),
props: vec![
(
String::from("reg"),
vec![00, 00, 00, 00, 0x02, 0x50, 0x00, 0x00],
),
(String::from("interrupts"), vec![00, 00, 00, 0x12]),
(String::from("interrupt-parent"), vec![00, 00, 00, 0x03]),
],
children: Vec::new(),
};
irq::plic::init_dt(&plic_node);
serial::uart::init_dt(&uart_node);
#[cfg(feature = "rtl8x")]
{
let gmacirq = 62;
net::rtl8x::init(String::from("rtl8211f"), Some(gmacirq));
}
#[cfg(feature = "loopback")]
{
net::loopback::init(String::from("loopback"));
}
}
interrupt::init();
}
pub struct Config {

View File

@ -1,7 +1,7 @@
use super::consts::*;
use super::interrupt;
use super::uart;
use crate::{putfmt, phys_to_virt};
use super::consts::*;
use crate::{phys_to_virt, putfmt};
//通过MMIO地址对平台级中断控制器PLIC的寄存器进行设置
//基于opensbi后一般运行于Hart0 S态为Target1
@ -79,6 +79,15 @@ pub fn handle_interrupt() {
1..=8 => {
//virtio::handle_interrupt(interrupt);
bare_println!("plic virtio external interrupt: {}", interrupt);
/*
if interrupt == 7 {
//virtio net irq
use crate::drivers::IRQ_MANAGER;
IRQ_MANAGER.read()
.try_handle_interrupt(Some(interrupt as usize));
}
*/
}
UART0_INT_NUM => {
//UART中断ID是10

View File

@ -1,5 +1,5 @@
use super::consts::UART_BASE;
use crate::{putfmt, phys_to_virt};
use crate::{phys_to_virt, putfmt};
use core::convert::TryInto;
use core::fmt::{Error, Write};

View File

@ -273,6 +273,17 @@ fn irq_enable_raw(irq: u8, vector: u8) {
ioapic.enable(irq, 0)
}
const IrqMin: usize = 0x20;
const IrqMax: usize = 0x3f;
// Drivers IrqManager
#[inline(always)]
pub fn enable_irq(irq: usize) {
let mut ioapic = unsafe { IoApic::new(phys_to_virt(super::IOAPIC_ADDR as usize)) };
ioapic.set_irq_vector(irq as u8, (IrqMin + irq) as u8);
ioapic.enable(irq as u8, 0);
}
#[export_name = "hal_irq_disable"]
pub fn irq_disable(irq: u32) {
info!("irq_disable");

View File

@ -23,7 +23,7 @@ use {
};
mod acpi_table;
mod interrupt;
pub mod interrupt;
mod keyboard;
/// Page Table
@ -301,7 +301,7 @@ lazy_static! {
}
/// Put a char by serial interrupt handler.
fn serial_put(mut x: u8) {
pub fn serial_put(mut x: u8) {
if x == b'\r' {
x = b'\n';
}

View File

@ -0,0 +1,61 @@
/*
use super::bus::virtio_mmio::virtio_probe;
use super::serial::uart16550;
*/
use super::irq::IntcDriver;
use super::CMDLINE;
use crate::phys_to_virt;
use alloc::{collections::BTreeMap, string::String, sync::Arc};
use core::slice;
pub use device_tree::{DeviceTree, Node};
use spin::RwLock;
const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed;
lazy_static! {
/// Compatible lookup
pub static ref DEVICE_TREE_REGISTRY: RwLock<BTreeMap<&'static str, fn(&Node)>> =
RwLock::new(BTreeMap::new());
/// Interrupt controller lookup
pub static ref DEVICE_TREE_INTC: RwLock<BTreeMap<u32, Arc<dyn IntcDriver>>> =
RwLock::new(BTreeMap::new());
}
fn walk_dt_node(dt: &Node, intc_only: bool) {
if let Ok(compatible) = dt.prop_str("compatible") {
if dt.has_prop("interrupt-controller") == intc_only {
let registry = DEVICE_TREE_REGISTRY.read();
if let Some(f) = registry.get(compatible) {
f(dt);
}
}
}
if let Ok(bootargs) = dt.prop_str("bootargs") {
if bootargs.len() > 0 {
info!("Kernel cmdline: {}", bootargs);
*CMDLINE.write() = String::from(bootargs);
}
}
for child in dt.children.iter() {
walk_dt_node(child, intc_only);
}
}
struct DtbHeader {
magic: u32,
size: u32,
}
pub fn init(dtb: usize) {
let header = unsafe { &*(dtb as *const DtbHeader) };
let magic = u32::from_be(header.magic);
if magic == DEVICE_TREE_MAGIC {
let size = u32::from_be(header.size);
let dtb_data = unsafe { slice::from_raw_parts(dtb as *const u8, size as usize) };
if let Ok(dt) = DeviceTree::load(dtb_data) {
// find interrupt controller first
walk_dt_node(&dt.root, true);
walk_dt_node(&dt.root, false);
}
}
}

View File

@ -0,0 +1,75 @@
//! BCM2836 interrupt
use super::super::DRIVERS;
use super::{super::IRQ_MANAGER, IntcDriver, IrqManager};
use crate::drivers::{
device_tree::DEVICE_TREE_INTC, device_tree::DEVICE_TREE_REGISTRY, DeviceType, Driver,
};
use crate::memory::phys_to_virt;
use crate::{sync::SpinNoIrqLock as Mutex, util::read, util::write};
use alloc::string::String;
use alloc::sync::Arc;
use bcm2837::interrupt::Controller;
use bcm2837::interrupt::Interrupt;
pub struct Bcm2837Intc {
manager: Mutex<IrqManager>,
}
impl Driver for Bcm2837Intc {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
let mut res = false;
let manager = self.manager.lock();
for intr in Controller::new().pending_interrupts() {
res |= manager.try_handle_interrupt(Some(intr as usize));
}
res
}
fn device_type(&self) -> DeviceType {
DeviceType::Intc
}
fn get_id(&self) -> String {
format!("bcm2837_intc")
}
}
impl IntcDriver for Bcm2837Intc {
/// Register interrupt controller local irq
fn register_local_irq(&self, irq: usize, driver: Arc<dyn Driver>) {
// enable irq
use bcm2837::interrupt::Interrupt::*;
let intr = match irq {
_ if irq == Timer1 as usize => Timer1,
_ if irq == Aux as usize => Aux,
_ => todo!(),
};
Controller::new().enable(intr);
let mut manager = self.manager.lock();
manager.register_irq(irq, driver);
}
}
// singleton
lazy_static! {
pub static ref BCM2837_INTC: Arc<Bcm2837Intc> = init();
}
fn init() -> Arc<Bcm2837Intc> {
info!("Init bcm2837 interrupt controller");
let intc = Arc::new(Bcm2837Intc {
manager: Mutex::new(IrqManager::new(false)),
});
DRIVERS.write().push(intc.clone());
// register under root irq manager
// 0x10002: from lower el, irq
IRQ_MANAGER.write().register_irq(0x10002, intc.clone());
// 0x10001: from current el, irq
IRQ_MANAGER.write().register_irq(0x10001, intc.clone());
intc
}
pub fn driver_init() {
lazy_static::initialize(&BCM2837_INTC);
}

View File

@ -0,0 +1,95 @@
use crate::arch::interrupt::enable_irq;
use alloc::collections::btree_map::Entry;
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use alloc::vec::Vec;
use kernel_hal::drivers::Driver;
#[cfg(feature = "board_raspi3")]
pub mod bcm2837;
pub mod plic;
// Irq manager
pub struct IrqManager {
// is root manager?
root: bool,
// drivers that only respond to specific irq
mapping: BTreeMap<usize, Vec<Arc<dyn Driver>>>,
// drivers that respond to all irqs
all: Vec<Arc<dyn Driver>>,
}
impl IrqManager {
pub fn new(root: bool) -> IrqManager {
IrqManager {
root,
mapping: BTreeMap::new(),
all: Vec::new(),
}
}
pub fn register_irq(&mut self, irq: usize, driver: Arc<dyn Driver>) {
// for root manager, enable irq in arch
// for other interrupt controllers, enable irq before calling this function
if self.root {
enable_irq(irq);
}
match self.mapping.entry(irq) {
Entry::Occupied(mut e) => {
e.get_mut().push(driver);
}
Entry::Vacant(e) => {
let mut v = Vec::new();
v.push(driver);
e.insert(v);
}
}
}
pub fn register_all(&mut self, driver: Arc<dyn Driver>) {
self.all.push(driver);
}
pub fn register_opt(&mut self, irq_opt: Option<usize>, driver: Arc<dyn Driver>) {
if let Some(irq) = irq_opt {
self.register_irq(irq, driver);
} else {
self.register_all(driver);
}
}
pub fn deregister_irq(&mut self, irq: usize, driver: Arc<dyn Driver>) {
if let Some(e) = self.mapping.get_mut(&irq) {
e.retain(|d| !Arc::ptr_eq(&d, &driver));
}
}
pub fn deregister_all(&mut self, driver: Arc<dyn Driver>) {
self.all.retain(|d| !Arc::ptr_eq(&d, &driver));
}
pub fn try_handle_interrupt(&self, irq_opt: Option<usize>) -> bool {
if let Some(irq) = irq_opt {
if let Some(e) = self.mapping.get(&irq) {
for dri in e.iter() {
if dri.try_handle_interrupt(Some(irq)) {
return true;
}
}
}
}
for dri in self.all.iter() {
if dri.try_handle_interrupt(irq_opt) {
return true;
}
}
false
}
}
// interrupt controller
pub trait IntcDriver: Driver {
/// Register interrupt controller local irq
fn register_local_irq(&self, irq: usize, driver: Arc<dyn Driver>);
}

View File

@ -0,0 +1,109 @@
//! RISC-V plic
use super::{super::IRQ_MANAGER, IntcDriver, IrqManager};
use crate::drivers::{device_tree::DEVICE_TREE_INTC, device_tree::DEVICE_TREE_REGISTRY};
use crate::phys_to_virt;
pub use kernel_hal::drivers::{DeviceType, Driver, DRIVERS};
//use crate::{sync::SpinNoIrqLock as Mutex, util::read, util::write};
use alloc::format;
use alloc::string::String;
use alloc::sync::Arc;
use core::ptr::{read_volatile, write_volatile};
use device_tree::Node;
use spin::Mutex;
pub struct Plic {
base: usize,
manager: Mutex<IrqManager>,
}
impl Driver for Plic {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
// Supported more than 32 irqs
/* Int id is pending
let id = 10;
let step = ((id / 32) * 4) as usize; //4节
let pending: u32 = read(self.base + step + 0x1000);
let is_pending = (pending & (1 << id%32)) != 0;
debug!("Plic handle irq, Is {} pending: {}", id, is_pending);
*/
let claim: u32 = read(self.base + 0x201004);
if claim != 0 {
//debug!("Plic handle irq: {}", claim);
let manager = self.manager.lock();
let res = manager.try_handle_interrupt(Some(claim as usize));
// complete
write(self.base + 0x201004, claim);
res
} else {
false
}
}
fn device_type(&self) -> DeviceType {
DeviceType::Intc
}
fn get_id(&self) -> String {
format!("plic_{}", self.base)
}
}
impl IntcDriver for Plic {
/// Register interrupt controller local irq
fn register_local_irq(&self, irq: usize, driver: Arc<dyn Driver>) {
let step = (irq / 32) * 4;
// enable irq for context 1
write(
self.base + step + 0x2080,
read::<u32>(self.base + step + 0x2080) | (1 << irq % 32),
);
// set priority to 7
write(self.base + irq * 4, 7);
let mut manager = self.manager.lock();
manager.register_irq(irq, driver);
}
}
pub const SupervisorExternal: usize = usize::MAX / 2 + 1 + 8;
pub fn init_dt(dt: &Node) {
let addr = dt.prop_u64("reg").unwrap() as usize;
let phandle = dt.prop_u32("phandle").unwrap();
info!("Found riscv plic at {:#x}, {:?}", addr, dt);
let base = phys_to_virt(addr);
let plic = Arc::new(Plic {
base,
manager: Mutex::new(IrqManager::new(false)),
});
// set prio threshold to 0 for context 1
write(base + 0x201000, 0);
DRIVERS.write().push(plic.clone());
// register under root irq manager
IRQ_MANAGER
.write()
.register_irq(SupervisorExternal, plic.clone());
// register interrupt controller. phandle: 3
DEVICE_TREE_INTC.write().insert(phandle, plic);
}
pub fn driver_init() {
DEVICE_TREE_REGISTRY.write().insert("riscv,plic0", init_dt);
}
#[inline(always)]
pub fn write<T>(addr: usize, content: T) {
let cell = (addr) as *mut T;
unsafe {
write_volatile(cell, content);
}
}
#[inline(always)]
pub fn read<T>(addr: usize) -> T {
let cell = (addr) as *const T;
unsafe { read_volatile(cell) }
}

View File

@ -1,2 +1,134 @@
pub mod virtio;
//use crate::sync::Condvar;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use rcore_fs::dev::{self, BlockDevice, DevError};
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use spin::RwLock;
pub use kernel_hal::drivers::{BlockDriver, BLK_DRIVERS};
pub use self::virtio::*;
//pub use block::BlockDriver;
//pub use net::NetDriver;
//pub use rtc::RtcDriver;
pub use serial::SerialDriver;
/// Block device
//pub mod block;
/// Bus controller
//pub mod bus;
/// Character console
//pub mod console;
/// Device tree
pub mod device_tree;
/// Display controller
//pub mod gpu;
/// Mouse device
//pub mod input;
/// Interrupt controller
pub mod irq;
/// Network controller
pub mod net;
/// For isomorphic_drivers
pub mod provider;
/// Real time clock
//pub mod rtc;
/// Serial port
pub mod serial;
/// MMC controller
//pub mod mmc;
/// virtio device
pub mod virtio;
/* define in kernel-hal
#[derive(Debug, Eq, PartialEq)]
pub enum DeviceType {
Net,
Gpu,
Input,
Block,
Rtc,
Serial,
Intc,
}
pub trait Driver: Send + Sync {
// if interrupt belongs to this driver, handle it and return true
// return false otherwise
// irq number is provided when available
// driver should skip handling when irq number is mismatched
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool;
// return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType;
// get unique identifier for this device
// should be different for each instance
fn get_id(&self) -> String;
// trait casting
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
/*
fn as_rtc(&self) -> Option<&dyn RtcDriver> {
None
}
*/
}
*/
lazy_static! {
// NOTE: RwLock only write when initializing drivers
/* define in kernel-hal
pub static ref DRIVERS: RwLock<Vec<Arc<dyn Driver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<dyn NetDriver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<dyn BlockDriver>>> = RwLock::new(Vec::new());
*/
pub static ref INPUT_DRIVERS: RwLock<Vec<Arc<dyn InputDriver>>> = RwLock::new(Vec::new());
pub static ref GPU_DRIVERS: RwLock<Vec<Arc<dyn GpuDriver>>> = RwLock::new(Vec::new());
//pub static ref RTC_DRIVERS: RwLock<Vec<Arc<dyn RtcDriver>>> = RwLock::new(Vec::new());
pub static ref SERIAL_DRIVERS: RwLock<Vec<Arc<dyn SerialDriver>>> = RwLock::new(Vec::new());
pub static ref IRQ_MANAGER: RwLock<irq::IrqManager> = RwLock::new(irq::IrqManager::new(true));
}
pub struct BlockDriverWrapper(pub Arc<dyn BlockDriver>);
impl BlockDevice for BlockDriverWrapper {
const BLOCK_SIZE_LOG2: u8 = 9; // 512
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> dev::Result<()> {
match self.0.read_block(block_id, buf) {
true => Ok(()),
false => Err(DevError),
}
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> dev::Result<()> {
match self.0.write_block(block_id, buf) {
true => Ok(()),
false => Err(DevError),
}
}
fn sync(&self) -> dev::Result<()> {
Ok(())
}
}
/*
lazy_static! {
//pub static ref SOCKET_ACTIVITY: Condvar = Condvar::new();
}
*/
lazy_static! {
// Write only once at boot
pub static ref CMDLINE: RwLock<String> = RwLock::new(String::new());
}

View File

@ -0,0 +1,227 @@
//! Intel PRO/1000 Network Adapter i.e. e1000 network driver
//! Datasheet: https://www.intel.ca/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use smoltcp::iface::*;
use smoltcp::phy::{self, DeviceCapabilities};
use smoltcp::time::Instant;
use smoltcp::wire::*;
use smoltcp::Result;
use crate::PAGE_SIZE;
use isomorphic_drivers::net::ethernet::intel::e1000::E1000;
use isomorphic_drivers::net::ethernet::structs::EthernetAddress as DriverEthernetAddress;
use crate::drivers::{provider::Provider, BlockDriver};
//use crate::sync::SpinNoIrqLock as Mutex;
use spin::Mutex;
use super::super::IRQ_MANAGER;
use kernel_hal::drivers::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKETS};
#[derive(Clone)]
pub struct E1000Driver(Arc<Mutex<E1000<Provider>>>);
pub struct E1000Interface {
iface: Mutex<Interface<'static, E1000Driver>>,
driver: E1000Driver,
name: String,
irq: Option<usize>,
}
impl Driver for E1000Interface {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
if irq.is_some() && self.irq.is_some() && irq != self.irq {
// not ours, skip it
return false;
}
let data = self.driver.0.lock().handle_interrupt();
if data {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
// Fix me
let timestamp = Instant::from_millis(100);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
//SOCKET_ACTIVITY.notify_all();
error!("e1000 try_handle_interrupt SOCKET_ACTIVITY unimplemented !");
}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
return data;
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
String::from("e1000")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl NetDriver for E1000Interface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}
fn get_ifname(&self) -> String {
self.name.clone()
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}
fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address()
}
fn poll(&self) {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
let timestamp = Instant::from_millis(100);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
//SOCKET_ACTIVITY.notify_all();
error!("e1000 poll SOCKET_ACTIVITY unimplemented !");
}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
fn send(&self, data: &[u8]) -> Option<usize> {
use smoltcp::phy::TxToken;
let token = E1000TxToken(self.driver.clone());
if token
.consume(Instant::from_millis(0), data.len(), |buffer| {
buffer.copy_from_slice(&data);
Ok(())
})
.is_ok()
{
Some(data.len())
} else {
None
}
}
fn get_arp(&self, ip: IpAddress) -> Option<EthernetAddress> {
/*
let iface = self.iface.lock();
let cache = iface.neighbor_cache();
cache.lookup(&ip, Instant::from_millis(0))
*/
unimplemented!()
}
}
pub struct E1000RxToken(Vec<u8>);
pub struct E1000TxToken(E1000Driver);
impl phy::Device<'_> for E1000Driver {
type RxToken = E1000RxToken;
type TxToken = E1000TxToken;
fn receive(&mut self) -> Option<(Self::RxToken, Self::TxToken)> {
self.0
.lock()
.receive()
.map(|vec| (E1000RxToken(vec), E1000TxToken(self.clone())))
}
fn transmit(&mut self) -> Option<Self::TxToken> {
if self.0.lock().can_send() {
Some(E1000TxToken(self.clone()))
} else {
None
}
}
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1536;
caps.max_burst_size = Some(64);
caps
}
}
impl phy::RxToken for E1000RxToken {
fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
f(&mut self.0)
}
}
impl phy::TxToken for E1000TxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
let mut buffer = [0u8; PAGE_SIZE];
let result = f(&mut buffer[..len]);
let mut driver = (self.0).0.lock();
driver.send(&buffer);
result
}
}
// JudgeDuck-OS/kern/e1000.c
pub fn init(name: String, irq: Option<usize>, header: usize, size: usize, index: usize) {
info!("Probing e1000 {}", name);
// randomly generated
let mac: [u8; 6] = [0x54, 0x51, 0x9F, 0x71, 0xC0, index as u8];
let e1000 = E1000::new(header, size, DriverEthernetAddress::from_bytes(&mac));
let net_driver = E1000Driver(Arc::new(Mutex::new(e1000)));
let ethernet_addr = EthernetAddress::from_bytes(&mac);
//let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, index as u8, 2), 24)];
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let iface = InterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.finalize();
info!("e1000 interface {} up with addr 10.0.{}.2/24", name, index);
let e1000_iface = E1000Interface {
iface: Mutex::new(iface),
driver: net_driver.clone(),
name,
irq,
};
let driver = Arc::new(e1000_iface);
DRIVERS.write().push(driver.clone());
IRQ_MANAGER.write().register_opt(irq, driver.clone());
NET_DRIVERS.write().push(driver);
}

View File

@ -0,0 +1,245 @@
//! Intel 10Gb Network Adapter 82599 i.e. ixgbe network driver
//! Datasheet: https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use alloc::collections::BTreeMap;
use isomorphic_drivers::net::ethernet::intel::ixgbe;
use log::*;
use smoltcp::iface::*;
use smoltcp::phy::{self, Checksum, DeviceCapabilities};
use smoltcp::time::Instant;
use smoltcp::wire::EthernetAddress;
use smoltcp::wire::*;
use smoltcp::Result;
//use crate::sync::FlagsGuard;
use spin::Mutex;
use super::super::{provider::Provider, IRQ_MANAGER};
use kernel_hal::drivers::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKETS};
#[derive(Clone)]
struct IXGBEDriver {
inner: Arc<Mutex<ixgbe::IXGBE<Provider>>>,
header: usize,
size: usize,
mtu: usize,
}
pub struct IXGBEInterface {
iface: Mutex<Interface<'static, IXGBEDriver>>,
driver: IXGBEDriver,
ifname: String,
irq: Option<usize>,
id: String,
}
impl Driver for IXGBEInterface {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
if irq.is_some() && self.irq.is_some() && irq != self.irq {
// not ours, skip it
return false;
}
let handled = {
//let _ = FlagsGuard::no_irq_region();
self.driver.inner.lock().try_handle_interrupt()
};
if handled {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
let timestamp = Instant::from_millis(100);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
//SOCKET_ACTIVITY.notify_all();
error!("ixgbe try_handle_interrupt SOCKET_ACTIVITY unimplemented !");
}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
return handled;
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
self.ifname.clone()
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
/*
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
*/
}
impl NetDriver for IXGBEInterface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}
fn get_ifname(&self) -> String {
self.ifname.clone()
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}
fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address()
}
fn poll(&self) {
//let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
let timestamp = Instant::from_millis(100);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
//SOCKET_ACTIVITY.notify_all();
error!("ixgbe poll SOCKET_ACTIVITY unimplemented !");
}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
fn send(&self, data: &[u8]) -> Option<usize> {
self.driver.inner.lock().send(&data);
Some(data.len())
}
fn get_arp(&self, ip: IpAddress) -> Option<EthernetAddress> {
/*
let iface = self.iface.lock();
let cache = iface.neighbor_cache();
cache.lookup_pure(&ip, Instant::from_millis(0))
*/
unimplemented!()
}
}
pub struct IXGBERxToken(Vec<u8>);
pub struct IXGBETxToken(IXGBEDriver);
impl<'a> phy::Device<'a> for IXGBEDriver {
type RxToken = IXGBERxToken;
type TxToken = IXGBETxToken;
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
//let _ = FlagsGuard::no_irq_region();
if self.inner.lock().can_send() {
if let Some(data) = self.inner.lock().recv() {
Some((IXGBERxToken(data), IXGBETxToken(self.clone())))
} else {
None
}
} else {
None
}
}
fn transmit(&'a mut self) -> Option<Self::TxToken> {
//let _ = FlagsGuard::no_irq_region();
if self.inner.lock().can_send() {
Some(IXGBETxToken(self.clone()))
} else {
None
}
}
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
// do not use max MTU by default
//caps.max_transmission_unit = ixgbe::IXGBEDriver::get_mtu(); // max MTU
caps.max_transmission_unit = self.mtu;
caps.max_burst_size = Some(256);
// IP Rx checksum is offloaded with RXCSUM
caps.checksum.ipv4 = Checksum::Tx;
caps
}
}
impl phy::RxToken for IXGBERxToken {
fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
f(&mut self.0)
}
}
impl phy::TxToken for IXGBETxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
//let _ = FlagsGuard::no_irq_region();
let mut buffer = [0u8; ixgbe::IXGBE::<Provider>::get_mtu()];
let result = f(&mut buffer[..len]);
if result.is_ok() {
self.0.inner.lock().send(&buffer[..len]);
}
result
}
}
pub fn ixgbe_init(
name: String,
irq: Option<usize>,
header: usize,
size: usize,
index: usize,
) -> Arc<IXGBEInterface> {
//let _ = FlagsGuard::no_irq_region();
let mut ixgbe = ixgbe::IXGBE::new(header, size);
ixgbe.enable_irq();
let ethernet_addr = EthernetAddress::from_bytes(&ixgbe.get_mac().as_bytes());
let net_driver = IXGBEDriver {
inner: Arc::new(Mutex::new(ixgbe)),
header,
size,
mtu: 1500,
};
//let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, index as u8, 2), 24)];
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let iface = InterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache)
.finalize();
info!("ixgbe interface {} up with addr 10.0.{}.2/24", name, index);
let ixgbe_iface = IXGBEInterface {
iface: Mutex::new(iface),
driver: net_driver.clone(),
ifname: name.clone(),
id: name,
irq,
};
let driver = Arc::new(ixgbe_iface);
IRQ_MANAGER.write().register_opt(irq, driver.clone());
DRIVERS.write().push(driver.clone());
NET_DRIVERS.write().push(driver.clone());
driver
}

View File

@ -0,0 +1,119 @@
// smoltcp
use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Route, Routes};
use smoltcp::phy::{Loopback, Medium};
use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use alloc::sync::Arc;
use kernel_hal::drivers::{DeviceType, Driver, NetDriver, NET_DRIVERS, SOCKETS};
use alloc::string::String;
use spin::Mutex;
#[derive(Clone)]
pub struct LoopbackInterface {
pub iface: Arc<Mutex<Interface<'static, Loopback>>>,
pub name: String,
}
impl Driver for LoopbackInterface {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
return false;
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
String::from("loopback")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
}
impl NetDriver for LoopbackInterface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
unimplemented!()
}
fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address()
}
fn poll(&self) {
let timestamp = Instant::from_millis(0);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
fn send(&self, data: &[u8]) -> Option<usize> {
unimplemented!()
}
fn get_arp(&self, ip: IpAddress) -> Option<EthernetAddress> {
/*
let iface = self.iface.lock();
let cache = iface.neighbor_cache();
cache.lookup(&ip, Instant::from_millis(0))
*/
unimplemented!()
}
}
pub fn init(name: String) {
warn!("loopback");
// 初始化 一个 协议栈
// 从外界 接受 一些 配置 参数 如果 没有 选择 默认 的
// 网络 设备
// 默认 loopback
let loopback = Loopback::new(Medium::Ethernet);
// 为 设备 分配 网络 身份
// 物理地址
let mac: [u8; 6] = [0x52, 0x54, 0x98, 0x76, 0x54, 0x32];
let ethernet_addr = EthernetAddress::from_bytes(&mac);
// ip 地址
let ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 24)];
// let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
// 路由
let default_gateway = Ipv4Address::new(127, 0, 0, 1);
// let default_gateway = Ipv4Address::new(10, 0, 2, 2);
static mut routes_storage: [Option<(IpCidr, Route)>; 1] = [None; 1];
let mut routes = unsafe { Routes::new(&mut routes_storage[..]) };
routes.add_default_ipv4_route(default_gateway).unwrap();
// arp缓存
let neighbor_cache = NeighborCache::new(BTreeMap::new());
// 设置 主要 设置 iface
let iface = InterfaceBuilder::new(loopback)
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.routes(routes)
.neighbor_cache(neighbor_cache)
.finalize();
let loopback_iface = LoopbackInterface {
iface: Arc::new(Mutex::new(iface)),
name,
};
let driver = Arc::new(loopback_iface);
NET_DRIVERS.write().push(driver);
}

View File

@ -0,0 +1,8 @@
pub mod e1000;
pub mod ixgbe;
pub mod rtl8x;
pub mod virtio_net;
pub mod realtek;
pub mod loopback;

View File

@ -0,0 +1,118 @@
// From Linux
/* Generic MII registers. */
pub const MII_BMCR: u32 = 0x00;
pub const MII_BMSR: u32 = 0x01;
pub const MII_PHYSID1: u32 = 0x02;
pub const MII_PHYSID2: u32 = 0x03;
pub const MII_ADVERTISE: u32 = 0x04;
pub const MII_LPA: u32 = 0x05;
pub const MII_EXPANSION: u32 = 0x06;
pub const MII_CTRL1000: u32 = 0x09;
pub const MII_STAT1000: u32 = 0x0a;
pub const MII_MMD_CTRL: u32 = 0x0d;
pub const MII_MMD_DATA: u32 = 0x0e;
pub const MII_ESTATUS: u32 = 0x0f;
pub const MII_DCOUNTER: u32 = 0x12;
pub const MII_FCSCOUNTER: u32 = 0x13;
pub const MII_NWAYTEST: u32 = 0x14;
pub const MII_RERRCOUNTER: u32 = 0x15;
pub const MII_SREVISION: u32 = 0x16;
pub const MII_RESV1: u32 = 0x17;
pub const MII_LBRERROR: u32 = 0x18;
pub const MII_PHYADDR: u32 = 0x19;
pub const MII_RESV2: u32 = 0x1a;
pub const MII_TPISTATUS: u32 = 0x1b;
pub const MII_NCONFIG: u32 = 0x1c;
/* Basic mode control register. */
pub const BMCR_RESV: u32 = 0x003f;
pub const BMCR_SPEED1000: u32 = 0x0040;
pub const BMCR_CTST: u32 = 0x0080;
pub const BMCR_FULLDPLX: u32 = 0x0100;
pub const BMCR_ANRESTART: u32 = 0x0200;
pub const BMCR_ISOLATE: u32 = 0x0400;
pub const BMCR_PDOWN: u32 = 0x0800;
pub const BMCR_ANENABLE: u32 = 0x1000;
pub const BMCR_SPEED100: u32 = 0x2000;
pub const BMCR_LOOPBACK: u32 = 0x4000;
pub const BMCR_RESET: u32 = 0x8000;
pub const BMCR_SPEED10: u32 = 0x0000;
/* Basic mode status register. */
pub const BMSR_ERCAP: u32 = 0x0001;
pub const BMSR_JCD: u32 = 0x0002;
pub const BMSR_LSTATUS: u32 = 0x0004;
pub const BMSR_ANEGCAPABLE: u32 = 0x0008;
pub const BMSR_RFAULT: u32 = 0x0010;
pub const BMSR_ANEGCOMPLETE: u32 = 0x0020;
pub const BMSR_RESV: u32 = 0x00c0;
pub const BMSR_ESTATEN: u32 = 0x0100;
pub const BMSR_100HALF2: u32 = 0x0200;
pub const BMSR_100FULL2: u32 = 0x0400;
pub const BMSR_10HALF: u32 = 0x0800;
pub const BMSR_10FULL: u32 = 0x1000;
pub const BMSR_100HALF: u32 = 0x2000;
pub const BMSR_100FULL: u32 = 0x4000;
pub const BMSR_100BASE4: u32 = 0x8000;
/* Advertisement control register. */
pub const ADVERTISE_SLCT: u32 = 0x001f;
pub const ADVERTISE_CSMA: u32 = 0x0001;
pub const ADVERTISE_10HALF: u32 = 0x0020;
pub const ADVERTISE_1000XFULL: u32 = 0x0020;
pub const ADVERTISE_10FULL: u32 = 0x0040;
pub const ADVERTISE_1000XHALF: u32 = 0x0040;
pub const ADVERTISE_100HALF: u32 = 0x0080;
pub const ADVERTISE_1000XPAUSE: u32 = 0x0080;
pub const ADVERTISE_100FULL: u32 = 0x0100;
pub const ADVERTISE_1000XPSE_ASYM: u32 = 0x0100;
pub const ADVERTISE_100BASE4: u32 = 0x0200;
pub const ADVERTISE_PAUSE_CAP: u32 = 0x0400;
pub const ADVERTISE_PAUSE_ASYM: u32 = 0x0800;
pub const ADVERTISE_RESV: u32 = 0x1000;
pub const ADVERTISE_RFAULT: u32 = 0x2000;
pub const ADVERTISE_LPACK: u32 = 0x4000;
pub const ADVERTISE_NPAGE: u32 = 0x8000;
pub const ADVERTISE_FULL: u32 = ADVERTISE_100FULL | ADVERTISE_10FULL | ADVERTISE_CSMA;
pub const ADVERTISE_ALL: u32 =
ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL;
/* Link partner ability register. */
pub const LPA_SLCT: u32 = 0x001f;
pub const LPA_10HALF: u32 = 0x0020;
pub const LPA_1000XFULL: u32 = 0x0020;
pub const LPA_10FULL: u32 = 0x0040;
pub const LPA_1000XHALF: u32 = 0x0040;
pub const LPA_100HALF: u32 = 0x0080;
pub const LPA_1000XPAUSE: u32 = 0x0080;
pub const LPA_100FULL: u32 = 0x0100;
pub const LPA_1000XPAUSE_ASYM: u32 = 0x0100;
pub const LPA_100BASE4: u32 = 0x0200;
pub const LPA_PAUSE_CAP: u32 = 0x0400;
pub const LPA_PAUSE_ASYM: u32 = 0x0800;
pub const LPA_RESV: u32 = 0x1000;
pub const LPA_RFAULT: u32 = 0x2000;
pub const LPA_LPACK: u32 = 0x4000;
pub const LPA_NPAGE: u32 = 0x8000;
pub const LPA_DUPLEX: u32 = (LPA_10FULL | LPA_100FULL);
pub const LPA_100: u32 = (LPA_100FULL | LPA_100HALF | LPA_100BASE4);
/* 1000BASE-T Control register */
pub const ADVERTISE_1000FULL: u32 = 0x0200;
pub const ADVERTISE_1000HALF: u32 = 0x0100;
pub const CTL1000_AS_MASTER: u32 = 0x0800;
pub const CTL1000_ENABLE_MASTER: u32 = 0x1000;
/* 1000BASE-T Status register */
pub const LPA_1000MSFAIL: u32 = 0x8000;
pub const LPA_1000LOCALRXOK: u32 = 0x2000;
pub const LPA_1000REMRXOK: u32 = 0x1000;
pub const LPA_1000FULL: u32 = 0x0800;
pub const LPA_1000HALF: u32 = 0x0400;
/* Flow control flags */
pub const FLOW_CTRL_TX: u32 = 0x01;
pub const FLOW_CTRL_RX: u32 = 0x02;

View File

@ -0,0 +1,41 @@
pub mod mii;
//pub mod rtl8211f;
use crate::{phys_to_virt, virt_to_phys};
use isomorphic_drivers::provider::Provider;
#[macro_use]
mod log {
macro_rules! trace {
($($arg:expr),*) => { $( let _ = $arg; )* };
}
macro_rules! debug {
($($arg:expr),*) => { $( let _ = $arg; )* };
}
macro_rules! info {
($($arg:expr),*) => { $( let _ = $arg; )*};
}
macro_rules! warn {
($($arg:expr),*) => { $( let _ = $arg; )*};
}
macro_rules! error {
($($arg:expr),*) => { $( let _ = $arg; )* };
}
}
pub mod rtl8211f;
/*
/// External functions that drivers must use
pub trait Provider {
/// Page size (usually 4K)
const PAGE_SIZE: usize;
/// Allocate consequent physical memory for DMA.
/// Return (`virtual address`, `physical address`).
/// The address is page aligned.
fn alloc_dma(size: usize) -> (usize, usize);
/// Deallocate DMA
fn dealloc_dma(vaddr: usize, size: usize);
}
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,219 @@
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use spin::Mutex;
use smoltcp::iface::*;
use smoltcp::phy::{self, Device, DeviceCapabilities, Medium};
use smoltcp::time::Instant;
use smoltcp::wire::*;
use smoltcp::Result;
use super::super::IRQ_MANAGER;
use super::realtek::rtl8211f::RTL8211F;
use crate::drivers::provider::Provider;
use crate::PAGE_SIZE;
use kernel_hal::drivers::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKETS};
#[derive(Clone)]
pub struct RTL8xDriver(Arc<Mutex<RTL8211F<Provider>>>);
#[derive(Clone)]
pub struct RTL8xInterface {
pub iface: Arc<Mutex<Interface<'static, RTL8xDriver>>>,
pub driver: RTL8xDriver,
pub name: String,
pub irq: Option<usize>,
}
impl Driver for RTL8xInterface {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
if irq.is_some() && self.irq.is_some() && irq != self.irq {
// not ours, skip it
return false;
}
let status = self.driver.0.lock().interrupt_status();
let handle_tx_rx = 3;
if status == handle_tx_rx {
let timestamp = Instant::from_millis(0);
let mut sockets = SOCKETS.lock(); //引发死锁?
self.driver.0.lock().int_disable();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
//SOCKET_ACTIVITY.notify_all();
// error!("rtl8x try_handle_interrupt SOCKET_ACTIVITY unimplemented !");
}
Err(err) => {
debug!("poll got err {}", err);
}
}
self.driver.0.lock().int_enable();
return true;
}
return false;
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
String::from("e1000")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
}
impl NetDriver for RTL8xInterface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}
fn get_ifname(&self) -> String {
self.name.clone()
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
Vec::from(self.iface.lock().ip_addrs())
}
fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address()
}
fn poll(&self) {
let timestamp = Instant::from_millis(0);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
//SOCKET_ACTIVITY.notify_all();
// error!("poll change : {}!", b);
}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
fn send(&self, data: &[u8]) -> Option<usize> {
self.driver.0.lock().geth_send(&data);
Some(data.len())
}
fn get_arp(&self, ip: IpAddress) -> Option<EthernetAddress> {
/*
let iface = self.iface.lock();
let cache = iface.neighbor_cache();
cache.lookup(&ip, Instant::from_millis(0))
*/
unimplemented!()
}
}
pub struct RTL8xRxToken(Vec<u8>);
pub struct RTL8xTxToken(RTL8xDriver);
impl<'a> Device<'a> for RTL8xDriver {
type RxToken = RTL8xRxToken;
type TxToken = RTL8xTxToken;
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1536;
caps.max_burst_size = Some(64);
caps.medium = Medium::Ethernet;
caps
}
fn receive(&mut self) -> Option<(Self::RxToken, Self::TxToken)> {
if self.0.lock().can_recv() {
//这里每次只接收一个网络包
let (vec_recv, rxcount) = self.0.lock().geth_recv(1);
Some((RTL8xRxToken(vec_recv), RTL8xTxToken(self.clone())))
} else {
None
}
}
fn transmit(&mut self) -> Option<Self::TxToken> {
if self.0.lock().can_send() {
Some(RTL8xTxToken(self.clone()))
} else {
None
}
}
}
impl phy::RxToken for RTL8xRxToken {
fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
// warn!("rx consume {:?}",self.0);
f(&mut self.0)
}
}
impl phy::TxToken for RTL8xTxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
use alloc::vec;
let mut buffer = vec![0u8; len];
let result = f(&mut buffer[..len]);
if result.is_ok() {
(self.0).0.lock().geth_send(&buffer[..len]);
}
result
}
}
pub fn init(name: String, irq: Option<usize>) {
let mut rtl8211f = RTL8211F::<Provider>::new(&[0u8; 6]);
let mac = rtl8211f.get_umac();
//启动前请为D1插上网线
warn!("Please plug in the Ethernet cable");
rtl8211f.open();
rtl8211f.set_rx_mode();
rtl8211f.adjust_link();
let net_driver = RTL8xDriver(Arc::new(Mutex::new(rtl8211f)));
let ethernet_addr = EthernetAddress::from_bytes(&mac);
let ip_addrs = [IpCidr::new(IpAddress::v4(192, 100, 1, 5), 24)];
let default_v4_gw = Ipv4Address::new(192, 100, 1, 1);
warn!("gate way {:?}", default_v4_gw);
#[allow(warnings)]
static mut routes_storage: [Option<(IpCidr, Route)>; 1] = [None; 1];
let mut routes = unsafe { Routes::new(&mut routes_storage[..]) };
routes.add_default_ipv4_route(default_v4_gw).unwrap();
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let iface = InterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.routes(routes)
.finalize();
info!("rtl8211f interface {} up with addr 192.100.1.5/24", name);
let rtl8211f_iface = RTL8xInterface {
iface: Arc::new(Mutex::new(iface)),
driver: net_driver.clone(),
name,
irq,
};
let driver = Arc::new(rtl8211f_iface);
DRIVERS.write().push(driver.clone());
IRQ_MANAGER.write().register_opt(irq, driver.clone());
NET_DRIVERS.write().push(driver);
}

View File

@ -0,0 +1,191 @@
use alloc::collections::BTreeMap;
use alloc::format;
use alloc::string::String;
use alloc::sync::Arc;
use device_tree::Node;
use smoltcp::iface::{InterfaceBuilder, NeighborCache};
use smoltcp::phy::{self, DeviceCapabilities};
use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use smoltcp::Result;
use virtio_drivers::{VirtIOHeader, VirtIONet};
use super::super::{device_tree::DEVICE_TREE_INTC, IRQ_MANAGER};
use kernel_hal::drivers::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS};
//use crate::{drivers::BlockDriver, sync::SpinNoIrqLock as Mutex};
use spin::Mutex;
#[derive(Clone)]
pub struct VirtIONetDriver(Arc<Mutex<VirtIONet<'static>>>);
impl NetDriver for VirtIONetDriver {
fn get_mac(&self) -> EthernetAddress {
EthernetAddress(self.0.lock().mac())
}
fn get_ifname(&self) -> String {
format!("virtio{:?}", self.0.lock().mac())
}
fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!()
}
fn poll(&self) {
unimplemented!()
}
}
impl Driver for VirtIONetDriver {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
info!("VirtIONetDriver got interrupt {:?}", irq);
//iface.poll()时中断内发生死锁,暂关闭该中断处理
self.0.lock().ack_interrupt()
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
format!("virtio_net")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
/*
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
*/
}
impl phy::Device<'_> for VirtIONetDriver {
type RxToken = VirtIONetDriver;
type TxToken = VirtIONetDriver;
fn receive(&mut self) -> Option<(Self::RxToken, Self::TxToken)> {
/*
let net = self.0.lock();
let r = net.can_recv();
*/
//初始时由于没有添加recv_queue和写queue_notify
//故can_recv()会一直返回false
//这里的判断等待包的过程转移到consume()的driver.recv()中去做吧
//当然最好的方式应该在此调用driver.recv()
if true {
Some((self.clone(), self.clone()))
} else {
None
}
}
fn transmit(&mut self) -> Option<Self::TxToken> {
let net = self.0.lock();
if net.can_send() {
info!("phy::Device transmit");
Some(self.clone())
} else {
None
}
}
fn capabilities(&self) -> DeviceCapabilities {
//info!("phy::Device capabilities()");
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1536;
caps.max_burst_size = Some(1);
caps
}
}
impl phy::RxToken for VirtIONetDriver {
fn consume<R, F>(self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
info!("RxToken recv consume()");
let mut buffer = [0u8; 2000];
let mut len = buffer.len();
{
//若无括号会与TxToken consume中的lock()发生死锁
let mut driver = self.0.lock();
//需要添加recv_queue和写queue_notify才能触发virtioNet网卡中断一次?
//这里有等待总能收到包TODO: fix me
len = driver.recv(&mut buffer).expect("failed to recv packet");
}
f(&mut buffer[..len])
}
}
impl phy::TxToken for VirtIONetDriver {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
info!("TxToken send consume()");
let mut buffer = [0u8; 2000];
let result = f(&mut buffer[..len]);
//发生死锁
let mut driver = self.0.lock();
driver.send(&buffer[..len]).expect("failed to send packet");
result
}
}
pub fn init(node: &Node, header: &'static mut VirtIOHeader) {
debug!("virtio net init");
let net = VirtIONet::new(header).expect("failed to create net driver");
//let mac = net.mac();
let device = VirtIONetDriver(Arc::new(Mutex::new(net)));
/* Todo like e1000
// let device = Loopback::new(Medium::Ethernet);
let hw_addr = EthernetAddress::from_bytes(&mac);
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
let iface = InterfaceBuilder::new(device.clone())
.ethernet_addr(hw_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.finalize();
*/
//let driver = Arc::new(iface);
let driver = Arc::new(device);
let mut found = false;
let irq_opt = node.prop_u32("interrupts").ok().map(|irq| irq as usize);
if let Ok(intc) = node.prop_u32("interrupt-parent") {
if let Some(irq) = irq_opt {
if let Some(manager) = DEVICE_TREE_INTC.write().get_mut(&intc) {
manager.register_local_irq(irq, driver.clone());
info!("Registed virtio net irq {} to INTC", irq);
found = true;
}
}
}
if !found {
info!("Registed virtio net driver to ROOT");
IRQ_MANAGER.write().register_opt(irq_opt, driver.clone());
}
/*
{
let mut buffer = [0u8; 2000];
let mut dri = driver.0.lock();
//触发virtioNet网卡中断一次。 不过现在中断hanlde会死锁
let len = dri.recv(&mut buffer).expect("failed to recv packet");
}
*/
DRIVERS.write().push(driver.clone());
NET_DRIVERS.write().push(driver);
}

View File

@ -0,0 +1,57 @@
use crate::{frame_dealloc, hal_frame_alloc_contiguous, phys_to_virt, virt_to_phys, PAGE_SIZE};
use isomorphic_drivers::provider;
pub struct Provider;
impl provider::Provider for Provider {
const PAGE_SIZE: usize = PAGE_SIZE;
fn alloc_dma(size: usize) -> (usize, usize) {
let paddr = virtio_dma_alloc(size / PAGE_SIZE);
let vaddr = phys_to_virt(paddr);
(vaddr, paddr)
}
fn dealloc_dma(vaddr: usize, size: usize) {
let paddr = virt_to_phys(vaddr);
for i in 0..size / PAGE_SIZE {
unsafe {
frame_dealloc(&(paddr + i * PAGE_SIZE));
}
//dealloc_frame(paddr + i * PAGE_SIZE);
}
}
}
#[no_mangle]
extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
//let paddr = alloc_frame_contiguous(pages, 0).unwrap();
let paddr = unsafe { hal_frame_alloc_contiguous(pages, 0).unwrap() };
trace!("alloc DMA: paddr={:#x}, pages={}", paddr, pages);
paddr
}
#[no_mangle]
extern "C" fn virtio_dma_dealloc(paddr: PhysAddr, pages: usize) -> i32 {
for i in 0..pages {
unsafe {
frame_dealloc(&(paddr + i * PAGE_SIZE));
}
//dealloc_frame(paddr + i * PAGE_SIZE);
}
trace!("dealloc DMA: paddr={:#x}, pages={}", paddr, pages);
0
}
#[no_mangle]
extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr {
phys_to_virt(paddr)
}
#[no_mangle]
extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
virt_to_phys(vaddr)
}
type VirtAddr = usize;
type PhysAddr = usize;

View File

@ -0,0 +1,36 @@
use super::SERIAL_DRIVERS;
use alloc::sync::Arc;
use core::fmt::{Result, Write};
use kernel_hal::drivers::Driver;
// #[cfg(feature = "board_raspi3")]
// pub mod bcm2837;
/*
#[cfg(target_arch = "x86_64")]
pub mod com;
#[cfg(target_arch = "x86_64")]
pub mod keyboard;
*/
pub mod uart;
pub mod uart16550;
//pub mod virtio_console;
pub trait SerialDriver: Driver {
// read one byte from tty
fn read(&self) -> u8;
// write bytes to tty
fn write(&self, data: &[u8]);
// get if it is ready. as a hint.
fn try_read(&self) -> Option<u8> {
Some(self.read())
}
}
/*
use crate::sync::Condvar;
lazy_static! {
pub static ref SERIAL_ACTIVITY: Condvar = Condvar::new();
}
*/

View File

@ -0,0 +1,185 @@
//use super::consts::UART_BASE;
use crate::arch::serial_put;
use crate::drivers::device_tree::{DEVICE_TREE_INTC, DEVICE_TREE_REGISTRY};
use crate::drivers::{SerialDriver, IRQ_MANAGER, SERIAL_DRIVERS};
use crate::{phys_to_virt, putfmt};
use alloc::{format, string::String, sync::Arc};
use core::convert::TryInto;
use core::fmt::{Error, Write};
use device_tree::Node;
use kernel_hal::drivers::{DeviceType, Driver, DRIVERS};
pub struct Uart {
base_address: usize,
}
// 结构体Uart的实现块
impl Uart {
pub fn new(base_address: usize) -> Self {
Uart { base_address }
}
#[cfg(not(feature = "board_d1"))]
pub fn simple_init(&mut self) {
let ptr = self.base_address as *mut u8;
unsafe {
// Enable FIFO; (base + 2)
ptr.add(2).write_volatile(0xC7);
// MODEM Ctrl; (base + 4)
ptr.add(4).write_volatile(0x0B);
// Enable interrupts; (base + 1)
ptr.add(1).write_volatile(0x01);
}
}
#[cfg(feature = "board_d1")]
pub fn simple_init(&mut self) {
let ptr = self.base_address as *mut u32;
unsafe {
// Enable FIFO; (base + 2)
ptr.add(2).write_volatile(0x7);
// MODEM Ctrl; (base + 4)
ptr.add(4).write_volatile(0x3);
//D1 ALLWINNER的uart中断使能
// D1 UART_IER offset = 0x4
//
// Enable interrupts; (base + 1)
ptr.add(1).write_volatile(0x1);
}
}
pub fn get(&self) -> Option<u8> {
#[cfg(not(feature = "board_d1"))]
let ptr = self.base_address as *const u8;
#[cfg(feature = "board_d1")]
let ptr = self.base_address as *const u32;
unsafe {
//查看LSR的DR位为1则有数据
if ptr.add(5).read_volatile() & 0b1 == 0 {
None
} else {
Some((ptr.add(0).read_volatile() & 0xff) as u8)
}
}
}
pub fn put(&self, c: u8) {
let ptr = self.base_address as *mut u8;
unsafe {
//此时transmitter empty
ptr.add(0).write_volatile(c);
}
}
}
impl Driver for Uart {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
if let Some(c) = self.get() {
let c = c & 0xff;
serial_put(c);
true
} else {
false
}
}
fn device_type(&self) -> DeviceType {
DeviceType::Serial
}
fn get_id(&self) -> String {
format!("uart_{}", self.base_address)
}
}
impl SerialDriver for Uart {
fn read(&self) -> u8 {
self.get().unwrap_or(0)
}
fn write(&self, data: &[u8]) {
for byte in data {
self.put(*byte);
}
}
fn try_read(&self) -> Option<u8> {
self.get()
}
}
// 需要实现的write_str()重要函数
impl Write for Uart {
fn write_str(&mut self, out: &str) -> Result<(), Error> {
for c in out.bytes() {
self.put(c);
}
Ok(())
}
}
/*
pub fn handle_interrupt() {
let mut my_uart = Uart::new(phys_to_virt(UART_BASE));
if let Some(c) = my_uart.get() {
let c = c & 0xff;
//CONSOLE
super::serial_put(c);
/*
* serial_write()
match c {
0x7f => { //0x8 [backspace] ; 而实际qemu运行[backspace]键输出0x7f, 表示del
bare_print!("{} {}", 8 as char, 8 as char);
},
10 | 13 => { // 新行或回车
bare_println!();
},
_ => {
bare_print!("{}", c as char);
},
}
*/
}
}
*/
pub fn init_dt(dt: &Node) {
let addr = dt.prop_usize("reg").unwrap();
let base = phys_to_virt(addr);
info!("Init Uart at {:#x}", base);
let mut us = Uart::new(base);
us.simple_init();
let com = Arc::new(us);
let mut found = false;
let irq_opt = dt.prop_u32("interrupts").ok().map(|irq| irq as usize);
DRIVERS.write().push(com.clone());
SERIAL_DRIVERS.write().push(com.clone());
if let Ok(intc) = dt.prop_u32("interrupt-parent") {
if let Some(irq) = irq_opt {
if let Some(manager) = DEVICE_TREE_INTC.write().get_mut(&intc) {
manager.register_local_irq(irq, com.clone());
info!("Registered Uart irq {} to PLIC intc", irq);
info!("Init Uart at {:#x}, {:?}", base, dt);
found = true;
}
}
}
if !found {
info!("Registered Uart to root");
IRQ_MANAGER.write().register_opt(irq_opt, com);
}
}
pub fn driver_init() {
DEVICE_TREE_REGISTRY.write().insert("ns16550a", init_dt);
}

View File

@ -0,0 +1,125 @@
//! 16550 serial adapter driver for malta board
use super::SerialDriver;
use crate::arch::serial_put;
use crate::drivers::device_tree::{DEVICE_TREE_INTC, DEVICE_TREE_REGISTRY};
use crate::drivers::IRQ_MANAGER;
use crate::drivers::SERIAL_DRIVERS;
use crate::phys_to_virt;
use kernel_hal::drivers::{DeviceType, Driver, DRIVERS};
use spin::Mutex;
/*
use crate::{
memory::phys_to_virt,
util::{read, write},
};
*/
use alloc::{format, string::String, sync::Arc};
use core::fmt::{Arguments, Result, Write};
use device_tree::Node;
use uart_16550::MmioSerialPort;
pub struct SerialPort {
base: usize,
ms: Mutex<MmioSerialPort>,
}
impl Driver for SerialPort {
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
if let Some(c) = self.getchar_option() {
serial_put(c);
//super::SERIAL_ACTIVITY.notify_all();
true
} else {
false
}
}
fn device_type(&self) -> DeviceType {
DeviceType::Serial
}
fn get_id(&self) -> String {
format!("com_{}", self.base)
}
}
impl SerialPort {
fn new(base: usize) -> SerialPort {
let mut mmio_serial_port = unsafe { MmioSerialPort::new(base) };
mmio_serial_port.init();
SerialPort {
base,
ms: Mutex::new(mmio_serial_port),
}
}
pub fn putchar(&self, c: u8) {
self.ms.lock().send(c);
}
pub fn getchar(&mut self) -> u8 {
let c = self.ms.lock().receive();
match c {
255 => b'\0', // null
c => c,
}
}
pub fn getchar_option(&self) -> Option<u8> {
let c = self.ms.lock().receive() as isize;
match c {
-1 => None,
c => Some(c as u8),
}
}
}
impl SerialDriver for SerialPort {
fn read(&self) -> u8 {
self.getchar_option().unwrap_or(0)
}
fn write(&self, data: &[u8]) {
for byte in data {
self.putchar(*byte);
}
}
fn try_read(&self) -> Option<u8> {
self.getchar_option()
}
}
pub fn init_dt(dt: &Node) {
let addr = dt.prop_usize("reg").unwrap();
//let shift = dt.prop_u32("reg-shift").unwrap_or(0) as usize;
let base = phys_to_virt(addr);
info!("Init uart16550 at {:#x}", base);
let com = Arc::new(SerialPort::new(base));
let mut found = false;
let irq_opt = dt.prop_u32("interrupts").ok().map(|irq| irq as usize);
DRIVERS.write().push(com.clone());
SERIAL_DRIVERS.write().push(com.clone());
if let Ok(intc) = dt.prop_u32("interrupt-parent") {
if let Some(irq) = irq_opt {
//PLIC phandle
if let Some(manager) = DEVICE_TREE_INTC.write().get_mut(&intc) {
manager.register_local_irq(irq, com.clone());
info!("registered uart16550 irq {} to PLIC intc", irq);
info!("Init uart16550 at {:#x}, {:?}", base, dt);
found = true;
}
}
}
if !found {
info!("registered uart16550 to root");
IRQ_MANAGER.write().register_opt(irq_opt, com);
}
}
pub fn driver_init() {
DEVICE_TREE_REGISTRY.write().insert("ns16550a", init_dt);
}

View File

@ -1,72 +1,9 @@
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use rcore_fs::dev::{self, BlockDevice, DevError};
use spin::RwLock;
//pub use block::BlockDriver;
use kernel_hal::drivers::{BlockDriver, DeviceType, Driver, BLK_DRIVERS, DRIVERS};
/// Block device
pub mod virtio;
/// Device tree
pub mod device_tree;
#[derive(Debug, Eq, PartialEq)]
pub enum DeviceType {
Net,
Gpu,
Input,
Block,
Rtc,
Serial,
Intc,
}
pub trait Driver: Send + Sync {
// if interrupt belongs to this driver, handle it and return true
// return false otherwise
// irq number is provided when available
// driver should skip handling when irq number is mismatched
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool;
// return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType;
// get unique identifier for this device
// should be different for each instance
fn get_id(&self) -> String;
// trait casting
/*
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
*/
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
/*
fn as_rtc(&self) -> Option<&dyn RtcDriver> {
None
}
*/
}
/////////
pub trait BlockDriver: Driver {
fn read_block(&self, _block_id: usize, _buf: &mut [u8]) -> bool {
unimplemented!("not a block driver")
}
fn write_block(&self, _block_id: usize, _buf: &[u8]) -> bool {
unimplemented!("not a block driver")
}
}
pub trait GpuDriver: Driver {
fn resolution(&self) -> (u32, u32) {
unimplemented!("not a gpu driver")
@ -87,40 +24,3 @@ pub trait InputDriver: Driver {
}
}
/////////
lazy_static! {
// NOTE: RwLock only write when initializing drivers
pub static ref DRIVERS: RwLock<Vec<Arc<dyn Driver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<dyn BlockDriver>>> = RwLock::new(Vec::new());
pub static ref INPUT_DRIVERS: RwLock<Vec<Arc<dyn InputDriver>>> = RwLock::new(Vec::new());
pub static ref GPU_DRIVERS: RwLock<Vec<Arc<dyn GpuDriver>>> = RwLock::new(Vec::new());
//pub static ref IRQ_MANAGER: RwLock<irq::IrqManager> = RwLock::new(irq::IrqManager::new(true));
}
pub struct BlockDriverWrapper(pub Arc<dyn BlockDriver>);
impl BlockDevice for BlockDriverWrapper {
const BLOCK_SIZE_LOG2: u8 = 9; // 512
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> dev::Result<()> {
match self.0.read_block(block_id, buf) {
true => Ok(()),
false => Err(DevError),
}
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> dev::Result<()> {
match self.0.write_block(block_id, buf) {
true => Ok(()),
false => Err(DevError),
}
}
fn sync(&self) -> dev::Result<()> {
Ok(())
}
}
lazy_static! {
// Write only once at boot
pub static ref CMDLINE: RwLock<String> = RwLock::new(String::new());
}

View File

@ -1,8 +1,13 @@
use crate::drivers::device_tree::DEVICE_TREE_REGISTRY;
use crate::drivers::net::virtio_net;
use crate::drivers::{GpuDriver, InputDriver, GPU_DRIVERS, INPUT_DRIVERS, IRQ_MANAGER};
use crate::{frame_dealloc, hal_frame_alloc_contiguous, phys_to_virt, virt_to_phys, PAGE_SIZE};
use device_tree::util::SliceRead;
use device_tree::Node;
use log::*;
use virtio_drivers::{VirtIOBlk, VirtIOGpu, VirtIOHeader, VirtIOInput};
//use kernel_hal::drivers::{Driver, BlockDriver, DeviceType, DRIVERS, BLK_DRIVERS};
use super::{BlockDriver, DeviceType, Driver, BLK_DRIVERS, DRIVERS};
pub fn virtio_probe(node: &Node) {
let reg = match node.prop_raw("reg") {
@ -23,12 +28,13 @@ pub fn virtio_probe(node: &Node) {
return;
}
info!(
"Detected virtio device with vendor id: {:#X}",
header.vendor_id()
"Detected virtio device with vendor id: {:#X}, DeviceType: {:?}",
header.vendor_id(),
header.device_type(),
);
info!("Device tree node {:?}", node);
match header.device_type() {
//DeviceType::Network => virtio_net::init(header),
virtio_drivers::DeviceType::Network => virtio_net::init(node, header),
virtio_drivers::DeviceType::Block => virtio_blk_init(header),
virtio_drivers::DeviceType::Input => virtio_input_init(header),
virtio_drivers::DeviceType::GPU => virtio_gpu_init(header),
@ -36,21 +42,20 @@ pub fn virtio_probe(node: &Node) {
}
}
pub fn driver_init() {
DEVICE_TREE_REGISTRY
.write()
.insert("virtio,mmio", virtio_probe);
}
use alloc::format;
/// virtio_mmio
/////////
/// virtio_blk
use alloc::string::String;
use alloc::sync::Arc;
use alloc::format;
use super::{
BlockDriver, DeviceType, Driver, GpuDriver, InputDriver, BLK_DRIVERS, DRIVERS, GPU_DRIVERS,
INPUT_DRIVERS,
};
//use crate::{sync::SpinNoIrqLock as Mutex};
use spin::Mutex;
//use crate::{sync::SpinNoIrqLock as Mutex};
struct VirtIOBlkDriver(Mutex<VirtIOBlk<'static>>);
struct VirtIOGpuDriver(Mutex<VirtIOGpu<'static>>);
@ -96,10 +101,6 @@ impl Driver for VirtIOGpuDriver {
fn get_id(&self) -> String {
format!("virtio_gpu")
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl GpuDriver for VirtIOGpuDriver {
@ -132,10 +133,6 @@ impl Driver for VirtIOInputDriver {
fn get_id(&self) -> String {
format!("virtio_input")
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl InputDriver for VirtIOInputDriver {
@ -148,7 +145,7 @@ pub fn virtio_blk_init(header: &'static mut VirtIOHeader) {
let blk = VirtIOBlk::new(header).expect("failed to init blk driver");
let driver = Arc::new(VirtIOBlkDriver(Mutex::new(blk)));
DRIVERS.write().push(driver.clone());
//IRQ_MANAGER.write().register_all(driver.clone());
IRQ_MANAGER.write().register_all(driver.clone());
BLK_DRIVERS.write().push(driver);
}
@ -169,37 +166,3 @@ pub fn virtio_gpu_init(header: &'static mut VirtIOHeader) {
DRIVERS.write().push(driver.clone());
GPU_DRIVERS.write().push(driver);
}
/////////
/// virtio dma alloc/dealloc
#[no_mangle]
extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
let paddr = unsafe { hal_frame_alloc_contiguous(pages, 0).unwrap() };
trace!("alloc DMA: paddr={:#x}, pages={}", paddr, pages);
paddr
}
#[no_mangle]
extern "C" fn virtio_dma_dealloc(paddr: PhysAddr, pages: usize) -> i32 {
for i in 0..pages {
unsafe {
frame_dealloc(&(paddr + i * PAGE_SIZE));
}
}
trace!("dealloc DMA: paddr={:#x}, pages={}", paddr, pages);
0
}
#[no_mangle]
extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr {
phys_to_virt(paddr)
}
#[no_mangle]
extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
virt_to_phys(vaddr)
}
type VirtAddr = usize;
type PhysAddr = usize;

View File

@ -13,6 +13,8 @@ trapframe = "0.8.0"
numeric-enum-macro = "0.2"
acpi = "1.1"
spin = "0.7"
lazy_static = { version = "1.4", features = ["spin_no_std"] }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
#[patch.crates-io]
#trapframe = { path = "/home/xly/rust/arch-lib/trapframe-rs" }
downcast-rs = { version = "1.2", default-features = false }

View File

@ -0,0 +1,11 @@
use super::Driver;
pub trait BlockDriver: Driver {
fn read_block(&self, _block_id: usize, _buf: &mut [u8]) -> bool {
unimplemented!("not a block driver")
}
fn write_block(&self, _block_id: usize, _buf: &[u8]) -> bool {
unimplemented!("not a block driver")
}
}

View File

@ -0,0 +1,99 @@
//use crate::sync::Condvar;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use smoltcp::socket::SocketSet;
use spin::Mutex;
use spin::RwLock;
//pub use self::virtio::*;
pub use block::BlockDriver;
pub use net::NetDriver;
/*
/// virtio device
pub mod virtio;
*/
pub mod block;
/// Network controller
pub mod net;
#[derive(Debug, Eq, PartialEq)]
pub enum DeviceType {
Net,
Gpu,
Input,
Block,
Rtc,
Serial,
Intc,
}
use downcast_rs::DowncastSync;
pub trait Driver: DowncastSync + Send + Sync {
// if interrupt belongs to this driver, handle it and return true
// return false otherwise
// irq number is provided when available
// driver should skip handling when irq number is mismatched
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool;
// return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType;
// get unique identifier for this device
// should be different for each instance
fn get_id(&self) -> String;
// trait casting
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
/*
fn as_rtc(&self) -> Option<&dyn RtcDriver> {
None
}
*/
}
lazy_static! {
// NOTE: RwLock only write when initializing drivers
pub static ref DRIVERS: RwLock<Vec<Arc<dyn Driver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<dyn NetDriver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<dyn BlockDriver>>> = RwLock::new(Vec::new());
}
lazy_static! {
/// Global SocketSet in smoltcp.
///
/// Because smoltcp is a single thread network stack,
/// every socket operation needs to lock this.
pub static ref SOCKETS: Arc<Mutex<SocketSet<'static>>> =
Arc::new(Mutex::new(SocketSet::new(vec![])));
}
/*
lazy_static! {
//pub static ref SOCKET_ACTIVITY: Condvar = Condvar::new();
}
*/
#[allow(warnings)]
#[export_name = "hal_get_driver"]
#[no_mangle]
pub extern "C" fn get_net_driver() -> Vec<Arc<dyn NetDriver>> {
NET_DRIVERS.read().clone()
}
#[export_name = "hal_get_net_sockets"]
pub fn get_net_sockets() -> Arc<Mutex<SocketSet<'static>>> {
SOCKETS.clone()
}

View File

@ -0,0 +1,64 @@
use super::Driver;
use alloc::string::String;
use alloc::vec::Vec;
// use core::any::Any;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
/*
* trait
* struct并实现该trait
* struct的函数用#[linkage = "weak"]
*
* traitstruct的函数
*/
pub trait NetDriver: Driver {
// get mac address for this device
fn get_mac(&self) -> EthernetAddress {
unimplemented!("not a net driver")
}
// get interface name for this device
fn get_ifname(&self) -> String {
unimplemented!("not a net driver")
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
unimplemented!("not a net driver")
}
// get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!("not a net driver")
}
// manually trigger a poll, use it after sending packets
fn poll(&self) {
unimplemented!("not a net driver")
}
// send an ethernet frame, only use it when necessary
fn send(&self, _data: &[u8]) -> Option<usize> {
unimplemented!("not a net driver")
}
// get mac address from ip address in arp table
fn get_arp(&self, _ip: IpAddress) -> Option<EthernetAddress> {
unimplemented!("not a net driver")
}
}
use downcast_rs::impl_downcast;
impl_downcast!(sync NetDriver);
// little hack, see https://users.rust-lang.org/t/how-to-downcast-from-a-trait-any-to-a-struct/11219/3
// pub trait AsAny : Sync + Send {
// fn as_any(&self) -> &dyn Any;
// }
// impl<T: Any + Send + Sync> AsAny for T {
// fn as_any(&self) -> &dyn Any {
// self
// }
// }

View File

@ -476,6 +476,28 @@ pub fn fill_random(_buf: &mut [u8]) {
// TODO
}
/// Generate a random u64.
#[cfg(target_arch = "x86_64")]
pub fn rand_u64() -> u64 {
let mut r = 0;
unsafe {
core::arch::x86_64::_rdrand64_step(&mut r);
}
r
}
/// Generate a random u64.
#[cfg(target_arch = "aarch64")]
pub fn rand_u64() -> u64 {
todo!()
}
/// Generate a random u64.
#[cfg(target_arch = "riscv64")]
pub fn rand_u64() -> u64 {
todo!()
}
#[linkage = "weak"]
#[export_name = "hal_current_pgtable"]
pub fn current_page_table() -> usize {

View File

@ -41,6 +41,7 @@ pub mod defs {
}
mod context;
pub mod drivers;
mod dummy;
mod fb;
mod future;
@ -49,6 +50,7 @@ pub mod vdso;
pub use self::context::*;
pub use self::defs::*;
pub use self::drivers::*;
pub use self::dummy::*;
pub use self::fb::*;
pub use self::future::*;

View File

@ -15,10 +15,15 @@ linux-object = { path = "../linux-object" }
zircon-object = { path = "../zircon-object" }
kernel-hal = { path = "../kernel-hal" }
rcore-fs-hostfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2", optional = true }
rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2"}
env_logger = { version = "0.8", optional = true }
kernel-hal-unix = { path = "../kernel-hal-unix", optional = true }
async-std = { version = "1.9", features = ["attributes"], optional = true }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
kernel-hal-bare = { path = "../kernel-hal-bare" }
byteorder = { version = "1.0", default-features = false }
[features]
default = ["std"]
std = ["env_logger", "async-std", "kernel-hal-unix", "rcore-fs-hostfs", "zircon-object/aspace-separate"]

870
linux-loader/src/lib-b.rs Normal file
View File

@ -0,0 +1,870 @@
//! Linux LibOS
//! - run process and manage trap/interrupt/syscall
#![no_std]
#![feature(asm)]
#![deny(warnings, unused_must_use, missing_docs)]
extern crate alloc;
#[macro_use]
extern crate log;
use {
alloc::{boxed::Box, string::String, sync::Arc, vec::Vec},
core::{future::Future, pin::Pin},
kernel_hal::{GeneralRegs, MMUFlags},
linux_object::{
fs::{vfs::FileSystem, INodeExt},
loader::LinuxElfLoader,
process::ProcessExt,
thread::ThreadExt,
},
linux_syscall::Syscall,
zircon_object::task::*,
};
/// Create and run main Linux process
pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) -> Arc<Process> {
let job = Job::root();
let proc = Process::create_linux(&job, rootfs.clone()).unwrap();
let thread = Thread::create_linux(&proc).unwrap();
let loader = LinuxElfLoader {
#[cfg(feature = "std")]
syscall_entry: kernel_hal_unix::syscall_entry as usize,
#[cfg(not(feature = "std"))]
syscall_entry: 0,
stack_pages: 8,
root_inode: rootfs.root_inode(),
};
let inode = rootfs.root_inode().lookup(&args[0]).unwrap();
let data = inode.read_as_vec().unwrap();
let path = args[0].clone();
let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap();
// run ping
thread
.start(entry, sp, 0, 0, thread_fn)
.expect("failed to start main thread");
// or run ping
proc
}
/// The function of a new thread.
///
/// loop:
/// - wait for the thread to be ready
/// - get user thread context
/// - enter user mode
/// - handle trap/interrupt/syscall according to the return value
/// - return the context to the user thread
async fn new_thread(thread: CurrentThread) {
loop {
// wait
let mut cx = thread.wait_for_run().await;
if thread.state() == ThreadState::Dying {
break;
}
// super_mode_net_udp_server_test();
// super_mode_net_tcp_server_test();
// super_mode_net_tcp_client_test();
// super_mode_frame_test();
super_mode_eap_test().await;
// run
trace!("go to user: {:#x?}", cx);
kernel_hal::context_run(&mut cx);
trace!("back from user: {:#x?}", cx);
// handle trap/interrupt/syscall
match cx.trap_num {
0x100 => handle_syscall(&thread, &mut cx.general).await,
0x20..=0x3f => {
kernel_hal::InterruptManager::handle(cx.trap_num as u8);
if cx.trap_num == 0x20 {
kernel_hal::yield_now().await;
}
}
0xe => {
let vaddr = kernel_hal::fetch_fault_vaddr();
let flags = if cx.error_code & 0x2 == 0 {
MMUFlags::READ
} else {
MMUFlags::WRITE
};
error!("page fualt from user mode {:#x} {:#x?}", vaddr, flags);
let vmar = thread.proc().vmar();
match vmar.handle_page_fault(vaddr, flags) {
Ok(()) => {}
Err(_) => {
panic!("Page Fault from user mode {:#x?}", cx);
}
}
}
_ => panic!("not supported interrupt from user mode. {:#x?}", cx),
}
thread.end_running(cx);
}
}
fn thread_fn(thread: CurrentThread) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> {
Box::pin(new_thread(thread))
}
/// syscall handler entry
async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
trace!("syscall: {:#x?}", regs);
let num = regs.rax as u32;
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
let mut syscall = Syscall {
thread,
#[cfg(feature = "std")]
syscall_entry: kernel_hal_unix::syscall_entry as usize,
#[cfg(not(feature = "std"))]
syscall_entry: 0,
thread_fn,
regs,
};
regs.rax = syscall.syscall(num, args).await as usize;
}
#[allow(dead_code)]
fn super_mode_net_udp_server_test() {
use core::str::from_utf8;
use kernel_hal::devices::get_net_driver;
use kernel_hal::timer_now;
use kernel_hal_bare::devices::net::e1000::E1000Interface;
//use smoltcp::socket::SocketSet;
use smoltcp::socket::UdpPacketMetadata;
use smoltcp::socket::UdpSocket;
use smoltcp::socket::UdpSocketBuffer;
//use smoltcp::time::Instant;
// udp s
let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 64]);
let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 128]);
// udp socket
let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
//use alloc::vec;
// use alloc::vec::Vec;
let mut sockets = SocketSet::new(vec![]);
let udp_handle = sockets.add(udp_socket);
let e1000 = get_net_driver()[0].clone();
// let local = NET_DRIVERS.read()[0].clone();
if let Ok(_li) = e1000.downcast_arc::<E1000Interface>() {
// use std::os::unix::io::AsRawFd;
// let fd = li.iface.lock().device().as_raw_fd();
// let mut sockets = SOCKETS.lock();
loop {
// let _timestamp = Instant::now();
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
match _li.iface.lock().poll(&mut sockets, timestamp) {
Ok(_a) => {
// warn!("poll ok: {}", a);
}
Err(e) => {
warn!("poll error: {}", e);
}
}
{
// udp bind
let mut socket = sockets.get::<UdpSocket>(udp_handle);
if !socket.is_open() {
warn!("bind 6969");
socket.bind(6969).unwrap()
}
// udp recv
let client = match socket.recv() {
Ok((data, endpoint)) => {
warn!(" udp recv : {} form {}", from_utf8(data).unwrap(), endpoint);
Some(endpoint)
}
Err(_) => None,
};
// udp send
if let Some(endpoint) = client {
let data = b"cargo test OK";
warn!(
"udp:6969 send data: {:?}",
from_utf8(data.as_ref()).unwrap()
);
socket.send_slice(data, endpoint).unwrap();
}
}
}
}
todo!();
}
// #[allow(dead_code)]
// fn super_mode_net_tcp_server_test() {
// use smoltcp::socket::TcpSocket;
// use smoltcp::socket::TcpSocketBuffer;
// use smoltcp::time::Instant;
// use core::str::from_utf8;
// use kernel_hal::devices::get_net_driver;
// use kernel_hal::timer_now;
// use kernel_hal_bare::devices::net::e1000::E1000Interface;
// use smoltcp::socket::SocketSet;
// let tcp1_rx_buffer = TcpSocketBuffer::new(vec![0; 64]);
// let tcp1_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);
// let tcp1_socket = TcpSocket::new(tcp1_rx_buffer, tcp1_tx_buffer);
// use alloc::vec;
// // use alloc::vec::Vec;
// let mut sockets = SocketSet::new(vec![]);
// let tcp1_handle = sockets.add(tcp1_socket);
// let e1000 = get_net_driver()[0].clone();
// // let local = NET_DRIVERS.read()[0].clone();
// if let Ok(_li) = e1000.downcast_arc::<E1000Interface>() {
// // use std::os::unix::io::AsRawFd;
// // let fd = li.iface.lock().device().as_raw_fd();
// // let mut sockets = SOCKETS.lock();
// loop {
// // let _timestamp = Instant::now();
// let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
// match _li.iface.lock().poll(&mut sockets, timestamp) {
// Ok(_a) => {
// // warn!("poll ok: {}", a);
// }
// Err(e) => {
// warn!("poll error: {}", e);
// }
// }
// {
// let mut socket = sockets.get::<TcpSocket>(tcp1_handle);
// if !socket.is_open() {
// socket.listen(6969).unwrap();
// }
// if socket.can_send() {
// let data = b"cargo tcp test OK";
// warn!(
// "server tcp:6969 send data: {:?}",
// from_utf8(data.as_ref()).unwrap()
// );
// socket.send_slice(&data[..]).unwrap();
// warn!("tcp:6969 close");
// socket.close();
// }
// }
// }
// }
// todo!();
// }
#[allow(dead_code)]
fn super_mode_net_tcp_client_test() {
use alloc::borrow::ToOwned;
use core::str::from_utf8;
use kernel_hal::devices::get_net_driver;
use kernel_hal::timer_now;
use kernel_hal_bare::devices::net::e1000::E1000Interface;
//use smoltcp::socket::SocketSet;
use smoltcp::socket::TcpSocket;
use smoltcp::socket::TcpSocketBuffer;
//use smoltcp::time::Instant;
//use smoltcp::wire::IpAddress;
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 64]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 128]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
//use alloc::vec;
// use alloc::vec::Vec;
let mut sockets = SocketSet::new(vec![]);
let tcp_handle = sockets.add(tcp_socket);
let e1000 = get_net_driver()[0].clone();
// let local = NET_DRIVERS.read()[0].clone();
if let Ok(_li) = e1000.downcast_arc::<E1000Interface>() {
let addr = IpAddress::v4(172, 25, 220, 230);
let port = 6969u16;
{
let mut socket = sockets.get::<TcpSocket>(tcp_handle);
socket.connect((addr, port), 49500).unwrap();
}
let mut tcp_active = false;
loop {
// let _timestamp = Instant::now();
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
match _li.iface.lock().poll(&mut sockets, timestamp) {
Ok(_a) => {
// warn!("poll ok: {}", a);
}
Err(e) => {
warn!("poll error: {}", e);
}
}
{
let mut socket = sockets.get::<TcpSocket>(tcp_handle);
if socket.is_active() && !tcp_active {
warn!("connected");
} else if !socket.is_active() && tcp_active {
warn!("disconnected");
// break
}
tcp_active = socket.is_active();
if socket.may_send() {
warn!("send");
let mut data: Vec<u8> = Vec::new();
data.push(100);
socket.send_slice(&data[..]).unwrap();
}
if socket.may_recv() {
let data = socket
.recv(|data| {
let mut data = data.to_owned();
if !data.is_empty() {
warn!(
"recv data: {:?}",
from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
);
data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
data.reverse();
data.extend(b"\n");
}
(data.len(), data)
})
.unwrap_or(vec![99]);
if socket.can_send() && !data.is_empty() {
warn!(
"send data: {:?}",
from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
);
socket.send_slice(&data[..]).unwrap();
}
} else if socket.may_send() {
warn!("close");
socket.close();
}
}
}
}
todo!();
}
#[allow(dead_code)]
#[allow(unused_imports)]
#[allow(unused_variables)]
fn super_mode_frame_test() {
use core::str::from_utf8;
use kernel_hal::devices::get_net_driver;
use kernel_hal::timer_now;
use kernel_hal_bare::devices::net::e1000::E1000Interface;
use smoltcp::socket::SocketSet;
use smoltcp::socket::UdpPacketMetadata;
use smoltcp::socket::UdpSocket;
use smoltcp::socket::UdpSocketBuffer;
use smoltcp::time::Instant;
// // udp s
// let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 64]);
// let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 128]);
// // udp socket
// let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
// use alloc::vec;
// // use alloc::vec::Vec;
// let mut sockets = SocketSet::new(vec![]);
// let udp_handle = sockets.add(udp_socket);
let e1000 = get_net_driver()[0].clone();
// let local = NET_DRIVERS.read()[0].clone();
if let Ok(_li) = e1000.downcast_arc::<E1000Interface>() {
// use std::os::unix::io::AsRawFd;
// let fd = li.iface.lock().device().as_raw_fd();
// let mut sockets = SOCKETS.lock();
loop {
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
let _x = _li.iface.lock().biubiu(timestamp);
}
// loop {
// // let _timestamp = Instant::now();
// let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
// let _x = _li.iface.lock().biubiu(timestamp);
// match _li.iface.lock().poll(&mut sockets, timestamp) {
// Ok(_a) => {
// // warn!("poll ok: {}", a);
// }
// Err(e) => {
// warn!("poll error: {}", e);
// }
// }
// {
// // udp bind
// let mut socket = sockets.get::<UdpSocket>(udp_handle);
// if !socket.is_open() {
// warn!("bind 6969");
// socket.bind(6969).unwrap()
// }
// // udp recv
// let client = match socket.recv() {
// Ok((data, endpoint)) => {
// warn!(" udp recv : {} form {}", from_utf8(data).unwrap(), endpoint);
// Some(endpoint)
// }
// Err(_) => None,
// };
// // udp send
// if let Some(endpoint) = client {
// let data = b"cargo test OK";
// warn!(
// "udp:6969 send data: {:?}",
// from_utf8(data.as_ref()).unwrap()
// );
// socket.send_slice(data, endpoint).unwrap();
// }
// }
// }
// loop{}
}
todo!();
}
#[allow(dead_code)]
#[allow(unused_imports)]
#[allow(unused_variables)]
async fn super_mode_eap_test() {
use core::str::from_utf8;
use kernel_hal::devices::get_net_driver;
use kernel_hal::timer_now;
use kernel_hal_bare::devices::net::e1000::E1000Interface;
use smoltcp::socket::SocketSet;
use smoltcp::socket::UdpPacketMetadata;
use smoltcp::socket::UdpSocket;
use smoltcp::socket::UdpSocketBuffer;
use smoltcp::time::Instant;
use smoltcp::wire::*;
use core::time::Duration;
use kernel_hal::sleep_until;
use kernel_hal::timer_tick;
let latency : u64 = 300;
let mac_addr = EthernetAddress([0x01, 0x80, 0xc2, 0x00, 0x00, 0x03]);
let e1000 = get_net_driver()[0].clone();
if let Ok(li) = e1000.downcast_arc::<E1000Interface>() {
loop {
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
let _x = li.iface.lock().eapol(timestamp); // eapol start
info!("<-- EAPOL Start from smoltcp");
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// eap 1
{
let eapol_repr = EAPoLRepr::EthernetEAPoL {
protocol_version: EAPoLProtocalVersion::X2001,
eap_type: EAPoLType::Packet,
len: 7,
};
let eap_repr = EAPRepr::EthernetEAP {
code: EAPCode::Response,
identifier: 4,
len: 7,
};
let eap_data_repr = EAPDataRepr::EthernetEAPData {
eapdata_type: EAPDataType::Identifier,
};
let f = |mut frame: EthernetFrame<&mut [u8]>| {
//frame.set_dst_addr(EthernetAddress::BROADCAST);
frame.set_dst_addr(mac_addr);
frame.set_ethertype(EthernetProtocol::EAPoL);
let mut eapol_packet = EAPoLPacket::new_unchecked(frame.payload_mut());
eapol_repr.emit(&mut eapol_packet);
let mut eap_packet = EAPPacket::new_unchecked(eapol_packet.packet_mut());
eap_repr.emit(&mut eap_packet);
let mut eap_data = EAPDataPacket::new_unchecked(eap_packet.data_mut());
eap_data_repr.emit(&mut eap_data);
/*
let typedata: [u8; 16] = [
0x43, 0x68, 0x65, 0x6e, 0x20, 0x58, 0x69, 0x6E, 0x67, 0x20, 0x7A, 0x43, 0x6F,
0x72, 0x65, 0x31,
];
*/
let typedata: [u8; 2] = [0x63, 0x6a]; //Identity: cj
eap_data.typedata_mut().copy_from_slice(&typedata[..]);
info!("EAP Response, eframe : {:x?}", frame);
};
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
let _x = li.iface.lock().eap(timestamp, eapol_repr.buffer_len(), f);
}
// 等待
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// eap 2
{
let eapol_repr = EAPoLRepr::EthernetEAPoL {
protocol_version: EAPoLProtocalVersion::X2001,
eap_type: EAPoLType::Packet,
len: 181,
};
let eap_repr = EAPRepr::EthernetEAP {
code: EAPCode::Response,
identifier: 5,
len: 181,
};
let eap_data_repr = EAPDataRepr::EthernetEAPData {
eapdata_type: EAPDataType::UnknownType,
};
let f = |mut frame: EthernetFrame<&mut [u8]>| {
//frame.set_dst_addr(EthernetAddress::BROADCAST);
frame.set_dst_addr(mac_addr);
frame.set_ethertype(EthernetProtocol::EAPoL);
let mut eapol_packet = EAPoLPacket::new_unchecked(frame.payload_mut());
eapol_repr.emit(&mut eapol_packet);
let mut eap_packet = EAPPacket::new_unchecked(eapol_packet.packet_mut());
eap_repr.emit(&mut eap_packet);
let mut eap_data = EAPDataPacket::new_unchecked(eap_packet.data_mut());
eap_data_repr.emit(&mut eap_data);
// 0d00000001000000820000c0582b9dbe365d6964049657b539a6fc736f01c4e0b45125278c936eefc98030070e000d005820c0582b9dbe365d6964049657b539a6fc736f01c4e0b45125278c936eefc9803030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000250000
let typedata: [u8; 176] = [0x0d, 0,0,0,0x01, 0,0,0,0x82, 0,0,0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36, 0x5d, 0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01, 0xc4, 0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30, 0x07, 0x0e, 0, 0x0d, 0, 0x58, 0x20, 0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36, 0x5d, 0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01, 0xc4, 0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30, 0x30, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x25,0,0];
// let typedata: [u8; 15] = [0x43 ,0x68 ,0x20 ,0x20 ,0x20 ,0x58 ,0x69 ,0x6E ,0x67 ,0x20 ,0x7A ,0x43 ,0x6F ,0x72 ,0x65];
eap_data.typedata_mut().copy_from_slice(&typedata[..]);
info!("EAP Response, eframe : {:x?}", frame);
};
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
let _x = li.iface.lock().eap(timestamp, eapol_repr.buffer_len(), f);
}
// 等待
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// eap 3
{
let eapol_repr = EAPoLRepr::EthernetEAPoL {
protocol_version: EAPoLProtocalVersion::X2001,
eap_type: EAPoLType::Packet,
len: 827,
};
let eap_repr = EAPRepr::EthernetEAP {
code: EAPCode::Response,
identifier: 6,
len: 827,
};
let eap_data_repr = EAPDataRepr::EthernetEAPData {
eapdata_type: EAPDataType::UnknownType,
};
let f = |mut frame: EthernetFrame<&mut [u8]>| {
//frame.set_dst_addr(EthernetAddress::BROADCAST);
frame.set_dst_addr(mac_addr);
frame.set_ethertype(EthernetProtocol::EAPoL);
let mut eapol_packet = EAPoLPacket::new_unchecked(frame.payload_mut());
eapol_repr.emit(&mut eapol_packet);
let mut eap_packet = EAPPacket::new_unchecked(eapol_packet.packet_mut());
eap_repr.emit(&mut eap_packet);
let mut eap_data = EAPDataPacket::new_unchecked(eap_packet.data_mut());
eap_data_repr.emit(&mut eap_data);
// 29581ef56be7dbc35aa776473712e35b3c0ac07f617a3c753110afa99790f8e4a80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021f56be7dbc35aa776473712e35b3c0ac07f617a3c753110afa99790f8e4a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001eeb6a0f36cab86e18f198d5f460a022bce63634f530e926ea6ab629b1da08cad0a401012004215820c0582b9dbe365d6964049657b539a6fc736f01c4e0b45125278c936eefc980306c7375626a656374206e616d65600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036a104411700000000000000000000000431e29aa20c17cae1ce9af087180e8d5556d84e00000000000000000000000000000000000000000b8368456e63727970743044a104411758585820eb6a0f36cab86e18f198d5f460a022bce63634f530e926ea6ab629b1da08cad0a401012004215820c0582b9dbe365d6964049657b539a6fc736f01c4e0b45125278c936eefc980306c7375626a656374206e616d65604bce9af087180e8d5556d84e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075
let typedata: [u8; 822] =
[0x29, 0x58, 0x1e, 0xf5, 0x6b, 0xe7, 0xdb, 0xc3, 0x5a, 0xa7, 0x76, 0x47, 0x37, 0x12, 0xe3, 0x5b, 0x3c, 0x0a, 0xc0, 0x7f, 0x61, 0x7a, 0x3c, 0x75, 0x31, 0x10, 0xaf, 0xa9, 0x97, 0x90, 0xf8, 0xe4, 0xa8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x21, 0xf5, 0x6b, 0xe7, 0xdb, 0xc3, 0x5a, 0xa7, 0x76, 0x47, 0x37, 0x12, 0xe3, 0x5b, 0x3c, 0x0a, 0xc0, 0x7f, 0x61, 0x7a, 0x3c, 0x75, 0x31, 0x10, 0xaf, 0xa9, 0x97, 0x90, 0xf8, 0xe4, 0xa8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x1e, 0xeb, 0x6a, 0x0f, 0x36, 0xca, 0xb8, 0x6e, 0x18, 0xf1, 0x98, 0xd5, 0xf4, 0x60, 0xa0, 0x22, 0xbc, 0xe6, 0x36, 0x34, 0xf5, 0x30, 0xe9, 0x26, 0xea, 0x6a, 0xb6, 0x29, 0xb1, 0xda, 0x08, 0xca, 0xd0, 0xa4, 0x01, 0x01, 0x20, 0x04, 0x21, 0x58, 0x20, 0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36, 0x5d, 0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01, 0xc4, 0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30, 0x6c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x60, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x36, 0xa1, 0x04, 0x41, 0x17, 0,0,0,0,0,0,0,0,0,0,0, 0x04, 0x31, 0xe2, 0x9a, 0xa2, 0x0c, 0x17, 0xca, 0xe1, 0xce, 0x9a, 0xf0, 0x87, 0x18, 0x0e, 0x8d, 0x55, 0x56, 0xd8, 0x4e, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0b, 0x83, 0x68, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x30, 0x44, 0xa1, 0x04, 0x41, 0x17, 0x58, 0x58, 0x58, 0x20, 0xeb, 0x6a, 0x0f, 0x36, 0xca, 0xb8, 0x6e, 0x18, 0xf1, 0x98, 0xd5, 0xf4, 0x60, 0xa0, 0x22, 0xbc, 0xe6, 0x36, 0x34, 0xf5, 0x30, 0xe9, 0x26, 0xea, 0x6a, 0xb6, 0x29, 0xb1, 0xda, 0x08, 0xca, 0xd0, 0xa4, 0x01, 0x01, 0x20, 0x04, 0x21, 0x58, 0x20, 0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36, 0x5d, 0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01, 0xc4, 0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30, 0x6c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x60, 0x4b, 0xce, 0x9a, 0xf0, 0x87, 0x18, 0x0e, 0x8d, 0x55, 0x56, 0xd8, 0x4e, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x75];
eap_data.typedata_mut().copy_from_slice(&typedata[..]);
info!("EAP Response, eframe : {:x?}", frame);
};
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
let _x = li.iface.lock().eap(timestamp, eapol_repr.buffer_len(), f);
}
// 等待30s
sleep_until(timer_now() + Duration::from_millis(30000)).await;
}//loop
}
loop {}
// todo!();
}
/////////
use alloc::vec;
use alloc::collections::BTreeMap;
use hashbrown::HashMap;
use byteorder::{ByteOrder, NetworkEndian};
use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
//use smoltcp::phy::wait as phy_wait;
//use smoltcp::phy::Device;
use smoltcp::socket::{IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer, SocketSet};
use smoltcp::wire::{
EthernetAddress, Icmpv4Packet, Icmpv4Repr, Icmpv6Packet, Icmpv6Repr, IpAddress, IpCidr,
Ipv4Address, Ipv6Address,
};
use smoltcp::{
phy::Medium,
time::{Duration, Instant},
};
macro_rules! send_icmp_ping {
( $repr_type:ident, $packet_type:ident, $ident:expr, $seq_no:expr,
$echo_payload:expr, $socket:expr, $remote_addr:expr ) => {{
let icmp_repr = $repr_type::EchoRequest {
ident: $ident,
seq_no: $seq_no,
data: &$echo_payload,
};
let icmp_payload = $socket.send(icmp_repr.buffer_len(), $remote_addr).unwrap();
let icmp_packet = $packet_type::new_unchecked(icmp_payload);
(icmp_repr, icmp_packet)
}};
}
macro_rules! get_icmp_pong {
( $repr_type:ident, $repr:expr, $payload:expr, $waiting_queue:expr, $remote_addr:expr,
$timestamp:expr, $received:expr ) => {{
if let $repr_type::EchoReply { seq_no, data, .. } = $repr {
if let Some(_) = $waiting_queue.get(&seq_no) {
let packet_timestamp_ms = NetworkEndian::read_i64(data);
info!(
"{} bytes from {}: icmp_seq={}, time={}ms",
data.len(),
$remote_addr,
seq_no,
$timestamp.total_millis() - packet_timestamp_ms
);
$waiting_queue.remove(&seq_no);
$received += 1;
}
}
}};
}
fn ping() {
//let address = IpAddress::from_str("192.168.1.100"); //remote addr
let address = IpAddress::v4(192, 168, 1, 100);
let count = 4;
let interval = Duration::from_secs(1);
let timeout = Duration::from_secs(5);
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let remote_addr = address;
let icmp_rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
let icmp_tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
let icmp_socket = IcmpSocket::new(icmp_rx_buffer, icmp_tx_buffer);
let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
let src_ipv6 = IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1);
let ip_addrs = [
IpCidr::new(IpAddress::v4(192, 168, 1, 10), 24),
IpCidr::new(src_ipv6, 64),
IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64),
];
let default_v4_gw = Ipv4Address::new(192, 168, 1, 100);
let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
let mut routes_storage = [None; 2];
let mut routes = Routes::new(&mut routes_storage[..]);
routes.add_default_ipv4_route(default_v4_gw).unwrap();
routes.add_default_ipv6_route(default_v6_gw).unwrap();
let medium = device.capabilities().medium;
let mut builder = InterfaceBuilder::new(device)
.ip_addrs(ip_addrs)
.routes(routes);
if medium == Medium::Ethernet {
builder = builder
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache);
}
let mut iface = builder.finalize();
let mut sockets = SocketSet::new(vec![]);
let icmp_handle = sockets.add(icmp_socket);
let mut send_at = Instant::from_millis(0);
let mut seq_no = 0;
let mut received = 0;
let mut echo_payload = [0xffu8; 40];
let mut waiting_queue = HashMap::new();
let ident = 0x22b;
loop {
//let timestamp = Instant::now(); // std? xly
let timestamp = Instant::from_millis(kernel_hal::timer_now().as_millis() as i64);
match iface.poll(&mut sockets, timestamp) {
Ok(_) => {}
Err(e) => {
debug!("poll error: {}", e);
}
}
{
//let timestamp = Instant::now();
let timestamp = Instant::from_millis(kernel_hal::timer_now().as_millis() as i64);
let mut socket = sockets.get::<IcmpSocket>(icmp_handle);
if !socket.is_open() {
socket.bind(IcmpEndpoint::Ident(ident)).unwrap();
send_at = timestamp;
}
if socket.can_send() && seq_no < count as u16 && send_at <= timestamp {
NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis());
match remote_addr {
IpAddress::Ipv4(_) => {
let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
Icmpv4Repr,
Icmpv4Packet,
ident,
seq_no,
echo_payload,
socket,
remote_addr
);
icmp_repr.emit(&mut icmp_packet, &device_caps.checksum);
}
IpAddress::Ipv6(_) => {
let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
Icmpv6Repr,
Icmpv6Packet,
ident,
seq_no,
echo_payload,
socket,
remote_addr
);
icmp_repr.emit(
&src_ipv6,
&remote_addr,
&mut icmp_packet,
&device_caps.checksum,
);
}
_ => unimplemented!(),
}
waiting_queue.insert(seq_no, timestamp);
seq_no += 1;
send_at += interval;
}
if socket.can_recv() {
let (payload, _) = socket.recv().unwrap();
match remote_addr {
IpAddress::Ipv4(_) => {
let icmp_packet = Icmpv4Packet::new_checked(&payload).unwrap();
let icmp_repr =
Icmpv4Repr::parse(&icmp_packet, &device_caps.checksum).unwrap();
get_icmp_pong!(
Icmpv4Repr,
icmp_repr,
payload,
waiting_queue,
remote_addr,
timestamp,
received
);
}
IpAddress::Ipv6(_) => {
let icmp_packet = Icmpv6Packet::new_checked(&payload).unwrap();
let icmp_repr = Icmpv6Repr::parse(
&remote_addr,
&src_ipv6,
&icmp_packet,
&device_caps.checksum,
)
.unwrap();
get_icmp_pong!(
Icmpv6Repr,
icmp_repr,
payload,
waiting_queue,
remote_addr,
timestamp,
received
);
}
_ => unimplemented!(),
}
}
waiting_queue.retain(|seq, from| {
if timestamp - *from < timeout {
true
} else {
info!("From {} icmp_seq={} timeout", remote_addr, seq);
false
}
});
if seq_no == count as u16 && waiting_queue.is_empty() {
break;
}
}
//let timestamp = Instant::now();
let timestamp = Instant::from_millis(kernel_hal::timer_now().as_millis() as i64);
match iface.poll_at(&sockets, timestamp) {
Some(poll_at) if timestamp < poll_at => {
// ? xly
//let resume_at = cmp::min(poll_at, send_at);
//phy_wait(fd, Some(resume_at - timestamp)).expect("wait error");
}
Some(_) => (),
None => {
// ? xly
//phy_wait(fd, Some(send_at - timestamp)).expect("wait error");
}
}
}
info!("--- {} ping statistics ---", remote_addr);
info!(
"{} packets transmitted, {} received, {:.0}% packet loss",
seq_no,
received,
100.0 * (seq_no - received) as f64 / seq_no as f64
);
}

View File

@ -2,7 +2,8 @@
//! - run process and manage trap/interrupt/syscall
#![no_std]
#![feature(asm)]
#![deny(warnings, unused_must_use, missing_docs)]
// #![deny(warnings, unused_must_use, missing_docs)]
#![deny(unused_must_use, missing_docs)]
extern crate alloc;
#[macro_use]
@ -62,6 +63,46 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
//调用zircon-object/src/task/thread.start设置好要执行的thread
let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap();
// run ping
thread
.start(entry, sp, 0, 0, thread_fn)
.expect("failed to start main thread");
proc
}
//待实际测试是否可用?
/// Create and run a Linux process
pub fn run_linux_proc(args: Vec<String>, entry: usize) -> Arc<Process> {
use rcore_fs_ramfs::RamFS;
let rootfs = RamFS::new();
let job = Job::root();
let proc = Process::create_linux(&job, rootfs.clone()).unwrap();
let thread = Thread::create_linux(&proc).unwrap();
info!("args {:?}", args);
{
let mut id = 0;
let rust_dir = rootfs.root_inode().lookup("/").unwrap();
debug!("Rootfs: / ");
while let Ok(name) = rust_dir.get_entry(id) {
id += 1;
debug!(" {}", name);
}
}
use zircon_object::vm::VmObject;
let stack_vmo = VmObject::new_paged(8);
let flags = MMUFlags::READ | MMUFlags::WRITE | MMUFlags::USER;
let stack_bottom = proc
.vmar()
.map(None, stack_vmo.clone(), 0, stack_vmo.len(), flags)
.unwrap();
//let sp = stack_bottom + stack_vmo.len();
let sp = stack_bottom + stack_vmo.len() - 4096;
debug!("load stack bottom: {:#x} -- {:#x}", stack_bottom, sp);
thread
.start(entry, sp, 0, 0, thread_fn)
.expect("failed to start main thread");
@ -84,6 +125,23 @@ async fn new_thread(thread: CurrentThread) {
break;
}
//========= 网络认证 添加 区域 start =======
// super_mode_net_udp_server_test();
// super_mode_net_tcp_server_test();
// super_mode_net_tcp_client_test();
// super_mode_frame_test();
// use core::time::Duration;
// use kernel_hal::sleep_until;
// use kernel_hal::timer_now;
// ping().await;
// super_mode_eap_test().await;
// ping().await;
// loop {}
//========= 网络认证 添加 区域 end =======
// run
trace!("go to user: {:#x?}", cx);
kernel_hal::context_run(&mut cx);
@ -242,3 +300,506 @@ async fn handle_syscall(thread: &CurrentThread, cx: &mut UserContext) {
};
cx.general.a0 = syscall.syscall(num, args).await as usize;
}
/// network testing
pub fn net_start_thread() {
// let ping_before_auth_future = Box::pin(ping_test());
let eap_future = Box::pin(eap_test());
// let ping_after_auth_future = Box::pin(ping_test());
let vmtoken = kernel_hal::current_page_table();
// kernel_hal::Thread::spawn(ping_before_auth_future, vmtoken);
kernel_hal::Thread::spawn(eap_future, vmtoken);
// kernel_hal::Thread::spawn(ping_after_auth_future, vmtoken);
}
/*
EAP test功能修改了smoltcp协议栈库, https://gitee.com/gcyyfun/smoltcp
TODO: smoltcp的方式实现EAP test功能;
*/
use kernel_hal::yield_now;
async fn eap_test() {
// for n in 0..3 {
ping().await;
super_mode_eap_test().await;
ping().await;
// }
}
async fn ping_test() {
ping().await;
}
#[allow(dead_code)]
#[allow(unused_imports)]
#[allow(unused_variables)]
async fn super_mode_eap_test() {
use core::str::from_utf8;
use kernel_hal::drivers::get_net_driver;
use kernel_hal::timer_now;
use kernel_hal_bare::drivers::net::rtl8x::RTL8xInterface;
use smoltcp::socket::SocketSet;
use smoltcp::socket::UdpPacketMetadata;
use smoltcp::socket::UdpSocket;
use smoltcp::socket::UdpSocketBuffer;
use smoltcp::time::Instant;
use smoltcp::wire::*;
use core::time::Duration;
use kernel_hal::sleep_until;
use kernel_hal::timer_tick;
let latency: u64 = 100; // 毫秒 millis
let rtl8x = get_net_driver()[0].clone();
if let Ok(li) = rtl8x.downcast_arc::<RTL8xInterface>() {
// loop {
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
// warn!("timestamp0 : {:?}",timestamp);
sleep_until(timer_now() + Duration::from_millis(latency)).await;
let _x = li.iface.lock().eapol(timestamp);
warn!("<-- EAPOL Start from smoltcp");
// sleep_until(timer_now() + Duration::from_secs(latency)).await;
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// eap 1
{
let eapol_repr = EAPoLRepr::EthernetEAPoL {
protocol_version: EAPoLProtocalVersion::X2001,
eap_type: EAPoLType::Packet,
len: 7,
};
let eap_repr = EAPRepr::EthernetEAP {
code: EAPCode::Response,
identifier: 1,
len: 7,
};
let eap_data_repr = EAPDataRepr::EthernetEAPData {
eapdata_type: EAPDataType::Identifier,
};
let f = |mut frame: EthernetFrame<&mut [u8]>| {
// frame.set_dst_addr(mac_addr);
frame.set_dst_addr(EthernetAddress::BROADCAST);
frame.set_ethertype(EthernetProtocol::EAPoL);
let mut eapol_packet = EAPoLPacket::new_unchecked(frame.payload_mut());
eapol_repr.emit(&mut eapol_packet);
let mut eap_packet = EAPPacket::new_unchecked(eapol_packet.packet_mut());
eap_repr.emit(&mut eap_packet);
let mut eap_data = EAPDataPacket::new_unchecked(eap_packet.data_mut());
eap_data_repr.emit(&mut eap_data);
// let typedata: [u8; 37] = [0x63, 0x6a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00];
let typedata: [u8; 2] = [0x63, 0x6a];
eap_data.typedata_mut().copy_from_slice(&typedata[..]);
// warn!("eframe : {:X?}", frame);
};
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
warn!("{:?} : EAP Respone ", timestamp);
let _x = li.iface.lock().eap(timestamp, eapol_repr.buffer_len(), f);
}
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// eap 2
{
let eapol_repr = EAPoLRepr::EthernetEAPoL {
protocol_version: EAPoLProtocalVersion::X2001,
eap_type: EAPoLType::Packet,
len: 181,
};
let eap_repr = EAPRepr::EthernetEAP {
code: EAPCode::Response,
identifier: 2,
len: 181,
};
let eap_data_repr = EAPDataRepr::EthernetEAPData {
eapdata_type: EAPDataType::UnknownType,
};
let f = |mut frame: EthernetFrame<&mut [u8]>| {
// frame.set_dst_addr(mac_addr);
frame.set_dst_addr(EthernetAddress::BROADCAST);
frame.set_ethertype(EthernetProtocol::EAPoL);
let mut eapol_packet = EAPoLPacket::new_unchecked(frame.payload_mut());
eapol_repr.emit(&mut eapol_packet);
let mut eap_packet = EAPPacket::new_unchecked(eapol_packet.packet_mut());
eap_repr.emit(&mut eap_packet);
let mut eap_data = EAPDataPacket::new_unchecked(eap_packet.data_mut());
eap_data_repr.emit(&mut eap_data);
// let typedata: [u8; 15] = [0x43 ,0x68 ,0x20 ,0x20 ,0x20 ,0x58 ,0x69 ,0x6E ,0x67 ,0x20 ,0x7A ,0x43 ,0x6F ,0x72 ,0x65];
// eap_data.typedata_mut().copy_from_slice(&typedata[..]);
let typedata: [u8; 176] = [
0x0d, 0, 0, 0, 0x01, 0, 0, 0, 0x82, 0, 0, 0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36,
0x5d, 0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01,
0xc4, 0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30,
0x07, 0x0e, 0, 0x0d, 0, 0x58, 0x20, 0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36, 0x5d,
0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01, 0xc4,
0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30, 0x30,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x25, 0, 0,
];
// 0000 01 80 c2 00 00 03 00 e0 4c 68 05 2c 88 8e 01 00 ........Lh.,....
// 0010 00 b1 02 c7 00 b1 39 0d 00 00 00 82 00 00 c0 58 ......9........X
// 0020 2b 9d be 36 5d 69 64 04 96 57 b5 39 a6 fc 73 6f +..6]id..W.9..so
// 0030 01 c4 e0 b4 51 25 27 8c 93 6e ef c9 80 30 07 00 ....Q%'..n...0..
// 0040 0d 00 58 20 c0 58 2b 9d be 36 5d 69 64 04 96 57 ..X .X+..6]id..W
// 0050 b5 39 a6 fc 73 6f 01 c4 e0 b4 51 25 27 8c 93 6e .9..so....Q%'..n
// 0060 ef c9 80 30 30 00 00 00 00 00 00 00 00 00 00 00 ...00...........
// 0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 25 ...............%
// 00c0 00 00 00 ...
eap_data.typedata_mut().copy_from_slice(&typedata[..]);
// warn!("eframe : {:X?}", frame);
};
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
warn!("{:?} : EAP Respone ", timestamp);
let _x = li.iface.lock().eap(timestamp, eapol_repr.buffer_len(), f);
}
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// eap 3
{
let eapol_repr = EAPoLRepr::EthernetEAPoL {
protocol_version: EAPoLProtocalVersion::X2001,
eap_type: EAPoLType::Packet,
len: 827,
};
let eap_repr = EAPRepr::EthernetEAP {
code: EAPCode::Response,
identifier: 3,
len: 827,
};
let eap_data_repr = EAPDataRepr::EthernetEAPData {
eapdata_type: EAPDataType::UnknownType,
};
let f = |mut frame: EthernetFrame<&mut [u8]>| {
// frame.set_dst_addr(mac_addr);
frame.set_dst_addr(EthernetAddress::BROADCAST);
frame.set_ethertype(EthernetProtocol::EAPoL);
let mut eapol_packet = EAPoLPacket::new_unchecked(frame.payload_mut());
eapol_repr.emit(&mut eapol_packet);
let mut eap_packet = EAPPacket::new_unchecked(eapol_packet.packet_mut());
eap_repr.emit(&mut eap_packet);
let mut eap_data = EAPDataPacket::new_unchecked(eap_packet.data_mut());
eap_data_repr.emit(&mut eap_data);
let typedata: [u8; 822] = [
0x29, 0x58, 0x1e, 0xf5, 0x6b, 0xe7, 0xdb, 0xc3, 0x5a, 0xa7, 0x76, 0x47, 0x37,
0x12, 0xe3, 0x5b, 0x3c, 0x0a, 0xc0, 0x7f, 0x61, 0x7a, 0x3c, 0x75, 0x31, 0x10,
0xaf, 0xa9, 0x97, 0x90, 0xf8, 0xe4, 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0x21, 0xf5, 0x6b, 0xe7, 0xdb, 0xc3, 0x5a, 0xa7, 0x76, 0x47, 0x37,
0x12, 0xe3, 0x5b, 0x3c, 0x0a, 0xc0, 0x7f, 0x61, 0x7a, 0x3c, 0x75, 0x31, 0x10,
0xaf, 0xa9, 0x97, 0x90, 0xf8, 0xe4, 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1e, 0xeb, 0x6a, 0x0f, 0x36, 0xca, 0xb8, 0x6e, 0x18,
0xf1, 0x98, 0xd5, 0xf4, 0x60, 0xa0, 0x22, 0xbc, 0xe6, 0x36, 0x34, 0xf5, 0x30,
0xe9, 0x26, 0xea, 0x6a, 0xb6, 0x29, 0xb1, 0xda, 0x08, 0xca, 0xd0, 0xa4, 0x01,
0x01, 0x20, 0x04, 0x21, 0x58, 0x20, 0xc0, 0x58, 0x2b, 0x9d, 0xbe, 0x36, 0x5d,
0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f, 0x01, 0xc4,
0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80, 0x30, 0x6c,
0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x60,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x36, 0xa1,
0x04, 0x41, 0x17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x04, 0x31, 0xe2, 0x9a,
0xa2, 0x0c, 0x17, 0xca, 0xe1, 0xce, 0x9a, 0xf0, 0x87, 0x18, 0x0e, 0x8d, 0x55,
0x56, 0xd8, 0x4e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x0b, 0x83, 0x68, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x30, 0x44, 0xa1,
0x04, 0x41, 0x17, 0x58, 0x58, 0x58, 0x20, 0xeb, 0x6a, 0x0f, 0x36, 0xca, 0xb8,
0x6e, 0x18, 0xf1, 0x98, 0xd5, 0xf4, 0x60, 0xa0, 0x22, 0xbc, 0xe6, 0x36, 0x34,
0xf5, 0x30, 0xe9, 0x26, 0xea, 0x6a, 0xb6, 0x29, 0xb1, 0xda, 0x08, 0xca, 0xd0,
0xa4, 0x01, 0x01, 0x20, 0x04, 0x21, 0x58, 0x20, 0xc0, 0x58, 0x2b, 0x9d, 0xbe,
0x36, 0x5d, 0x69, 0x64, 0x04, 0x96, 0x57, 0xb5, 0x39, 0xa6, 0xfc, 0x73, 0x6f,
0x01, 0xc4, 0xe0, 0xb4, 0x51, 0x25, 0x27, 0x8c, 0x93, 0x6e, 0xef, 0xc9, 0x80,
0x30, 0x6c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x6e, 0x61, 0x6d,
0x65, 0x60, 0x4b, 0xce, 0x9a, 0xf0, 0x87, 0x18, 0x0e, 0x8d, 0x55, 0x56, 0xd8,
0x4e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x75,
];
eap_data.typedata_mut().copy_from_slice(&typedata[..]);
// 0000 01 80 c2 00 00 03 00 e0 4c 68 05 2c 88 8e 01 00 ........Lh.,....
// 0010 03 3b 02 c8 03 3b 39 33 58 1d 99 6e c2 9c 8e 6d .;...;93X..n...m
// 0020 d9 85 b5 7f 03 38 61 9f 9d c2 38 d5 44 6f 26 4e .....8a...8.Do&N
// 0030 6d e2 29 9a 0a 85 34 00 00 00 00 00 00 00 00 00 m.)...4.........
// 0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0090 00 00 00 00 00 00 20 99 6e c2 9c 8e 6d d9 85 b5 ...... .n...m...
// 00a0 7f 03 38 61 9f 9d c2 38 d5 44 6f 26 4e 6d e2 29 ..8a...8.Do&Nm.)
// 00b0 9a 0a 85 34 00 00 00 00 00 00 00 00 00 00 00 00 ...4............
// 00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 00f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0110 00 00 00 00 00 00 1d dd bf f6 fc 11 b4 1b df 86 ................
// 0120 17 c5 24 42 ef 3c a5 9f e7 1a 7d e5 2f fa 7f 02 ..$B.<....}./...
// 0130 27 0b df 64 ad cc 66 a4 01 01 20 04 21 58 20 c0 '..d..f... .!X .
// 0140 58 2b 9d be 36 5d 69 64 04 96 57 b5 39 a6 fc 73 X+..6]id..W.9..s
// 0150 6f 01 c4 e0 b4 51 25 27 8c 93 6e ef c9 80 30 6c o....Q%'..n...0l
// 0160 73 75 62 6a 65 63 74 20 6e 61 6d 65 60 00 00 00 subject name`...
// 0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 01a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 01b0 00 00 00 00 00 00 36 a1 04 41 17 00 00 00 00 00 ......6..A......
// 01c0 00 00 00 00 00 00 04 52 0a d3 71 b5 a4 66 e7 f0 .......R..q..f..
// 01d0 87 18 0e 8d 55 56 d8 4e 35 00 00 00 00 00 00 00 ....UV.N5.......
// 01e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 83 ................
// 01f0 68 45 6e 63 72 79 70 74 30 44 a1 04 41 17 58 58 hEncrypt0D..A.XX
// 0200 58 20 dd bf f6 fc 11 b4 1b df 86 17 c5 24 42 ef X ...........$B.
// 0210 3c a5 9f e7 1a 7d e5 2f fa 7f 02 27 0b df 64 ad <....}./...'..d.
// 0220 cc 66 a4 01 01 20 04 21 58 20 c0 58 2b 9d be 36 .f... .!X .X+..6
// 0230 5d 69 64 04 96 57 b5 39 a6 fc 73 6f 01 c4 e0 b4 ]id..W.9..so....
// 0240 51 25 27 8c 93 6e ef c9 80 30 6c 73 75 62 6a 65 Q%'..n...0lsubje
// 0250 63 74 20 6e 61 6d 65 60 4a f0 87 18 0e 8d 55 56 ct name`J.....UV
// 0260 d8 4e 35 00 00 00 00 00 00 00 00 00 00 00 00 00 .N5.............
// 0270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 02a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 02b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 02c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 02d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 02e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 02f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 0340 00 00 00 00 00 00 00 00 00 00 00 00 74 ............t
// warn!("eframe : {:X?}", frame);
};
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
warn!("{:?} : EAP Respone ", timestamp);
let _x = li.iface.lock().eap(timestamp, eapol_repr.buffer_len(), f);
}
sleep_until(timer_now() + Duration::from_millis(latency)).await;
// #[cfg(target_arch = "riscv64")]
// kernel_hal_bare::interrupt::wait_for_interrupt();
// yield_now().await;
// }
}
}
async fn ping() {
macro_rules! send_icmp_ping {
( $repr_type:ident, $packet_type:ident, $ident:expr, $seq_no:expr,
$echo_payload:expr, $socket:expr, $remote_addr:expr ) => {{
let icmp_repr = $repr_type::EchoRequest {
ident: $ident,
seq_no: $seq_no,
data: &$echo_payload,
};
let icmp_payload = $socket.send(icmp_repr.buffer_len(), $remote_addr).unwrap();
let icmp_packet = $packet_type::new_unchecked(icmp_payload);
(icmp_repr, icmp_packet)
}};
}
macro_rules! get_icmp_pong {
( $repr_type:ident, $repr:expr, $payload:expr, $waiting_queue:expr, $remote_addr:expr,
$timestamp:expr, $received:expr ) => {{
if let $repr_type::EchoReply { seq_no, data, .. } = $repr {
if let Some(_) = $waiting_queue.get(&seq_no) {
let packet_timestamp_ms = NetworkEndian::read_i64(data);
warn!(
"{} bytes from {}: icmp_seq={}, time={}ms",
data.len(),
$remote_addr,
seq_no,
$timestamp.total_millis() - packet_timestamp_ms
);
$waiting_queue.remove(&seq_no);
$received += 1;
}
}
}};
}
use alloc::collections::BTreeMap;
use alloc::vec;
use byteorder::{ByteOrder, NetworkEndian};
use core::str::FromStr;
use kernel_hal::drivers::get_net_driver;
use kernel_hal::timer_now;
use kernel_hal_bare::drivers::net::rtl8x::RTL8xInterface;
use smoltcp::phy::Device;
use smoltcp::socket::{
IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer, SocketSet,
};
use smoltcp::time::Duration;
use smoltcp::time::Instant;
use smoltcp::wire::{Icmpv4Packet, Icmpv4Repr, IpAddress};
let rtl8x = get_net_driver()[0].clone();
let icmp_rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
let icmp_tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 256]);
let icmp_socket = IcmpSocket::new(icmp_rx_buffer, icmp_tx_buffer);
let mut sockets = SocketSet::new(vec![]);
let icmp_handle = sockets.add(icmp_socket);
let mut send_at = Instant::from_millis(0);
let mut seq_no = 0;
let mut received = 0;
let mut echo_payload = [0xffu8; 40];
let mut waiting_queue = BTreeMap::new();
let ident = 0x22b;
let count = 4;
// ping 的 目的 地址 、um.. 暂时手动修改吧
// baidu
// let ip_addr = "220.181.38.251";
// 114 dns
let ip_addr = "114.114.114.114";
//let ip_addr = "192.168.0.62";
// let ip_addr = "172.24.103.1";
let remote_addr = IpAddress::from_str(ip_addr).expect("invalid address format");
warn!("ping ip addr {:?}", remote_addr);
let interval = Duration::from_secs(1);
let timeout = Duration::from_secs(10);
if let Ok(_li) = rtl8x.downcast_arc::<RTL8xInterface>() {
let device = _li.iface.lock().device().clone();
let device_caps = device.capabilities();
let mut timeout_return: bool = false;
loop {
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
match _li.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
// warn!("poll ok {}", b);
}
Err(e) => {
debug!("poll error: {}", e);
}
}
{
let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
let mut socket = sockets.get::<IcmpSocket>(icmp_handle);
if !socket.is_open() {
// warn!("no open");
// warn!("bind ident {} to icmp socket", ident);
socket.bind(IcmpEndpoint::Ident(ident)).unwrap();
send_at = timestamp;
}
if socket.can_send() && seq_no < count as u16 && send_at <= timestamp {
NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis());
match remote_addr {
IpAddress::Ipv4(addr) => {
// warn!("ping send addr : {}", addr);
let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
Icmpv4Repr,
Icmpv4Packet,
ident,
seq_no,
echo_payload,
socket,
remote_addr
);
icmp_repr.emit(&mut icmp_packet, &device_caps.checksum);
}
_ => unimplemented!(),
}
waiting_queue.insert(seq_no, timestamp);
seq_no += 1;
send_at += interval;
}
if socket.can_recv() {
let (payload, _) = socket.recv().unwrap();
match remote_addr {
IpAddress::Ipv4(addr) => {
// warn!("ping recv addr : {}", addr);
let icmp_packet = Icmpv4Packet::new_checked(&payload).unwrap();
let icmp_repr =
Icmpv4Repr::parse(&icmp_packet, &device_caps.checksum).unwrap();
get_icmp_pong!(
Icmpv4Repr,
icmp_repr,
payload,
waiting_queue,
remote_addr,
timestamp,
received
);
}
_ => unimplemented!(),
}
}
// #[cfg(target_arch = "riscv64")]
// kernel_hal_bare::interrupt::wait_for_interrupt();
// yield_now().await;
waiting_queue.retain(|seq, from| {
if timestamp - *from < timeout {
true
} else {
warn!("From {} icmp_seq={} timeout", remote_addr, seq);
timeout_return = true;
warn!("timeout_return {}", timeout_return);
false
}
});
if seq_no == count as u16 && waiting_queue.is_empty() {
break;
}
}
if timeout_return {
return;
}
#[cfg(target_arch = "riscv64")]
kernel_hal_bare::interrupt::wait_for_interrupt();
yield_now().await;
}
}
}

View File

@ -17,6 +17,8 @@ hashbrown = "0.9"
numeric-enum-macro = "0.2"
zircon-object = { path = "../zircon-object", features = ["elf"] }
kernel-hal = { path = "../kernel-hal" }
#xly
kernel-hal-bare = { path = "../kernel-hal-bare" }
downcast-rs = { version = "1.2", default-features = false }
lazy_static = { version = "1.4", features = ["spin_no_std"] }
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
@ -24,3 +26,4 @@ rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
smoltcp = { git = "https://gitee.com/gcyyfun/smoltcp", rev="043eb60", default-features = false, features = ["alloc","log", "async", "medium-ethernet","proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }

View File

@ -4,6 +4,7 @@
#![deny(warnings, unsafe_code, missing_docs)]
#![allow(clippy::upper_case_acronyms)]
#![feature(bool_to_option)]
#![feature(untagged_unions)]
extern crate alloc;
@ -15,6 +16,7 @@ pub mod error;
// layer 1
pub mod fs;
pub mod net;
// layer 2
pub mod ipc;

View File

@ -0,0 +1,219 @@
// icmpsocket
#![allow(dead_code)]
// crate
use crate::net::IpEndpoint;
use crate::net::poll_ifaces;
use crate::net::get_net_sockets;
use crate::net::Endpoint;
use crate::net::GlobalSocketHandle;
use crate::net::IpAddress;
use crate::net::LxResult;
use crate::net::Socket;
use crate::net::SysResult;
use crate::net::ICMP_METADATA_BUF;
use crate::net::ICMP_RECVBUF;
use crate::net::ICMP_SENDBUF;
use alloc::sync::Arc;
use spin::Mutex;
// alloc
use alloc::boxed::Box;
use alloc::vec;
// smoltcp
use smoltcp::socket::IcmpPacketMetadata;
use smoltcp::socket::IcmpSocket;
use smoltcp::socket::IcmpSocketBuffer;
// async
use async_trait::async_trait;
// third part
use zircon_object::impl_kobject;
use zircon_object::object::*;
/// missing documentation
pub struct IcmpSocketState {
/// missing documentation
base: KObjectBase,
/// missing documentation
handle: GlobalSocketHandle,
}
impl Default for IcmpSocketState {
fn default() -> Self {
Self::new()
}
}
impl IcmpSocketState {
/// missing documentation
pub fn new() -> Self {
let rx_buffer = IcmpSocketBuffer::new(
vec![IcmpPacketMetadata::EMPTY; ICMP_METADATA_BUF],
vec![0; ICMP_RECVBUF],
);
let tx_buffer = IcmpSocketBuffer::new(
vec![IcmpPacketMetadata::EMPTY; ICMP_METADATA_BUF],
vec![0; ICMP_SENDBUF],
);
let socket = IcmpSocket::new(rx_buffer, tx_buffer);
let handle = GlobalSocketHandle(get_net_sockets().lock().add(socket));
IcmpSocketState {
base: KObjectBase::new(),
handle,
}
}
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
loop {
poll_ifaces();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<IcmpSocket>(self.handle.0);
if socket.can_recv() {
if let Ok((size,ip)) = socket.recv_slice(data) {
if size > 0 {
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
// tcp udp use endpoint , but icmp use ip address
return (Ok(size), Endpoint::Ip(IpEndpoint::Ip(ip)));
}
}
} else {
return (
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
);
}
}
}
fn write(&self, _data: &[u8], _remote_addr: IpAddress) -> SysResult {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<IcmpSocket>(self.handle.0);
if socket.is_open() {
if socket.can_send() {
match socket.send_slice(data) {
Ok(size) => {
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
Ok(size)
}
Err(_) => Err(LxError::ENOBUFS),
}
} else {
Err(LxError::ENOBUFS)
}
} else {
Err(LxError::ENOTCONN)
}
}
fn poll(&self) -> (bool, bool, bool) {
unimplemented!()
}
fn connect(&mut self, _endpoint: Endpoint) -> SysResult {
unimplemented!()
}
fn bind(&mut self, _endpoint: Endpoint) -> SysResult {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<IcmpSocket>(self.handle.0);
#[allow(irrefutable_let_patterns)]
if let Endpoint::Ip(mut ip) = endpoint {
if ip.port == 0 {
ip.port = get_ephemeral_port();
}
match socket.bind(ip) {
Ok(()) => Ok(0),
Err(_) => Err(LxError::EINVAL),
}
} else {
Err(LxError::EINVAL)
}
}
fn ioctl(&mut self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
unimplemented!()
}
fn endpoint(&self) -> Option<Endpoint> {
unimplemented!()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
unimplemented!()
}
}
impl_kobject!(IcmpSocketState);
#[async_trait]
impl Socket for IcmpSocketState {
/// read to buffer
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
self.read(data).await
}
/// write from buffer
fn write(&self, _data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
self.write(data, sendto_endpoint)
}
/// connect
async fn connect(&self, _endpoint: Endpoint) -> SysResult {
unimplemented!()
// self.connect(_endpoint).await
}
/// wait for some event on a file descriptor
fn poll(&self) -> (bool, bool, bool) {
unimplemented!()
// self.poll()
}
fn bind(&mut self, _endpoint: Endpoint) -> SysResult {
self.bind(endpoint)
}
fn listen(&mut self) -> SysResult {
unimplemented!()
// self.listen()
}
fn shutdown(&self) -> SysResult {
unimplemented!()
// self.shutdown()
}
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
unimplemented!()
// self.accept().await
}
fn endpoint(&self) -> Option<Endpoint> {
unimplemented!()
// self.endpoint()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
unimplemented!()
// self.remote_endpoint()
}
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
unimplemented!()
// self.setsockopt(level, opt, data)
}
/// manipulate file descriptor
fn ioctl(&self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
Ok(0)
}
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
Ok(0)
}
}

477
linux-object/src/net/mod.rs Normal file
View File

@ -0,0 +1,477 @@
//! Linux socket objects
//!
/// missing documentation
pub mod socket_address;
pub use socket_address::*;
/// missing documentation
pub mod tcp;
pub use tcp::*;
/// missing documentation
pub mod udp;
pub use udp::*;
/// missing documentation
// pub mod raw;
// pub use raw::*;
/// missing documentation
// pub mod icmp;
// pub use icmp::*;
// pub mod stack;
// ============= Socket Set =============
use kernel_hal::get_net_sockets;
use spin::Mutex;
// lazy_static! {
// /// Global SocketSet in smoltcp.
// ///
// /// Because smoltcp is a single thread network stack,
// /// every socket operation needs to lock this.
// pub static ref SOCKETS: Mutex<SocketSet<'static>> =
// Mutex::new(SocketSet::new(vec![]));
// }
// ============= Socket Set =============
// ============= Define =============
// ========TCP
/// missing documentation
pub const TCP_SENDBUF: usize = 512 * 1024; // 512K
/// missing documentation
pub const TCP_RECVBUF: usize = 512 * 1024; // 512K
// ========UDP
/// missing documentation
pub const UDP_METADATA_BUF: usize = 1024;
/// missing documentation
pub const UDP_SENDBUF: usize = 64 * 1024; // 64K
/// missing documentation
pub const UDP_RECVBUF: usize = 64 * 1024; // 64K
// ========RAW
/// missing documentation
pub const RAW_METADATA_BUF: usize = 1024;
/// missing documentation
pub const RAW_SENDBUF: usize = 64 * 1024; // 64K
/// missing documentation
pub const RAW_RECVBUF: usize = 64 * 1024; // 64K
// ========RAW
/// missing documentation
pub const ICMP_METADATA_BUF: usize = 1024;
/// missing documentation
pub const ICMP_SENDBUF: usize = 64 * 1024; // 64K
/// missing documentation
pub const ICMP_RECVBUF: usize = 64 * 1024; // 64K
// ========Other
/// missing documentation
pub const IPPROTO_IP: usize = 0;
/// missing documentation
pub const IP_HDRINCL: usize = 3;
// ============= Define =============
// ============= SocketHandle =============
use smoltcp::socket::SocketHandle;
/// A wrapper for `SocketHandle`.
/// Auto increase and decrease reference count on Clone and Drop.
#[derive(Debug)]
struct GlobalSocketHandle(SocketHandle);
impl Clone for GlobalSocketHandle {
fn clone(&self) -> Self {
get_net_sockets().lock().retain(self.0);
Self(self.0)
}
}
impl Drop for GlobalSocketHandle {
fn drop(&mut self) {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
sockets.release(self.0);
sockets.prune();
// send FIN immediately when applicable
drop(sockets);
poll_ifaces();
}
}
// #[cfg(feature = "e1000")]
use kernel_hal::get_net_driver;
#[cfg(feature = "loopback")]
use hashbrown::HashMap;
#[cfg(feature = "loopback")]
use kernel_hal::timer_now;
#[cfg(feature = "loopback")]
use net_stack::{NetStack, NET_STACK};
#[cfg(feature = "loopback")]
use smoltcp::time::Instant;
// /// miss doc
// #[cfg(feature = "loopback")]
// pub fn get_net_stack() -> HashMap<usize, Arc<dyn NetStack>> {
// NET_STACK.read().clone()
// }
/// miss doc
fn poll_ifaces() {
for iface in get_net_driver().iter() {
iface.poll();
}
}
// /// miss doc
// #[cfg(feature = "loopback")]
// fn poll_ifaces_loopback() {
// for (_key, stack) in get_net_stack().iter() {
// let timestamp = Instant::from_millis(timer_now().as_millis() as i64);
// stack.poll(&(*get_net_sockets()), timestamp);
// }
// }
use core::future::Future;
use core::pin::Pin;
use core::task::Context;
use core::task::Poll;
// use core::task::Waker;
// impl Future for IFaceFuture {
// type Output = ();
// fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
// // let ss = get_net_sockets();
// // let mut sockets = ss.lock();
// // for s in sockets.iter_mut() {
// // warn!("poll register waker");
// // use smoltcp::socket::SocketRef;
// // let ms = SocketRef::into_inner(s);
// // use smoltcp::socket::Socket;
// // match ms {
// // Socket::Udp(u) => {
// // u.register_recv_waker(&_cx.waker().clone());
// // u.register_send_waker(&_cx.waker().clone());
// // }
// // Socket::Tcp(t) => {
// // t.register_recv_waker(&_cx.waker().clone());
// // t.register_send_waker(&_cx.waker().clone());
// // }
// // Socket::Raw(r) => {
// // r.register_recv_waker(&_cx.waker().clone());
// // r.register_send_waker(&_cx.waker().clone());
// // }
// // _ => {
// // warn!("None");
// // }
// // }
// // }
// for iface in get_net_driver().iter() {
// match iface.poll(&(*get_net_sockets())) {
// Ok(b) => {
// warn!("..............b {}", b);
// let ss = get_net_sockets();
// let mut sockets = ss.lock();
// for s in sockets.iter_mut() {
// warn!("poll register waker");
// use smoltcp::socket::SocketRef;
// let ms = SocketRef::into_inner(s);
// use smoltcp::socket::Socket;
// match ms {
// Socket::Udp(u) => {
// warn!("udp register");
// if !u.can_send() && !u.can_recv() {
// u.register_send_waker(&_cx.waker());
// u.register_recv_waker(&_cx.waker());
// return Poll::Pending;
// } else {
// u.register_send_waker(&_cx.waker());
// u.register_recv_waker(&_cx.waker());
// return Poll::Ready(());
// }
// }
// Socket::Tcp(t) => {
// if !t.can_send() && !t.can_recv() {
// t.register_send_waker(&_cx.waker());
// t.register_recv_waker(&_cx.waker());
// return Poll::Pending;
// } else {
// t.register_send_waker(&_cx.waker());
// t.register_recv_waker(&_cx.waker());
// return Poll::Ready(());
// }
// }
// Socket::Raw(r) => {
// if !r.can_send() && !r.can_recv() {
// r.register_send_waker(&_cx.waker());
// r.register_recv_waker(&_cx.waker());
// return Poll::Pending;
// } else {
// r.register_send_waker(&_cx.waker());
// r.register_recv_waker(&_cx.waker());
// return Poll::Ready(());
// }
// }
// _ => {
// warn!("None");
// }
// }
// }
// }
// Err(_err) => {
// warn!("err {:?}", _err);
// return Poll::Pending;
// }
// }
// }
// Poll::Pending
// // let ss = get_net_sockets();
// // let mut sockets = ss.lock();
// // for s in sockets.iter_mut() {
// // warn!("poll register waker");
// // use smoltcp::socket::SocketRef;
// // let ms = SocketRef::into_inner(s);
// // use smoltcp::socket::Socket;
// // match ms {
// // Socket::Udp(u) => {
// // u.register_recv_waker(&_cx.waker().clone());
// // u.register_send_waker(&_cx.waker().clone());
// // }
// // Socket::Tcp(t) => {
// // t.register_recv_waker(&_cx.waker().clone());
// // t.register_send_waker(&_cx.waker().clone());
// // }
// // Socket::Raw(r) => {
// // r.register_recv_waker(&_cx.waker().clone());
// // r.register_send_waker(&_cx.waker().clone());
// // }
// // _ => {
// // warn!("None");
// // }
// // }
// // }
// // warn!("register ok");
// // // let mut socket = sockets.get::<UdpSocket>(self.handle.0);
// // Poll::Ready(())
// // match self.iface.lock().poll(&mut sockets, timestamp) {
// // Ok(_) => {iface
// // warn!("interrupt iface poll");
// // Poll::Ready(()
// // }
// // Err(err) => {
// // debug!("poll got err {}", err);
// // _cx.waker().clone().wake();
// // Poll::Pending
// // }
// // }
// }
// }
use smoltcp::socket::TcpSocket;
struct ConnectFuture<'a> {
socket: &'a mut TcpSocket<'a>,
}
impl Future for ConnectFuture<'_> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
use smoltcp::socket::TcpState;
if self.socket.state() == TcpState::SynSent {
self.socket.register_recv_waker(&_cx.waker().clone());
self.socket.register_send_waker(&_cx.waker().clone());
Poll::Pending
} else {
Poll::Ready(())
}
}
}
struct AcceptFuture<'a> {
socket: &'a mut TcpSocket<'a>,
}
impl Future for AcceptFuture<'_> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.socket.is_active() {
Poll::Ready(())
} else {
self.socket.register_recv_waker(&_cx.waker().clone());
self.socket.register_send_waker(&_cx.waker().clone());
Poll::Pending
}
}
}
// ============= SocketHandle =============
// ============= Endpoint =============
use smoltcp::wire::IpEndpoint;
/// missing documentation
#[derive(Clone, Debug)]
pub enum Endpoint {
/// missing documentation
Ip(IpEndpoint),
/// missing documentation
LinkLevel(LinkLevelEndpoint),
/// missing documentation
Netlink(NetlinkEndpoint),
}
/// missing documentation
#[derive(Clone, Debug)]
pub struct LinkLevelEndpoint {
/// missing documentation
pub interface_index: usize,
}
impl LinkLevelEndpoint {
/// missing documentation
pub fn new(ifindex: usize) -> Self {
LinkLevelEndpoint {
interface_index: ifindex,
}
}
}
/// missing documentation
#[derive(Clone, Debug)]
pub struct NetlinkEndpoint {
/// missing documentation
pub port_id: u32,
/// missing documentation
pub multicast_groups_mask: u32,
}
impl NetlinkEndpoint {
/// missing documentation
pub fn new(port_id: u32, multicast_groups_mask: u32) -> Self {
NetlinkEndpoint {
port_id,
multicast_groups_mask,
}
}
}
// ============= Endpoint =============
// ============= Rand Port =============
/// !!!! need riscv rng
pub fn rand() -> u64 {
// use core::arch::x86_64::_rdtsc;
// rdrand is not implemented in QEMU
// so use rdtsc instead
10000
}
#[allow(unsafe_code)]
/// missing documentation
fn get_ephemeral_port() -> u16 {
// TODO selects non-conflict high port
static mut EPHEMERAL_PORT: u16 = 0;
unsafe {
if EPHEMERAL_PORT == 0 {
EPHEMERAL_PORT = (49152 + rand() % (65536 - 49152)) as u16;
}
if EPHEMERAL_PORT == 65535 {
EPHEMERAL_PORT = 49152;
} else {
EPHEMERAL_PORT += 1;
}
EPHEMERAL_PORT
}
}
// ============= Rand Port =============
// ============= Util =============
#[allow(unsafe_code)]
/// # Safety
/// Convert C string to Rust string
pub unsafe fn from_cstr(s: *const u8) -> &'static str {
use core::{slice, str};
let len = (0usize..).find(|&i| *s.add(i) == 0).unwrap();
str::from_utf8(slice::from_raw_parts(s, len)).unwrap()
}
// ============= Util =============
use crate::error::*;
use alloc::boxed::Box;
use alloc::fmt::Debug;
use alloc::sync::Arc;
use async_trait::async_trait;
// use core::ops::{Deref, DerefMut};
/// Common methods that a socket must have
#[async_trait]
pub trait Socket: Send + Sync + Debug {
/// missing documentation
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint);
/// missing documentation
fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult;
/// missing documentation
fn poll(&self) -> (bool, bool, bool); // (in, out, err)
/// missing documentation
async fn connect(&self, endpoint: Endpoint) -> SysResult;
/// missing documentation
fn bind(&mut self, _endpoint: Endpoint) -> SysResult {
Err(LxError::EINVAL)
}
/// missing documentation
fn listen(&mut self) -> SysResult {
Err(LxError::EINVAL)
}
/// missing documentation
fn shutdown(&self) -> SysResult {
Err(LxError::EINVAL)
}
/// missing documentation
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
Err(LxError::EINVAL)
}
/// missing documentation
fn endpoint(&self) -> Option<Endpoint> {
None
}
/// missing documentation
fn remote_endpoint(&self) -> Option<Endpoint> {
None
}
/// missing documentation
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
warn!("setsockopt is unimplemented");
Ok(0)
}
/// missing documentation
fn ioctl(&self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
warn!("ioctl is unimplemented for this socket");
Ok(0)
}
/// missing documentation
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
warn!("ioctl is unimplemented for this socket");
Ok(0)
}
}

View File

@ -0,0 +1,7 @@
#![allow(unsafe_code, unused_imports, missing_docs)]
// pub mod structs;
pub mod test;
// pub use self::structs::*;
pub use self::test::server;

221
linux-object/src/net/raw.rs Normal file
View File

@ -0,0 +1,221 @@
// rawsocket
#![allow(dead_code)]
// crate
use helper::error::LxError;
use helper::error::LxResult;
use crate::net::get_net_driver;
use crate::net::get_net_sockets;
use crate::net::Endpoint;
use crate::net::GlobalSocketHandle;
use crate::net::IpAddress;
use crate::net::IpEndpoint;
use crate::net::Socket;
use crate::net::SysResult;
use crate::net::IPPROTO_IP;
use crate::net::IP_HDRINCL;
use crate::net::RAW_METADATA_BUF;
use crate::net::RAW_RECVBUF;
use crate::net::RAW_SENDBUF;
use alloc::sync::Arc;
use spin::Mutex;
// alloc
use alloc::boxed::Box;
use alloc::vec;
// smoltcp
use smoltcp::socket::RawPacketMetadata;
use smoltcp::socket::RawSocket;
use smoltcp::socket::RawSocketBuffer;
use smoltcp::wire::IpProtocol;
use smoltcp::wire::IpVersion;
use smoltcp::wire::Ipv4Packet;
// async
use async_trait::async_trait;
// third part
use zircon_object::impl_kobject;
use zircon_object::object::*;
/// missing documentation
pub struct RawSocketState {
/// missing documentation
base: KObjectBase,
/// missing documentation
handle: GlobalSocketHandle,
/// missing documentation
header_included: bool,
}
impl RawSocketState {
/// missing documentation
pub fn new(protocol: u8) -> Self {
let rx_buffer = RawSocketBuffer::new(
vec![RawPacketMetadata::EMPTY; RAW_METADATA_BUF],
vec![0; RAW_RECVBUF],
);
let tx_buffer = RawSocketBuffer::new(
vec![RawPacketMetadata::EMPTY; RAW_METADATA_BUF],
vec![0; RAW_SENDBUF],
);
let socket = RawSocket::new(
IpVersion::Ipv4,
IpProtocol::from(protocol),
rx_buffer,
tx_buffer,
);
let handle = GlobalSocketHandle(get_net_sockets().lock().add(socket));
RawSocketState {
base: KObjectBase::new(),
handle,
header_included: false,
}
}
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (LxResult<usize>, Endpoint) {
loop {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<RawSocket>(self.handle.0);
if let Ok(size) = socket.recv_slice(data) {
let packet = Ipv4Packet::new_unchecked(data);
return (
Ok(size),
Endpoint::Ip(IpEndpoint {
addr: IpAddress::Ipv4(packet.src_addr()),
port: 0,
}),
);
}
drop(socket);
}
}
/// missing documentation
pub fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> LxResult<usize> {
if self.header_included {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<RawSocket>(self.handle.0);
match socket.send_slice(data) {
Ok(()) => Ok(data.len()),
Err(_) => Err(LxError::ENOBUFS),
}
} else if let Some(Endpoint::Ip(endpoint)) = sendto_endpoint {
// temporary solution
let iface = &*(get_net_driver()[0]);
let v4_src = iface.ipv4_address().unwrap();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<RawSocket>(self.handle.0);
if let IpAddress::Ipv4(v4_dst) = endpoint.addr {
let len = data.len();
// using 20-byte IPv4 header
let mut buffer = vec![0u8; len + 20];
let mut packet = Ipv4Packet::new_unchecked(&mut buffer);
packet.set_version(4);
packet.set_header_len(20);
packet.set_total_len((20 + len) as u16);
packet.set_protocol(socket.ip_protocol());
packet.set_src_addr(v4_src);
packet.set_dst_addr(v4_dst);
let payload = packet.payload_mut();
payload.copy_from_slice(data);
packet.fill_checksum();
socket.send_slice(&buffer).unwrap();
// avoid deadlock
drop(socket);
drop(sockets);
if let Ok(_) = iface.poll(&(*get_net_sockets())) {};
Ok(len)
} else {
unimplemented!("ip type")
}
} else {
Err(LxError::ENOTCONN)
}
}
/// missing documentation
pub fn setsockopt(&mut self, level: usize, opt: usize, data: &[u8]) -> SysResult {
if let (IPPROTO_IP, IP_HDRINCL) = (level, opt) {
if let Some(arg) = data.first() {
self.header_included = *arg > 0;
debug!("hdrincl set to {}", self.header_included);
}
}
Ok(0)
}
}
impl_kobject!(RawSocketState);
#[async_trait]
impl Socket for RawSocketState {
/// read to buffer
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
self.read(data).await
}
/// write from buffer
fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult {
self.write(data, sendto_endpoint)
}
/// connect
async fn connect(&self, _endpoint: Endpoint) -> SysResult {
unimplemented!()
// self.connect(_endpoint).await
}
/// wait for some event on a file descriptor
fn poll(&self) -> (bool, bool, bool) {
unimplemented!()
// self.poll()
}
fn bind(&mut self, _endpoint: Endpoint) -> SysResult {
unimplemented!()
// self.bind(endpoint)
}
fn listen(&mut self) -> SysResult {
unimplemented!()
// self.listen()
}
fn shutdown(&self) -> SysResult {
unimplemented!()
// self.shutdown()
}
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
unimplemented!()
// self.accept().await
}
fn endpoint(&self) -> Option<Endpoint> {
unimplemented!()
// self.endpoint()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
unimplemented!()
// self.remote_endpoint()
}
fn setsockopt(&mut self, level: usize, opt: usize, data: &[u8]) -> SysResult {
self.setsockopt(level, opt, data)
}
/// manipulate file descriptor
fn ioctl(&self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
Ok(0)
}
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
Ok(0)
}
}

View File

@ -0,0 +1,301 @@
// core
use core::cmp::min;
use core::mem::size_of;
// crate
use crate::error::LxError;
use crate::net::Endpoint;
// smoltcp
pub use smoltcp::wire::{IpAddress, Ipv4Address};
// #
use crate::net::*;
use kernel_hal::user::{UserInOutPtr, UserOutPtr};
// use numeric_enum_macro::numeric_enum;
/// missing documentation
#[repr(C)]
pub union SockAddr {
/// missing documentation
pub family: u16,
/// missing documentation
pub addr_in: SockAddrIn,
/// missing documentation
pub addr_un: SockAddrUn,
/// missing documentation
pub addr_ll: SockAddrLl,
/// missing documentation
pub addr_nl: SockAddrNl,
/// missing documentation
pub addr_ph: SockAddrPlaceholder,
}
/// missing documentation
#[repr(C)]
pub struct SockAddrIn {
/// missing documentation
pub sin_family: u16,
/// missing documentation
pub sin_port: u16,
/// missing documentation
pub sin_addr: u32,
/// missing documentation
pub sin_zero: [u8; 8],
}
/// missing documentation
#[repr(C)]
pub struct SockAddrUn {
/// missing documentation
pub sun_family: u16,
/// missing documentation
pub sun_path: [u8; 108],
}
/// missing documentation
#[repr(C)]
pub struct SockAddrLl {
/// missing documentation
pub sll_family: u16,
/// missing documentation
pub sll_protocol: u16,
/// missing documentation
pub sll_ifindex: u32,
/// missing documentation
pub sll_hatype: u16,
/// missing documentation
pub sll_pkttype: u8,
/// missing documentation
pub sll_halen: u8,
/// missing documentation
pub sll_addr: [u8; 8],
}
/// missing documentation
#[repr(C)]
pub struct SockAddrNl {
nl_family: u16,
nl_pad: u16,
nl_pid: u32,
nl_groups: u32,
}
/// missing documentation
#[repr(C)]
pub struct SockAddrPlaceholder {
/// missing documentation
pub family: u16,
/// missing documentation
pub data: [u8; 14],
}
impl From<Endpoint> for SockAddr {
fn from(endpoint: Endpoint) -> Self {
#[allow(warnings)]
if let Endpoint::Ip(ip) = endpoint {
match ip.addr {
IpAddress::Ipv4(ipv4) => SockAddr {
addr_in: SockAddrIn {
sin_family: AddressFamily::Internet.into(),
sin_port: u16::to_be(ip.port),
sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)),
sin_zero: [0; 8],
},
},
IpAddress::Unspecified => SockAddr {
addr_ph: SockAddrPlaceholder {
family: AddressFamily::Unspecified.into(),
data: [0; 14],
},
},
_ => unimplemented!("only ipv4"),
}
// } else if let Endpoint::LinkLevel(link_level) = endpoint {
// SockAddr {
// addr_ll: SockAddrLl {
// sll_family: AddressFamily::Packet.into(),
// sll_protocol: 0,
// sll_ifindex: link_level.interface_index as u32,
// sll_hatype: 0,
// sll_pkttype: 0,
// sll_halen: 0,
// sll_addr: [0; 8],
// },
// }
// } else if let Endpoint::Netlink(netlink) = endpoint {
// SockAddr {
// addr_nl: SockAddrNl {
// nl_family: AddressFamily::Netlink.into(),
// nl_pad: 0,
// nl_pid: netlink.port_id,
// nl_groups: netlink.multicast_groups_mask,
// },
// }
} else {
unimplemented!("only ip");
}
}
}
/// missing documentation
pub fn sockaddr_to_endpoint(addr: SockAddr, len: usize) -> Result<Endpoint, LxError> {
if len < size_of::<u16>() {
return Err(LxError::EINVAL);
}
// let addr = unsafe { vm.check_read_ptr(addr)? };
if len < addr.len()? {
return Err(LxError::EINVAL);
}
#[allow(unsafe_code)]
unsafe {
match AddressFamily::from(addr.family) {
AddressFamily::Internet => {
let port = u16::from_be(addr.addr_in.sin_port);
let addr = IpAddress::from(Ipv4Address::from_bytes(
&u32::from_be(addr.addr_in.sin_addr).to_be_bytes()[..],
));
Ok(Endpoint::Ip((addr, port).into()))
}
AddressFamily::Unix => Err(LxError::EINVAL),
// AddressFamily::Packet => Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
// addr.addr_ll.sll_ifindex as usize,
// ))),
// AddressFamily::Netlink => Ok(Endpoint::Netlink(NetlinkEndpoint::new(
// addr.addr_nl.nl_pid,
// addr.addr_nl.nl_groups,
// ))),
_ => Err(LxError::EINVAL),
}
}
}
impl SockAddr {
fn len(&self) -> Result<usize, LxError> {
#[allow(unsafe_code)]
match AddressFamily::from(unsafe { self.family }) {
AddressFamily::Internet => Ok(size_of::<SockAddrIn>()),
AddressFamily::Packet => Ok(size_of::<SockAddrLl>()),
AddressFamily::Netlink => Ok(size_of::<SockAddrNl>()),
AddressFamily::Unix => Err(LxError::EINVAL),
_ => Err(LxError::EINVAL),
}
}
/// # Safety
/// Write to user sockaddr
/// Check mutability for user
#[allow(dead_code)]
pub fn write_to(
self,
addr: UserOutPtr<SockAddr>,
mut addr_len: UserInOutPtr<u32>,
) -> SysResult {
// Ignore NULL
if addr.is_null() {
return Ok(0);
}
let max_addr_len = addr_len.read()? as usize;
let full_len = self.len()?;
let written_len = min(max_addr_len, full_len);
if written_len > 0 {
#[allow(unsafe_code)]
let source = unsafe {
core::slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len)
};
#[allow(unsafe_code)]
let mut addr: UserOutPtr<u8> = unsafe { core::mem::transmute(addr) };
addr.write_array(source)?;
}
addr_len.write(full_len as u32)?;
Ok(0)
}
}
macro_rules! enum_with_unknown {
(
$( #[$enum_attr:meta] )*
pub enum $name:ident($ty:ty) {
$( $variant:ident = $value:expr ),+ $(,)*
}
) => {
enum_with_unknown! {
$( #[$enum_attr] )*
pub doc enum $name($ty) {
$( #[doc(shown)] $variant = $value ),+
}
}
};
(
$( #[$enum_attr:meta] )*
pub doc enum $name:ident($ty:ty) {
$(
$( #[$variant_attr:meta] )+
$variant:ident = $value:expr $(,)*
),+
}
) => {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
$( #[$enum_attr] )*
pub enum $name {
$(
$( #[$variant_attr] )*
$variant
),*,
/// missing documentation
Unknown($ty)
}
impl ::core::convert::From<$ty> for $name {
fn from(value: $ty) -> Self {
match value {
$( $value => $name::$variant ),*,
other => $name::Unknown(other)
}
}
}
impl ::core::convert::From<$name> for $ty {
fn from(value: $name) -> Self {
match value {
$( $name::$variant => $value ),*,
$name::Unknown(other) => other
}
}
}
}
}
enum_with_unknown! {
/// Address families
pub doc enum AddressFamily(u16) {
/// Unspecified
Unspecified = 0,
/// Unix domain sockets
Unix = 1,
/// Internet IP Protocol
Internet = 2,
/// Netlink
Netlink = 16,
/// Packet family
Packet = 17,
}
}
/// missing documentation
#[repr(C)]
pub struct ArpReq {
/// missing documentation
pub arp_pa: SockAddrPlaceholder,
/// missing documentation
pub arp_ha: SockAddrPlaceholder,
/// missing documentation
pub arp_flags: u32,
/// missing documentation
pub arp_netmask: SockAddrPlaceholder,
/// missing documentation
pub arp_dev: [u8; 16],
}

File diff suppressed because it is too large Load Diff

672
linux-object/src/net/tcp.rs Normal file
View File

@ -0,0 +1,672 @@
// Tcpsocket
#![allow(dead_code)]
// crate
use crate::error::LxError;
use crate::error::LxResult;
use crate::net::get_ephemeral_port;
use crate::net::get_net_sockets;
use crate::net::poll_ifaces;
#[allow(unused_imports)]
#[cfg(feature = "e1000")]
use crate::net::poll_ifaces_e1000;
#[cfg(feature = "loopback")]
use crate::net::poll_ifaces_loopback;
use crate::net::Endpoint;
use crate::net::GlobalSocketHandle;
use crate::net::IpEndpoint;
use crate::net::Socket;
use crate::net::SysResult;
use crate::net::TCP_RECVBUF;
use crate::net::TCP_SENDBUF;
use alloc::sync::Arc;
use spin::Mutex;
// alloc
use alloc::boxed::Box;
use alloc::vec;
// smoltcp
use smoltcp::socket::TcpSocket;
use smoltcp::socket::TcpSocketBuffer;
// async
use async_trait::async_trait;
// third part
#[allow(unused_imports)]
use zircon_object::object::*;
// future
// use core::future::Future;
// use core::pin::Pin;
// use core::task::Context;
// use core::task::Poll;
/// missing documentation
#[derive(Debug)]
pub struct TcpSocketState {
/// missing documentation
// base: KObjectBase,
/// missing documentation
handle: GlobalSocketHandle,
/// missing documentation
local_endpoint: Option<IpEndpoint>, // save local endpoint for bind()
/// missing documentation
is_listening: bool,
}
impl Default for TcpSocketState {
fn default() -> Self {
TcpSocketState::new()
}
}
impl TcpSocketState {
/// missing documentation
pub fn new() -> Self {
let rx_buffer = TcpSocketBuffer::new(vec![0; TCP_RECVBUF]);
let tx_buffer = TcpSocketBuffer::new(vec![0; TCP_SENDBUF]);
let socket = TcpSocket::new(rx_buffer, tx_buffer);
let handle = GlobalSocketHandle(get_net_sockets().lock().add(socket));
TcpSocketState {
// base: KObjectBase::new(),
handle,
local_endpoint: None,
is_listening: false,
}
}
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (LxResult<usize>, Endpoint) {
warn!("tcp read");
loop {
poll_ifaces();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.may_recv() {
if let Ok(size) = socket.recv_slice(data) {
if size > 0 {
let endpoint = socket.remote_endpoint();
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
return (Ok(size), Endpoint::Ip(endpoint));
}
}
} else {
return (
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
);
}
}
}
/// missing documentation
#[cfg(feature = "e1000")]
pub async fn read(&self, data: &mut [u8]) -> (LxResult<usize>, Endpoint) {
warn!("tcp read");
use core::task::Poll;
futures::future::poll_fn(|cx| {
self.with(|s| {
if s.can_recv() {
warn!("can recv ok");
if let Ok(size) = s.recv_slice(data) {
warn!("--------------Ok size {}", size);
if size > 0 {
let endpoint = s.remote_endpoint();
Poll::Ready((Ok(size), Endpoint::Ip(endpoint)))
} else {
warn!("wait size > 0");
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
} else {
warn!("recv_slice not Oksize");
Poll::Ready((
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
))
}
} else {
error!("can not recv");
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
})
})
.await
// let net_sockets = get_net_sockets();
// let mut sockets = net_sockets.lock();
// let mut socket = sockets.get::<TcpSocket>(self.handle.0);
// // if socket.may_recv() {
// if let Ok(size) = socket.recv_slice(data) {
// let endpoint = socket.remote_endpoint();
// return (Ok(size), Endpoint::Ip(endpoint));
// } else {
// return (
// Err(LxError::ENOTCONN),
// Endpoint::Ip(IpEndpoint::UNSPECIFIED),
// );
// }
}
/// missing documentation
pub fn write(&self, data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
warn!("tcp write");
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.is_open() {
if socket.can_send() {
match socket.send_slice(data) {
Ok(size) => {
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
Ok(size)
}
Err(_) => Err(LxError::ENOBUFS),
}
} else {
Err(LxError::ENOBUFS)
}
} else {
Err(LxError::ENOTCONN)
}
}
/// missing documentation
fn poll(&self) -> (bool, bool, bool) {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
let (mut input, mut output, mut err) = (false, false, false);
if self.is_listening && socket.is_active() {
// a new connection
input = true;
} else if !socket.is_open() {
err = true;
} else {
if socket.can_recv() {
input = true;
}
if socket.can_send() {
output = true;
}
}
(input, output, err)
}
/// missing documentation
pub async fn connect(&self, endpoint: Endpoint) -> SysResult {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
#[allow(warnings)]
if let Endpoint::Ip(ip) = endpoint {
let local_port = get_ephemeral_port();
socket
.connect(ip, local_port)
.map_err(|_| LxError::ENOBUFS)?;
// avoid deadlock
drop(socket);
drop(sockets);
// wait for connection result
loop {
poll_ifaces();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
use smoltcp::socket::TcpState;
match socket.state() {
TcpState::SynSent => {
// still connecting
drop(socket);
drop(sockets);
poll_ifaces();
}
TcpState::Established => {
break Ok(0);
}
_ => {
break Err(LxError::ECONNREFUSED);
}
}
}
} else {
drop(socket);
drop(sockets);
return Err(LxError::EINVAL);
}
}
/// missing documentation
#[cfg(feature = "e1000")]
pub async fn connect(&self, endpoint: Endpoint) -> SysResult {
warn!("tcp connect");
// if let Endpoint::Ip(ip) = endpoint {
// let local_port = get_ephemeral_port();
// self.with(|ss| ss.connect(ip, local_port).map_err(|_| LxError::ENOBUFS))?;
// // use crate::net::IFaceFuture;
// // IFaceFuture { flag: false }.await;
// // warn!("no");
// // use smoltcp::socket::TcpState;
// // let ret = self.with(|ss| match ss.state() {
// // TcpState::SynSent => {
// // // still connecting
// // warn!("SynSent");
// // Ok(0)
// // }
// // TcpState::Established => Ok(0),
// // _ => Err(LxError::ECONNREFUSED),
// // });
// // Ok(0)
// // socket
// // .connect(ip, local_port)
// // .map_err(|_| LxError::ENOBUFS)?;
// // use crate::net::ConnectFuture;
// // use smoltcp::socket::SocketRef;
// // let c = ConnectFuture {
// // socket: SocketRef::into_inner(socket),
// // }
// // .await;
// // drop(c);
// // use core::future::Future;
// // use core::pin::Pin;
// // use core::task::Context;
// use crate::net::IFaceFuture;
// IFaceFuture.await;
// // warn!("no");
// // IFaceFuture.await;
// // warn!("no");
// // IFaceFuture.await;
// // warn!("no");
// // IFaceFuture.await;
// // warn!("no");
// use core::task::Poll;
// use smoltcp::socket::TcpState;
// let ret = futures::future::poll_fn(|cx| {
// self.with(|s| {
// // s.connect(ip, local_port).map_err(|_| LxError::ENOBUFS)?;
// match s.state() {
// TcpState::Closed | TcpState::TimeWait => {
// warn!("Closed|TimeWait");
// Poll::Ready(Err(LxError::ECONNREFUSED))
// }
// TcpState::Listen => {
// warn!("Listen");
// Poll::Ready(Err(LxError::ECONNREFUSED))
// }
// TcpState::SynSent => {
// warn!("SynSent");
// s.register_recv_waker(cx.waker());
// s.register_send_waker(cx.waker());
// // drop(s);
// // #[cfg(feature = "e1000")]
// // poll_ifaces_e1000();
// // IFaceFuture.await
// Poll::Pending
// }
// TcpState::SynReceived => {
// warn!("SynReceived");
// s.register_recv_waker(cx.waker());
// s.register_send_waker(cx.waker());
// Poll::Pending
// }
// TcpState::Established => {
// warn!("Established");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// // TcpState::TimeWait => {
// // warn!("TimeWait");
// // // s.register_recv_waker(cx.waker());
// // // s.register_send_waker(cx.waker());
// // Poll::Ready(Ok(0))
// // // Poll::Pending
// // }
// TcpState::FinWait1 => {
// warn!("------------------------------------FinWait1");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// TcpState::FinWait2 => {
// warn!("----------------------------------------FinWait2");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// TcpState::Closing => {
// warn!("-------------------------------------------Closing");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// TcpState::LastAck => {
// warn!("-------------------------------------------LastAck");
// // s.register_recv_waker(cx.waker());
// // s.register_send_waker(cx.waker());
// Poll::Ready(Ok(0))
// // Poll::Pending
// }
// _ => {
// warn!("_");
// Poll::Ready(Err(LxError::ECONNREFUSED))
// }
// }
// })
// })
// .await;
// // #[cfg(feature = "e1000")]
// // poll_ifaces_e1000();
// IFaceFuture.await;
// warn!("ret {:?}", ret);
// ret
// // Ok(0)
// } else {
// return Err(LxError::EINVAL);
// }
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
#[allow(warnings)]
if let Endpoint::Ip(ip) = endpoint {
let local_port = get_ephemeral_port();
socket
.connect(ip, local_port)
.map_err(|_| LxError::ENOBUFS)?;
// avoid deadlock
drop(socket);
drop(sockets);
#[cfg(feature = "e1000")]
poll_ifaces_e1000();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
// wait for connection result
loop {
warn!("loop");
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
use smoltcp::socket::TcpState;
match socket.state() {
TcpState::SynSent => {
// still connecting
warn!("SynSent");
drop(socket);
drop(sockets);
#[cfg(feature = "e1000")]
poll_ifaces_e1000();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
}
TcpState::Established => {
warn!("estab");
break Ok(0);
}
_ => {
break Err(LxError::ECONNREFUSED);
}
}
}
} else {
drop(socket);
drop(sockets);
return Err(LxError::EINVAL);
}
}
/// missing documentation
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
if let Endpoint::Ip(mut ip) = endpoint {
if ip.port == 0 {
ip.port = get_ephemeral_port();
}
self.local_endpoint = Some(ip);
self.is_listening = false;
Ok(0)
} else {
Err(LxError::EINVAL)
}
}
/// missing documentation
fn listen(&mut self) -> SysResult {
if self.is_listening {
// it is ok to listen twice
return Ok(0);
}
let local_endpoint = self.local_endpoint.ok_or(LxError::EINVAL)?;
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
info!("socket listening on {:?}", local_endpoint);
if socket.is_listening() {
return Ok(0);
}
match socket.listen(local_endpoint) {
Ok(()) => {
self.is_listening = true;
Ok(0)
}
Err(_) => Err(LxError::EINVAL),
}
}
/// missing documentation
fn shutdown(&self) -> SysResult {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
socket.close();
Ok(0)
}
/// missing documentation
async fn accept(&mut self) -> Result<(Arc<Mutex<dyn Socket>>, Endpoint), LxError> {
let endpoint = self.local_endpoint.ok_or(LxError::EINVAL)?;
loop {
poll_ifaces();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.is_active() {
let remote_endpoint = socket.remote_endpoint();
drop(socket);
let new_socket = {
let rx_buffer = TcpSocketBuffer::new(vec![0; TCP_RECVBUF]);
let tx_buffer = TcpSocketBuffer::new(vec![0; TCP_SENDBUF]);
let mut socket = TcpSocket::new(rx_buffer, tx_buffer);
socket.listen(endpoint).unwrap();
let new_handle = GlobalSocketHandle(sockets.add(socket));
let old_handle = ::core::mem::replace(&mut self.handle, new_handle);
Arc::new(Mutex::new(TcpSocketState {
// base: KObjectBase::new(),
handle: old_handle,
local_endpoint: self.local_endpoint,
is_listening: false,
}))
};
drop(sockets);
poll_ifaces();
return Ok((new_socket, Endpoint::Ip(remote_endpoint)));
}
drop(socket);
drop(sockets);
}
}
#[cfg(feature = "e1000")]
async fn accept(&mut self) -> Result<(Arc<Mutex<dyn Socket>>, Endpoint), LxError> {
let endpoint = self.local_endpoint.ok_or(LxError::EINVAL)?;
// let net_sockets = get_net_sockets();
// let mut sockets = net_sockets.lock();
// let socket = sockets.get::<TcpSocket>(self.handle.0);
// if socket.is_active() {
// use crate::net::AcceptFuture;
// AcceptFuture {
// socket: &mut socket,
// }
// .await;
use core::task::Poll;
futures::future::poll_fn(|cx| {
self.with(|s| {
if s.is_active() {
Poll::Ready(())
} else {
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
})
})
.await;
let remote_endpoint = self.with(|s| s.remote_endpoint());
// drop(socket);
let new_socket = {
let rx_buffer = TcpSocketBuffer::new(vec![0; TCP_RECVBUF]);
let tx_buffer = TcpSocketBuffer::new(vec![0; TCP_SENDBUF]);
let mut socket = TcpSocket::new(rx_buffer, tx_buffer);
socket.listen(endpoint).unwrap();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let new_handle = GlobalSocketHandle(sockets.add(socket));
let old_handle = ::core::mem::replace(&mut self.handle, new_handle);
Arc::new(Mutex::new(TcpSocketState {
// base: KObjectBase::new(),
handle: old_handle,
local_endpoint: self.local_endpoint,
is_listening: false,
}))
};
return Ok((new_socket, Endpoint::Ip(remote_endpoint)));
}
/// missing documentation
fn endpoint(&self) -> Option<Endpoint> {
self.local_endpoint.map(Endpoint::Ip).or_else(|| {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
let endpoint = socket.local_endpoint();
if endpoint.port != 0 {
Some(Endpoint::Ip(endpoint))
} else {
None
}
})
}
/// missing documentation
fn remote_endpoint(&self) -> Option<Endpoint> {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<TcpSocket>(self.handle.0);
if socket.is_open() {
Some(Endpoint::Ip(socket.remote_endpoint()))
} else {
None
}
}
fn ioctl(&self) -> SysResult {
Err(LxError::ENOSYS)
}
fn with<R>(&self, f: impl FnOnce(&mut TcpSocket) -> R) -> R {
let res = {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<TcpSocket>(self.handle.0);
f(&mut *socket)
};
res
}
}
// impl_kobject!(TcpSocketState);
#[async_trait]
impl Socket for TcpSocketState {
/// read to buffer
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
self.read(data).await
}
/// write from buffer
fn write(&self, _data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
self.write(_data, _sendto_endpoint)
}
/// connect
async fn connect(&self, _endpoint: Endpoint) -> SysResult {
self.connect(_endpoint).await
}
/// wait for some event on a file descriptor
fn poll(&self) -> (bool, bool, bool) {
self.poll()
}
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
self.bind(endpoint)
}
fn listen(&mut self) -> SysResult {
self.listen()
}
fn shutdown(&self) -> SysResult {
self.shutdown()
}
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
self.accept().await
}
fn endpoint(&self) -> Option<Endpoint> {
self.endpoint()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
self.remote_endpoint()
}
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
Ok(0)
}
/// manipulate file descriptor
fn ioctl(&self, _request: usize, _arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
Ok(0)
}
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
warn!("fnctl is unimplemented for this socket");
// now no fnctl impl but need to pass libctest , so just do a trick
match _cmd {
1 => Ok(1),
3 => Ok(0o4000),
_ => Ok(0),
}
}
}

View File

@ -0,0 +1,148 @@
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use alloc::vec;
use core::fmt::Write;
use kernel_hal::drivers::NET_DRIVERS;
use kernel_hal::drivers::SOCKETS;
use kernel_hal::NetDriver;
use smoltcp::iface::{InterfaceBuilder, NeighborCache};
use smoltcp::socket::*;
use smoltcp::time::Instant;
use smoltcp::wire::{IpAddress, IpCidr};
pub extern "C" fn server(_arg: usize) -> ! {
//判断Vec中是否有保存初始化好的驱动
if NET_DRIVERS.read().len() < 1 {
loop {
//thread::yield_now();
}
}
use kernel_hal_bare::drivers::net::rtl8x::RTL8xInterface;
// Ref: https://github.com/elliott10/rCore/blob/6f1953b9773d66cf7ab831c345a44e89036751c1/kernel/src/net/test.rs
let driver = {
//选第一个网卡驱动
let ref_driver = Arc::clone(&NET_DRIVERS.write()[0]);
//需实现Clone
ref_driver
.as_any()
.downcast_ref::<RTL8xInterface>()
.unwrap()
.clone()
};
let ethernet_addr = driver.get_mac();
let ifname = driver.get_ifname();
debug!("NET_DRIVERS read OK!\n{} MAC: {:x?}", ifname, ethernet_addr);
debug!("IP address: {:?}", driver.get_ip_addresses());
let mut iface = driver.iface.lock();
/*
//let hw_addr = EthernetAddress::from_bytes(&mac);
let hw_addr = ethernet_addr;
let neighbor_cache = NeighborCache::new(BTreeMap::new());
//let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24)];
let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 100, 10), 24)];
let mut iface = InterfaceBuilder::new(driver)
.ethernet_addr(hw_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.finalize();
*/
let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 64]);
let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 128]);
let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let tcp2_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
let tcp2_tx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
let tcp2_socket = TcpSocket::new(tcp2_rx_buffer, tcp2_tx_buffer);
let mut sockets = SOCKETS.lock();
let udp_handle = sockets.add(udp_socket);
let tcp_handle = sockets.add(tcp_socket);
let tcp2_handle = sockets.add(tcp2_socket);
drop(sockets);
loop {
{
let mut sockets = SOCKETS.lock();
let timestamp = Instant::from_millis(0);
//poll一般不要被阻塞,以便可以响应下列监听的网络协议
match iface.poll(&mut sockets, timestamp) {
Ok(_) => {}
Err(e) => {
error!("poll error: {}", e);
}
}
// udp server
{
let mut socket = sockets.get::<UdpSocket>(udp_handle);
if !socket.is_open() {
socket.bind(6969).unwrap();
debug!("UDP bind port 6969");
}
let client = match socket.recv() {
Ok((_, endpoint)) => Some(endpoint),
Err(_) => None,
};
if let Some(endpoint) = client {
info!("UDP 6969 recv");
let hello = b"hello from zCore\n";
socket.send_slice(hello, endpoint).unwrap();
}
}
// simple http server
{
let mut socket = sockets.get::<TcpSocket>(tcp_handle);
if !socket.is_open() {
socket.listen(80).unwrap();
debug!("TCP listen port 80");
}
if socket.can_send() {
info!("TCP 80 recv");
write!(socket, "HTTP/1.1 200 OK\r\nServer: zCore\r\nContent-Length: 13\r\nContent-Type: text/html\r\nConnection: Closed\r\n\r\nHello! zCore \r\n").unwrap();
socket.close();
}
}
// simple tcp server that just eats everything
{
let mut socket = sockets.get::<TcpSocket>(tcp2_handle);
if !socket.is_open() {
socket.listen(2222).unwrap();
debug!("TCP listen port 2222");
}
if socket.can_recv() {
info!("TCP 2222 recv");
let mut data = [0u8; 2048];
let _size = socket.recv_slice(&mut data).unwrap();
let mut linebuf: [char; 16] = [0 as char; 16];
for i in 0..linebuf.len() {
linebuf[i] = data[i] as char;
}
info!("Got: {:?}", linebuf);
}
}
}
//一般大量循环打印是正常状态
trace!("--- loop() ---");
//thread::yield_now();
}
}

386
linux-object/src/net/udp.rs Normal file
View File

@ -0,0 +1,386 @@
// udpsocket
#![allow(dead_code)]
// crate
use crate::error::LxError;
use crate::error::LxResult;
use crate::net::from_cstr;
use crate::net::get_ephemeral_port;
use crate::net::get_net_driver;
use crate::net::get_net_sockets;
use crate::net::poll_ifaces;
#[allow(unused_imports)]
#[cfg(feature = "e1000")]
use crate::net::poll_ifaces_e1000;
#[cfg(feature = "loopback")]
use crate::net::poll_ifaces_loopback;
use crate::net::AddressFamily;
use crate::net::ArpReq;
use crate::net::Endpoint;
use crate::net::GlobalSocketHandle;
use crate::net::IpAddress;
use crate::net::IpEndpoint;
use crate::net::Ipv4Address;
use crate::net::SockAddr;
use crate::net::SockAddrPlaceholder;
use crate::net::Socket;
use crate::net::SysResult;
use crate::net::UDP_METADATA_BUF;
use crate::net::UDP_RECVBUF;
use crate::net::UDP_SENDBUF;
use spin::Mutex;
// alloc
use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec;
// smoltcp
use smoltcp::socket::UdpPacketMetadata;
use smoltcp::socket::UdpSocket;
use smoltcp::socket::UdpSocketBuffer;
// async
use async_trait::async_trait;
// third part
#[allow(unused_imports)]
use zircon_object::impl_kobject;
#[allow(unused_imports)]
use zircon_object::object::*;
/// missing documentation
#[derive(Debug)]
pub struct UdpSocketState {
/// missing documentation
// base: KObjectBase,
/// missing documentation
handle: GlobalSocketHandle,
/// missing documentation
remote_endpoint: Option<IpEndpoint>, // remember remote endpoint for connect()
}
impl Default for UdpSocketState {
fn default() -> Self {
UdpSocketState::new()
}
}
impl UdpSocketState {
/// missing documentation
pub fn new() -> Self {
let rx_buffer = UdpSocketBuffer::new(
vec![UdpPacketMetadata::EMPTY; UDP_METADATA_BUF],
vec![0; UDP_RECVBUF],
);
let tx_buffer = UdpSocketBuffer::new(
vec![UdpPacketMetadata::EMPTY; UDP_METADATA_BUF],
vec![0; UDP_SENDBUF],
);
let socket = UdpSocket::new(rx_buffer, tx_buffer);
let handle = GlobalSocketHandle(get_net_sockets().lock().add(socket));
UdpSocketState {
// base: KObjectBase::new(),
handle,
remote_endpoint: None,
}
}
fn default() -> Self {
Self::new()
}
/// missing documentation
pub async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
loop {
poll_ifaces();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
if socket.can_recv() {
if let Ok((size, remote_endpoint)) = socket.recv_slice(data) {
let endpoint = remote_endpoint;
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
return (Ok(size), Endpoint::Ip(endpoint));
}
} else {
return (
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
);
}
drop(socket);
drop(sockets);
}
}
/// missing documentation
#[cfg(feature = "e1000")]
pub async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
use core::task::Poll;
futures::future::poll_fn(|cx| {
self.with(|s| {
if s.can_recv() {
if let Ok((size, remote_endpoint)) = s.recv_slice(data) {
let endpoint = remote_endpoint;
warn!("udp read => size : {} , enpoint : {} ", size, endpoint);
Poll::Ready((Ok(size), Endpoint::Ip(endpoint)))
} else {
warn!("recv faill message");
Poll::Ready((
Err(LxError::ENOTCONN),
Endpoint::Ip(IpEndpoint::UNSPECIFIED),
))
}
} else {
warn!("udp can not recv ,because rx buffer is null");
s.register_recv_waker(cx.waker());
s.register_send_waker(cx.waker());
Poll::Pending
}
})
})
.await
}
/// missing documentation
pub fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult {
let remote_endpoint = {
if let Some(Endpoint::Ip(ref endpoint)) = sendto_endpoint {
endpoint
} else if let Some(ref endpoint) = self.remote_endpoint {
endpoint
} else {
return Err(LxError::ENOTCONN);
}
};
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
if socket.endpoint().port == 0 {
let temp_port = get_ephemeral_port();
socket
.bind(IpEndpoint::new(IpAddress::Unspecified, temp_port))
.unwrap();
}
if socket.can_send() {
match socket.send_slice(data, *remote_endpoint) {
Ok(()) => {
// avoid deadlock
drop(socket);
drop(sockets);
poll_ifaces();
#[cfg(feature = "loopback")]
poll_ifaces_loopback();
Ok(data.len())
}
Err(_) => Err(LxError::ENOBUFS),
}
} else {
Err(LxError::ENOBUFS)
}
}
/// missing documentation
pub fn poll(&self) -> (bool, bool, bool) {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<UdpSocket>(self.handle.0);
let (mut input, mut output, err) = (false, false, false);
if socket.can_recv() {
input = true;
}
if socket.can_send() {
output = true;
}
(input, output, err)
}
async fn connect(&mut self, endpoint: Endpoint) -> SysResult {
#[allow(irrefutable_let_patterns)]
if let Endpoint::Ip(ip) = endpoint {
self.remote_endpoint = Some(ip);
Ok(0)
} else {
Err(LxError::EINVAL)
}
}
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
#[allow(irrefutable_let_patterns)]
if let Endpoint::Ip(mut ip) = endpoint {
if ip.port == 0 {
ip.port = get_ephemeral_port();
}
match socket.bind(ip) {
Ok(()) => Ok(0),
Err(_) => Err(LxError::EINVAL),
}
} else {
Err(LxError::EINVAL)
}
}
fn ioctl(&self, request: usize, arg1: usize, _arg2: usize, _arg3: usize) -> SysResult {
match request {
// SIOCGARP
0x8954 => {
// TODO: check addr
#[allow(unsafe_code)]
let req = unsafe { &mut *(arg1 as *mut ArpReq) };
if let AddressFamily::Internet = AddressFamily::from(req.arp_pa.family) {
let name = req.arp_dev.as_ptr();
#[allow(unsafe_code)]
let ifname = unsafe { from_cstr(name) };
let addr = &req.arp_pa as *const SockAddrPlaceholder as *const SockAddr;
#[allow(unsafe_code)]
let addr = unsafe {
IpAddress::from(Ipv4Address::from_bytes(
&u32::from_be((*addr).addr_in.sin_addr).to_be_bytes()[..],
))
};
for iface in get_net_driver().iter() {
if iface.get_ifname() == ifname {
debug!("get arp matched ifname {}", ifname);
return match iface.get_arp(addr) {
Some(mac) => {
// TODO: update flags
req.arp_ha.data[0..6].copy_from_slice(mac.as_bytes());
Ok(0)
}
None => Err(LxError::ENOENT),
};
}
}
Err(LxError::ENOENT)
} else {
Err(LxError::EINVAL)
}
}
_ => Ok(0),
}
}
fn endpoint(&self) -> Option<Endpoint> {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let socket = sockets.get::<UdpSocket>(self.handle.0);
let endpoint = socket.endpoint();
if endpoint.port != 0 {
Some(Endpoint::Ip(endpoint))
} else {
None
}
}
fn remote_endpoint(&self) -> Option<Endpoint> {
self.remote_endpoint.map(Endpoint::Ip)
}
// fn register_recv_waker(&mut self, waker: &Waker) {
// let net_sockets = get_net_sockets();
// let mut sockets = net_sockets.lock();
// let socket = sockets.get::<UdpSocket>(self.handle.0);
// socket.register_recv_waker(waker);
// }
// fn register_send_waker(&mut self, waker: &Waker) {
// let net_sockets = get_net_sockets();
// let mut sockets = net_sockets.lock();
// let socket = sockets.get::<UdpSocket>(self.handle.0);
// socket.register_send_waker(waker);
// }
fn with<R>(&self, f: impl FnOnce(&mut UdpSocket) -> R) -> R {
let res = {
let net_sockets = get_net_sockets();
let mut sockets = net_sockets.lock();
let mut socket = sockets.get::<UdpSocket>(self.handle.0);
f(&mut *socket)
};
res
}
}
// impl_kobject!(UdpSocketState);
/// missing in implementation
#[async_trait]
impl Socket for UdpSocketState {
/// read to buffer
async fn read(&self, data: &mut [u8]) -> (SysResult, Endpoint) {
self.read(data).await
}
/// write from buffer
fn write(&self, data: &[u8], sendto_endpoint: Option<Endpoint>) -> SysResult {
self.write(data, sendto_endpoint)
}
/// connect
async fn connect(&self, endpoint: Endpoint) -> SysResult {
self.connect(endpoint).await
}
/// wait for some event on a file descriptor
fn poll(&self) -> (bool, bool, bool) {
self.poll()
}
fn bind(&mut self, endpoint: Endpoint) -> SysResult {
self.bind(endpoint)
// Err(LxError::EINVAL)
}
fn listen(&mut self) -> SysResult {
Err(LxError::EINVAL)
}
fn shutdown(&self) -> SysResult {
Err(LxError::EINVAL)
}
async fn accept(&mut self) -> LxResult<(Arc<Mutex<dyn Socket>>, Endpoint)> {
Err(LxError::EINVAL)
}
fn endpoint(&self) -> Option<Endpoint> {
self.endpoint()
}
fn remote_endpoint(&self) -> Option<Endpoint> {
self.remote_endpoint()
}
fn setsockopt(&mut self, _level: usize, _opt: usize, _data: &[u8]) -> SysResult {
warn!("setsockopt is unimplemented");
Ok(0)
}
/// manipulate file descriptor
fn ioctl(&self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
warn!("ioctl is unimplemented for this socket");
self.ioctl(request, arg1, arg2, arg3)
}
fn fcntl(&self, _cmd: usize, _arg: usize) -> SysResult {
warn!("fnctl is unimplemented for this socket");
Ok(0)
}
// fn register_recv_waker(&mut self, waker: &Waker) {
// self.register_recv_waker(waker);
// }
// fn register_send_waker(&mut self, waker: &Waker) {
// self.register_send_waker(waker);
// }
}

View File

@ -3,6 +3,7 @@
use crate::error::*;
use crate::fs::*;
use crate::ipc::*;
use crate::net::Socket;
use crate::signal::{Signal as LinuxSignal, SignalAction};
use alloc::vec::Vec;
use alloc::{
@ -14,6 +15,7 @@ use core::sync::atomic::AtomicI32;
use hashbrown::HashMap;
use kernel_hal::VirtAddr;
use rcore_fs::vfs::{FileSystem, INode};
use smoltcp::socket::SocketHandle;
use spin::*;
use zircon_object::{
object::{KernelObject, KoID, Signal},
@ -162,6 +164,8 @@ struct LinuxProcessInner {
children: HashMap<KoID, Arc<Process>>,
/// Signal actions
signal_actions: SignalActions,
/// Sockets
sockets: HashMap<SocketHandle, Arc<Mutex<dyn Socket>>>,
}
#[derive(Clone)]
@ -320,6 +324,43 @@ impl LinuxProcess {
inner.files.remove(&fd).map(|_| ()).ok_or(LxError::EBADF)
}
/// miss
pub fn add_socket(&self, socket: Arc<Mutex<dyn Socket>>) -> LxResult<SocketHandle> {
let inner = self.inner.lock();
let fd = inner.get_free_hd();
self.insert_socket(inner, fd, socket)
// unimplemented!()
}
/// insert a file and fd into the file descriptor table
fn insert_socket(
&self,
mut inner: MutexGuard<LinuxProcessInner>,
fd: SocketHandle,
socket: Arc<Mutex<dyn Socket>>,
) -> LxResult<SocketHandle> {
if inner.sockets.len() < inner.file_limit.cur as usize {
inner.sockets.insert(fd, socket);
Ok(fd)
} else {
Err(LxError::EMFILE)
}
}
/// Get the `Socket` with given `fd`.
pub fn get_socket(&self, fd: SocketHandle) -> LxResult<Arc<Mutex<dyn Socket>>> {
// unimplemented!()
let inner = self.inner.lock();
let socket = inner.sockets.get(&fd).cloned().ok_or(LxError::EBADF);
socket
}
/// Close file descriptor `fd`.
pub fn close_socket(&self, fd: SocketHandle) -> LxResult {
let mut inner = self.inner.lock();
inner.sockets.remove(&fd).map(|_| ()).ok_or(LxError::EBADF)
}
/// Get root INode of the process.
pub fn root_inode(&self) -> &Arc<dyn INode> {
&self.root_inode
@ -454,4 +495,10 @@ impl LinuxProcessInner {
.find(|fd| !self.files.contains_key(fd))
.unwrap()
}
fn get_free_hd(&self) -> SocketHandle {
(10000usize..)
.map(|i| i.into())
.find(|fd| !self.sockets.contains_key(fd))
.unwrap()
}
}

View File

@ -59,7 +59,12 @@ impl Syscall<'_> {
pub fn sys_close(&self, fd: FileDesc) -> SysResult {
info!("close: fd={:?}", fd);
let proc = self.linux_process();
proc.close_file(fd)?;
if usize::from(fd) >= 10000usize {
let x = usize::from(fd);
proc.close_socket(x.into())?;
} else {
proc.close_file(fd)?;
}
Ok(0)
}

View File

@ -21,11 +21,22 @@ impl Syscall<'_> {
pub async fn sys_read(&self, fd: FileDesc, mut base: UserOutPtr<u8>, len: usize) -> SysResult {
info!("read: fd={:?}, base={:?}, len={:#x}", fd, base, len);
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
let mut buf = vec![0u8; len];
let len = file_like.read(&mut buf).await?;
base.write_array(&buf[..len])?;
Ok(len)
if usize::from(fd) >= 10000usize {
let x = usize::from(fd);
let socket = proc.get_socket(x.into())?;
let mut buf = vec![0u8; len];
let (len, _) = socket.lock().read(&mut buf).await;
let len = len.unwrap_or(0);
base.write_array(&buf[..len])?;
Ok(len)
} else {
let file_like = proc.get_file_like(fd)?;
let mut buf = vec![0u8; len];
let len = file_like.read(&mut buf).await?;
base.write_array(&buf[..len])?;
Ok(len)
}
}
/// Writes to a specified file using a file descriptor. Before using this call,
@ -96,11 +107,21 @@ impl Syscall<'_> {
info!("readv: fd={:?}, iov={:?}, count={}", fd, iov_ptr, iov_count);
let mut iovs = iov_ptr.read_iovecs(iov_count)?;
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
let mut buf = vec![0u8; iovs.total_len()];
let len = file_like.read(&mut buf).await?;
iovs.write_from_buf(&buf)?;
Ok(len)
if usize::from(fd) >= 10000usize {
let x = usize::from(fd);
let socket = proc.get_socket(x.into())?;
let mut buf = vec![0u8; iovs.total_len()];
let (len, _) = socket.lock().read(&mut buf).await;
let len = len.unwrap();
iovs.write_from_buf(&buf)?;
Ok(len)
} else {
let file_like = proc.get_file_like(fd)?;
let mut buf = vec![0u8; iovs.total_len()];
let len = file_like.read(&mut buf).await?;
iovs.write_from_buf(&buf)?;
Ok(len)
}
}
/// works just like write except that multiple buffers are written out.
@ -119,9 +140,16 @@ impl Syscall<'_> {
let iovs = iov_ptr.read_iovecs(iov_count)?;
let buf = iovs.read_to_vec()?;
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
let len = file_like.write(&buf)?;
Ok(len)
if usize::from(fd) >= 10000usize {
let x = usize::from(fd);
let socket = proc.get_socket(x.into())?;
let len = socket.lock().write(&buf, None)?;
Ok(len)
} else {
let file_like = proc.get_file_like(fd)?;
let len = file_like.write(&buf)?;
Ok(len)
}
}
/// repositions the offset of the open file associated with the file descriptor fd
@ -291,8 +319,15 @@ impl Syscall<'_> {
fd, request, arg1, arg2, arg3
);
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
file_like.ioctl(request, arg1, arg2, arg3)
if usize::from(fd) >= 10000usize {
let f = usize::from(fd);
let socket = proc.get_socket(f.into())?;
let x = socket.lock();
x.ioctl(request, arg1, arg2, arg3)
} else {
let file_like = proc.get_file_like(fd)?;
file_like.ioctl(request, arg1, arg2, arg3)
}
}
/// Manipulate a file descriptor.
@ -301,8 +336,15 @@ impl Syscall<'_> {
pub fn sys_fcntl(&self, fd: FileDesc, cmd: usize, arg: usize) -> SysResult {
info!("fcntl: fd={:?}, cmd={:x}, arg={}", fd, cmd, arg);
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
file_like.fcntl(cmd, arg)
if usize::from(fd) >= 10000usize {
let f = usize::from(fd);
let socket = proc.get_socket(f.into())?;
let x = socket.lock();
x.fcntl(cmd, arg)
} else {
let file_like = proc.get_file_like(fd)?;
file_like.fcntl(cmd, arg)
}
}
/// Checks whether the calling process can access the file pathname

View File

@ -47,6 +47,7 @@ mod consts {
mod file;
mod ipc;
mod misc;
mod net;
mod signal;
mod task;
mod time;
@ -166,22 +167,28 @@ impl Syscall<'_> {
Sys::SCHED_GETAFFINITY => self.unimplemented("sched_getaffinity", Ok(0)),
// socket
// Sys::SOCKET => self.sys_socket(a0, a1, a2),
// Sys::CONNECT => self.sys_connect(a0, a1.into(), a2),
// Sys::ACCEPT => self.sys_accept(a0, a1.into(), a2.into()),
Sys::SOCKET => self.sys_socket(a0, a1, a2),
Sys::CONNECT => self.sys_connect(a0, a1.into(), a2).await,
Sys::ACCEPT => self.sys_accept(a0, a1.into(), a2.into()).await,
// Sys::ACCEPT4 => self.sys_accept(a0, a1.into(), a2.into()), // use accept for accept4
// Sys::SENDTO => self.sys_sendto(a0, a1.into(), a2, a3, a4.into(), a5),
// Sys::RECVFROM => self.sys_recvfrom(a0, a1.into(), a2, a3, a4.into(), a5.into()),
// Sys::SENDMSG => self.sys_sendmsg(),
// Sys::RECVMSG => self.sys_recvmsg(a0, a1.into(), a2),
// Sys::SHUTDOWN => self.sys_shutdown(a0, a1),
// Sys::BIND => self.sys_bind(a0, a1.into(), a2),
// Sys::LISTEN => self.sys_listen(a0, a1),
// Sys::GETSOCKNAME => self.sys_getsockname(a0, a1.into(), a2.into()),
// Sys::GETPEERNAME => self.sys_getpeername(a0, a1.into(), a2.into()),
// Sys::SETSOCKOPT => self.sys_setsockopt(a0, a1, a2, a3.into(), a4),
// Sys::GETSOCKOPT => self.sys_getsockopt(a0, a1, a2, a3.into(), a4.into()),
Sys::SENDTO => self.sys_sendto(a0, a1.into(), a2, a3, a4.into(), a5),
Sys::RECVFROM => {
self.sys_recvfrom(a0, a1.into(), a2, a3, a4.into(), a5.into())
.await
}
Sys::SENDMSG => self.unimplemented("sys_sendmsg(),", Ok(0)),
Sys::RECVMSG => self.unimplemented("sys_recvmsg(a0, a1.into(), a2),", Ok(0)),
Sys::SHUTDOWN => self.sys_shutdown(a0, a1),
Sys::BIND => self.sys_bind(a0, a1.into(), a2),
Sys::LISTEN => self.sys_listen(a0, a1),
Sys::GETSOCKNAME => self.sys_getsockname(a0, a1.into(), a2.into()),
Sys::GETPEERNAME => {
self.unimplemented("sys_getpeername(a0, a1.into(), a2.into()),", Ok(0))
}
Sys::SETSOCKOPT => self.sys_setsockopt(a0, a1, a2, a3.into(), a4),
Sys::GETSOCKOPT => {
self.unimplemented("sys_getsockopt(a0, a1, a2, a3.into(), a4.into()),", Ok(0))
}
// process
Sys::CLONE => self.sys_clone(a0, a1, a2.into(), a3.into(), a4),
Sys::EXECVE => self.sys_execve(a0.into(), a1.into(), a2.into()),

270
linux-syscall/src/net.rs Normal file
View File

@ -0,0 +1,270 @@
use super::*;
// use net_stack::net::sockaddr_to_endpoint;
// use net_stack::net::IcmpSocketState;
// use net_stack::net::RawSocketState;
// use net_stack::net::SockAddr;
// use net_stack::net::Socket;
// use net_stack::net::TcpSocketState;
// use net_stack::net::UdpSocketState;
use linux_object::net::sockaddr_to_endpoint;
// use net_stack::net::IcmpSocketState;
// use net_stack::net::RawSocketState;
use linux_object::net::SockAddr;
use linux_object::net::Socket;
use linux_object::net::TcpSocketState;
use linux_object::net::UdpSocketState;
use spin::Mutex;
impl Syscall<'_> {
/// net socket
pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult {
info!(
"sys_socket: domain: {:?}, socket_type: {:?}, protocol: {}",
domain, socket_type, protocol
);
let proc = self.linux_process();
let socket: Arc<Mutex<dyn Socket>> = match domain {
// musl
// domain local 1
// domain inet 2
// domain inet6 10
2 | 1 => match socket_type {
// musl socket type
// 1 STREAM
// 2 DGRAM
// 3 RAW
// 4 RDM
// 5 SEQPACKET
// 5 SEQPACKET
// 6 DCCP
// 10 SOCK_PACKET
1 => Arc::new(Mutex::new(TcpSocketState::new())),
2 => Arc::new(Mutex::new(UdpSocketState::new())),
3 => match protocol {
1 => Arc::new(Mutex::new(UdpSocketState::new())),
_ => {
// Arc::new(Mutex::new(UdpSocketState::new(protocol as u8)))
Arc::new(Mutex::new(UdpSocketState::new()))
}
},
_ => return Err(LxError::EINVAL),
},
_ => return Err(LxError::EAFNOSUPPORT),
};
// socket
let fd = proc.add_socket(socket)?;
Ok(fd.into())
}
/// net sys_connect
pub async fn sys_connect(
&mut self,
fd: usize,
addr: UserInPtr<SockAddr>,
addr_len: usize,
) -> SysResult {
warn!(
"sys_connect: fd: {}, addr: {:?}, addr_len: {}",
fd, addr, addr_len
);
let mut _proc = self.linux_process();
let sa: SockAddr = addr.read()?;
let endpoint = sockaddr_to_endpoint(sa, addr_len)?;
let socket = _proc.get_socket(fd.into())?;
let x = socket.lock();
x.connect(endpoint).await?;
Ok(0)
}
/// net setsockopt
pub fn sys_setsockopt(
&mut self,
sockfd: usize,
level: usize,
optname: usize,
optval: UserInPtr<u8>,
optlen: usize,
) -> SysResult {
info!(
"sys_setsockopt : sockfd : {:?}, level : {:?}, optname : {:?}, optval : {:?} , optlen : {:?}",
sockfd, level, optname,optval,optlen
);
let proc = self.linux_process();
let data = optval.read_array(optlen)?;
let socket = proc.get_socket(sockfd.into())?;
let len = socket.lock().setsockopt(level, optname, &data)?;
Ok(len)
}
/// net setsockopt
pub fn sys_sendto(
&mut self,
sockfd: usize,
buffer: UserInPtr<u8>,
length: usize,
flags: usize,
dest_addr: UserInPtr<SockAddr>,
addrlen: usize,
) -> SysResult {
warn!(
"sys_sendto : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addrlen : {:?}",
sockfd,buffer,length,flags,dest_addr,addrlen
);
let proc = self.linux_process();
let data = buffer.read_array(length)?;
let endpoint = if dest_addr.is_null() {
None
} else {
let _sa: SockAddr = dest_addr.read()?;
let endpoint = sockaddr_to_endpoint(dest_addr.read()?, addrlen)?;
Some(endpoint)
};
let socket = proc.get_socket(sockfd.into())?;
let len = socket.lock().write(&data, endpoint)?;
Ok(len)
}
/// net setsockopt
pub async fn sys_recvfrom(
&mut self,
sockfd: usize,
mut buffer: UserOutPtr<u8>,
length: usize,
flags: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
info!(
"sys_recvfrom : sockfd : {:?}, buffer : {:?}, length : {:?}, flags : {:?} , optlen : {:?}, addr_len : {:?}",
sockfd, buffer, length,flags,addr,addr_len
);
let proc = self.linux_process();
let mut data = vec![0u8; length];
let socket = proc.get_socket(sockfd.into())?;
let x = socket.lock();
let (result, endpoint) = x.read(&mut data).await;
if result.is_ok() && !addr.is_null() {
let sockaddr_in = SockAddr::from(endpoint);
sockaddr_in.write_to(addr, addr_len)?;
}
buffer.write_array(&data[..length])?;
result
}
/// net bind
pub fn sys_bind(&mut self, fd: usize, addr: UserInPtr<SockAddr>, addr_len: usize) -> SysResult {
info!("sys_bind: fd={:?} addr={:?} len={}", fd, addr, addr_len);
let proc = self.linux_process();
let sa: SockAddr = addr.read()?;
let endpoint = sockaddr_to_endpoint(sa, addr_len)?;
info!("sys_bind: fd={:?} bind to {:?}", fd, endpoint);
let socket = proc.get_socket(fd.into())?;
let mut x = socket.lock();
x.bind(endpoint)
}
/// net listen
pub fn sys_listen(&mut self, fd: usize, backlog: usize) -> SysResult {
info!("sys_listen: fd={:?} backlog={}", fd, backlog);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let mut x = socket.lock();
x.listen()
}
/// net shutdown
pub fn sys_shutdown(&mut self, fd: usize, how: usize) -> SysResult {
info!("sys_shutdown: fd={:?} how={}", fd, how);
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let x = socket.lock();
x.shutdown()
}
/// net accept
pub async fn sys_accept(
&mut self,
fd: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
warn!(
"sys_accept: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let proc = self.linux_process();
let socket = proc.get_socket(fd.into())?;
let (new_socket, remote_endpoint) = socket.lock().accept().await?;
let new_fd = proc.add_socket(new_socket)?;
if !addr.is_null() {
let sockaddr_in = SockAddr::from(remote_endpoint);
sockaddr_in.write_to(addr, addr_len)?;
}
Ok(new_fd.into())
}
/// net getsocknames
pub fn sys_getsockname(
&mut self,
fd: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
info!(
"sys_getsockname: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
let proc = self.linux_process();
if addr.is_null() {
return Err(LxError::EINVAL);
}
let socket = proc.get_socket(fd.into())?;
let endpoint = socket.lock().endpoint().ok_or(LxError::EINVAL)?;
let sockaddr_in = SockAddr::from(endpoint);
sockaddr_in.write_to(addr, addr_len)?;
Ok(0)
}
/// net getpeername
pub fn sys_getpeername(
&mut self,
fd: usize,
addr: UserOutPtr<SockAddr>,
addr_len: UserInOutPtr<u32>,
) -> SysResult {
info!(
"sys_getpeername: fd={:?} addr={:?} addr_len={:?}",
fd, addr, addr_len
);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let proc = self.linux_process();
if addr.is_null() {
return Err(LxError::EINVAL);
}
let socket = proc.get_socket(fd.into())?;
let remote_endpoint = socket.lock().remote_endpoint().ok_or(LxError::EINVAL)?;
let sockaddr_in = SockAddr::from(remote_endpoint);
sockaddr_in.write_to(addr, addr_len)?;
Ok(0)
}
}

View File

@ -0,0 +1,107 @@
import serial
import os
import sys
import re
import time
import threading
import subprocess
BASE = 'linux/'
CHECK_FILE = BASE + 'baremetal-test-ones.txt'
OUTPUT_FILE = BASE + 'stdout-zcore'
OUTPUT_NET = BASE + 'netout-zcore'
TMP_FILE = BASE + 'tmp-zcore'
TIMEOUT = 60
FAILED = ["failed","ERROR","panicked"]
passed = set()
failed = set()
timeout = set()
def rcv_data():
while True:
rcv=serial.readline()
rcv=rcv.decode()
print(rcv)
with open(OUTPUT_FILE, 'a') as f: print(rcv, file=f)
with open(TMP_FILE, 'a') as f: print(rcv, file=f)
if __name__=='__main__':
# port_list = list(serial.tools.list_ports.comports())
# k=0
# for i in port_list:
# print(i,k)
# k=k+1
#
# if len(port_list) <= 0:
# print("not find serial")
# sys.exit()
#
# serial_k=input("please switch serial:")
# k = int(serial_k)
# serial_list = list(port_list[k])
# serialName = serial_list[0]
# serialName = input("please input serial dev : ")
serialName = "/dev/ttyUSB0"
serial=serial.Serial(serialName,115200,timeout=3600)
if not serial.isOpen():
print("open failed >",serial.name)
with open(OUTPUT_FILE, 'w') as f: print("open failed >", serial.name, file=f)
sys.exit()
print("open succeed >",serial.name)
with open(OUTPUT_FILE, 'w') as f: print("open succeed >", serial.name, file=f)
th=threading.Thread(target=rcv_data)
th.setDaemon(True)
th.start()
with open(CHECK_FILE, 'r') as f:
allow_files = set([case.strip() for case in f.readlines()])
for cmd in allow_files:
with open(TMP_FILE, 'w') as f: print("", file=f)
basename = os.path.basename(cmd)
cmd = cmd + '\n'
serial.write(cmd.encode())
start_time = time.time()
while True:
with open(TMP_FILE, 'r') as f: output = f.read()
if re.search(r"/ # [\r\n]", output):
time.sleep(1)
break_out_flag = False
for pattern in FAILED:
if re.search(pattern, output):
break_out_flag = True
failed.add(cmd)
os.rename(TMP_FILE, BASE+"failed-"+basename)
break
if not break_out_flag:
passed.add(cmd)
os.rename(TMP_FILE, BASE+"passed-"+basename)
break
if time.time() - start_time > TIMEOUT:
break_out_flag = False
for pattern in FAILED:
if re.search(pattern, output):
break_out_flag = True
failed.add(cmd)
os.rename(TMP_FILE, BASE+"failed-"+basename)
break
if not break_out_flag:
timeout.add(cmd)
os.rename(TMP_FILE, BASE+"timeout-"+basename)
break
print("=======================================")
print("PASSED num: ", len(passed))
print("=======================================")
print("FAILED num: ", len(failed))
if len(failed) > 0: print(failed)
print("=======================================")
print("TIMEOUT num: ", len(timeout))
if len(timeout) > 0: print(timeout)
print("=======================================")
print("Total tested num: ", len(allow_files))
print("=======================================")

View File

@ -0,0 +1,103 @@
import serial
import os
import sys
import re
import time
import threading
import subprocess
BASE = 'linux/'
CHECK_FILE = BASE + 'baremetal-test-ones.txt'
OUTPUT_FILE = BASE + 'stdout-zcore'
OUTPUT_NET = BASE + 'netout-zcore'
TMP_FILE = BASE + 'tmp-zcore'
TIMEOUT = 60
FAILED = ["failed","ERROR","panicked"]
passed = set()
failed = set()
timeout = set()
def rcv_data():
while True:
rcv=serial.readline()
rcv=rcv.decode()
#print(rcv)
with open(OUTPUT_FILE, 'a') as f: print(rcv, file=f)
with open(TMP_FILE, 'a') as f: print(rcv, file=f)
def rcv_netdata():
print("in rcv_netdata")
with open(OUTPUT_NET, 'w') as f:
subprocess.run(['tcpdump -en#XXvv'], shell=True, stdout=f)
def net_test():
print("in net_test")
# ICMP
subprocess.run(['ping 192.168.0.123 -c 4'], shell=True)
start_time = time.time()
with open(OUTPUT_NET, 'r') as f: output = f.read()
if re.search("ICMP", output): passed.add("nettest : ping")
else: failed.add("nettest : ping")
# TCP
try: subprocess.run(['nc -v 192.168.0.123 80'], shell=True, timeout=5)
except Exception: pass
start_time = time.time()
with open(OUTPUT_NET, 'r') as f: output = f.read()
if re.search("Hello! zCore", output): passed.add("nettest : tcp")
if time.time() - start_time > 10: timeout.add("nettest : tcp")
# UDP
try: subprocess.run(['nc -uv 192.168.0.123 6969'], shell=True, timeout=5)
except Exception: pass
start_time = time.time()
with open(OUTPUT_NET, 'r') as f: output = f.read()
if re.search("from", output): passed.add("nettest : udp")
if time.time() - start_time > 10: timeout.add("nettest : udp")
if __name__=='__main__':
# port_list = list(serial.tools.list_ports.comports())
# k=0
# for i in port_list:
# print(i,k)
# k=k+1
#
# if len(port_list) <= 0:
# print("not find serial")
# sys.exit()
#
# serial_k=input("please switch serial:")
# k = int(serial_k)
# serial_list = list(port_list[k])
# serialName = serial_list[0]
serialName = input("please input serial dev : ")
serial=serial.Serial(serialName,115200,timeout=3600)
if not serial.isOpen():
print("open failed >",serial.name)
with open(OUTPUT_FILE, 'w') as f: print("open failed >", serial.name, file=f)
sys.exit()
print("open succeed >",serial.name)
with open(OUTPUT_FILE, 'w') as f: print("open succeed >", serial.name, file=f)
th=threading.Thread(target=rcv_data)
th.setDaemon(True)
th.start()
nd = threading.Thread(target=rcv_netdata)
nd.setDaemon(True)
nd.start()
net_test()
print("=======================================")
print("PASSED num: ", len(passed))
print("=======================================")
print("FAILED num: ", len(failed))
if len(failed) > 0: print(failed)
print("=======================================")
print("TIMEOUT num: ", len(timeout))
if len(timeout) > 0: print(timeout)
print("=======================================")
print("Total tested num: 3")
print("=======================================")

View File

@ -0,0 +1,7 @@
/libc-test/functional/utime-static.exe
/libc-test/functional/fscanf-static.exe
/libc-test/functional/stat-static.exe
/libc-test/functional/fdopen-static.exe
/libc-test/functional/fwscanf-static.exe
/libc-test/functional/ungetc-static.exe
/libc-test/functional/socket-static.exe

View File

@ -0,0 +1,20 @@
/libc-test/functional/time-static.exe
/libc-test/functional/mbc-static.exe
/libc-test/functional/string-static.exe
/libc-test/functional/string_memcpy-static.exe
/libc-test/functional/qsort-static.exe
/libc-test/functional/iconv_open-static.exe
/libc-test/functional/string_memset-static.exe
/libc-test/functional/strtof-static.exe
/libc-test/functional/strtod_simple-static.exe
/libc-test/functional/strtod-static.exe
/libc-test/functional/strtold-static.exe
/libc-test/functional/memstream-static.exe
/libc-test/functional/string_memmem-static.exe
/libc-test/functional/string_strstr-static.exe
/libc-test/functional/strftime-static.exe
/libc-test/functional/search_insque-static.exe
/libc-test/functional/search_hsearch-static.exe
/libc-test/functional/search_lsearch-static.exe
/libc-test/functional/wcsstr-static.exe
/libc-test/functional/search_tsearch-static.exe

View File

@ -0,0 +1,11 @@
/libc-test/functional/string_strchr-static.exe
/libc-test/functional/crypt-static.exe
/libc-test/functional/string_strcspn-static.exe
/libc-test/functional/swprintf-static.exe
/libc-test/functional/random-static.exe
/libc-test/functional/env-static.exe
/libc-test/functional/fnmatch-static.exe
/libc-test/functional/argv-static.exe
/libc-test/functional/setjmp-static.exe
/libc-test/functional/dirname-static.exe
/libc-test/functional/basename-static.exe

View File

@ -0,0 +1,9 @@
/libc-test/functional/snprintf-static.exe
/libc-test/functional/sscanf_long-static.exe
/libc-test/functional/strtol-static.exe
/libc-test/functional/wcstol-static.exe
/libc-test/functional/clock_gettime-static.exe
/libc-test/functional/udiv-static.exe
/libc-test/functional/tls_align-static.exe
/libc-test/functional/inet_pton-static.exe
/libc-test/functional/sscanf-static.exe

View File

@ -15,6 +15,9 @@ zircon = ["zircon-loader"]
linux = ["linux-loader", "linux-object", "rcore-fs-sfs"]
#hypervisor = ["rvm", "zircon", "zircon-object/hypervisor", "zircon-syscall/hypervisor"]
loopback = ["kernel-hal-bare/loopback"]
rtl8x = ["kernel-hal-bare/rtl8x"]
[profile.release]
lto = true

View File

@ -9,6 +9,7 @@ user ?=
hypervisor ?=
smp ?= 1
test_filter ?= *.*
loopback= ?= 0
build_args := -Z build-std=core,alloc --target $(arch).json
build_path := target/$(arch)/$(mode)
@ -31,7 +32,7 @@ ifeq ($(arch), riscv64)
ifeq ($(board), d1)
build_args += --features board_d1 --features link_user_img
else
build_args += --features board_qemu --features link_user_img
build_args += --features board_qemu
endif
endif
@ -45,9 +46,17 @@ else
build_args += --features zircon
endif
ifeq ($(loopback), 1)
build_args += --features loopback
else
build_args += --features rtl8x
endif
qemu_opts := \
-smp $(smp)
qemu_net_opts :=
ifeq ($(arch), x86_64)
qemu_opts += \
-machine q35 \
@ -82,6 +91,10 @@ qemu_opts += \
-device virtio-blk-device,drive=sfs \
-kernel $(kernel_bin)
qemu_net_opts += \
-netdev type=tap,id=net0,script=no,downscript=no \
-device virtio-net-device,netdev=net0
endif
ifeq ($(hypervisor), 1)
@ -97,6 +110,11 @@ qemu_opts += -accel kvm -cpu host,migratable=no,+invtsc
endif
endif
ifeq ($(net), on)
qemu_opts += $(qemu_net_opts)
qemu := sudo $(qemu)
endif
ifeq ($(graphic), on)
build_args += --features graphic
ifeq ($(arch), riscv64)
@ -140,8 +158,8 @@ $(kernel_img): $(kernel_bin)
ifeq ($(board), d1)
run-thead: build
@cp ../prebuilt/firmware/fw_jump-0x40020000.bin fw-zCore.bin
@dd if=$(kernel_bin) of=fw-zCore.bin bs=1 seek=131072
cp ../prebuilt/firmware/fw_jump-0x40020000.bin fw-zCore.bin
dd if=$(kernel_bin) of=fw-zCore.bin bs=1 seek=131072 status=progress
xfel ddr ddr3
xfel write 0x40000000 fw-zCore.bin
xfel exec 0x40000000

View File

@ -7,15 +7,21 @@ fn main() {
let board = std::env::var("BOARD").unwrap();
let kernel_base_addr: u64 = if board.contains("d1") {
0xffffffffc0020000
} else if board.contains("qemu") {
// opensbi仍旧把kernel放在0x80200000物理内存中
0xffffffff80200000
// } else if board.contains("qemu") {
} else {
// opensbi仍旧把kernel放在0x80200000物理内存中
// 0xffffffff80200000
// } else {
0xffffffff80200000
};
let mut fout = std::fs::File::create("src/arch/riscv/boot/kernel-vars.ld").unwrap();
writeln!(fout, "/* Generated by build.rs. DO NOT EDIT. */").unwrap();
writeln!(fout, "PROVIDE_HIDDEN(BASE_ADDRESS = {:#x});", kernel_base_addr).unwrap();
writeln!(
fout,
"PROVIDE_HIDDEN(BASE_ADDRESS = {:#x});",
kernel_base_addr
)
.unwrap();
}
}

View File

@ -7,4 +7,3 @@ pub use self::x86_64::*;
pub mod riscv;
#[cfg(target_arch = "riscv64")]
pub use self::riscv::*;

View File

@ -0,0 +1,2 @@
/* Generated by build.rs. DO NOT EDIT. */
PROVIDE_HIDDEN(BASE_ADDRESS = 0xffffffffc0020000);

View File

@ -1,7 +1,7 @@
use alloc::sync::Arc;
use rcore_fs::vfs::FileSystem;
use kernel_hal_bare::drivers::{BlockDriverWrapper, BLK_DRIVERS};
use linux_object::fs::MemBuf;
use kernel_hal_bare::drivers::virtio::{BlockDriverWrapper, BLK_DRIVERS};
use rcore_fs::vfs::FileSystem;
pub fn init_filesystem(ramfs_data: &'static mut [u8]) -> Arc<dyn FileSystem> {
#[cfg(target_arch = "x86_64")]
@ -9,7 +9,7 @@ pub fn init_filesystem(ramfs_data: &'static mut [u8]) -> Arc<dyn FileSystem> {
#[cfg(feature = "link_user_img")]
let ramfs_data = unsafe {
extern {
extern "C" {
fn _user_img_start();
fn _user_img_end();
}
@ -23,7 +23,7 @@ pub fn init_filesystem(ramfs_data: &'static mut [u8]) -> Arc<dyn FileSystem> {
#[cfg(feature = "link_user_img")]
let device = Arc::new(MemBuf::new(ramfs_data));
#[cfg(all(target_arch="riscv64", not(feature="link_user_img")))]
#[cfg(all(target_arch = "riscv64", not(feature = "link_user_img")))]
let device = {
let driver = BlockDriverWrapper(
BLK_DRIVERS
@ -45,6 +45,7 @@ pub fn init_filesystem(ramfs_data: &'static mut [u8]) -> Arc<dyn FileSystem> {
}
// Hard link rootfs img
// 原生字符串: r#"hello"#
#[cfg(feature = "link_user_img")]
global_asm!(concat!(
r#"

View File

@ -21,8 +21,8 @@ extern crate rlibc_opt; //Only for x86_64
#[macro_use]
mod logging;
mod lang;
mod arch;
mod lang;
mod memory;
#[cfg(feature = "linux")]
@ -33,16 +33,16 @@ use rboot::BootInfo;
#[cfg(target_arch = "riscv64")]
use kernel_hal_bare::{
phys_to_virt, remap_the_kernel,
drivers::virtio::{GPU_DRIVERS, CMDLINE},
BootInfo, GraphicInfo,
drivers::{CMDLINE, GPU_DRIVERS},
phys_to_virt, remap_the_kernel, BootInfo, GraphicInfo,
};
use alloc::{
format,vec,
vec::Vec,
boxed::Box,
format,
string::{String, ToString},
vec,
vec::Vec,
};
#[cfg(feature = "board_qemu")]
@ -99,7 +99,10 @@ fn main(ramfs_data: &[u8], cmdline: &str) -> ! {
#[cfg(target_arch = "riscv64")]
#[no_mangle]
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
println!("zCore rust_main( hartid: {}, device_tree_paddr: {:#x} )", hartid, device_tree_paddr);
println!(
"zCore rust_main( hartid: {}, device_tree_paddr: {:#x} )",
hartid, device_tree_paddr
);
let device_tree_vaddr = phys_to_virt(device_tree_paddr);
let boot_info = BootInfo {
@ -198,6 +201,13 @@ fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! {
let rootfs = fs::init_filesystem(ramfs_data);
let _proc = linux_loader::run(args, envs, rootfs);
info!("linux_loader run linux proc +++");
linux_loader::net_start_thread();
/* 用户程序无法访问内核的代码??? 页表USER
linux_loader::run_linux_proc(vec!["run_linux_proc".into()], server as usize);
*/
info!("linux_loader is complete");
run();

View File

@ -1,8 +1,8 @@
//! Define the FrameAllocator for physical memory
//! x86_64 -- 64GB
use {bitmap_allocator::BitAlloc, buddy_system_allocator::LockedHeap, spin::Mutex};
use crate::arch::consts::*;
use {bitmap_allocator::BitAlloc, buddy_system_allocator::LockedHeap, spin::Mutex};
#[cfg(target_arch = "x86_64")]
use {