1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-26 01:43:29 +04:00

Move socket set to iface, redesign NetDriver trait and implement blocking net syscalls

This commit is contained in:
Jiajie Chen 2019-03-04 15:34:02 +08:00
parent 738554386b
commit 1a1e39c960
10 changed files with 227 additions and 117 deletions

View File

@ -71,7 +71,7 @@ qemu_opts += \
-serial mon:stdio \ -serial mon:stdio \
-device isa-debug-exit -device isa-debug-exit
qemu_net_opts += \ qemu_net_opts += \
-device e1000,netdev=net0 -device e1000e,netdev=net0
else ifeq ($(arch), riscv32) else ifeq ($(arch), riscv32)
qemu_opts += \ qemu_opts += \

View File

@ -67,6 +67,7 @@
use super::consts::*; use super::consts::*;
use super::TrapFrame; use super::TrapFrame;
use log::*; use log::*;
use crate::drivers::DRIVERS;
global_asm!(include_str!("trap.asm")); global_asm!(include_str!("trap.asm"));
global_asm!(include_str!("vector.asm")); global_asm!(include_str!("vector.asm"));
@ -89,7 +90,16 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
COM1 => com1(), COM1 => com1(),
COM2 => com2(), COM2 => com2(),
IDE => ide(), IDE => ide(),
_ => panic!("Invalid IRQ number: {}", irq), _ => {
let mut drivers = DRIVERS.lock();
for driver in drivers.iter_mut() {
if driver.try_handle_interrupt() == true {
debug!("driver processed interrupt");
return;
}
}
warn!("unhandled external IRQ number: {}", irq);
},
} }
} }
SwitchToKernel => to_kernel(tf), SwitchToKernel => to_kernel(tf),

View File

