nic_router: futile ip config updates on dhcp renew

If the IP config does not change on updates to the router IP config of a domain
change (a common case on DHCP RENEW), prevent detaching from the old config and
attaching to the new one. Because this would not only create unnecessary CPU
overhead but also force all clients at all interfaces that are listening to
this config (via config attribute 'dns_config_from') to restart their
networking (re-do DHCP).

Ref #4696
This commit is contained in:
Martin Stein 2022-11-08 13:58:26 +01:00 committed by Christian Helmuth
parent 68ba648897
commit 7a7cac57d9
3 changed files with 40 additions and 2 deletions

View File

@ -118,8 +118,19 @@ void Domain::discard_ip_config()
void Domain::ip_config_from_dhcp_ack(Dhcp_packet &dhcp_ack) void Domain::ip_config_from_dhcp_ack(Dhcp_packet &dhcp_ack)
{ {
/*
* If the IP config didn't change (a common case on DHCP RENEW), prevent
* detaching from the old config and attaching to the new one. Because this
* would not only create unnecessary CPU overhead but also force all
* clients at all interfaces that are listening to this config (via config
* attribute 'dns_config_from') to restart their networking (re-do DHCP).
*/
Ipv4_config const new_ip_config { dhcp_ack, _alloc, *this };
if (*_ip_config == new_ip_config) {
return;
}
_reconstruct_ip_config([&] (Reconstructible<Ipv4_config> &ip_config) { _reconstruct_ip_config([&] (Reconstructible<Ipv4_config> &ip_config) {
ip_config.construct(dhcp_ack, _alloc, *this); }); ip_config.construct(new_ip_config); });
} }

View File

@ -49,7 +49,27 @@ Ipv4_config::Ipv4_config(Ipv4_config const &ip_config,
{ {
ip_config.for_each_dns_server([&] (Dns_server const &dns_server) { ip_config.for_each_dns_server([&] (Dns_server const &dns_server) {
Dns_server::construct( Dns_server::construct(
alloc, dns_server.ip(), _alloc, dns_server.ip(),
[&] /* handle_success */ (Dns_server &server)
{
_dns_servers.insert_as_tail(server);
},
[&] /* handle_failure */ () { }
);
});
_dns_domain_name.set_to(ip_config.dns_domain_name());
}
Ipv4_config::Ipv4_config(Ipv4_config const &ip_config)
:
_alloc { ip_config._alloc },
_interface { ip_config._interface },
_gateway { ip_config._gateway }
{
ip_config.for_each_dns_server([&] (Dns_server const &dns_server) {
Dns_server::construct(
_alloc, dns_server.ip(),
[&] /* handle_success */ (Dns_server &server) [&] /* handle_success */ (Dns_server &server)
{ {
_dns_servers.insert_as_tail(server); _dns_servers.insert_as_tail(server);

View File

@ -59,6 +59,8 @@ class Net::Ipv4_config
Ipv4_config(Ipv4_config const &ip_config, Ipv4_config(Ipv4_config const &ip_config,
Genode::Allocator &alloc); Genode::Allocator &alloc);
Ipv4_config(Ipv4_config const &ip_config);
Ipv4_config(Genode::Allocator &alloc); Ipv4_config(Genode::Allocator &alloc);
~Ipv4_config(); ~Ipv4_config();
@ -71,6 +73,11 @@ class Net::Ipv4_config
!_dns_domain_name.equal_to(other._dns_domain_name); !_dns_domain_name.equal_to(other._dns_domain_name);
} }
bool operator == (Ipv4_config const &other) const
{
return !(*this != other);
}
template <typename FUNC> template <typename FUNC>
void for_each_dns_server(FUNC && func) const void for_each_dns_server(FUNC && func) const
{ {