在asterinas中,其一个iface对应自身的一个socketset以及端口占用表。是否需要重新设计内核中socket与iface的资源关系?
现有的端口占用表是全局的,应该将其与网卡相绑定
但是如果将socketset与iface绑定,那么对应的sockethandle的管理也会与iface绑定,那系统统计socket状态与数量的话似乎只能一个个iface轮询过去?就不能再统一地管理socket了;同时沿用从前的信息传递的实现的话,仍然需要轮询所有网卡而非进程打开的socket对应的网卡,那么对于解决 同一时间只能由一个进程访问socketset 的问题意义不大?
或者说,需要引入机制,使得进程只会poll对应bind或listen的socket所在的iface,从而限制进程占用的资源的范围?
@atm7718 你怎么看
我现在尝试引入 IfaceCommon
来解耦 iface
的实现,并把 SocketSet
分离进 IfaceCommon
pub trait Iface: crate::driver::base::device::Device {
/// # `common`
/// 获取网卡的公共信息
fn common(&self) -> &IfaceCommon;
/// # `mac`
/// 获取网卡的MAC地址
fn mac(&self) -> smoltcp::wire::EthernetAddress;
/// # `name`
/// 获取网卡名
fn name(&self) -> String;
/// # `nic_id`
/// 获取网卡id
fn nic_id(&self) -> usize {
self.common().iface_id
}
/// # `poll`
/// 用于轮询接口的状态。
/// ## 参数
/// - `sockets` :一个可变引用到 `smoltcp::iface::SocketSet`,表示要轮询的套接字集
/// ## 返回值
/// - 成功返回 `Ok(())`
/// - 如果轮询失败,返回 `Err(SystemError::EAGAIN_OR_EWOULDBLOCK)`,表示需要再次尝试或者操作会阻塞
fn poll(&self) -> Result<(), SystemError>;
/// # `update_ip_addrs`
/// 用于更新接口的 IP 地址
/// ## 参数
/// - `ip_addrs` :一个包含 `smoltcp::wire::IpCidr` 的切片,表示要设置的 IP 地址和子网掩码
/// ## 返回值
/// - 如果 `ip_addrs` 的长度不为 1,返回 `Err(SystemError::EINVAL)`,表示输入参数无效
fn update_ip_addrs(&self, ip_addrs: &[smoltcp::wire::IpCidr]) -> Result<(), SystemError> {
self.common().update_ip_addrs(ip_addrs)
}
/// @brief 获取smoltcp的网卡接口类型
#[inline(always)]
fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface> {
&self.common().iface
}
// fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
/// # `sockets`
/// 获取网卡的套接字集
fn sockets(&self) -> &SpinLock<smoltcp::iface::SocketSet<'static>> {
&self.common().sockets
}
/// # `port_manager`
/// 用于管理网卡的端口
fn port_manager(&self) -> &crate::net::socket::PortManager {
&self.common().port_manager
}
}
pub struct IfaceCommon {
iface_id: usize,
iface: SpinLock<smoltcp::iface::Interface>,
sockets: SpinLock<smoltcp::iface::SocketSet<'static>>,
port_manager: crate::net::socket::PortManager,
_poll_at_ms: core::sync::atomic::AtomicU64,
}
impl fmt::Debug for IfaceCommon {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IfaceCommon")
.field("iface_id", &self.iface_id)
.field("sockets", &self.sockets)
.field("port_manager", &self.port_manager)
.field("_poll_at_ms", &self._poll_at_ms)
.finish()
}
}
impl IfaceCommon {
pub fn new(iface_id: usize, iface: smoltcp::iface::Interface) -> Self {
IfaceCommon {
iface_id,
iface: SpinLock::new(iface),
sockets: SpinLock::new(smoltcp::iface::SocketSet::new(vec![])),
port_manager: crate::net::socket::PortManager::new(),
_poll_at_ms: core::sync::atomic::AtomicU64::new(0),
}
}
pub fn poll<D>(&self, device: &mut D) -> Result<(), SystemError>
where
D: smoltcp::phy::Device + ?Sized,
{
let timestamp = crate::time::Instant::now().into();
let mut sockets = self.sockets.lock();
if self.iface.lock().poll(timestamp, device, &mut sockets) {
return Ok(());
} else {
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
}
pub fn update_ip_addrs(&self, ip_addrs: &[smoltcp::wire::IpCidr]) -> Result<(), SystemError> {
if ip_addrs.len() != 1 {
return Err(SystemError::EINVAL);
}
self.iface.lock().update_ip_addrs(|addrs| {
let dest = addrs.iter_mut().next();
if let Some(dest) = dest {
*dest = ip_addrs[0];
} else {
addrs.push(ip_addrs[0]).expect("Push ipCidr failed: full");
}
});
return Ok(());
}
}
但是我发现紧接着 SocketHandle
也会因此与网卡相绑定;那么 Iface
还需要管理 Socket
,耦合反而严重了……?
@GnoCiYeH 你怎么看这个问题