From 71336aca5c4792a90aa2e969f8ae4fdaaeebfe8f Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 28 Feb 2019 12:31:10 +0800 Subject: [PATCH] Redesign NetDriver trait and update drivers --- kernel/src/backtrace.rs | 2 +- kernel/src/drivers/block/virtio_blk.rs | 5 +-- kernel/src/drivers/bus/pci.rs | 8 ++--- kernel/src/drivers/bus/virtio_mmio.rs | 1 - kernel/src/drivers/gpu/virtio_gpu.rs | 1 - kernel/src/drivers/mod.rs | 5 ++- kernel/src/drivers/net/e1000.rs | 50 ++++++++++++++++++++------ kernel/src/drivers/net/virtio_net.rs | 6 ++-- kernel/src/fs/mod.rs | 1 - kernel/src/net/test.rs | 32 ++++------------- kernel/src/process/structs.rs | 6 ++++ kernel/src/syscall/fs.rs | 2 +- kernel/src/syscall/mod.rs | 4 ++- kernel/src/syscall/net.rs | 29 +++++++++++++++ 14 files changed, 98 insertions(+), 54 deletions(-) create mode 100644 kernel/src/syscall/net.rs diff --git a/kernel/src/backtrace.rs b/kernel/src/backtrace.rs index 3d56916..a10c070 100644 --- a/kernel/src/backtrace.rs +++ b/kernel/src/backtrace.rs @@ -72,7 +72,7 @@ pub fn backtrace() { // Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) // size = 512 pages current_fp = *(current_fp as *const usize).offset(0); - if (current_fp >= 0x0000_57ac_0000_0000 + 512 * PAGE_SIZE - size_of::()) { + if current_fp >= 0x0000_57ac_0000_0000 + 512 * PAGE_SIZE - size_of::() { break; } current_pc = *(current_fp as *const usize).offset(1); diff --git a/kernel/src/drivers/block/virtio_blk.rs b/kernel/src/drivers/block/virtio_blk.rs index 4cebfdc..d05e62a 100644 --- a/kernel/src/drivers/block/virtio_blk.rs +++ b/kernel/src/drivers/block/virtio_blk.rs @@ -1,9 +1,7 @@ use alloc::prelude::*; use alloc::sync::Arc; -use alloc::vec; use core::cmp::min; -use core::fmt; -use core::mem::{size_of, zeroed}; +use core::mem::{size_of}; use core::slice; use bitflags::*; @@ -16,7 +14,6 @@ use volatile::Volatile; use rcore_fs::dev::BlockDevice; -use crate::arch::cpu; use crate::memory::active_table; use crate::sync::SpinNoIrqLock as Mutex; diff --git a/kernel/src/drivers/bus/pci.rs b/kernel/src/drivers/bus/pci.rs index 2c6a266..f6fd456 100644 --- a/kernel/src/drivers/bus/pci.rs +++ b/kernel/src/drivers/bus/pci.rs @@ -1,6 +1,4 @@ use crate::drivers::net::e1000; -use crate::logging::*; -use core::slice; use x86_64::instructions::port::Port; const VENDOR: u32 = 0x00; @@ -67,7 +65,7 @@ impl PciTag { pci_addr.write(0); let ret = d >> (rsh * 8); - let m = if (width < 4) { + let m = if width < 4 { (1 << (8 * width)) - 1 } else { 0xffffffff @@ -109,13 +107,13 @@ impl PciTag { base = base & PCI_BASE_ADDRESS_MEM_MASK; max_base = max_base & PCI_BASE_ADDRESS_MEM_MASK; - if (max_base == 0) { + if max_base == 0 { return None; } // linux/drivers/pci/probe.c pci_size let mut size = PCI_BASE_ADDRESS_MEM_MASK & max_base; - if (size == 0) { + if size == 0 { return None; } size = (size & !(size - 1)) - 1; diff --git a/kernel/src/drivers/bus/virtio_mmio.rs b/kernel/src/drivers/bus/virtio_mmio.rs index eb7e555..a423bee 100644 --- a/kernel/src/drivers/bus/virtio_mmio.rs +++ b/kernel/src/drivers/bus/virtio_mmio.rs @@ -12,7 +12,6 @@ use rcore_memory::PAGE_SIZE; use rcore_memory::paging::PageTable; use volatile::{ReadOnly, Volatile, WriteOnly}; -use crate::arch::memory; use crate::HEAP_ALLOCATOR; use crate::memory::active_table; use crate::arch::consts::{KERNEL_OFFSET, MEMORY_OFFSET}; diff --git a/kernel/src/drivers/gpu/virtio_gpu.rs b/kernel/src/drivers/gpu/virtio_gpu.rs index 104cf9c..83938d8 100644 --- a/kernel/src/drivers/gpu/virtio_gpu.rs +++ b/kernel/src/drivers/gpu/virtio_gpu.rs @@ -1,6 +1,5 @@ use alloc::alloc::{GlobalAlloc, Layout}; use alloc::prelude::*; -use core::mem::size_of; use core::slice; use bitflags::*; diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index 232183e..ff0500b 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -3,6 +3,7 @@ use core::any::Any; use lazy_static::lazy_static; use smoltcp::wire::EthernetAddress; +use smoltcp::socket::SocketSet; use crate::sync::SpinNoIrqLock; @@ -29,12 +30,14 @@ pub trait Driver : Send + AsAny { fn device_type(&self) -> DeviceType; } -pub trait NetDriver: Driver { +pub trait NetDriver : Send { // get mac address for this device fn get_mac(&self) -> EthernetAddress; // get interface name for this device fn get_ifname(&self) -> String; + + fn poll(&mut self, socket: &mut SocketSet) -> Option; } // little hack, see https://users.rust-lang.org/t/how-to-downcast-from-a-trait-any-to-a-struct/11219/3 diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index d570f3d..d7cb399 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -6,10 +6,7 @@ use core::mem::size_of; use core::slice; use core::sync::atomic::{fence, Ordering}; -use crate::arch::consts::{KERNEL_OFFSET, MEMORY_OFFSET}; use bitflags::*; -use device_tree::util::SliceRead; -use device_tree::Node; use log::*; use rcore_memory::paging::PageTable; use rcore_memory::PAGE_SIZE; @@ -17,14 +14,17 @@ use smoltcp::phy::{self, DeviceCapabilities}; use smoltcp::time::Instant; use smoltcp::wire::EthernetAddress; use smoltcp::Result; -use volatile::{ReadOnly, Volatile}; +use smoltcp::wire::*; +use smoltcp::iface::*; +use smoltcp::socket::*; +use alloc::collections::BTreeMap; +use volatile::{Volatile}; -use crate::arch::cpu; use crate::memory::active_table; use crate::sync::SpinNoIrqLock as Mutex; use crate::HEAP_ALLOCATOR; -use super::super::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS}; +use super::super::{DeviceType, Driver, NetDriver, NET_DRIVERS}; pub struct E1000 { header: usize, @@ -56,6 +56,10 @@ const E1000_MTA: usize = 0x5200 / 4; const E1000_RAL: usize = 0x5400 / 4; const E1000_RAH: usize = 0x5404 / 4; +pub struct E1000Interface { + iface: EthernetInterface<'static, 'static, 'static, E1000Driver> +} + #[derive(Clone)] pub struct E1000Driver(Arc>); @@ -118,14 +122,27 @@ impl E1000 { } } -impl NetDriver for E1000Driver { +impl NetDriver for E1000Interface { fn get_mac(&self) -> EthernetAddress { - self.0.lock().mac + self.iface.ethernet_addr() } fn get_ifname(&self) -> String { format!("e1000") } + + fn poll(&mut self, sockets: &mut SocketSet) -> Option { + let timestamp = Instant::from_millis(unsafe { crate::trap::TICK as i64 }); + match self.iface.poll(sockets, timestamp) { + Ok(update) => { + Some(update) + } + Err(err) => { + debug!("poll got err {}", err); + None + } + } + } } #[repr(C)] @@ -407,6 +424,19 @@ pub fn e1000_init(header: usize, size: usize) { let net_driver = E1000Driver(Arc::new(Mutex::new(driver))); - DRIVERS.lock().push(Box::new(net_driver.clone())); - NET_DRIVERS.lock().push(Box::new(net_driver)); + let ethernet_addr = EthernetAddress::from_bytes(&mac); + let ip_addrs = [IpCidr::new(IpAddress::v4(10,0,0,2), 24)]; + let neighbor_cache = NeighborCache::new(BTreeMap::new()); + let iface = EthernetInterfaceBuilder::new(net_driver) + .ethernet_addr(ethernet_addr) + .ip_addrs(ip_addrs) + .neighbor_cache(neighbor_cache) + .finalize(); + + let e1000_iface = E1000Interface { + iface, + }; + + //DRIVERS.lock().push(Box::new(net_driver.clone())); + NET_DRIVERS.lock().push(Box::new(e1000_iface)); } diff --git a/kernel/src/drivers/net/virtio_net.rs b/kernel/src/drivers/net/virtio_net.rs index 0e1e765..8ec7104 100644 --- a/kernel/src/drivers/net/virtio_net.rs +++ b/kernel/src/drivers/net/virtio_net.rs @@ -4,7 +4,6 @@ use alloc::prelude::*; use alloc::sync::Arc; use core::mem::size_of; use core::slice; -use core::sync::atomic::{fence, Ordering}; use bitflags::*; use device_tree::Node; @@ -16,9 +15,9 @@ use smoltcp::phy::{self, DeviceCapabilities}; use smoltcp::Result; use smoltcp::time::Instant; use smoltcp::wire::EthernetAddress; +use smoltcp::socket::SocketSet; use volatile::{ReadOnly, Volatile}; -use crate::arch::cpu; use crate::HEAP_ALLOCATOR; use crate::memory::active_table; use crate::sync::SpinNoIrqLock as Mutex; @@ -86,6 +85,9 @@ impl NetDriver for VirtIONetDriver { format!("virtio{}", self.0.lock().interrupt) } + fn poll(&mut self, sockets: &mut SocketSet) -> Option { + unimplemented!() + } } pub struct VirtIONetRxToken(VirtIONetDriver); diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index dc18fd9..1d06536 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -7,7 +7,6 @@ use rcore_fs_sfs::SimpleFileSystem; #[cfg(target_arch = "x86_64")] use crate::arch::driver::ide; -use crate::drivers::{self, AsAny}; use crate::drivers::block::virtio_blk::VirtIOBlkDriver; pub use self::file::*; diff --git a/kernel/src/net/test.rs b/kernel/src/net/test.rs index 4bf2d28..ec7842f 100644 --- a/kernel/src/net/test.rs +++ b/kernel/src/net/test.rs @@ -1,14 +1,8 @@ use crate::thread; use crate::drivers::NET_DRIVERS; -use smoltcp::wire::*; -use smoltcp::iface::*; use smoltcp::socket::*; -use alloc::collections::BTreeMap; use crate::drivers::NetDriver; -use crate::drivers::net::virtio_net::VirtIONetDriver; -use crate::drivers::net::e1000::E1000Driver; use alloc::vec; -use smoltcp::time::Instant; use core::fmt::Write; pub extern fn server(_arg: usize) -> ! { @@ -18,20 +12,6 @@ pub extern fn server(_arg: usize) -> ! { } } - let driver = { - let ref_driver = &mut *NET_DRIVERS.lock()[0]; - // TODO: support multiple net drivers here - ref_driver.as_any().downcast_ref::().unwrap().clone() - }; - let ethernet_addr = driver.get_mac(); - let ip_addrs = [IpCidr::new(IpAddress::v4(10,0,0,2), 24)]; - let neighbor_cache = NeighborCache::new(BTreeMap::new()); - let mut iface = EthernetInterfaceBuilder::new(driver.clone()) - .ethernet_addr(ethernet_addr) - .ip_addrs(ip_addrs) - .neighbor_cache(neighbor_cache) - .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); @@ -51,15 +31,15 @@ pub extern fn server(_arg: usize) -> ! { loop { { - let timestamp = Instant::from_millis(unsafe { crate::trap::TICK as i64 }); - match iface.poll(&mut sockets, timestamp) { - Ok(event) => { - if (!event) { + let iface = &mut *NET_DRIVERS.lock()[0]; + match iface.poll(&mut sockets) { + Some(event) => { + if !event { continue; } }, - Err(e) => { - println!("poll error: {}", e); + None => { + continue } } diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 6bfd400..ff43a47 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -172,6 +172,12 @@ impl Thread { } } +impl Process { + pub fn get_free_inode(&self) -> usize { + (0..).find(|i| !self.files.contains_key(i)).unwrap() + } +} + /// Generate a MemorySet according to the ELF file. /// Also return the real entry point address. diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 92f8cdf..07c82eb 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -89,7 +89,7 @@ pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { } }; - let fd = (3..).find(|i| !proc.files.contains_key(i)).unwrap(); + let fd = proc.get_free_inode(); let file = FileHandle::new(inode, flags.to_options()); proc.files.insert(fd, file); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 9145fde..91b9452 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -18,12 +18,14 @@ use self::mem::*; use self::proc::*; use self::time::*; use self::ctrl::*; +use self::net::*; mod fs; mod mem; mod proc; mod time; mod ctrl; +mod net; /// System call dispatcher pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { @@ -48,7 +50,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { 035 => sys_sleep(args[0]), // TODO: nanosleep 039 => sys_getpid(), // 040 => sys_getppid(), -// 041 => sys_socket(), + 041 => sys_socket(args[0], args[1], args[2]), // 042 => sys_connect(), // 043 => sys_accept(), // 044 => sys_sendto(), diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs new file mode 100644 index 0000000..7620b58 --- /dev/null +++ b/kernel/src/syscall/net.rs @@ -0,0 +1,29 @@ +//! Syscalls for networking + +use super::*; + +const AF_INET: usize = 2; + +const SOCK_STREAM: usize = 1; + +pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResult { + info!("socket: domain: {}, socket_type: {:?}, protocol: {:#x}", domain, socket_type, protocol); + let mut proc = process(); + match domain { + AF_INET => { + return match socket_type { + SOCK_STREAM => { + let fd = proc.get_free_inode(); + + Ok(fd as isize) + } + _ => { + Err(SysError::Inval) + } + } + } + _ => { + return Err(SysError::Inval); + } + } +} \ No newline at end of file