Skip to content
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

nic_router: broken SSH pipes #4729

Closed
m-stein opened this issue Jan 17, 2023 · 44 comments
Closed

nic_router: broken SSH pipes #4729

m-stein opened this issue Jan 17, 2023 · 44 comments
Assignees
Labels

Comments

@m-stein
Copy link
Contributor

m-stein commented Jan 17, 2023

@chelmuth reported that SSH connections from his Sculpt VM towards a server on a remote machine sporadically end up broken (without router re-configuration involved).

@m-stein m-stein added the bug label Jan 17, 2023
@m-stein m-stein self-assigned this Jan 17, 2023
@chelmuth
Copy link
Member

I'm going to integrate the fixes in #4728 plus your debug commit into my Sculpt system and will report any insights.

@chelmuth
Copy link
Member

Update: I had one aborted connection yesterday but the log did not reveal any new information as I didn't enable verbose packet log yet. But, after I integrate your additional debug commit networking broke completely with the following error.

[runtime -> nic_router] Error: Uncaught exception of type 'Net::Interface::Bad_transport_protocol'
[runtime -> nic_router] Warning: abort called - thread: ep

Thus, I investigated and finally 7d1779e fixed the uncaught exception.

[runtime -> nic_router] Warning: unknown transport layer protocol
[runtime -> nic_router] Warning: unknown transport layer protocol

I'm curious how this may happen and how you ensure the exception is caught at all other places.

@chelmuth
Copy link
Member

chelmuth commented Oct 6, 2023

Small update: I use Sculpt 23.04 and had an SSH interruption this morning with the following extended error message.

packet_write_wait: Connection to <IP address> port 22: Broken pipe
packet_write_wait: Connection to UNKNOWN port 65535: Broken pipe

The second line bothers me. It may stem from the nature of the connection that uses the SSH proxy mechanism but could also hint the issue we are looking for.

@chelmuth
Copy link
Member

chelmuth commented Dec 5, 2023

I set up a Linux-based bridge to monitor all network traffic of my Sculpt machine and sighted two SSH connection interruptions. In both cases the TCP source port of the established connection on the Sculpt side suddenly changes, which the server side denied by RST. Further packets from the SSH server to the original TCP port are denied by NIC router with ICMP Destination unreachable (Network unreachable). @m-stein I can provide you with the PCAP files.

This morning I provoked stress on the NIC router with sudo nmap -sS -O <LAN router IP> and triggered SSH interruption with comparable symptoms after some seconds.

    No.     Time                           Source     SPort  Destination  DPort  Protocol  Length  Info
    672353  2023-12-05 07:41:00,134210878  10.0.0.30  51419  10.0.0.6     22     TCP       66      51419 → 22 [ACK] Seq=131622 Ack=6142062 Win=161664 Len=0 TSval=2000755302 TSecr=1528207574
    672461  2023-12-05 07:41:30,178468389  10.0.0.30  51419  10.0.0.6     22     SSHv2     118     Client: Encrypted packet (len=52)
    672462  2023-12-05 07:41:30,178846776  10.0.0.6   22     10.0.0.30    51419  SSHv2     94      Server: Encrypted packet (len=28)
