From c944d2269db71f14b8ee2fc59b859bec0e032bdf Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Thu, 4 Apr 2019 20:31:46 +0800 Subject: [PATCH] Enable user to send to iface directly via packet socket --- kernel/src/drivers/mod.rs | 5 +++++ kernel/src/drivers/net/e1000.rs | 17 +++++++++++++++++ kernel/src/net/structs.rs | 20 +++++++++++++++++--- kernel/src/syscall/net.rs | 12 ++++++++---- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index 61e64bb5..c9c0cd56 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -66,6 +66,11 @@ pub trait Driver: Send + Sync { unimplemented!("not a net driver") } + // send an ethernet frame, only use it when necessary + fn send(&self, data: &[u8]) -> Option { + unimplemented!("not a net driver") + } + // block related drivers should implement these fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool { unimplemented!("not a block driver") diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index 74610980..39a91332 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -149,6 +149,23 @@ impl Driver for E1000Interface { } } } + + // send an ethernet frame, only use it when necessary + fn send(&self, data: &[u8]) -> Option { + 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 + } + } } #[repr(C)] diff --git a/kernel/src/net/structs.rs b/kernel/src/net/structs.rs index 6a9e5698..064dfaa5 100644 --- a/kernel/src/net/structs.rs +++ b/kernel/src/net/structs.rs @@ -8,7 +8,17 @@ use smoltcp::socket::*; use smoltcp::wire::*; #[derive(Clone, Debug)] -pub struct LinkLevelEndpoint {} +pub struct LinkLevelEndpoint { + interface_index: usize, +} + +impl LinkLevelEndpoint { + pub fn new(ifindex: usize) -> Self { + LinkLevelEndpoint { + interface_index: ifindex, + } + } +} #[derive(Clone, Debug)] pub enum Endpoint { @@ -633,8 +643,12 @@ impl Socket for PacketSocketState { } fn write(&self, data: &[u8], sendto_endpoint: Option) -> SysResult { - if let Some(endpoint) = sendto_endpoint { - unimplemented!() + if let Some(Endpoint::LinkLevel(endpoint)) = sendto_endpoint { + let ifaces = NET_DRIVERS.read(); + match ifaces[endpoint.interface_index].send(data) { + Some(len) => Ok(len), + None => Err(SysError::ENOBUFS), + } } else { Err(SysError::ENOTCONN) } diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 71aca45e..a39c55bb 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -4,7 +4,8 @@ use super::*; use crate::drivers::SOCKET_ACTIVITY; use crate::fs::FileLike; use crate::net::{ - Endpoint, PacketSocketState, RawSocketState, Socket, TcpSocketState, UdpSocketState, SOCKETS, + Endpoint, LinkLevelEndpoint, PacketSocketState, RawSocketState, Socket, TcpSocketState, + UdpSocketState, SOCKETS, }; use crate::sync::{MutexGuard, SpinNoIrq, SpinNoIrqLock as Mutex}; use alloc::boxed::Box; @@ -288,14 +289,15 @@ pub struct SockAddrUn { sun_path: [u8; 108], } -#[repr(C)] +// beware of alignment issue +#[repr(C, packed)] pub struct SockAddrLl { sll_protocol: u16, sll_ifindex: u32, sll_hatype: u16, sll_pkttype: u8, sll_halen: u8, - sll_addr: u8, + sll_addr: [u8; 8], } #[repr(C)] @@ -361,7 +363,9 @@ fn sockaddr_to_endpoint( if len < size_of::() + size_of::() { return Err(SysError::EINVAL); } - unimplemented!() + Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( + (*addr).payload.addr_ll.sll_ifindex as usize, + ))) } _ => Err(SysError::EINVAL), }