@ -1,14 +1,25 @@
use crate::drivers::net::e1000; use crate::drivers::net::e1000;
use x86_64::instructions::port::Port; use x86_64::instructions::port::Port;
const VENDOR: u32 = 0x00; const PCI_VENDOR: u32 = 0x00;
const DEVICE: u32 = 0x02; const PCI_DEVICE: u32 = 0x02;
const COMMAND: u32 = 0x04; const PCI_COMMAND: u32 = 0x04;
const STATUS: u32 = 0x06; const PCI_STATUS: u32 = 0x06;
const SUBCLASS: u32 = 0x0a; const PCI_SUBCLASS: u32 = 0x0a;
const CLASS: u32 = 0x0b; const PCI_CLASS: u32 = 0x0b;
const HEADER: u32 = 0x0e; const PCI_HEADER: u32 = 0x0e;
const BAR0: u32 = 0x10; const PCI_BAR0: u32 = 0x10; // first
const PCI_BAR5: u32 = 0x24; // last
const PCI_CAP_PTR: u32 = 0x34;
const PCI_INTERRUPT_LINE: u32 = 0x3c;
const PCI_INTERRUPT_PIN: u32 = 0x3d;
const PCI_MSI_CTRL_CAP: u32 = 0x00;
const PCI_MSI_ADDR: u32 = 0x04;
const PCI_MSI_UPPER_ADDR: u32 = 0x08;
const PCI_MSI_DATA: u32 = 0x0C;
const PCI_CAP_ID_MSI: u32 = 0x05;
const PCI_ADDR_PORT: u16 = 0xcf8; const PCI_ADDR_PORT: u16 = 0xcf8;
const PCI_DATA_PORT: u16 = 0xcfc; const PCI_DATA_PORT: u16 = 0xcfc;
@ -93,7 +104,7 @@ impl PciTag {
// return (addr, len) // return (addr, len)
pub unsafe fn get_bar_mem(&self, bar_number: u32) -> Option<(usize, usize)> { pub unsafe fn get_bar_mem(&self, bar_number: u32) -> Option<(usize, usize)> {
assert!(bar_number <= 4); assert!(bar_number <= 4);
let bar = BAR0 + 4 * bar_number; let bar = PCI_BAR0 + 4 * bar_number;
let mut base = self.read(bar, 4); let mut base = self.read(bar, 4);
self.write(bar, 0xffffffff); self.write(bar, 0xffffffff);
let mut max_base = self.read(bar, 4); let mut max_base = self.read(bar, 4);
@ -129,14 +140,14 @@ impl PciTag {
// returns a tuple of (vid, did, next) // returns a tuple of (vid, did, next)
pub fn probe(&self) -> Option<(u32, u32, bool)> { pub fn probe(&self) -> Option<(u32, u32, bool)> {
unsafe { unsafe {
let v = self.read(VENDOR, 2); let v = self.read(PCI_VENDOR, 2);
if v == 0xffff { if v == 0xffff {
return None; return None;
} }
let d = self.read(DEVICE, 2); let d = self.read(PCI_DEVICE, 2);
let mf = self.read(HEADER, 1); let mf = self.read(PCI_HEADER, 1);
let cl = self.read(CLASS, 1); let cl = self.read(PCI_CLASS, 1);
let scl = self.read(SUBCLASS, 1); let scl = self.read(PCI_SUBCLASS, 1);
info!( info!(
"{}: {}: {}: {:#X} {:#X} ({} {})", "{}: {}: {}: {:#X} {:#X} ({} {})",
self.bus(), self.bus(),
@ -153,9 +164,29 @@ impl PciTag {
} }
pub unsafe fn enable(&self) { pub unsafe fn enable(&self) {
let orig = self.read(COMMAND, 2); let orig = self.read(PCI_COMMAND, 2);
// IO_ENABLE | MEM_ENABLE | MASTER_ENABLE // IO Space | MEM Space | Bus Mastering | Special Cycles | PCI Interrupt Disable
self.write(COMMAND, orig | 0xf); self.write(PCI_COMMAND, orig | 0x40f);
// find MSI cap
let mut cap_ptr = self.read(PCI_CAP_PTR, 1);
while cap_ptr > 0 {
let cap_id = self.read(cap_ptr, 1);
if cap_id == PCI_CAP_ID_MSI {
self.write(cap_ptr + PCI_MSI_ADDR, 0xfee << 20);
// irq 23 temporarily
self.write(cap_ptr + PCI_MSI_DATA, 55 | 0 << 12);
let orig_ctrl = self.read(cap_ptr + PCI_MSI_CTRL_CAP, 4);
debug!("orig ctrl {:b}", orig_ctrl);
self.write(cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
debug!("new ctrl {:b}", self.read(cap_ptr + PCI_MSI_CTRL_CAP, 2));
break;
}
info!("cap id {} at {:#X}", self.read(cap_ptr, 1), cap_ptr);
cap_ptr = self.read(cap_ptr + 1, 1);
}
} }
} }

View File

@ -5,7 +5,7 @@ use lazy_static::lazy_static;
use smoltcp::wire::{EthernetAddress, Ipv4Address}; use smoltcp::wire::{EthernetAddress, Ipv4Address};
use smoltcp::socket::SocketSet; use smoltcp::socket::SocketSet;
use crate::sync::SpinNoIrqLock; use crate::sync::{SpinNoIrqLock, Condvar, MutexGuard, SpinNoIrq};
mod device_tree; mod device_tree;
pub mod bus; pub mod bus;
@ -40,8 +40,11 @@ pub trait NetDriver : Send {
// get ipv4 address // get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address>; fn ipv4_address(&self) -> Option<Ipv4Address>;
// poll for sockets // get sockets
fn poll(&mut self, socket: &mut SocketSet) -> Option<bool>; fn sockets(&mut self) -> MutexGuard<SocketSet<'static, 'static, 'static>, SpinNoIrq>;
// manually trigger a poll, use it after sending packets
fn poll(&mut self);
} }
@ -53,6 +56,10 @@ lazy_static! {
pub static ref NET_DRIVERS: SpinNoIrqLock<Vec<Box<NetDriver>>> = SpinNoIrqLock::new(Vec::new()); pub static ref NET_DRIVERS: SpinNoIrqLock<Vec<Box<NetDriver>>> = SpinNoIrqLock::new(Vec::new());
} }
lazy_static! {
pub static ref SOCKET_ACTIVITY: Condvar = Condvar::new();
}
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
pub fn init(dtb: usize) { pub fn init(dtb: usize) {
device_tree::init(dtb); device_tree::init(dtb);

View File

@ -2,7 +2,7 @@ use alloc::alloc::{GlobalAlloc, Layout};
use alloc::format; use alloc::format;
use alloc::prelude::*; use alloc::prelude::*;
use alloc::sync::Arc; use alloc::sync::Arc;
use core::mem::size_of; use core::mem::{size_of, transmute};
use core::slice; use core::slice;
use core::sync::atomic::{fence, Ordering}; use core::sync::atomic::{fence, Ordering};
@ -22,9 +22,10 @@ use volatile::{Volatile};
use crate::memory::active_table; use crate::memory::active_table;
use crate::sync::SpinNoIrqLock as Mutex; use crate::sync::SpinNoIrqLock as Mutex;
use crate::sync::{MutexGuard, SpinNoIrq};
use crate::HEAP_ALLOCATOR; use crate::HEAP_ALLOCATOR;
use super::super::{DeviceType, Driver, NetDriver, NET_DRIVERS}; use super::super::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
pub struct E1000 { pub struct E1000 {
header: usize, header: usize,
@ -37,8 +38,13 @@ pub struct E1000 {
first_trans: bool, first_trans: bool,
} }
#[derive(Clone)]
pub struct E1000Driver(Arc<Mutex<E1000>>);
const E1000_STATUS: usize = 0x0008 / 4; const E1000_STATUS: usize = 0x0008 / 4;
const E1000_ICR: usize = 0x00C0 / 4;
const E1000_IMS: usize = 0x00D0 / 4; const E1000_IMS: usize = 0x00D0 / 4;
const E1000_IMC: usize = 0x00D8 / 4;
const E1000_RCTL: usize = 0x0100 / 4; const E1000_RCTL: usize = 0x0100 / 4;
const E1000_TCTL: usize = 0x0400 / 4; const E1000_TCTL: usize = 0x0400 / 4;
const E1000_TIPG: usize = 0x0410 / 4; const E1000_TIPG: usize = 0x0410 / 4;
@ -56,21 +62,50 @@ const E1000_MTA: usize = 0x5200 / 4;
const E1000_RAL: usize = 0x5400 / 4; const E1000_RAL: usize = 0x5400 / 4;
const E1000_RAH: usize = 0x5404 / 4; const E1000_RAH: usize = 0x5404 / 4;
#[derive(Clone)]
pub struct E1000Interface { pub struct E1000Interface {
iface: EthernetInterface<'static, 'static, 'static, E1000Driver> iface: Arc<Mutex<EthernetInterface<'static, 'static, 'static, E1000Driver>>>,
driver: E1000Driver,
sockets: Arc<Mutex<SocketSet<'static, 'static, 'static>>>,
} }
#[derive(Clone)] impl Driver for E1000Interface {
pub struct E1000Driver(Arc<Mutex<E1000>>);
impl Driver for E1000Driver {
fn try_handle_interrupt(&mut self) -> bool { fn try_handle_interrupt(&mut self) -> bool {
let driver = self.0.lock(); let irq = {
let driver = self.driver.0.lock();
let mut current_addr = driver.header;
while current_addr < driver.header + driver.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
// ensure header page is mapped let e1000 =
active_table().map_if_not_exists(driver.header, driver.size); unsafe { slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4) };
return false; let icr = e1000[E1000_ICR].read();
if icr != 0 {
// clear it
e1000[E1000_ICR].write(icr);
true
} else {
false
}
};
if irq {
let timestamp = Instant::from_millis(unsafe { crate::trap::TICK as i64 });
let mut sockets = self.sockets.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
Ok(_) => {
SOCKET_ACTIVITY.notify_all();
}
Err(err) => {
debug!("poll got err {}", err);
}
}
}
return irq;
} }
fn device_type(&self) -> DeviceType { fn device_type(&self) -> DeviceType {
@ -90,14 +125,13 @@ impl E1000 {
let e1000 = let e1000 =
unsafe { slice::from_raw_parts_mut(self.header as *mut Volatile<u32>, self.size / 4) }; unsafe { slice::from_raw_parts_mut(self.header as *mut Volatile<u32>, self.size / 4) };
let send_queue_size = PAGE_SIZE / size_of::<E1000SendDesc>(); let send_queue_size = PAGE_SIZE / size_of::<E1000SendDesc>();
let mut send_queue = unsafe { let send_queue = unsafe {
slice::from_raw_parts_mut(self.send_page as *mut E1000RecvDesc, send_queue_size) slice::from_raw_parts_mut(self.send_page as *mut E1000RecvDesc, send_queue_size)
}; };
let mut tdt = e1000[E1000_TDT].read(); let tdt = e1000[E1000_TDT].read();
let index = (tdt as usize + 1) % send_queue_size; let index = (tdt as usize) % send_queue_size;
let send_desc = &mut send_queue[index]; let send_desc = &mut send_queue[index];
// TODO: fix it
return self.first_trans || (*send_desc).status & 1 != 0; return self.first_trans || (*send_desc).status & 1 != 0;
} }
@ -124,29 +158,33 @@ impl E1000 {
impl NetDriver for E1000Interface { impl NetDriver for E1000Interface {
fn get_mac(&self) -> EthernetAddress { fn get_mac(&self) -> EthernetAddress {
self.iface.ethernet_addr() self.iface.lock().ethernet_addr()
} }
fn get_ifname(&self) -> String { fn get_ifname(&self) -> String {
format!("e1000") format!("e1000")
} }
fn poll(&mut self, sockets: &mut SocketSet) -> Option<bool> { fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.lock().ipv4_address()
}
fn sockets(&mut self) -> MutexGuard<SocketSet<'static, 'static, 'static>, SpinNoIrq> {
self.sockets.lock()
}
fn poll(&mut self) {
let timestamp = Instant::from_millis(unsafe { crate::trap::TICK as i64 }); let timestamp = Instant::from_millis(unsafe { crate::trap::TICK as i64 });
match self.iface.poll(sockets, timestamp) { let mut sockets = self.sockets.lock();
Ok(update) => { match self.iface.lock().poll(&mut sockets, timestamp) {
Some(update) Ok(_) => {
SOCKET_ACTIVITY.notify_all();
} }
Err(err) => { Err(err) => {
debug!("poll got err {}", err); debug!("poll got err {}", err);
None
} }
} }
} }
fn ipv4_address(&self) -> Option<Ipv4Address> {
self.iface.ipv4_address()
}
} }
#[repr(C)] #[repr(C)]
@ -201,7 +239,7 @@ impl<'a> phy::Device<'a> for E1000Driver {
fn capabilities(&self) -> DeviceCapabilities { fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default(); let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = 1536; caps.max_transmission_unit = 1536;
caps.max_burst_size = Some(1); caps.max_burst_size = Some(32);
caps caps
} }
} }
@ -263,12 +301,10 @@ impl phy::TxToken for E1000TxToken {
}; };
let mut tdt = e1000[E1000_TDT].read(); let mut tdt = e1000[E1000_TDT].read();
let index_next = (tdt as usize + 1) % send_queue_size;
let send_desc = &mut send_queue[index_next];
assert!(driver.first_trans || send_desc.status & 1 != 0);
let index = (tdt as usize) % send_queue_size; let index = (tdt as usize) % send_queue_size;
let send_desc = &mut send_queue[index]; let send_desc = &mut send_queue[index];
assert!(driver.first_trans || send_desc.status & 1 != 0);
let target = let target =
unsafe { slice::from_raw_parts_mut(driver.send_buffers[index] as *mut u8, len) }; unsafe { slice::from_raw_parts_mut(driver.send_buffers[index] as *mut u8, len) };
target.copy_from_slice(&buffer[..len]); target.copy_from_slice(&buffer[..len]);
@ -400,7 +436,13 @@ pub fn e1000_init(header: usize, size: usize) {
for i in E1000_MTA..E1000_RAL { for i in E1000_MTA..E1000_RAL {
e1000[i].write(0); e1000[i].write(0);
} }
e1000[E1000_IMS].write(0); // IMS
// enable interrupt
// RXT0
e1000[E1000_IMS].write(1 << 7); // IMS
// clear interrupt
e1000[E1000_ICR].write(e1000[E1000_ICR].read());
e1000[E1000_RDBAL].write(recv_page_pa as u32); // RDBAL e1000[E1000_RDBAL].write(recv_page_pa as u32); // RDBAL
e1000[E1000_RDBAH].write((recv_page_pa >> 32) as u32); // RDBAH e1000[E1000_RDBAH].write((recv_page_pa >> 32) as u32); // RDBAH
@ -431,16 +473,18 @@ pub fn e1000_init(header: usize, size: usize) {
let ethernet_addr = EthernetAddress::from_bytes(&mac); let ethernet_addr = EthernetAddress::from_bytes(&mac);
let ip_addrs = [IpCidr::new(IpAddress::v4(10,0,0,2), 24)]; let ip_addrs = [IpCidr::new(IpAddress::v4(10,0,0,2), 24)];
let neighbor_cache = NeighborCache::new(BTreeMap::new()); let neighbor_cache = NeighborCache::new(BTreeMap::new());
let iface = EthernetInterfaceBuilder::new(net_driver) let iface = EthernetInterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr) .ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs) .ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.finalize(); .finalize();
let e1000_iface = E1000Interface { let e1000_iface = E1000Interface {
iface, iface: Arc::new(Mutex::new(iface)),
sockets: Arc::new(Mutex::new(SocketSet::new(vec![]))),
driver: net_driver.clone(),
}; };
//DRIVERS.lock().push(Box::new(net_driver.clone())); DRIVERS.lock().push(Box::new(e1000_iface.clone()));
NET_DRIVERS.lock().push(Box::new(e1000_iface)); NET_DRIVERS.lock().push(Box::new(e1000_iface));
} }

View File

@ -21,6 +21,7 @@ use volatile::{ReadOnly, Volatile};
use crate::HEAP_ALLOCATOR; use crate::HEAP_ALLOCATOR;
use crate::memory::active_table; use crate::memory::active_table;
use crate::sync::SpinNoIrqLock as Mutex; use crate::sync::SpinNoIrqLock as Mutex;
use crate::sync::{MutexGuard, SpinNoIrq};
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, NetDriver}; use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, NetDriver};
use super::super::bus::virtio_mmio::*; use super::super::bus::virtio_mmio::*;
@ -85,11 +86,15 @@ impl NetDriver for VirtIONetDriver {
format!("virtio{}", self.0.lock().interrupt) format!("virtio{}", self.0.lock().interrupt)
} }
fn poll(&mut self, sockets: &mut SocketSet) -> Option<bool> { fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!() unimplemented!()
} }
fn ipv4_address(&self) -> Option<Ipv4Address> { fn sockets(&mut self) -> MutexGuard<SocketSet<'static, 'static, 'static>, SpinNoIrq> {
unimplemented!()
}
fn poll(&mut self) {
unimplemented!() unimplemented!()
} }
} }

