mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
nic_router: improve handling of TCP termination
Like suggested by RFC 2663, reprogram the dissolve timeout of a TCP link state to 2 times the maximum segment lifetime (by default 1 minute) when receiving a matching packet with the FIN flag set, or with the ACK flag set to acknowledge a FIN of the remote side. Mark a link state as closed (no further reprogramming of the dissolve timeout) and set the dissolve timeout to 2 times the maximum segment lifetime when receiving a packet with the RESET flag set. Issue #2953
This commit is contained in:
parent
3db7181104
commit
bd77bb41df
@ -218,46 +218,34 @@ Tcp_link::Tcp_link(Interface &cln_interface,
|
||||
{ }
|
||||
|
||||
|
||||
void Tcp_link::_fin_acked()
|
||||
void Tcp_link::_tcp_packet(Tcp_packet &tcp,
|
||||
Peer &sender,
|
||||
Peer &receiver)
|
||||
{
|
||||
if (_server_fin_acked && _client_fin_acked) {
|
||||
_dissolve_timeout.schedule(Microseconds(_config().tcp_max_segm_lifetime().value << 1));
|
||||
_closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Tcp_link::server_packet(Tcp_packet &tcp)
|
||||
{
|
||||
if (_closed) {
|
||||
if (_state == State::CLOSED) {
|
||||
return; }
|
||||
|
||||
if (tcp.fin()) {
|
||||
_server_fin = true; }
|
||||
|
||||
if (tcp.ack() && _client_fin) {
|
||||
_client_fin_acked = true;
|
||||
_fin_acked();
|
||||
if (tcp.rst()) {
|
||||
_state = State::CLOSED;
|
||||
} else {
|
||||
if (tcp.fin()) {
|
||||
sender.fin = true;
|
||||
_state = State::CLOSING;
|
||||
}
|
||||
if (receiver.fin && tcp.ack()) {
|
||||
receiver.fin_acked = true;
|
||||
if (sender.fin_acked) {
|
||||
_state = State::CLOSED; }
|
||||
else {
|
||||
_state = State::CLOSING; }
|
||||
}
|
||||
}
|
||||
if (!_closed) {
|
||||
_packet(); }
|
||||
}
|
||||
|
||||
|
||||
void Tcp_link::client_packet(Tcp_packet &tcp)
|
||||
{
|
||||
if (_closed) {
|
||||
return; }
|
||||
|
||||
if (tcp.fin()) {
|
||||
_client_fin = true; }
|
||||
|
||||
if (tcp.ack() && _server_fin) {
|
||||
_server_fin_acked = true;
|
||||
_fin_acked();
|
||||
if (_state == State::OPEN) {
|
||||
_packet();
|
||||
} else {
|
||||
_dissolve_timeout.schedule(
|
||||
Microseconds(_config().tcp_max_segm_lifetime().value << 1));
|
||||
}
|
||||
if (!_closed) {
|
||||
_packet(); }
|
||||
}
|
||||
|
||||
|
||||
|
@ -200,13 +200,21 @@ class Net::Tcp_link : public Link
|
||||
{
|
||||
private:
|
||||
|
||||
bool _client_fin { false };
|
||||
bool _server_fin { false };
|
||||
bool _client_fin_acked { false };
|
||||
bool _server_fin_acked { false };
|
||||
bool _closed { false };
|
||||
enum class State : Genode::uint8_t { OPEN, CLOSING, CLOSED, };
|
||||
|
||||
void _fin_acked();
|
||||
struct Peer
|
||||
{
|
||||
bool fin { false };
|
||||
bool fin_acked { false };
|
||||
};
|
||||
|
||||
State _state { State::OPEN };
|
||||
Peer _client { };
|
||||
Peer _server { };
|
||||
|
||||
void _tcp_packet(Tcp_packet &tcp,
|
||||
Peer &sender,
|
||||
Peer &receiver);
|
||||
|
||||
public:
|
||||
|
||||
@ -219,9 +227,9 @@ class Net::Tcp_link : public Link
|
||||
Configuration &config,
|
||||
L3_protocol const protocol);
|
||||
|
||||
void client_packet(Tcp_packet &tcp);
|
||||
void client_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _client, _server); }
|
||||
|
||||
void server_packet(Tcp_packet &tcp);
|
||||
void server_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _server, _client); }
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user