1   672463  2023-12-05 07:41:30,179274264  10.0.0.30  51419  10.0.0.6     22     TCP       66      51419 → 22 [ACK] Seq=131674 Ack=6142090 Win=162048 Len=0 TSval=2000785277 TSecr=1528237619
2   674726  2023-12-05 07:42:00,157076594  10.0.0.30  54273  10.0.0.6     22     SSH       118     Client: Encrypted packet (len=52)
3   674727  2023-12-05 07:42:00,157343544  10.0.0.6   22     10.0.0.30    54273  TCP       60      22 → 54273 [RST] Seq=1 Win=0 Len=0
4   674728  2023-12-05 07:42:00,163496730  10.0.0.6   22     10.0.0.30    51419  SSHv2     478     Server: Encrypted packet (len=412)
5   674729  2023-12-05 07:42:00,163788823  10.0.0.30  22     10.0.0.6     51419  ICMP      70      Destination unreachable (Network unreachable)
    674734  2023-12-05 07:42:00,370934689  10.0.0.6   22     10.0.0.30    51419  TCP       478     [TCP Retransmission] 22 → 51419 [PSH, ACK] Seq=6142090 Ack=131674 Win=64128 Len=412 TSval=1528267812 TSecr=2000785277
    674735  2023-12-05 07:42:00,371266450  10.0.0.30  22     10.0.0.6     51419  ICMP      70      Destination unreachable (Network unreachable)
    674742  2023-12-05 07:42:00,578927168  10.0.0.6   22     10.0.0.30    51419  TCP       478     [TCP Retransmission] 22 → 51419 [PSH, ACK] Seq=6142090 Ack=131674 Win=64128 Len=412 TSval=1528268020 TSecr=2000785277
  1. Last successful ACK of the SSH connection (source port 51419)
  2. Sudden source-port change to 54273 (which is just 1 more than the source port of the last nmap stress packet)
  3. SSH server rejects 54273 by RST
  4. SSH server sends to original 51419
  5. NIC router rejects with ICMP but source and destination port seem mixed up?

@chelmuth
Copy link
Member

chelmuth commented Dec 7, 2023

  1. NIC router rejects with ICMP but source and destination port seem mixed up?

Let me update my interpretation here: There is nothing mixed up, it's just the original TCP packet embedded in the ICMP message. Nevertheless I think Destination unreachable (Network unreachable) is not the correct error reply here. According to RFC1812

If a packet is to be forwarded to a host on a network that is directly connected to the router (i.e., the router is the last-hop router) and the router has ascertained that there is no path to the destination host then the router MUST generate a Destination Unreachable, Code 1 (Host Unreachable) ICMP message.

I propose to change the nic_router as follows.

+++ b/repos/os/src/server/nic_router/interface.cc
@@ -1396,7 +1396,7 @@ void Interface::_handle_ip(Ethernet_frame          &eth,
 	if(not ip.dst().is_multicast()) {
 
 		_send_icmp_dst_unreachable(local_intf, eth, ip,
-		                           Icmp_packet::Code::DST_NET_UNREACHABLE);
+		                           Icmp_packet::Code::DST_HOST_UNREACHABLE);
 	}
 	if (_config().verbose()) {
 		log("[", local_domain, "] unroutable packet"); }

After looking at the captured packet traffic during four connection drops, I'm certain that the NIC router decides to drop the link for no reason related to the traffic itself.

@m-stein
Copy link
Contributor Author

m-stein commented Dec 7, 2023

@chelmuth Thanks a lot for gathering and providing all this detailed information! As discussed offline, I'll continue with this issue as soon as the File Vault has settled on a presentable state again. The ICMP-code modification you suggest for the router sounds sensible to me!

chelmuth added a commit that referenced this issue Dec 7, 2023
According to RFC 1812 ICMP Destination unreachable (Network unreachable)
does not quite our case of clients directly behind the router.

  If a packet is to be forwarded to a host on a network that is directly
  connected to the router (i.e., the router is the last-hop router) and
  the router has ascertained that there is no path to the destination
  host then the router MUST generate a Destination Unreachable, Code 1
  (Host Unreachable) ICMP message.

Issue #4729
nfeske pushed a commit that referenced this issue Dec 13, 2023
According to RFC 1812 ICMP Destination unreachable (Network unreachable)
does not quite our case of clients directly behind the router.

  If a packet is to be forwarded to a host on a network that is directly
  connected to the router (i.e., the router is the last-hop router) and
  the router has ascertained that there is no path to the destination
  host then the router MUST generate a Destination Unreachable, Code 1
  (Host Unreachable) ICMP message.

Issue #4729
@m-stein
Copy link
Contributor Author

m-stein commented May 1, 2024

Thanks to the wonderful trace recorder, I was able to create a pcap trace in sculpt and debug the issue in wireshark.

