Add Interface struct wrapping smoltcp iface

This commit is contained in:
Vincent Ollivier 2022-05-04 19:02:21 +02:00
parent 03de98381d
commit ede7d5d0c9
7 changed files with 68 additions and 65 deletions

View File

@ -16,10 +16,12 @@ use spin::Mutex;
mod rtl8139; mod rtl8139;
mod pcnet; mod pcnet;
pub type Interface = smoltcp::iface::Interface<'static, EthernetDevice>; pub struct Interface {
pub iface: smoltcp::iface::Interface<'static, EthernetDevice>,
}
lazy_static! { lazy_static! {
pub static ref IFACE: Mutex<Option<Interface>> = Mutex::new(None); pub static ref INTERFACE: Mutex<Option<Interface>> = Mutex::new(None);
} }
#[derive(Clone)] #[derive(Clone)]
@ -228,8 +230,9 @@ pub fn init() {
builder = builder.hardware_addr(mac.into()).neighbor_cache(neighbor_cache); builder = builder.hardware_addr(mac.into()).neighbor_cache(neighbor_cache);
} }
let iface = builder.finalize(); let iface = builder.finalize();
let interface = Interface { iface };
*IFACE.lock() = Some(iface); *INTERFACE.lock() = Some(interface);
} }
}; };

View File

