diff --git a/kernel/src/net/iface/any_socket.rs b/kernel/src/net/iface/any_socket.rs index 5a3fb6757..cce36b625 100644 --- a/kernel/src/net/iface/any_socket.rs +++ b/kernel/src/net/iface/any_socket.rs @@ -113,16 +113,34 @@ impl AnyBoundSocket { self.0.raw_with(f) } - /// Try to connect to a remote endpoint. Tcp socket only. + /// Connects to a remote endpoint. + /// + /// # Panics + /// + /// This method will panic if the socket is not a TCP socket. pub fn do_connect(&self, remote_endpoint: IpEndpoint) -> Result<()> { - let mut sockets = self.0.iface.sockets(); + let common = self.iface().common(); + + let mut sockets = common.sockets(); let socket = sockets.get_mut::(self.0.handle); - let port = self.0.port; - let mut iface_inner = self.0.iface.iface_inner(); - let cx = iface_inner.context(); + + let mut iface = common.interface(); + let cx = iface.context(); + + // The only reason this method might fail is because we're trying to connect to an + // unspecified address (i.e. 0.0.0.0). We currently have no support for binding to, + // listening on, or connecting to the unspecified address. + // + // We assume the remote will just refuse to connect, so we return `ECONNREFUSED`. socket - .connect(cx, remote_endpoint, port) - .map_err(|_| Error::with_message(Errno::ENOBUFS, "send connection request failed"))?; + .connect(cx, remote_endpoint, self.0.port) + .map_err(|_| { + Error::with_message( + Errno::ECONNREFUSED, + "connecting to an unspecified address is not supported", + ) + })?; + Ok(()) } @@ -194,7 +212,7 @@ impl AnyBoundSocketInner { &self, mut f: F, ) -> R { - let mut sockets = self.iface.sockets(); + let mut sockets = self.iface.common().sockets(); let socket = sockets.get_mut::(self.handle); f(socket) } diff --git a/kernel/src/net/iface/common.rs b/kernel/src/net/iface/common.rs index 18cd31333..02125123e 100644 --- a/kernel/src/net/iface/common.rs +++ b/kernel/src/net/iface/common.rs @@ -8,7 +8,6 @@ use ostd::sync::{LocalIrqDisabled, WaitQueue}; use smoltcp::{ iface::{SocketHandle, SocketSet}, phy::Device, - wire::IpCidr, }; use super::{ @@ -66,14 +65,6 @@ impl IfaceCommon { self.interface.disable_irq().lock().ipv4_addr() } - pub(super) fn netmask(&self) -> Option { - let interface = self.interface.disable_irq().lock(); - let ip_addrs = interface.ip_addrs(); - ip_addrs.first().map(|cidr| match cidr { - IpCidr::Ipv4(ipv4_cidr) => ipv4_cidr.netmask(), - }) - } - pub(super) fn polling_wait_queue(&self) -> &WaitQueue { &self.polling_wait_queue } diff --git a/kernel/src/net/iface/loopback.rs b/kernel/src/net/iface/loopback.rs index ddb4010e2..eba160a69 100644 --- a/kernel/src/net/iface/loopback.rs +++ b/kernel/src/net/iface/loopback.rs @@ -24,7 +24,6 @@ pub const LOOPBACK_ADDRESS_PREFIX_LEN: u8 = 8; // mask: 255.0.0.0 pub struct IfaceLoopback { driver: Mutex, common: IfaceCommon, - weak_self: Weak, } impl IfaceLoopback { @@ -44,10 +43,9 @@ impl IfaceLoopback { }; println!("Loopback ipaddr: {}", interface.ipv4_addr().unwrap()); let common = IfaceCommon::new(interface); - Arc::new_cyclic(|weak| Self { + Arc::new(Self { driver: Mutex::new(loopback), common, - weak_self: weak.clone(), }) } } @@ -56,10 +54,6 @@ impl IfaceInternal for IfaceLoopback { fn common(&self) -> &IfaceCommon { &self.common } - - fn arc_self(&self) -> Arc { - self.weak_self.upgrade().unwrap() - } } impl Iface for IfaceLoopback { @@ -67,10 +61,6 @@ impl Iface for IfaceLoopback { "lo" } - fn mac_addr(&self) -> Option { - None - } - fn poll(&self) { let mut device = self.driver.lock(); self.common.poll(&mut *device); diff --git a/kernel/src/net/iface/mod.rs b/kernel/src/net/iface/mod.rs index 40596afd9..552fbb3bc 100644 --- a/kernel/src/net/iface/mod.rs +++ b/kernel/src/net/iface/mod.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 use ostd::sync::WaitQueue; -use smoltcp::iface::SocketSet; use self::common::IfaceCommon; use crate::prelude::*; @@ -18,78 +17,72 @@ pub use any_socket::{ TCP_SEND_BUF_LEN, UDP_RECV_PAYLOAD_LEN, UDP_SEND_PAYLOAD_LEN, }; pub use loopback::IfaceLoopback; -use ostd::sync::LocalIrqDisabled; pub use smoltcp::wire::EthernetAddress; pub use util::{spawn_background_poll_thread, BindPortConfig}; pub use virtio::IfaceVirtio; use crate::net::socket::ip::Ipv4Address; -/// Network interface. +/// A network interface. /// -/// A network interface (abbreviated as iface) is a hardware or software component that connects a device or computer to a network. -/// Network interfaces can be physical components like Ethernet ports or wireless adapters, -/// or they can be virtual interfaces created by software such as virtual private network (VPN) connections. +/// A network interface (abbreviated as iface) is a hardware or software component that connects a +/// computer to a network. Network interfaces can be physical components like Ethernet ports or +/// wireless adapters. They can also be virtual interfaces created by software, such as virtual +/// private network (VPN) connections. pub trait Iface: internal::IfaceInternal + Send + Sync { - /// The iface name. For linux, usually the driver name followed by a unit number. + /// Gets the name of the iface. + /// + /// In Linux, the name is usually the driver name followed by a unit number. fn name(&self) -> &str; - /// The optional mac address - fn mac_addr(&self) -> Option; - - /// Transmit packets queued in the iface, and receive packets queued in the iface. - /// It any event happens, this function will also update socket status. + /// Transmits or receives packets queued in the iface, and updates socket status accordingly. fn poll(&self); +} - /// Bind a socket to the iface. So the packet for this socket will be dealt with by the interface. - /// If port is None, the iface will pick up an ephemeral port for the socket. - /// FIXME: The reason for binding socket and interface together is because there are limitations inside smoltcp. - /// See discussion at . - fn bind_socket( - &self, +impl dyn Iface { + /// Binds a socket to the iface. + /// + /// After binding the socket to the iface, the iface will handle all packets to and from the + /// socket. + /// + /// If [`BindPortConfig::Ephemeral`] is specified, the iface will pick up an ephemeral port for + /// the socket. + /// + /// FIXME: The reason for binding the socket and the iface together is because there are + /// limitations inside smoltcp. See discussion at + /// . + pub fn bind_socket( + self: &Arc, socket: Box, config: BindPortConfig, ) -> core::result::Result)> { let common = self.common(); - common.bind_socket(self.arc_self(), socket, config) + common.bind_socket(self.clone(), socket, config) } - /// The optional ipv4 address - /// FIXME: An interface indeed support multiple addresses - fn ipv4_addr(&self) -> Option { + /// Gets the IPv4 address of the iface, if any. + /// + /// FIXME: One iface may have multiple IPv4 addresses. + pub fn ipv4_addr(&self) -> Option { self.common().ipv4_addr() } - /// The netmask. - /// FIXME: The netmask and IP address should be one-to-one if there are multiple ip address - fn netmask(&self) -> Option { - self.common().netmask() - } - - /// The waitqueue used to background polling thread + /// Gets the wait queue that the background polling thread will sleep on. fn polling_wait_queue(&self) -> &WaitQueue { self.common().polling_wait_queue() } + + /// Gets the time when we should perform another poll. + fn next_poll_at_ms(&self) -> Option { + self.common().next_poll_at_ms() + } } mod internal { use super::*; - /// A helper trait + /// An internal trait that abstracts the common part of different ifaces. pub trait IfaceInternal { fn common(&self) -> &IfaceCommon; - /// The inner socket set - fn sockets(&self) -> SpinLockGuard, LocalIrqDisabled> { - self.common().sockets() - } - /// The inner iface. - fn iface_inner(&self) -> SpinLockGuard { - self.common().interface() - } - /// The time we should do another poll. - fn next_poll_at_ms(&self) -> Option { - self.common().next_poll_at_ms() - } - fn arc_self(&self) -> Arc; } } diff --git a/kernel/src/net/iface/virtio.rs b/kernel/src/net/iface/virtio.rs index 6fe6cf458..4d47fcbb2 100644 --- a/kernel/src/net/iface/virtio.rs +++ b/kernel/src/net/iface/virtio.rs @@ -16,7 +16,6 @@ pub struct IfaceVirtio { driver: Arc>, common: IfaceCommon, dhcp_handle: SocketHandle, - weak_self: Weak, } impl IfaceVirtio { @@ -42,11 +41,10 @@ impl IfaceVirtio { let mut socket_set = common.sockets(); let dhcp_handle = init_dhcp_client(&mut socket_set); drop(socket_set); - Arc::new_cyclic(|weak| Self { + Arc::new(Self { driver: virtio_net, common, dhcp_handle, - weak_self: weak.clone(), }) } @@ -93,10 +91,6 @@ impl IfaceInternal for IfaceVirtio { fn common(&self) -> &IfaceCommon { &self.common } - - fn arc_self(&self) -> Arc { - self.weak_self.upgrade().unwrap() - } } impl Iface for IfaceVirtio { @@ -104,15 +98,6 @@ impl Iface for IfaceVirtio { "virtio" } - fn mac_addr(&self) -> Option { - let interface = self.common.interface(); - let hardware_addr = interface.hardware_addr(); - match hardware_addr { - wire::HardwareAddress::Ethernet(ethe_address) => Some(ethe_address), - wire::HardwareAddress::Ip => None, - } - } - fn poll(&self) { let mut driver = self.driver.disable_irq().lock(); self.common.poll(&mut *driver);