In a setup where I have an open ssh connection and then run nmap -sS -O , the connection breaks quickly. It does so because after a bit of a pause in the ssh exchange, my vbox guest sends a valid ssh packet again (maybe keep alive) that is then nat'ed by the nic router to a source port other than the one used before in the connection. The server doesn't like this and sends a tcp reply with reset flag set on the new port. The reply is nat'ed back to the correct guest ports and so, my ssh has no chance of understanding why the connection was cancelled.

I found a disappointingly simple explanation for the events: The nmap causes the nic router to run into resource exhaustion with the session at some point. So, the internal link state of the ssh connection is thrown away in an attempt to free resources for the nmap stress. When ssh eventually becomes active again, the nic router creates a new link state with a different port.

I can only guess that the reason for this not being a frequent problem is that not so security-aware applications may just work around a changing source port (ignorance, new connection). Anyway, I'm not sure yet what to do about the ssh issue. One solution would be to give a nic router client the opportunity to resolve resource exhaustion by updating the session quota before throwing stuff away. Kind of a band aid would be to make garbage collection smarter, in case it actually makes a difference which link state to throw away and which not.

@chelmuth
Copy link
Member

Regarding our offline discussion about network timeouts it seems worthwhile to look in to Linux. For Linux as client or server host I played around with sudo netstat -ncow --tcp and issued several short-living ssh -t <server host> true sessions. The server side always dropped the connection immediately while the client entered TIME_WAIT for 60s. Also noteworthy is the server output for long-living ssh -t <server host> bash sessions that alternates between the following lines (with differing timeout values).

tcp        0      0 <server IP>:22             <client IP>:56988         ESTABLISHED keepalive (6218,43/0/0)
tcp        0    164 <server IP>:22             <client IP>:56988         ESTABLISHED on (0,20/0/0)

@m-stein
Copy link
Contributor Author

m-stein commented May 16, 2024

I took some reading into online resources regarding the topic. Here are some things I found:

Timeouts

Resource exhaustion