@ -18,9 +18,9 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
} }
} }
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
let dhcp_socket = Dhcpv4Socket::new(); let dhcp_socket = Dhcpv4Socket::new();
let dhcp_handle = iface.add_socket(dhcp_socket); let dhcp_handle = interface.iface.add_socket(dhcp_socket);
if verbose { if verbose {
debug!("DHCP Discover transmitted"); debug!("DHCP Discover transmitted");
} }
@ -29,21 +29,21 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
loop { loop {
if syscall::realtime() - started > timeout { if syscall::realtime() - started > timeout {
error!("Timeout reached"); error!("Timeout reached");
iface.remove_socket(dhcp_handle); interface.iface.remove_socket(dhcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
if sys::console::end_of_text() { if sys::console::end_of_text() {
eprintln!(); eprintln!();
iface.remove_socket(dhcp_handle); interface.iface.remove_socket(dhcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64); let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) { if let Err(e) = interface.iface.poll(timestamp) {
error!("Network Error: {}", e); error!("Network Error: {}", e);
} }
let event = iface.get_socket::<Dhcpv4Socket>(dhcp_handle).poll(); let event = interface.iface.get_socket::<Dhcpv4Socket>(dhcp_handle).poll();
match event { match event {
None => {} None => {}
Some(Dhcpv4Event::Configured(config)) => { Some(Dhcpv4Event::Configured(config)) => {
@ -51,14 +51,14 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
if verbose { if verbose {
debug!("DHCP Offer received"); debug!("DHCP Offer received");
} }
iface.remove_socket(dhcp_handle); interface.iface.remove_socket(dhcp_handle);
break; break;
} }
Some(Dhcpv4Event::Deconfigured) => { Some(Dhcpv4Event::Deconfigured) => {
} }
} }
if let Some(wait_duration) = iface.poll_delay(timestamp) { if let Some(wait_duration) = interface.iface.poll_delay(timestamp) {
syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0); syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
} }
} }
@ -72,10 +72,10 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
usr::net::main(&["net", "config", "ip"]); usr::net::main(&["net", "config", "ip"]);
if let Some(router) = config.router { if let Some(router) = config.router {
//iface.routes_mut().add_default_ipv4_route(router).unwrap(); //interface.iface.routes_mut().add_default_ipv4_route(router).unwrap();
usr::net::main(&["net", "config", "gw", &router.to_string()]); usr::net::main(&["net", "config", "gw", &router.to_string()]);
} else { } else {
//iface.routes_mut().remove_default_ipv4_route(); //interface.iface.routes_mut().remove_default_ipv4_route();
usr::net::main(&["net", "config", "gw", ""]); usr::net::main(&["net", "config", "gw", ""]);
} }
usr::net::main(&["net", "config", "gw"]); usr::net::main(&["net", "config", "gw"]);

View File

@ -153,8 +153,8 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
#[derive(Debug)] #[derive(Debug)]
enum State { Bind, Query, Response } enum State { Bind, Query, Response }
let mut state = State::Bind; let mut state = State::Bind;
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
match iface.ipv4_addr() { match interface.iface.ipv4_addr() {
None => { None => {
return Err(ResponseCode::NetworkError); return Err(ResponseCode::NetworkError);
} }
@ -164,21 +164,21 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
_ => {} _ => {}
} }
let udp_handle = iface.add_socket(udp_socket); let udp_handle = interface.iface.add_socket(udp_socket);
let timeout = 5.0; let timeout = 5.0;
let started = syscall::realtime(); let started = syscall::realtime();
loop { loop {
if syscall::realtime() - started > timeout { if syscall::realtime() - started > timeout {
iface.remove_socket(udp_handle); interface.iface.remove_socket(udp_handle);
return Err(ResponseCode::NetworkError); return Err(ResponseCode::NetworkError);
} }
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64); let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) { if let Err(e) = interface.iface.poll(timestamp) {
error!("Network Error: {}", e); error!("Network Error: {}", e);
} }
let socket = iface.get_socket::<UdpSocket>(udp_handle); let socket = interface.iface.get_socket::<UdpSocket>(udp_handle);
state = match state { state = match state {
State::Bind if !socket.is_open() => { State::Bind if !socket.is_open() => {
@ -193,7 +193,7 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
let (data, _) = socket.recv().expect("cannot receive"); let (data, _) = socket.recv().expect("cannot receive");
let message = Message::from(data); let message = Message::from(data);
if message.id() == query.id() && message.is_response() { if message.id() == query.id() && message.is_response() {
iface.remove_socket(udp_handle); interface.iface.remove_socket(udp_handle);
return match message.rcode() { return match message.rcode() {
ResponseCode::NoError => { ResponseCode::NoError => {
// TODO: Parse the datagram instead of // TODO: Parse the datagram instead of
@ -214,7 +214,7 @@ pub fn resolve(name: &str) -> Result<IpAddress, ResponseCode> {
_ => state _ => state
}; };
if let Some(wait_duration) = iface.poll_delay(timestamp) { if let Some(wait_duration) = interface.iface.poll_delay(timestamp) {
syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0); syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
} }

View File

@ -108,8 +108,8 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
enum State { Connect, Request, Response } enum State { Connect, Request, Response }
let mut state = State::Connect; let mut state = State::Connect;
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
let tcp_handle = iface.add_socket(tcp_socket); let tcp_handle = interface.iface.add_socket(tcp_socket);
let mut is_header = true; let mut is_header = true;
let timeout = 5.0; let timeout = 5.0;
@ -117,20 +117,20 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
loop { loop {
if syscall::realtime() - started > timeout { if syscall::realtime() - started > timeout {
error!("Timeout reached"); error!("Timeout reached");
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
if sys::console::end_of_text() { if sys::console::end_of_text() {
eprintln!(); // FIXME eprintln!(); // FIXME
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64); let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) { if let Err(e) = interface.iface.poll(timestamp) {
error!("Network Error: {}", e); error!("Network Error: {}", e);
} }
let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle); let (socket, cx) = interface.iface.get_socket_and_context::<TcpSocket>(tcp_handle);
state = match state { state = match state {
State::Connect if !socket.is_active() => { State::Connect if !socket.is_active() => {
@ -142,7 +142,7 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
} }
if socket.connect(cx, (address, url.port), local_port).is_err() { if socket.connect(cx, (address, url.port), local_port).is_err() {
error!("Could not connect to {}:{}", address, url.port); error!("Could not connect to {}:{}", address, url.port);
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
State::Request State::Request
@ -201,11 +201,11 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
_ => state _ => state
}; };
if let Some(wait_duration) = iface.poll_delay(timestamp) { if let Some(wait_duration) = interface.iface.poll_delay(timestamp) {
syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0); syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
} }
} }
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
println!(); println!();
usr::shell::ExitCode::CommandSuccessful usr::shell::ExitCode::CommandSuccessful
} else { } else {

View File

@ -17,29 +17,29 @@ pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
let csi_reset = Style::reset(); let csi_reset = Style::reset();
let port = 80; let port = 80;
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
println!("{}HTTP Server listening on 0.0.0.0:{}{}", csi_color, port, csi_reset); println!("{}HTTP Server listening on 0.0.0.0:{}{}", csi_color, port, csi_reset);
let mtu = iface.device().capabilities().max_transmission_unit; let mtu = interface.iface.device().capabilities().max_transmission_unit;
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; mtu]); let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; mtu]); let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
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 = iface.add_socket(tcp_socket); let tcp_handle = interface.iface.add_socket(tcp_socket);
let mut send_queue: VecDeque<Vec<u8>> = VecDeque::new(); let mut send_queue: VecDeque<Vec<u8>> = VecDeque::new();
loop { loop {
if sys::console::end_of_text() { if sys::console::end_of_text() {
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
println!(); println!();
return usr::shell::ExitCode::CommandSuccessful; return usr::shell::ExitCode::CommandSuccessful;
} }
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64); let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) { if let Err(e) = interface.iface.poll(timestamp) {
error!("Network Error: {}", e); error!("Network Error: {}", e);
} }
let socket = iface.get_socket::<TcpSocket>(tcp_handle); let socket = interface.iface.get_socket::<TcpSocket>(tcp_handle);
if !socket.is_open() { if !socket.is_open() {
socket.listen(port).unwrap(); socket.listen(port).unwrap();
@ -175,7 +175,7 @@ pub fn main(_args: &[&str]) -> usr::shell::ExitCode {
socket.close(); socket.close();
send_queue.clear(); send_queue.clear();
} }
if let Some(wait_duration) = iface.poll_delay(timestamp) { if let Some(wait_duration) = interface.iface.poll_delay(timestamp) {
syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0); syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
} }
} }

View File

@ -40,8 +40,8 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
} }
/* /*
"stat" => { "stat" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
let stats = iface.device().stats.clone(); let stats = interface.iface.device().stats.clone();
let csi_color = Style::color("LightCyan"); let csi_color = Style::color("LightCyan");
let csi_reset = Style::reset(); let csi_reset = Style::reset();
println!("{}rx:{} {} packets ({} bytes)", csi_color, csi_reset, stats.rx_packets_count(), stats.rx_bytes_count()); println!("{}rx:{} {} packets ({} bytes)", csi_color, csi_reset, stats.rx_packets_count(), stats.rx_bytes_count());
@ -51,14 +51,14 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
} }
} }
"monitor" => { "monitor" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
iface.device_mut().debug_mode = true; interface.iface.device_mut().debug_mode = true;
let mtu = iface.device().capabilities().max_transmission_unit; let mtu = interface.iface.device().capabilities().max_transmission_unit;
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; mtu]); let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; mtu]); let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; mtu]);
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 = iface.add_socket(tcp_socket); let tcp_handle = interface.iface.add_socket(tcp_socket);
loop { loop {
if sys::console::end_of_text() { if sys::console::end_of_text() {
@ -68,11 +68,11 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
syscall::sleep(0.1); syscall::sleep(0.1);
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64); let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) { if let Err(e) = interface.iface.poll(timestamp) {
error!("Network Error: {}", e); error!("Network Error: {}", e);
} }
let socket = iface.get_socket::<TcpSocket>(tcp_handle); let socket = interface.iface.get_socket::<TcpSocket>(tcp_handle);
if socket.may_recv() { if socket.may_recv() {
socket.recv(|buffer| { socket.recv(|buffer| {
let recvd_len = buffer.len(); let recvd_len = buffer.len();
@ -136,16 +136,16 @@ const DNS_FILE: &str = "/ini/dns";
pub fn get_config(attribute: &str) -> Option<String> { pub fn get_config(attribute: &str) -> Option<String> {
match attribute { match attribute {
"mac" => { "mac" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
return Some(iface.hardware_addr().to_string()); return Some(interface.iface.hardware_addr().to_string());
} else { } else {
error!("Network error"); error!("Network error");
} }
None None
} }
"ip" => { "ip" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
if let Some(ip_cidr) = iface.ip_addrs().iter().next() { if let Some(ip_cidr) = interface.iface.ip_addrs().iter().next() {
return Some(format!("{}/{}", ip_cidr.address(), ip_cidr.prefix_len())); return Some(format!("{}/{}", ip_cidr.address(), ip_cidr.prefix_len()));
} }
} else { } else {
@ -155,8 +155,8 @@ pub fn get_config(attribute: &str) -> Option<String> {
} }
"gw" => { "gw" => {
let mut res = None; let mut res = None;
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
iface.routes_mut().update(|storage| { interface.iface.routes_mut().update(|storage| {
if let Some((_, route)) = storage.iter().next() { if let Some((_, route)) = storage.iter().next() {
res = Some(route.via_router.to_string()); res = Some(route.via_router.to_string());
} }
@ -191,8 +191,8 @@ pub fn set_config(attribute: &str, value: &str) {
match attribute { match attribute {
/* /*
"debug" => { "debug" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
iface.device_mut().debug_mode = match value { interface.iface.device_mut().debug_mode = match value {
"1" | "true" => true, "1" | "true" => true,
"0" | "false" => false, "0" | "false" => false,
_ => { _ => {
@ -207,8 +207,8 @@ pub fn set_config(attribute: &str, value: &str) {
*/ */
"ip" => { "ip" => {
if let Ok(ip) = IpCidr::from_str(value) { if let Ok(ip) = IpCidr::from_str(value) {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
iface.update_ip_addrs(|addrs| { interface.iface.update_ip_addrs(|addrs| {
if let Some(addr) = addrs.iter_mut().next() { if let Some(addr) = addrs.iter_mut().next() {
*addr = ip; *addr = ip;
} }
@ -222,8 +222,8 @@ pub fn set_config(attribute: &str, value: &str) {
} }
"gw" => { "gw" => {
if let Ok(ip) = Ipv4Address::from_str(value) { if let Ok(ip) = Ipv4Address::from_str(value) {
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
iface.routes_mut().add_default_ipv4_route(ip).unwrap(); interface.iface.routes_mut().add_default_ipv4_route(ip).unwrap();
} else { } else {
error!("Network error"); error!("Network error");
} }

View File

@ -54,28 +54,28 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
enum State { Connect, Request, Response } enum State { Connect, Request, Response }
let mut state = State::Connect; let mut state = State::Connect;
if let Some(ref mut iface) = *sys::net::IFACE.lock() { if let Some(ref mut interface) = *sys::net::INTERFACE.lock() {
let tcp_handle = iface.add_socket(tcp_socket); let tcp_handle = interface.iface.add_socket(tcp_socket);
let timeout = 5.0; let timeout = 5.0;
let started = syscall::realtime(); let started = syscall::realtime();
loop { loop {
if syscall::realtime() - started > timeout { if syscall::realtime() - started > timeout {
error!("Timeout reached"); error!("Timeout reached");
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
if sys::console::end_of_text() { if sys::console::end_of_text() {
eprintln!(); eprintln!();
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
return usr::shell::ExitCode::CommandError; return usr::shell::ExitCode::CommandError;
} }
let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64); let timestamp = Instant::from_micros((syscall::realtime() * 1000000.0) as i64);
if let Err(e) = iface.poll(timestamp) { if let Err(e) = interface.iface.poll(timestamp) {
error!("Network Error: {}", e); error!("Network Error: {}", e);
} }
let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle); let (socket, cx) = interface.iface.get_socket_and_context::<TcpSocket>(tcp_handle);
state = match state { state = match state {
State::Connect if !socket.is_active() => { State::Connect if !socket.is_active() => {
@ -109,11 +109,11 @@ pub fn main(args: &[&str]) -> usr::shell::ExitCode {
_ => state _ => state
}; };
if let Some(wait_duration) = iface.poll_delay(timestamp) { if let Some(wait_duration) = interface.iface.poll_delay(timestamp) {
syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0); syscall::sleep((wait_duration.total_micros() as f64) / 1000000.0);
} }
} }
iface.remove_socket(tcp_handle); interface.iface.remove_socket(tcp_handle);
usr::shell::ExitCode::CommandSuccessful usr::shell::ExitCode::CommandSuccessful
} else { } else {
usr::shell::ExitCode::CommandError usr::shell::ExitCode::CommandError