nic_router: remove use of exception handling

Remove 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.

This also 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, thereby causing broken connections. The change is part of this
commit as the approach to integrating garbage collection relied strongly on
exception handling.

The user story behind removing garbage collection: The router emergency-dropped
an established TCP connection (with NAPT) and on the next matching packet
re-created it with a 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 #4729
This commit is contained in:
Martin Stein
2024-05-02 13:25:26 +02:00
committed by Norman Feske
parent 0faec6afaa
commit ac42ade48c
49 changed files with 1727 additions and 1913 deletions

View File

@ -205,26 +205,19 @@ class Net::Dhcp_packet
/**
* Domain name server option
*/
class Dns_server : public Option
struct Dns_server : public Option
{
private:
static constexpr Code CODE = Code::DNS_SERVER;
Ipv4_address _dns_servers[0];
Dns_server(Genode::size_t len) : Option(CODE, (Genode::uint8_t)len) { }
public:
void for_each_address(auto const &fn) const
{
Ipv4_address const *dns_servers = (Ipv4_address const *)((Genode::addr_t)this + sizeof(*this));
for (unsigned idx = 0; idx < len() / sizeof(*dns_servers); idx++)
fn(dns_servers[idx]);
}
static constexpr Code CODE = Code::DNS_SERVER;
Dns_server(Genode::size_t len) : Option(CODE, (Genode::uint8_t)len) { }
void for_each_address(auto const &fn) const
{
for (unsigned idx = 0;
idx < len() / sizeof(_dns_servers[0]); idx++) {
fn(_dns_servers[idx]);
}
}
};
/**
@ -516,6 +509,24 @@ class Net::Dhcp_packet
}
}
template <typename T>
void with_option(auto const &found_fn, auto const &not_found_fn) const
{
bool found = false;
for_each_option([&] (Option const &opt) {
if (found || opt.code() != T::CODE)
return;
found = true;
found_fn(*(T const *)(&opt));
});
if (!found)
not_found_fn();
}
template <typename T>
void with_option(auto const &fn) const { with_option<T>(fn, []{}); }
/***************
** Accessors **