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:
parent
738554386b
commit
1a1e39c960
@ -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 += \
|
||||||
|
@ -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),
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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![])
|
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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.");
|
||||||
|
@ -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) };
|
||||||
match socket.recv_slice(&mut slice) {
|
if let Ok(size) = 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();
|
||||||
|
Loading…
Reference in New Issue
Block a user