nic_router: fix uncaught bit alloc exception

* catch every possible path of the Bit_allocator_dynamic::Out_of_indices
  exception
* add unconditional log output in the new "catch" directives, so, we will be
  able to debug the problem a bit more in detail next time

Fixes #4036
This commit is contained in:
Martin Stein 2021-03-03 13:28:25 +01:00 committed by Norman Feske
parent 89ffc48576
commit 25a212aa24
4 changed files with 57 additions and 12 deletions

View File

@ -150,9 +150,27 @@ void Dhcp_server::alloc_ip(Ipv4_address const &ip)
}
void Dhcp_server::free_ip(Ipv4_address const &ip)
void Dhcp_server::free_ip(Domain const &domain,
Ipv4_address const &ip)
{
_ip_alloc.free(ip.to_uint32_little_endian() - _ip_first_raw);
try {
_ip_alloc.free(ip.to_uint32_little_endian() - _ip_first_raw);
}
catch (Bit_allocator_dynamic::Out_of_indices) {
/*
* This message is printed independent from the routers
* verbosity configuration in order to track down an exception
* of type Bit_allocator_dynamic::Out_of_indices that was
* previously not caught. We have observed this exception once,
* but without a specific use pattern that would
* enable for a systematic reproduction of the issue.
* The uncaught exception was observed in a 21.03 Sculpt OS
* with a manually configured router, re-configuration involved.
*/
log("[", domain, "] DHCP server: failed to free IP ",
ip, " (IP range: first ", _ip_first, " last ", _ip_last, ")");
}
}

View File

@ -100,7 +100,8 @@ class Net::Dhcp_server : private Genode::Noncopyable,
void alloc_ip(Ipv4_address const &ip);
void free_ip(Ipv4_address const &ip);
void free_ip(Domain const &domain,
Ipv4_address const &ip);
bool ready() const;

View File

@ -258,16 +258,42 @@ void Domain::init(Domain_tree &domains)
if (_ip_config_dynamic) {
_invalid("DHCP server and client at once"); }
Dhcp_server &dhcp_server = *new (_alloc)
Dhcp_server(dhcp_server_node, *this, _alloc,
ip_config().interface, domains);
try {
Dhcp_server &dhcp_server = *new (_alloc)
Dhcp_server(dhcp_server_node, *this, _alloc,
ip_config().interface, domains);
try { dhcp_server.dns_server_from().ip_config_dependents().insert(this); }
catch (Pointer<Domain>::Invalid) { }
try {
dhcp_server.
dns_server_from().ip_config_dependents().insert(this);
}
catch (Pointer<Domain>::Invalid) { }
_dhcp_server = dhcp_server;
if (_config.verbose()) {
log("[", *this, "] DHCP server: ", _dhcp_server()); }
_dhcp_server = dhcp_server;
if (_config.verbose()) {
log("[", *this, "] DHCP server: ", _dhcp_server()); }
}
catch (Bit_allocator_dynamic::Out_of_indices) {
/*
* This message is printed independent from the routers
* verbosity configuration in order to track down an exception
* of type Bit_allocator_dynamic::Out_of_indices that was
* previously not caught. We have observed this exception once,
* but without a specific use pattern that would
* enable for a systematic reproduction of the issue.
* The uncaught exception was observed in a 21.03 Sculpt OS
* with a manually configured router, re-configuration involved.
*/
log("[", *this, "] DHCP server: failed to initialize ",
"(IP range: first ",
dhcp_server_node.attribute_value("ip_first", Ipv4_address()),
" last ",
dhcp_server_node.attribute_value("ip_last", Ipv4_address()),
")");
throw Dhcp_server::Invalid { };
}
}
catch (Xml_node::Nonexistent_sub_node) { }
catch (Dhcp_server::Invalid) { _invalid("invalid DHCP server"); }

View File

@ -1488,7 +1488,7 @@ void Interface::_ready_to_ack()
void Interface::_destroy_dhcp_allocation(Dhcp_allocation &allocation,
Domain &local_domain)
{
try { local_domain.dhcp_server().free_ip(allocation.ip()); }
try { local_domain.dhcp_server().free_ip(local_domain, allocation.ip()); }
catch (Pointer<Dhcp_server>::Invalid) { }
destroy(_alloc, &allocation);
}