asterinas/kernel/libs/aster-bigtcp/src/iface/common.rs

272 lines
7.6 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
2024-09-06 10:49:37 +00:00
use alloc::{
2024-12-27 08:28:11 +00:00
collections::btree_map::{BTreeMap, Entry},
2024-12-03 01:47:47 +00:00
string::String,
2024-09-06 10:49:37 +00:00
sync::Arc,
2024-12-02 15:11:43 +00:00
vec::Vec,
2024-09-06 10:49:37 +00:00
};
2023-05-31 02:47:52 +00:00
use ostd::sync::{LocalIrqDisabled, SpinLock, SpinLockGuard};
2023-05-31 02:47:52 +00:00
use smoltcp::{
2024-09-20 03:33:20 +00:00
iface::{packet::Packet, Context},
2023-05-31 02:47:52 +00:00
phy::Device,
2024-12-02 15:11:43 +00:00
wire::{IpAddress, IpEndpoint, Ipv4Address, Ipv4Packet},
2023-05-31 02:47:52 +00:00
};
2024-09-20 03:33:20 +00:00
use super::{
poll::{FnHelper, PollContext},
port::BindPortConfig,
time::get_network_timestamp,
Iface,
};
2024-09-06 10:49:37 +00:00
use crate::{
errors::BindError,
2024-12-03 01:47:47 +00:00
ext::Ext,
2024-12-27 08:28:11 +00:00
socket::{TcpListenerBg, UdpSocketBg},
socket_table::SocketTable,
2023-05-31 02:47:52 +00:00
};
2024-12-03 01:47:47 +00:00
pub struct IfaceCommon<E: Ext> {
name: String,
2024-09-12 01:52:40 +00:00
interface: SpinLock<smoltcp::iface::Interface, LocalIrqDisabled>,
used_ports: SpinLock<BTreeMap<u16, usize>, LocalIrqDisabled>,
2024-12-27 08:28:11 +00:00
sockets: SpinLock<SocketTable<E>, LocalIrqDisabled>,
2024-12-03 01:47:47 +00:00
sched_poll: E::ScheduleNextPoll,
2023-05-31 02:47:52 +00:00
}
2024-12-03 01:47:47 +00:00
impl<E: Ext> IfaceCommon<E> {
pub(super) fn new(
name: String,
interface: smoltcp::iface::Interface,
sched_poll: E::ScheduleNextPoll,
) -> Self {
2024-12-27 08:28:11 +00:00
let sockets = SocketTable::new();
2024-12-02 15:11:43 +00:00
2023-05-31 02:47:52 +00:00
Self {
2024-12-03 01:47:47 +00:00
name,
2023-05-30 08:34:28 +00:00
interface: SpinLock::new(interface),
2024-09-20 03:33:20 +00:00
used_ports: SpinLock::new(BTreeMap::new()),
2024-12-02 15:11:43 +00:00
sockets: SpinLock::new(sockets),
2024-12-03 01:47:47 +00:00
sched_poll,
2023-05-31 02:47:52 +00:00
}
}
2024-12-03 01:47:47 +00:00
pub(super) fn name(&self) -> &str {
&self.name
}
2024-09-24 05:27:17 +00:00
pub(super) fn ipv4_addr(&self) -> Option<Ipv4Address> {
self.interface.lock().ipv4_addr()
}
2024-12-03 01:47:47 +00:00
pub(super) fn sched_poll(&self) -> &E::ScheduleNextPoll {
&self.sched_poll
2024-09-24 05:27:17 +00:00
}
}
2024-12-27 08:28:11 +00:00
// Lock order: interface -> sockets
2024-12-03 01:47:47 +00:00
impl<E: Ext> IfaceCommon<E> {
2024-07-29 02:40:00 +00:00
/// Acquires the lock to the interface.
2024-09-06 10:49:37 +00:00
pub(crate) fn interface(&self) -> SpinLockGuard<smoltcp::iface::Interface, LocalIrqDisabled> {
2024-09-12 01:52:40 +00:00
self.interface.lock()
2023-05-31 02:47:52 +00:00
}
2024-12-27 08:28:11 +00:00
/// Acquires the lock to the socket table.
pub(crate) fn sockets(&self) -> SpinLockGuard<'_, SocketTable<E>, LocalIrqDisabled> {
self.sockets.lock()
}
2024-09-24 05:27:17 +00:00
}
2023-05-31 02:47:52 +00:00
2024-09-24 05:27:17 +00:00
const IP_LOCAL_PORT_START: u16 = 32768;
const IP_LOCAL_PORT_END: u16 = 60999;
2024-12-03 01:47:47 +00:00
impl<E: Ext> IfaceCommon<E> {
2024-12-02 15:11:43 +00:00
pub(super) fn bind(
2024-09-20 03:33:20 +00:00
&self,
iface: Arc<dyn Iface<E>>,
config: BindPortConfig,
2024-12-02 15:11:43 +00:00
) -> core::result::Result<BoundPort<E>, BindError> {
let port = self.bind_port(config)?;
Ok(BoundPort { iface, port })
2023-05-31 02:47:52 +00:00
}
2024-09-24 05:30:47 +00:00
/// Allocates an unused ephemeral port.
///
/// We follow the port range that many Linux kernels use by default, which is 32768-60999.
///
/// See <https://en.wikipedia.org/wiki/Ephemeral_port>.
2024-09-06 10:49:37 +00:00
fn alloc_ephemeral_port(&self) -> Option<u16> {
2024-09-19 11:13:56 +00:00
let mut used_ports = self.used_ports.lock();
2023-05-31 02:47:52 +00:00
for port in IP_LOCAL_PORT_START..=IP_LOCAL_PORT_END {
2023-09-04 03:04:42 +00:00
if let Entry::Vacant(e) = used_ports.entry(port) {
e.insert(0);
2024-09-06 10:49:37 +00:00
return Some(port);
2023-05-31 02:47:52 +00:00
}
}
2024-09-06 10:49:37 +00:00
None
2023-05-31 02:47:52 +00:00
}
2024-09-20 03:33:20 +00:00
fn bind_port(&self, config: BindPortConfig) -> Result<u16, BindError> {
let port = if let Some(port) = config.port() {
port
} else {
match self.alloc_ephemeral_port() {
Some(port) => port,
None => return Err(BindError::Exhausted),
}
};
2024-09-19 11:13:56 +00:00
let mut used_ports = self.used_ports.lock();
2024-09-20 03:33:20 +00:00
2023-05-31 02:47:52 +00:00
if let Some(used_times) = used_ports.get_mut(&port) {
2024-09-20 03:33:20 +00:00
if *used_times == 0 || config.can_reuse() {
2024-08-24 04:01:08 +00:00
// FIXME: Check if the previous socket was bound with SO_REUSEADDR.
2023-09-04 03:04:42 +00:00
*used_times += 1;
2023-05-31 02:47:52 +00:00
} else {
2024-09-20 03:33:20 +00:00
return Err(BindError::InUse);
2023-05-31 02:47:52 +00:00
}
} else {
used_ports.insert(port, 1);
}
2024-09-20 03:33:20 +00:00
Ok(port)
2024-09-24 05:27:17 +00:00
}
2024-09-20 03:33:20 +00:00
/// Releases the port so that it can be used again (if it is not being reused).
fn release_port(&self, port: u16) {
let mut used_ports = self.used_ports.lock();
if let Some(used_times) = used_ports.remove(&port) {
if used_times != 1 {
used_ports.insert(port, used_times - 1);
}
2024-09-24 05:27:17 +00:00
}
2023-05-31 02:47:52 +00:00
}
2024-09-24 05:27:17 +00:00
}
2023-05-31 02:47:52 +00:00
2024-12-02 15:11:43 +00:00
impl<E: Ext> IfaceCommon<E> {
2024-12-27 08:28:11 +00:00
pub(crate) fn register_udp_socket(&self, socket: Arc<UdpSocketBg<E>>) {
2024-12-02 15:11:43 +00:00
let mut sockets = self.sockets.lock();
2024-12-27 08:28:11 +00:00
sockets.insert_udp_socket(socket);
2024-12-02 15:11:43 +00:00
}
2024-12-27 08:28:11 +00:00
pub(crate) fn remove_tcp_listener(&self, socket: &Arc<TcpListenerBg<E>>) {
2024-12-02 15:11:43 +00:00
let mut sockets = self.sockets.lock();
2024-12-27 08:28:11 +00:00
let removed = sockets.remove_listener(socket);
debug_assert!(removed.is_some());
2024-12-02 15:11:43 +00:00
}
2024-12-27 08:28:11 +00:00
pub(crate) fn remove_udp_socket(&self, socket: &Arc<UdpSocketBg<E>>) {
2024-12-02 15:11:43 +00:00
let mut sockets = self.sockets.lock();
2024-12-27 08:28:11 +00:00
let removed = sockets.remove_udp_socket(socket);
debug_assert!(removed.is_some());
2024-12-02 15:11:43 +00:00
}
}
2024-12-03 01:47:47 +00:00
impl<E: Ext> IfaceCommon<E> {
2024-09-20 03:33:20 +00:00
pub(super) fn poll<D, P, Q>(
&self,
device: &mut D,
2024-12-02 15:11:43 +00:00
mut process_phy: P,
2024-09-20 03:33:20 +00:00
mut dispatch_phy: Q,
) -> Option<u64>
where
D: Device + ?Sized,
P: for<'pkt, 'cx, 'tx> FnHelper<
&'pkt [u8],
&'cx mut Context,
D::TxToken<'tx>,
Option<(Ipv4Packet<&'pkt [u8]>, D::TxToken<'tx>)>,
>,
Q: FnMut(&Packet, &mut Context, D::TxToken<'_>),
{
let mut interface = self.interface();
interface.context().now = get_network_timestamp();
2024-12-02 15:11:43 +00:00
let mut sockets = self.sockets.lock();
loop {
let mut new_tcp_conns = Vec::new();
2024-09-20 03:33:20 +00:00
2024-12-02 15:11:43 +00:00
let mut context = PollContext::new(interface.context(), &sockets, &mut new_tcp_conns);
context.poll_ingress(device, &mut process_phy, &mut dispatch_phy);
context.poll_egress(device, &mut dispatch_phy);
2024-09-20 03:33:20 +00:00
2024-12-02 15:11:43 +00:00
// New packets sent by new connections are not handled. So if there are new
// connections, try again.
if new_tcp_conns.is_empty() {
break;
} else {
2024-12-27 08:28:11 +00:00
new_tcp_conns.into_iter().for_each(|tcp_conn| {
let res = sockets.insert_connection(tcp_conn);
debug_assert!(res.is_ok());
});
2024-12-02 15:11:43 +00:00
}
}
2024-12-27 08:28:11 +00:00
sockets.remove_dead_tcp_connections();
2024-12-02 15:11:43 +00:00
2024-12-27 08:28:11 +00:00
for socket in sockets.tcp_listener_iter() {
2024-11-13 15:39:55 +00:00
if socket.has_events() {
socket.on_events();
2024-06-18 07:41:52 +00:00
}
2024-12-27 08:28:11 +00:00
}
for socket in sockets.tcp_conn_iter() {
2024-11-13 15:39:55 +00:00
if socket.has_events() {
socket.on_events();
2024-09-20 03:33:20 +00:00
}
2024-12-27 08:28:11 +00:00
}
for socket in sockets.udp_socket_iter() {
2024-12-02 15:11:43 +00:00
if socket.has_events() {
socket.on_events();
2024-09-20 03:33:20 +00:00
}
2024-12-27 08:28:11 +00:00
}
2024-12-02 15:11:43 +00:00
// Note that only TCP connections can have timers set, so as far as the time to poll is
// concerned, we only need to consider TCP connections.
sockets
2024-12-27 08:28:11 +00:00
.tcp_conn_iter()
2024-12-02 15:11:43 +00:00
.map(|socket| socket.next_poll_at_ms())
.min()
}
}
/// A port bound to an iface.
///
/// When dropped, the port is automatically released.
//
// FIXME: TCP and UDP ports are independent. Find a way to track the protocol here.
pub struct BoundPort<E: Ext> {
iface: Arc<dyn Iface<E>>,
port: u16,
}
impl<E: Ext> BoundPort<E> {
/// Returns a reference to the iface.
pub fn iface(&self) -> &Arc<dyn Iface<E>> {
&self.iface
}
/// Returns the port number.
pub fn port(&self) -> u16 {
self.port
}
/// Returns the bound endpoint.
pub fn endpoint(&self) -> Option<IpEndpoint> {
let ip_addr = {
let ipv4_addr = self.iface().ipv4_addr()?;
IpAddress::Ipv4(ipv4_addr)
};
Some(IpEndpoint::new(ip_addr, self.port))
}
}
impl<E: Ext> Drop for BoundPort<E> {
fn drop(&mut self) {
self.iface.common().release_port(self.port);
2023-05-31 02:47:52 +00:00
}
}