View File

@ -24,24 +24,18 @@ pub extern fn server(_arg: usize) -> ! {
let tcp2_tx_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 tcp2_socket = TcpSocket::new(tcp2_rx_buffer, tcp2_tx_buffer);
let mut sockets = SocketSet::new(vec![]); let iface = &mut *(NET_DRIVERS.lock()[0]);
let mut sockets = iface.sockets();
let udp_handle = sockets.add(udp_socket); let udp_handle = sockets.add(udp_socket);
let tcp_handle = sockets.add(tcp_socket); let tcp_handle = sockets.add(tcp_socket);
let tcp2_handle = sockets.add(tcp2_socket); let tcp2_handle = sockets.add(tcp2_socket);
drop(sockets);
drop(iface);
loop { loop {
{ {
let iface = &mut *NET_DRIVERS.lock()[0]; let iface = &mut *(NET_DRIVERS.lock()[0]);
match iface.poll(&mut sockets) { let mut sockets = iface.sockets();
Some(event) => {
if !event {
continue;
}
},
None => {
continue
}
}
// udp server // udp server
{ {

View File

@ -9,6 +9,8 @@ use smoltcp::socket::{SocketSet, SocketHandle};
use crate::arch::interrupt::{Context, TrapFrame}; use crate::arch::interrupt::{Context, TrapFrame};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet}; use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use crate::fs::{FileHandle, OpenOptions}; use crate::fs::{FileHandle, OpenOptions};
use crate::sync::Condvar;
use crate::drivers::NET_DRIVERS;
use super::abi::{self, ProcInitInfo}; use super::abi::{self, ProcInitInfo};
@ -43,8 +45,6 @@ pub struct Process {
pub memory_set: MemorySet, pub memory_set: MemorySet,
pub files: BTreeMap<usize, FileLike>, pub files: BTreeMap<usize, FileLike>,
pub cwd: String, pub cwd: String,
// TODO: discuss: move it to interface or leave it here
pub sockets: SocketSet<'static, 'static, 'static>,
} }
/// Let `rcore_thread` can switch between our `Thread` /// Let `rcore_thread` can switch between our `Thread`
@ -66,7 +66,6 @@ impl Thread {
memory_set: MemorySet::new(), memory_set: MemorySet::new(),
files: BTreeMap::default(), files: BTreeMap::default(),
cwd: String::from("/"), cwd: String::from("/"),
sockets: SocketSet::new(vec![])
})), })),
}) })
} }
@ -82,7 +81,6 @@ impl Thread {
memory_set, memory_set,
files: BTreeMap::default(), files: BTreeMap::default(),
cwd: String::from("/"), cwd: String::from("/"),
sockets: SocketSet::new(vec![])
})), })),
}) })
} }
@ -161,7 +159,6 @@ impl Thread {
memory_set, memory_set,
files, files,
cwd: String::from("/"), cwd: String::from("/"),
sockets: SocketSet::new(vec![])
})), })),
}) })
} }
@ -193,8 +190,6 @@ impl Thread {
memory_set, memory_set,
files: self.proc.lock().files.clone(), files: self.proc.lock().files.clone(),
cwd: self.proc.lock().cwd.clone(), cwd: self.proc.lock().cwd.clone(),
// TODO: duplicate sockets for child process
sockets: SocketSet::new(vec![])
})), })),
}) })
} }

