forked from rcore-os/zCore
Compare commits
27 Commits
master
...
net-testin
| Author | SHA1 | Date |
|---|---|---|
|
|
2c903512c8 | |
|
|
ae8450f87c | |
|
|
ec695dcac8 | |
|
|
59181a89f0 | |
|
|
475a335d7b | |
|
|
a7a26829ac | |
|
|
6ea8243554 | |
|
|
fb13d4078f | |
|
|
5d8ce43ca1 | |
|
|
348094a644 | |
|
|
c7a4652230 | |
|
|
bb99eefe7e | |
|
|
133e2c75ef | |
|
|
4b1123686a | |
|
|
953b8d58f4 | |
|
|
67b6796757 | |
|
|
535b41e70a | |
|
|
1110f894a1 | |
|
|
011a87a003 | |
|
|
99980683e0 | |
|
|
a3df5ddb69 | |
|
|
c5d829bc32 | |
|
|
1990915537 | |
|
|
a9d85db871 | |
|
|
1ba370de72 | |
|
|
9d0fb90eb9 | |
|
|
9757df80ae |
|
|
@ -17,4 +17,5 @@ stdout-zcore
|
|||
scripts/script.sh
|
||||
stdout-baremetal-test-rv64
|
||||
stdout-rv64
|
||||
zCore/fw-zCore.bin
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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>);
|
||||
}
|
||||
|
|
@ -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) }
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
pub mod e1000;
|
||||
pub mod ixgbe;
|
||||
pub mod rtl8x;
|
||||
pub mod virtio_net;
|
||||
|
||||
pub mod realtek;
|
||||
|
||||
pub mod loopback;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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();
|
||||
}
|
||||
*/
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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"]
|
||||
*
|
||||
* 在底层再实现一遍该trait,并替代以上的struct的函数
|
||||
*/
|
||||
|
||||
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
|
||||
// }
|
||||
// }
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"] }
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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 Ok(size)");
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
// }
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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("=======================================")
|
||||
|
|
@ -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("=======================================")
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,3 @@ pub use self::x86_64::*;
|
|||
pub mod riscv;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use self::riscv::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
/* Generated by build.rs. DO NOT EDIT. */
|
||||
PROVIDE_HIDDEN(BASE_ADDRESS = 0xffffffffc0020000);
|
||||
|
|
@ -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#"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue