mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 07:46:42 +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) {
|
if (_state == State::CLOSED) {
|
||||||
_dissolve_timeout.schedule(Microseconds(_config().tcp_max_segm_lifetime().value << 1));
|
|
||||||
_closed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Tcp_link::server_packet(Tcp_packet &tcp)
|
|
||||||
{
|
|
||||||
if (_closed) {
|
|
||||||
return; }
|
return; }
|
||||||
|
|
||||||
|
if (tcp.rst()) {
|
||||||
|
_state = State::CLOSED;
|
||||||
|
} else {
|
||||||
if (tcp.fin()) {
|
if (tcp.fin()) {
|
||||||
_server_fin = true; }
|
sender.fin = true;
|
||||||
|
_state = State::CLOSING;
|
||||||
if (tcp.ack() && _client_fin) {
|
|
||||||
_client_fin_acked = true;
|
|
||||||
_fin_acked();
|
|
||||||
}
|
}
|
||||||
if (!_closed) {
|
if (receiver.fin && tcp.ack()) {
|
||||||
_packet(); }
|
receiver.fin_acked = true;
|
||||||
}
|
if (sender.fin_acked) {
|
||||||
|
_state = State::CLOSED; }
|
||||||
|
else {
|
||||||
void Tcp_link::client_packet(Tcp_packet &tcp)
|
_state = State::CLOSING; }
|
||||||
{
|
}
|
||||||
if (_closed) {
|
}
|
||||||
return; }
|
if (_state == State::OPEN) {
|
||||||
|
_packet();
|
||||||
if (tcp.fin()) {
|
} else {
|
||||||
_client_fin = true; }
|
_dissolve_timeout.schedule(
|
||||||
|
Microseconds(_config().tcp_max_segm_lifetime().value << 1));
|
||||||
if (tcp.ack() && _server_fin) {
|
|
||||||
_server_fin_acked = true;
|
|
||||||
_fin_acked();
|
|
||||||
}
|
}
|
||||||
if (!_closed) {
|
|
||||||
_packet(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,13 +200,21 @@ class Net::Tcp_link : public Link
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _client_fin { false };
|
enum class State : Genode::uint8_t { OPEN, CLOSING, CLOSED, };
|
||||||
bool _server_fin { false };
|
|
||||||
bool _client_fin_acked { false };
|
|
||||||
bool _server_fin_acked { false };
|
|
||||||
bool _closed { false };
|
|
||||||
|
|
||||||
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:
|
public:
|
||||||
|
|
||||||
@ -219,9 +227,9 @@ class Net::Tcp_link : public Link
|
|||||||
Configuration &config,
|
Configuration &config,
|
||||||
L3_protocol const protocol);
|
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