View File

@ -7,8 +7,8 @@ use crate::process::*;
use crate::thread; use crate::thread;
pub fn run_user_shell() { pub fn run_user_shell() {
use crate::net::server; //use crate::net::server;
processor().manager().add(Thread::new_kernel(server, 0), 0); //processor().manager().add(Thread::new_kernel(server, 0), 0);
if let Ok(inode) = ROOT_INODE.lookup("sh") { if let Ok(inode) = ROOT_INODE.lookup("sh") {
println!("Going to user mode shell."); println!("Going to user mode shell.");
println!("Use 'ls' to list available programs."); println!("Use 'ls' to list available programs.");

View File

@ -1,7 +1,7 @@
//! Syscalls for networking //! Syscalls for networking
use super::*; use super::*;
use crate::drivers::NET_DRIVERS; use crate::drivers::{NET_DRIVERS, SOCKET_ACTIVITY};
use core::mem::size_of; use core::mem::size_of;
use smoltcp::socket::*; use smoltcp::socket::*;
use smoltcp::wire::*; use smoltcp::wire::*;
@ -49,6 +49,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu
domain, socket_type, protocol domain, socket_type, protocol
); );
let mut proc = process(); let mut proc = process();
let iface = &mut *(NET_DRIVERS.lock()[0]);
match domain { match domain {
AF_INET => match socket_type { AF_INET => match socket_type {
SOCK_STREAM => { SOCK_STREAM => {
@ -58,7 +59,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 2048]); let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 2048]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let tcp_handle = proc.sockets.add(tcp_socket); let tcp_handle = iface.sockets().add(tcp_socket);
proc.files.insert( proc.files.insert(
fd, fd,
FileLike::Socket(SocketWrapper { FileLike::Socket(SocketWrapper {
@ -83,7 +84,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu
raw_tx_buffer, raw_tx_buffer,
); );
let raw_handle = proc.sockets.add(raw_socket); let raw_handle = iface.sockets().add(raw_socket);
proc.files.insert( proc.files.insert(
fd, fd,
FileLike::Socket(SocketWrapper { FileLike::Socket(SocketWrapper {
@ -140,6 +141,7 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
let mut proc = process(); let mut proc = process();
proc.memory_set.check_ptr(addr)?; proc.memory_set.check_ptr(addr)?;
let iface = &mut *(NET_DRIVERS.lock()[0]);
let mut dest = None; let mut dest = None;
let mut port = 0; let mut port = 0;
@ -152,14 +154,10 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
let mut proc = process();
// little hack: kick it forward
let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets);
let wrapper = proc.get_socket(fd)?; let wrapper = proc.get_socket(fd)?;
if let SocketType::Tcp = wrapper.socket_type { if let SocketType::Tcp = wrapper.socket_type {
let mut socket = proc.sockets.get::<TcpSocket>(wrapper.handle); let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
// TODO selects non-conflict high port // TODO selects non-conflict high port
static mut EPHEMERAL_PORT: u16 = 49152; static mut EPHEMERAL_PORT: u16 = 49152;
@ -173,8 +171,27 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
}; };
match socket.connect((dest.unwrap(), port), temp_port) { match socket.connect((dest.unwrap(), port), temp_port) {
Ok(()) => Ok(0), Ok(()) => {
Err(_) => Err(SysError::EISCONN), drop(socket);
drop(sockets);
// wait for connection result
loop {
iface.poll();
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
if socket.state() == TcpState::SynSent {
// still connecting
SOCKET_ACTIVITY._wait()
} else if socket.state() == TcpState::Established {
break Ok(0)
} else if socket.state() == TcpState::Closed {
break Err(SysError::ECONNREFUSED)
}
}
},
Err(_) => Err(SysError::ENOBUFS),
} }
} else { } else {
unimplemented!("socket type") unimplemented!("socket type")
@ -182,18 +199,22 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
} }
pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usize) -> SysResult { pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usize) -> SysResult {
// little hack: kick it forward let iface = &mut *(NET_DRIVERS.lock()[0]);
let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets);
let wrapper = proc.get_socket(fd)?; let wrapper = proc.get_socket(fd)?;
if let SocketType::Tcp = wrapper.socket_type { if let SocketType::Tcp = wrapper.socket_type {
let mut socket = proc.sockets.get::<TcpSocket>(wrapper.handle); let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
let slice = unsafe { slice::from_raw_parts(base, len) }; let slice = unsafe { slice::from_raw_parts(base, len) };
if socket.is_open() { if socket.is_open() {
if socket.can_send() { if socket.can_send() {
match socket.send_slice(&slice) { match socket.send_slice(&slice) {
Ok(size) => Ok(size as isize), Ok(size) => {
drop(socket);
drop(sockets);
iface.poll();
Ok(size as isize)
},
Err(err) => Err(SysError::ENOBUFS), Err(err) => Err(SysError::ENOBUFS),
} }
} else { } else {
@ -231,17 +252,18 @@ pub fn sys_sendto(
"sys_sendto: fd: {} buffer: {:?} len: {} addr: {:?} addr_len: {}", "sys_sendto: fd: {} buffer: {:?} len: {} addr: {:?} addr_len: {}",
fd, buffer, len, addr, addr_len fd, buffer, len, addr, addr_len
); );
let mut proc = process(); let mut proc = process();
proc.memory_set.check_ptr(addr)?; proc.memory_set.check_ptr(addr)?;
proc.memory_set.check_array(buffer, len)?; proc.memory_set.check_array(buffer, len)?;
// little hack: kick it forward let iface = &mut *(NET_DRIVERS.lock()[0]);
let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets);
let wrapper = proc.get_socket(fd)?; let wrapper = proc.get_socket(fd)?;
if let SocketType::Raw = wrapper.socket_type { if let SocketType::Raw = wrapper.socket_type {
let mut socket = proc.sockets.get::<RawSocket>(wrapper.handle); let v4_src = iface.ipv4_address().unwrap();
let mut sockets = iface.sockets();
let mut socket = sockets.get::<RawSocket>(wrapper.handle);
let mut dest = None; let mut dest = None;
let mut port = 0; let mut port = 0;
@ -252,7 +274,7 @@ pub fn sys_sendto(
if dest == None { if dest == None {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} else if let Some(IpAddress::Ipv4(v4_dest)) = dest { } else if let Some(IpAddress::Ipv4(v4_dst)) = dest {
let slice = unsafe { slice::from_raw_parts(buffer, len) }; let slice = unsafe { slice::from_raw_parts(buffer, len) };
// using 20-byte IPv4 header // using 20-byte IPv4 header
let mut buffer = vec![0u8; len + 20]; let mut buffer = vec![0u8; len + 20];
@ -261,14 +283,18 @@ pub fn sys_sendto(
packet.set_header_len(20); packet.set_header_len(20);
packet.set_total_len((20 + len) as u16); packet.set_total_len((20 + len) as u16);
packet.set_protocol(socket.ip_protocol().into()); packet.set_protocol(socket.ip_protocol().into());
packet.set_src_addr(iface.ipv4_address().unwrap()); packet.set_src_addr(v4_src);
packet.set_dst_addr(v4_dest); packet.set_dst_addr(v4_dst);
let payload = packet.payload_mut(); let payload = packet.payload_mut();
payload.copy_from_slice(slice); payload.copy_from_slice(slice);
packet.fill_checksum(); packet.fill_checksum();
socket.send_slice(&buffer).unwrap(); socket.send_slice(&buffer).unwrap();
drop(socket);
drop(sockets);
iface.poll();
Ok(len as isize) Ok(len as isize)
} else { } else {
unimplemented!("ip type") unimplemented!("ip type")
@ -292,18 +318,16 @@ pub fn sys_recvfrom(
); );
let mut proc = process(); let mut proc = process();
// little hack: kick it forward let iface = &mut *(NET_DRIVERS.lock()[0]);
let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets);
let wrapper = proc.get_socket(fd)?; let wrapper = proc.get_socket(fd)?;
if let SocketType::Raw = wrapper.socket_type { if let SocketType::Raw = wrapper.socket_type {
let mut socket = proc.sockets.get::<RawSocket>(wrapper.handle); loop {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<RawSocket>(wrapper.handle);
let mut slice = unsafe { slice::from_raw_parts_mut(buffer, len) };
let mut slice = unsafe { slice::from_raw_parts_mut(buffer, len) }; if let Ok(size) = socket.recv_slice(&mut slice) {
match socket.recv_slice(&mut slice) {
Ok(size) => {
let mut packet = Ipv4Packet::new_unchecked(&slice); let mut packet = Ipv4Packet::new_unchecked(&slice);
// FIXME: check size as per sin_family // FIXME: check size as per sin_family
@ -311,12 +335,11 @@ pub fn sys_recvfrom(
fill_addr(&mut sockaddr_in, IpAddress::Ipv4(packet.src_addr()), 0); fill_addr(&mut sockaddr_in, IpAddress::Ipv4(packet.src_addr()), 0);
unsafe { *addr_len = size_of::<SockaddrIn>() }; unsafe { *addr_len = size_of::<SockaddrIn>() };
Ok(size as isize) return Ok(size as isize);
}
Err(err) => {
warn!("err {:?}", err);
Err(SysError::ENOBUFS)
} }
drop(socket);
SOCKET_ACTIVITY._wait()
} }
} else { } else {
unimplemented!("socket type") unimplemented!("socket type")
@ -324,7 +347,8 @@ pub fn sys_recvfrom(
} }
pub fn sys_close_socket(proc: &mut Process, fd: usize, handle: SocketHandle) -> SysResult { pub fn sys_close_socket(proc: &mut Process, fd: usize, handle: SocketHandle) -> SysResult {
let mut socket = proc.sockets.remove(handle); let iface = &mut *(NET_DRIVERS.lock()[0]);
let mut socket = iface.sockets().remove(handle);
match socket { match socket {
Socket::Tcp(ref mut tcp_socket) => { Socket::Tcp(ref mut tcp_socket) => {
tcp_socket.close(); tcp_socket.close();