Socket 系统
ax-net 的 socket 层向上提供统一的 POSIX-like socket facade,向下分别连接 smoltcp IP socket、内核 Unix domain socket transport 和可选 vsock transport。IP 类 socket 共享单个 smoltcp SocketSet,但 TCP 监听、UDP bind 冲突、raw packet 过滤、Unix namespace 和 vsock connection manager 都由 ax-net 在协议核心外补齐。
核心源码:
| 源码 | 职责 |
|---|---|
socket.rs | 统一地址、send/recv 选项、SocketOps trait、Socket 枚举分发 |
general.rs | 通用 socket 选项、超时、nonblocking、SO_BINDTODEVICE、poll helper |
wrapper.rs | 全局 smoltcp SocketSet 包装和 UDP bind side table |
state.rs | TCP 等 socket 的轻量状态门禁 |
listen_table.rs | TCP listen bucket、SYN/accept 队列、accept waker |
tcp.rs | TCP stream socket、端口仲裁、connect/listen/accept、orphan 接入 |
udp.rs | UDP datagram socket、connected peer、MSG_MORE corking、route-aware source selection |
raw.rs | Raw IP socket、ICMP loopback、peer filter、deferred RX |
unix/ | Unix stream/datagram transport、abstract/path namespace |
vsock/ | 可选 AF_VSOCK facade 和 stream transport |
设计边界
socket 层通过 SocketOps trait 和 Socket 枚举把系统调用语义映射到协议栈内部对象。它将 AF_INET、AF_UNIX、AF_VSOCK 的地址统一为 SocketAddrEx,将 bind/connect/listen/accept/send/recv/shutdown 统一为 trait 方法,并通过 GeneralOptions 维护 O_NONBLOCK、SO_REUSEADDR、超时和 SO_BINDTODEVICE 等通用选项。
IP 类 socket(TCP/UDP/raw)持有 smoltcp SocketHandle,注册到全局 SocketSetWrapper。socket 层补齐 smoltcp 不直接提供的 POSIX 语义——TCP accept queue(ListenTable)、UDP wildcard bind 冲突(udp_binds side table)、raw connected-peer 过滤。出接口选择由控制面 NetControl 在 bind/connect 时决策,实际发包由 Router::dispatch() 在 net-poll worker 中完成;socket 操作本身不同步推进 Interface::poll(),只调用 request_poll() 请求 worker 推进。
Unix domain socket 和 vsock 不经过 smoltcp,各自维护独立的 transport、namespace 和连接状态,但共享 SocketOps/Configurable/Pollable 入口,向上层呈现一致的 socket facade。
典型关系如下:
公共 Facade
公共 facade 定义跨协议族共享的数据形状和操作入口。系统调用层只需要持有 Socket,不需要知道底层是 smoltcp、Unix transport 还是 vsock connection manager。
地址与选项
SocketAddrEx 是跨地址族的统一地址类型:
// socket.rs
pub enum SocketAddrEx {
Ip(SocketAddr),
Unix(UnixSocketAddr),
#[cfg(feature = "vsock")]
Vsock(VsockAddr),
}
send/recv 选项保留 Linux MSG_* 语义:
pub struct SendOptions {
pub to: Option<SocketAddrEx>,
pub flags: SendFlags,
pub cmsg: Vec<CMsgData>,
}
pub struct RecvOptions<'a> {
pub from: Option<&'a mut SocketAddrEx>,
pub flags: RecvFlags,
pub cmsg: Option<&'a mut Vec<CMsgData>>,
pub truncated: Option<&'a mut bool>,
}
其中 MSG_DONTWAIT 只影响当前调用,不修改 socket 自身的 O_NONBLOCK;MSG_PEEK、MSG_TRUNC、MSG_MORE 由具体 transport 按协议语义解释。
SocketOps
SocketOps 是所有 backend 的统一接口:
pub trait SocketOps: Configurable {
fn bind(&self, local_addr: SocketAddrEx) -> AxResult;
fn connect(&self, remote_addr: SocketAddrEx) -> AxResult;
fn listen(&self, _backlog: usize) -> AxResult {
Err(AxError::OperationNotSupported)
}
fn accept(&self) -> AxResult<Socket> {
Err(AxError::OperationNotSupported)
}
fn send(&self, src: impl Read + IoBuf, options: SendOptions) -> AxResult<usize>;
fn recv(&self, dst: impl Write + IoBufMut, options: RecvOptions<'_>) -> AxResult<usize>;
fn recv_available(&self) -> AxResult<usize> {
Err(AxError::OperationNotSupported)
}
fn local_addr(&self) -> AxResult<SocketAddrEx>;
fn peer_addr(&self) -> AxResult<SocketAddrEx>;
fn shutdown(&self, how: Shutdown) -> AxResult;
}
默认实现只给出“不支持”的语义,具体 backend 再按协议覆盖。例如 TCP 支持 listen/accept,UDP/raw 不支持;Unix stream 支持 accept,Unix datagram 不按 TCP listen 语义工作;vsock 提供 stream transport。
Backend 分发
Socket 枚举负责把统一 API 分发到具体 backend:
pub enum Socket {
Udp(Box<UdpSocket>),
Tcp(Box<TcpSocket>),
Raw(Box<RawSocket>),
Unix(Box<UnixSocket>),
#[cfg(feature = "vsock")]
Vsock(Box<VsockSocket>),
}
| Backend | 地址族/类型 | 协议核心 | 关键状态 |
|---|---|---|---|
TcpSocket | AF_INET / SOCK_STREAM | smoltcp TCP socket | StateLock、TCP_BOUND_PORTS、ListenTable、orphan |
UdpSocket | AF_INET / SOCK_DGRAM | smoltcp UDP socket | UDP bind side table、connected peer、cork |
RawSocket | AF_INET / SOCK_RAW | smoltcp raw socket | local/peer filter、loopback RX、deferred RX |
UnixSocket | AF_UNIX / stream,dgram | in-kernel transport | abstract/path namespace、stream/dgram transport |
VsockSocket | AF_VSOCK / stream | rdif-vsock transport | connection manager、stream ring buffers |