Prevention and recovery
This paper (https://netdevconf.info/2.1/papers/conntrack.pdf) elaborates the topic for nf_conntrack:

  • Those connections might be dropped early under stress:
    • Connections that have not seen traffic in both directions yet
    • TCP that has not seen the whole 3-way handshake yet
    • UDP that has not seen at least one Request-Reply-Request sequence yet
    • TCP in WAIT states
  • Use recommended timeouts by default and only under stress check connections against smaller timeouts
  • Allow for more efficient flow-specific timeouts, e.g., per port or rule
  • Let the router probe connections in order to detect abandoned ones (timeout- or stress-triggered)

Furthermore I found an article series about nf_conntrack (https://thermalcircle.de/doku.php?id=blog:linux:connection_tracking_3_state_and_examples) that gives some insight about "early dropping":

  • Connections are marked with IPS_ASSURED when they should not be early-dropped.
  • ICMP connections never have this flag
  • For UDP and TCP the flag is set according to the suggestions in the above paper

We should also keep in mind, that the above referenced examples are talking about very different limits than we do. While they usually accept at least several 10K connections, I observed limits like 170-270 connections with a session to the NIC router.

@nfeske
Copy link
Member

nfeske commented May 23, 2024

Thanks for the exhaustive review.

@m-stein given those findings, do you already have an actionable plan?

If not, for addressing the concrete issue at hand, I'd suggest two steps:

  1. Keeping the pool of UDP-related meta data separate from TCP-related meta data. So UDP cannot interfere with the connection state of TCP-based protocols.
  2. Evicting connection meta data for non-IPS_ASSURED connections in a least-recently used fashion. If all connections are marked with IPS_ASSURED, evict the least recently used one.

@chelmuth
Copy link
Member

I took some reading into online resources regarding the topic. Here are some things I found:

Timeouts

Just some links for reference depicting Linux kernel default values.

https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_conntrack_proto_icmp.c#L25
https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_conntrack_proto_udp.c#L27
https://elixir.bootlin.com/linux/latest/source/net/netfilter/nf_conntrack_proto_tcp.c#L61

A unidirectional UDP timeout of 30s looks quite reasonable to me and may be implemented first following @nfeske's plan.

@m-stein
Copy link
Contributor Author

m-stein commented May 25, 2024

@nfeske Thanks for your feedback!

On 23.05.24 13:49, Norman Feske wrote:

Thanks for the exhaustive review.

@m-stein https://github.com/m-stein given those findings, do you already have an actionable plan?

So far:

  • I've re-implemented basic garbage collection without exceptions and inline. The latter means that the router doesn't jump out of packet handling, free resources and try handling the packet again from the beginning, but instead frees resources where exhaustion happens and continues).

  • I've implemented that only as much quota as needed is freed.

  • I'm at implementing proper TCP connection-state tracking as it is currently very rudimentary and not sufficient for determining something like IPS_ASSURED)

  • My plan is to use an IPS_ASSURED-like member in link objects which is always false for ICMP, true with timeout after request-reply-request for UDP and true for TCP in ESTABLISHED state. Furthermore, the router should try to evict ICMP first, then UDP and TCP last

If not, for addressing the concrete issue at hand, I'd suggest two steps:

  1. Keeping the pool of UDP-related meta data separate from TCP-related
    meta data. So UDP cannot interfere with the connection state of
    TCP-based protocols.
    These pools are separate. What kind of interference do you mean?
  1. Evicting connection meta data for non-IPS_ASSURED connections in a
    least-recently used fashion. If all connections are marked with
    IPS_ASSURED, evict the least recently used one.

I'll implement the first but would advice against the latter. As far as I learned, other appliances simply drop new packets in this case in order to prevent the issue that @chelmuth ran into. What do you think of the probing-approach instead?

Martin

@m-stein
Copy link
Contributor Author

m-stein commented May 25, 2024

@chelmuth Thanks for these helpful references! My suggestion would be to use all nf_conntrack timeouts as default in the nic_router and actively probe established TCP, say every 5 minutes, in order to cut down the 5 days.

@chelmuth
Copy link
Member

My suggestion would be to use all nf_conntrack timeouts as default in the nic_router and actively probe established TCP, say every 5 minutes, in order to cut down the 5 days.

Probing sounds interesting. How does it work?

@m-stein
Copy link
Contributor Author

m-stein commented May 27, 2024

From https://netdevconf.info/2.1/papers/conntrack.pdf:

Instead of just closing a connection without warning, it would be possible to actively probe endpoints similar to what is done by the SO_KEEPALIVE mechanism described in the tcp manual page[7] by injecting packets after the connection has been idle for some time.

So, in essence, the router would do the same as any Linux with TCP keepalive but not after an eternity but much more frequent.

From https://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/:

... send your peer a keepalive probe packet with no data in it and the ACK flag turned on. You can do this because of the TCP/IP specifications, as a sort of duplicate ACK, and the remote endpoint will have no arguments, as TCP is a stream-oriented protocol. On the other hand, you will receive a reply from the remote host (which doesn't need to support keepalive at all, just TCP/IP), with no data and the ACK set.

As far as I understand it:

  • The router would send keepalives to both peers.
  • In case that a peer is not reachable anymore, a short reply-timeout at the router would eventually remove the connection state and the router could optionally also close the connection at the other peer by sending an RST.
  • In case that a peer is reachable but somehow lost awareness of the connection (e.g. hard reset) this peer responds to the keepalive with an RST packet, causing the router and the other peer to close the connection.

There's also a paragraph in the latter regarding the more general topic of this issue:

The other useful goal of keepalive is to prevent inactivity from disconnecting the channel. It's a very common issue, when you are behind a NAT proxy or a firewall, to be disconnected without a reason. This behavior is caused by the connection tracking procedures implemented in proxies and firewalls, which keep track of all connections that pass through them. Because of the physical limits of these machines, they can only keep a finite number of connections in their memory. The most common and logical policy is to keep newest connections and to discard old and inactive connections first. ... periodically sending packets over the network is a good way to always be in a polar position with a minor risk of deletion.

@chelmuth
Copy link
Member

#4534 seems related this discussion (ARP waiter removal).

@m-stein
Copy link
Contributor Author

m-stein commented May 31, 2024

@chelmuth Thanks for cross-referencing.

@m-stein
Copy link
Contributor Author

m-stein commented May 31, 2024

Regarding probing:

  • @chelmuth added that interfering with the connection traffic might cause problems if not done right and that we should first find out how others do that.
  • It's not easy to find resources regarding simple tcp probing implementations in routers (only for checking liveliness) and other probing seems quite elaborate.
  • However, RFC 5382 also encourages the approach

A common method that is applicable only to TCP is to preferentially abandon sessions for crashed endpoints, followed by closed TCP connections and partially open connections. A NAT can check if an endpoint for a session has crashed by sending a TCP keep-alive packet and receiving a TCP RST packet in response. If the NAT cannot determine whether the endpoint is active, it should not abandon the session until the TCP connection has been idle for some time. Note that an established TCP connection can stay idle (but live) indefinitely; hence, there is no fixed value for an idle-timeout that accommodates all applications. However, a large idle-timeout motivated by recommendations in [RFC1122] can reduce the chances of abandoning a live session.

  • Furthermore, from tldp.org:

In fact, TCP permits you to handle a stream, not packets, and so a zero-length data packet is not dangerous for the user program.

  • And the wireshark docs give insight on the keepalive packets layout (we'd have to keep track of the last sequence number):

TCP Keep-Alive
Set when the segment size is zero or one, the current sequence number is one byte less than the next expected sequence number, and none of SYN, FIN, or RST are set.

TCP Keep-Alive ACK
Set when all of the following are true:
The segment size is zero.
The window size is non-zero and hasn’t changed.
The current sequence number is the same as the next expected sequence number.
The current acknowledgment number is the same as the last-seen acknowledgment number.
The most recently seen packet in the reverse direction was a keepalive.
The packet is not a SYN, FIN, or RST.

@m-stein
Copy link
Contributor Author

m-stein commented Jun 3, 2024

@chelmuth Regarding our offline discussion:

Currently, a NIC session request at the router comes in with 3,5M quota, of which only 205K remain after create_session.

The sizes of dynamically allocated session objects:

  • TCP Link: 432
  • UDP Link: 424
  • ICMP Link: 424
  • ARP Waiter: 72
  • DHCP Allocation: 240

So, theoretical max number of connections (without counting DHCP/ARP objects or meta data) is 485.

Furthermore, I have to correct myself regarding the current idle timeouts:

  • established TCP: 10 minutes
  • other TCP: 1 minute (note: also after a complete close handshake as RFC recommends it just in case)
  • UDP: 30 seconds
  • ICMP: 10 seconds

Suggestions:

  • I would drop TCP links right after the close handshake.
  • I would lower non-established TCP to 30 seconds as 60 seconds seem too much to me.
  • I would slightly increase the default quota of NIC sessions because 205K doesn't seem too much to me.
  • Although RFCs and OSs suggest 7440 seconds, I'd stay with the 10 minutes for established TCP as we had no problems with this so far.

@chelmuth
Copy link
Member

chelmuth commented Jun 3, 2024

Suggestions:

  • I would drop TCP links right after the close handshake.
  • I would lower non-established TCP to 30 seconds as 60 seconds seem too much to me.
  • I would slightly increase the default quota of NIC sessions because 205K doesn't seem too much to me.
  • Although RFCs and OSs suggest 7440 seconds, I'd stay with the 10 minutes for established TCP as we had no problems with this so far.

I agree to all four points but request your special attention regarding the impact of increased default resource requirements in point 3. Automatic tests may need to be adapted and Sculpt integration tested.

@m-stein
Copy link
Contributor Author

m-stein commented Jun 3, 2024

@chelmuth Thanks for your feedback. I'll keep an eye on the tests.

m-stein pushed a commit to m-stein/genode that referenced this issue Jun 4, 2024
Similar to how XML nodes can be accessed via a lambda, this commit implements
accessing attributes of XML nodes via a lambda. There are two new methods in
Xml_node: 'with_optional_attribute' calls a functor only if the attribute was
found and with_attribute' additionally calls a functor if the attribute could
not be found. Both methods are const and call the "found" functor with one
argument 'Xml_attribute const &'.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 4, 2024
This commit raises the default RAM quota for Nic/Uplink connections from
'rx/tx buffers + 256K' (x86_64) to 'rx/tx buffers + 512K'. This follows the
observation that a Nic/Uplink connection at the NIC router had only 205K left
after 'create_session' for things like TCP/UDP connection states. This limited
the max number of simultaneous TCP/UDP connections to something like 480.

Note that this increases the total amount of quota per session by only 7% but
the max number of TCP/UDP connections per session by 120%.

Furthermore, this commit makes the quota arch-independent as there are no
indications for why it should depend on the architecture.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 4, 2024
Adds default constructor to Net::Port that initializes the value to 0. This
allows for using Net::Port with the Genode::Attempt utility.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 4, 2024
This removes the garbage collection that the router used to do when a session
ran out of quota. This is motivated by the fact that the garbage collection was
rather simple and removed connection states regardless of their current state.

This caused problems, e.g., when the router dropped an established TCP
connection with NAPT and on the next matching packet re-created it with
different NAPT port, thereby breaking the connection. With this commit,
existing connections are prioritized over new ones during resource exhaustion
and the packets that attempt to create a new connection in such a state are
dropped with a warning in the log (verbose_packet_drop="yes").

Note that the state resolves itself with time as existing connections time out
or are closed by peers.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 4, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
This commit is part of a series that aims for removing the use of C++ exception
as much as possible from the router as C++ exception handling can be resource
intensive and can make code hard to understand.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
The deinitialization method of Domain used to rely on Domain::with_dhcp_server
in order to dissolve and destroy a present DHCP server. However, this method
skipped calling its functor argument also when there was a DHCP server but an
invalid one. This commt replaces the with_dhcp_server with a pointer null-check
in order to fix the leak.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
The Reference and Const_reference utility were introduced in order to express
that something is a reference (no null value) but can be changed dynamically
(not possible with built-in C++ references). However, the idea of preventing
every possibility for null pointer faults, whith wich the router was built
initially, has not prevailed and using pointers instead of the utility saves
logic and makes the code more readable to other C++ developers.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
The TCP connection state "ESTABLISHED" (in the router "OPEN") is a privileged
one for peers because it lasts very long without any peer interaction (in the
NIC router it's only 10 minutes, but RFCs recommend not less than 2 hours and
4 minutes). Furthermore, TCP connections in this state are normally not
available for early-drop on resource exhaustion. This means that this state
binds resources to a connection potentially for a long time without the option
of regaining them under stress. Therefore, this state should be entered with
care.

Up to now, the router marked a TCP connection with this state as soon as it had
seen one matching packet in both directions, which is rather quick. However,
implementing a very precise tracking of the exact TCP states of both peers and
only marking the connection "ESTABLISHED" when both peers are "ESTABLISHED" is
a difficult task with lots of corner cases.

That said, this commit implements a compromise. The router now has two flags
for each peer of a TCP connection - FIN sent and FIN acked - and sets them
according to the observed TCP flags. The "ESTABLISHED" state is entered only
when FIN acked is set for both peers (without having observed an RST or FIN
flag meanwhile).

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
The previous value of 60 seconds was never observed in real-time scenarios and
UDP, for instance always used a timeout of 30 seconds without causing issues.
Note that this applies only to TCP connections in a state other than
ESTABLISHED, i.e., while it is still safe to early-drop the connection.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
RFCs recommend to keep TCP connections for a certain time even after they
finished a close handshake, AFAIK, in order to be able to recognize astray
packets when they arrive later. This seems overambitious especially when in
the context of the router where session quota is pretty limited. Therefore,
this commit drops this final timeout and drops closed connections immediately.

Ref genodelabs#4729
m-stein pushed a commit to m-stein/genode that referenced this issue Jun 25, 2024
The only object that is dynamically allocated by a network interface and that
was not equipped with a self-destruct timeout was the ARP waiter. This commit
closes this gap by adding a timeout to each ARP waiter that is set to 10
seconds by default but can be configured via the new <config> attribute
'arp_request_timeout_sec'.

Ref genodelabs#4729
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants