-
-
Notifications
You must be signed in to change notification settings - Fork 167
refactor(net): 重构TCP listening backlog为动态扩展 #1316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,10 +4,12 @@ use crate::filesystem::epoll::EPollEventType; | |||||||||||
| use crate::libs::rwlock::RwLock; | ||||||||||||
| use crate::net::socket::{self, inet::Types}; | ||||||||||||
| use alloc::boxed::Box; | ||||||||||||
| use alloc::vec::Vec; | ||||||||||||
| use alloc::sync::Arc; | ||||||||||||
| use alloc::collections::VecDeque; | ||||||||||||
| use smoltcp; | ||||||||||||
| use smoltcp::socket::tcp; | ||||||||||||
| use system_error::SystemError; | ||||||||||||
| use log::debug; | ||||||||||||
|
|
||||||||||||
| // pub const DEFAULT_METADATA_BUF_SIZE: usize = 1024; | ||||||||||||
| pub const DEFAULT_RX_BUF_SIZE: usize = 128 * 1024; | ||||||||||||
|
|
@@ -134,25 +136,7 @@ impl Init { | |||||||||||
| smoltcp::wire::IpListenEndpoint::from(local) | ||||||||||||
| }; | ||||||||||||
| log::debug!("listen at {:?}", listen_addr); | ||||||||||||
| let mut inners = Vec::new(); | ||||||||||||
| if let Err(err) = || -> Result<(), SystemError> { | ||||||||||||
| for _ in 0..(backlog - 1) { | ||||||||||||
| // -1 because the first one is already bound | ||||||||||||
| let new_listen = socket::inet::BoundInner::bind( | ||||||||||||
| new_listen_smoltcp_socket(listen_addr), | ||||||||||||
| listen_addr | ||||||||||||
| .addr | ||||||||||||
| .as_ref() | ||||||||||||
| .unwrap_or(&smoltcp::wire::IpAddress::from( | ||||||||||||
| smoltcp::wire::Ipv4Address::UNSPECIFIED, | ||||||||||||
| )), | ||||||||||||
| )?; | ||||||||||||
| inners.push(new_listen); | ||||||||||||
| } | ||||||||||||
| Ok(()) | ||||||||||||
| }() { | ||||||||||||
| return Err((Init::Bound((inner, local)), err)); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| if let Err(err) = inner.with_mut::<smoltcp::socket::tcp::Socket, _, _>(|socket| { | ||||||||||||
| socket | ||||||||||||
|
|
@@ -162,11 +146,12 @@ impl Init { | |||||||||||
| return Err((Init::Bound((inner, local)), err)); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| inners.push(inner); | ||||||||||||
| let mut inners = VecDeque::new(); | ||||||||||||
| inners.push_back(Arc::new(inner)); | ||||||||||||
| return Ok(Listening { | ||||||||||||
| inners, | ||||||||||||
| connect: AtomicUsize::new(0), | ||||||||||||
| inners: RwLock::new(inners), | ||||||||||||
| listen_addr, | ||||||||||||
| backlog, | ||||||||||||
| }); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
|
|
@@ -289,55 +274,78 @@ impl Connecting { | |||||||||||
|
|
||||||||||||
| #[derive(Debug)] | ||||||||||||
| pub struct Listening { | ||||||||||||
| inners: Vec<socket::inet::BoundInner>, | ||||||||||||
| connect: AtomicUsize, | ||||||||||||
| inners: RwLock<VecDeque<Arc<socket::inet::BoundInner>>>, | ||||||||||||
| backlog: usize, | ||||||||||||
| listen_addr: smoltcp::wire::IpListenEndpoint, | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| impl Listening { | ||||||||||||
| pub fn accept(&mut self) -> Result<(Established, smoltcp::wire::IpEndpoint), SystemError> { | ||||||||||||
| let connected: &mut socket::inet::BoundInner = self | ||||||||||||
| .inners | ||||||||||||
| .get_mut(self.connect.load(core::sync::atomic::Ordering::Relaxed)) | ||||||||||||
| .unwrap(); | ||||||||||||
| let inners_guard = self.inners.read(); | ||||||||||||
| let inner = match inners_guard.front() { | ||||||||||||
| Some(v) => v, | ||||||||||||
| None => return Err(SystemError::EAGAIN_OR_EWOULDBLOCK), | ||||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| if connected.with::<smoltcp::socket::tcp::Socket, _, _>(|socket| !socket.is_active()) { | ||||||||||||
| if inner.with::<smoltcp::socket::tcp::Socket, _, _>(|socket| !socket.is_active()) { | ||||||||||||
| return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); | ||||||||||||
| } | ||||||||||||
| drop(inners_guard); | ||||||||||||
|
|
||||||||||||
| let mut inners_writer = self.inners.write(); | ||||||||||||
| let connected = match inners_writer.pop_front() { | ||||||||||||
| Some(v) => v, | ||||||||||||
| None => return Err(SystemError::EAGAIN_OR_EWOULDBLOCK), | ||||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| if inners_writer.len() == 0 { | ||||||||||||
| let new_listen = match socket::inet::BoundInner::bind( | ||||||||||||
| new_listen_smoltcp_socket(self.listen_addr), | ||||||||||||
| self.listen_addr | ||||||||||||
| .addr | ||||||||||||
| .as_ref() | ||||||||||||
| .unwrap_or(&smoltcp::wire::IpAddress::from( | ||||||||||||
| smoltcp::wire::Ipv4Address::UNSPECIFIED, | ||||||||||||
| )), | ||||||||||||
| ) { | ||||||||||||
| Ok(inner) => inner, | ||||||||||||
| Err(_) => return Err(SystemError::EAGAIN_OR_EWOULDBLOCK), | ||||||||||||
| }; | ||||||||||||
| inners_writer.push_back(Arc::new(new_listen)); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| let remote_endpoint = connected.with::<smoltcp::socket::tcp::Socket, _, _>(|socket| { | ||||||||||||
| socket | ||||||||||||
| .remote_endpoint() | ||||||||||||
| .expect("A Connected Tcp With No Remote Endpoint") | ||||||||||||
| }); | ||||||||||||
|
|
||||||||||||
| // log::debug!("local at {:?}", local_endpoint); | ||||||||||||
|
|
||||||||||||
| let mut new_listen = socket::inet::BoundInner::bind( | ||||||||||||
| new_listen_smoltcp_socket(self.listen_addr), | ||||||||||||
| self.listen_addr | ||||||||||||
| .addr | ||||||||||||
| .as_ref() | ||||||||||||
| .unwrap_or(&smoltcp::wire::IpAddress::from( | ||||||||||||
| smoltcp::wire::Ipv4Address::UNSPECIFIED, | ||||||||||||
| )), | ||||||||||||
| )?; | ||||||||||||
|
|
||||||||||||
| // swap the connected socket with the new_listen socket | ||||||||||||
| // TODO is smoltcp socket swappable? | ||||||||||||
| core::mem::swap(&mut new_listen, connected); | ||||||||||||
|
|
||||||||||||
| return Ok((Established { inner: new_listen }, remote_endpoint)); | ||||||||||||
| return Ok((Established { inner: Arc::try_unwrap(connected).unwrap() }, remote_endpoint)); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| pub fn update_io_events(&self, pollee: &AtomicUsize) { | ||||||||||||
| let position = self.inners.iter().position(|inner| { | ||||||||||||
| inner.with::<smoltcp::socket::tcp::Socket, _, _>(|socket| socket.is_active()) | ||||||||||||
| }); | ||||||||||||
| let mut inners_guard = self.inners.write(); | ||||||||||||
| let inner = match inners_guard.back() { | ||||||||||||
| Some(inner) => inner, | ||||||||||||
| None => return debug!("the tcp socket inners is empty"), | ||||||||||||
|
||||||||||||
| None => return debug!("the tcp socket inners is empty"), | |
| None => { | |
| debug!("the tcp socket inners is empty"); | |
| return; | |
| } |
Mico-rstar marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Oct 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using debug! macro in a return statement is unconventional. Consider using a separate debug! call followed by return, or return an appropriate value/error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里直接unwarp吗,加个判断是否为空吧,为空的话就返回None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
能说说你这里为什么要逐包处理吗
之前的写法可以一次性处理多个包,然后唤醒bound_sockets,然后可以同时唤醒多个在等待数据的socket
但是现在你这样的写法,每次有一个包的到来,都会去唤醒整个bound_sockets,但是最终只有一个socket真正收到数据,会不会有点不太必要
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
之前的写法能够一次处理多个包,关键在于提前bind backlog个数量的socket,这个pr希望实现类似于linux动态扩展wait_queue的机制。考虑过两种解决方案:
方案2相对优雅,且可以对smoltcp的分发机制进行优化,例如用hashmap来维护sockets set,但需要对smoltcp进行修改。
是否有更好的方案,或者是否有准备对smoltcp进行优化