mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-19 04:26:39 +00:00
Remove TimeWait socket if a new Syn is received
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
438dad888e
commit
c1fd09fd41
@ -12,9 +12,9 @@ use core::{
|
|||||||
use ostd::sync::{LocalIrqDisabled, RwLock, SpinLock, SpinLockGuard};
|
use ostd::sync::{LocalIrqDisabled, RwLock, SpinLock, SpinLockGuard};
|
||||||
use smoltcp::{
|
use smoltcp::{
|
||||||
iface::Context,
|
iface::Context,
|
||||||
socket::{udp::UdpMetadata, PollAt},
|
socket::{tcp::State, udp::UdpMetadata, PollAt},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
wire::{IpAddress, IpEndpoint, IpRepr, TcpRepr, UdpRepr},
|
wire::{IpAddress, IpEndpoint, IpRepr, TcpControl, TcpRepr, UdpRepr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{event::SocketEventObserver, RawTcpSocket, RawUdpSocket};
|
use super::{event::SocketEventObserver, RawTcpSocket, RawUdpSocket};
|
||||||
@ -103,6 +103,16 @@ impl TcpSocket {
|
|||||||
self.is_dead.store(true, Ordering::Relaxed);
|
self.is_dead.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the TCP socket in [`TimeWait`] state as dead.
|
||||||
|
///
|
||||||
|
/// See [`BoundTcpSocketInner::is_dead`] for the definition of dead TCP sockets.
|
||||||
|
///
|
||||||
|
/// [`TimeWait`]: smoltcp::socket::tcp::State::TimeWait
|
||||||
|
fn set_dead_timewait(&self, socket: &RawTcpSocketExt) {
|
||||||
|
debug_assert!(socket.in_background && socket.state() == smoltcp::socket::tcp::State::TimeWait);
|
||||||
|
self.is_dead.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnySocket for TcpSocket {
|
impl AnySocket for TcpSocket {
|
||||||
@ -451,6 +461,27 @@ impl<E> BoundTcpSocketInner<E> {
|
|||||||
return TcpProcessResult::NotProcessed;
|
return TcpProcessResult::NotProcessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the socket is in the TimeWait state and a new packet arrives that is a SYN packet
|
||||||
|
// without ack number, the TimeWait socket will be marked as dead,
|
||||||
|
// and the packet will be passed on to any other listening sockets for processing.
|
||||||
|
//
|
||||||
|
// FIXME: Directly marking the TimeWait socket dead is not the correct approach.
|
||||||
|
// In Linux, a TimeWait socket remains alive to handle "old duplicate segments".
|
||||||
|
// If a TimeWait socket receives a new SYN packet, Linux will select a suitable
|
||||||
|
// listening socket from the socket table to respond to that SYN request.
|
||||||
|
// (https://elixir.bootlin.com/linux/v6.0.9/source/net/ipv4/tcp_ipv4.c#L2137)
|
||||||
|
// Moreover, the Initial Sequence Number (ISN) will be set to prevent the TimeWait socket
|
||||||
|
// from erroneously handling packets from the new connection.
|
||||||
|
// (https://elixir.bootlin.com/linux/v6.0.9/source/net/ipv4/tcp_minisocks.c#L194)
|
||||||
|
// Implementing such behavior is challenging with the current smoltcp APIs.
|
||||||
|
if socket.state() == State::TimeWait
|
||||||
|
&& tcp_repr.control == TcpControl::Syn
|
||||||
|
&& tcp_repr.ack_number.is_none()
|
||||||
|
{
|
||||||
|
self.socket.set_dead_timewait(&socket);
|
||||||
|
return TcpProcessResult::NotProcessed;
|
||||||
|
}
|
||||||
|
|
||||||
let result = match socket.process(cx, ip_repr, tcp_repr) {
|
let result = match socket.process(cx, ip_repr, tcp_repr) {
|
||||||
None => TcpProcessResult::Processed,
|
None => TcpProcessResult::Processed,
|
||||||
Some((ip_repr, tcp_repr)) => TcpProcessResult::ProcessedWithReply(ip_repr, tcp_repr),
|
Some((ip_repr, tcp_repr)) => TcpProcessResult::ProcessedWithReply(ip_repr, tcp_repr),
|
||||||
|
Reference in New Issue
Block a user