From 0313e0104ccac8b3b129f18c2ce7e1ffb233998e Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 9 Mar 2020 16:23:31 +0100 Subject: [PATCH] nic_router: keep dyn IP when updating domain obj When updating the domain object of interfaces that stay with the same domain during a reconfiguration, until now, the normal "detach raw" function was used. This caused the old domain object to discard a dynamic IP config as all interfaces detached. This caused interfaces also to discard network links established with the old configuration although it wasn't necessary. Thus, now we use a dedicated "detach" in case that an interface actually stays with its domain. This new "detach" doesn't decrease the interface counter of the domain, so, it'll not discard its dynamic IP config. If, however, during a reconfiguration, there's no interface calling this function (all interfaces move to another or no domain), the dynamic IP config is still discarded as expected. Fixes #3686 --- repos/os/src/server/nic_router/domain.cc | 7 ++++++ repos/os/src/server/nic_router/domain.h | 2 ++ repos/os/src/server/nic_router/interface.cc | 27 ++++++++++++++++++--- repos/os/src/server/nic_router/interface.h | 2 ++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/repos/os/src/server/nic_router/domain.cc b/repos/os/src/server/nic_router/domain.cc index 34c54b1e8..a37284366 100644 --- a/repos/os/src/server/nic_router/domain.cc +++ b/repos/os/src/server/nic_router/domain.cc @@ -355,6 +355,13 @@ void Domain::detach_interface(Interface &interface) } } + +void Domain::interface_updates_domain_object(Interface &interface) +{ + _interfaces.remove(&interface); +} + + void Domain::report(Xml_generator &xml) { xml.node("domain", [&] () { diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h index 587086e81..fccd40e79 100644 --- a/repos/os/src/server/nic_router/domain.h +++ b/repos/os/src/server/nic_router/domain.h @@ -179,6 +179,8 @@ class Net::Domain : public Domain_base, void detach_interface(Interface &interface); + void interface_updates_domain_object(Interface &interface); + void raise_rx_bytes(Genode::size_t bytes) { _rx_bytes += bytes; } void raise_tx_bytes(Genode::size_t bytes) { _tx_bytes += bytes; } diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 38345c125..1c2e58cbb 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -340,6 +340,29 @@ void Interface::_detach_from_domain_raw() } +void Interface::_update_domain_object(Domain &new_domain) { + + /* detach raw */ + Domain &old_domain = _domain(); + old_domain.interface_updates_domain_object(*this); + _interfaces.insert(this); + _domain = Pointer(); + Signal_transmitter(_session_link_state_sigh).submit(); + + old_domain.tcp_stats().dissolve_interface(_tcp_stats); + old_domain.udp_stats().dissolve_interface(_udp_stats); + old_domain.icmp_stats().dissolve_interface(_icmp_stats); + old_domain.arp_stats().dissolve_interface(_arp_stats); + old_domain.dhcp_stats().dissolve_interface(_dhcp_stats); + + /* attach raw */ + _domain = new_domain; + Signal_transmitter(_session_link_state_sigh).submit(); + _interfaces.remove(this); + new_domain.attach_interface(*this); +} + + void Interface::attach_to_domain() { try { @@ -1992,9 +2015,7 @@ void Interface::handle_config_2() } return; } - /* move to new domain object without considering any state objects */ - _detach_from_domain_raw(); - _attach_to_domain_raw(new_domain); + _update_domain_object(new_domain); /* destruct or construct DHCP client if IP-config type changes */ if (old_domain.ip_config_dynamic() && diff --git a/repos/os/src/server/nic_router/interface.h b/repos/os/src/server/nic_router/interface.h index d31107592..2456ce39c 100644 --- a/repos/os/src/server/nic_router/interface.h +++ b/repos/os/src/server/nic_router/interface.h @@ -332,6 +332,8 @@ class Net::Interface : private Interface_list::Element void _destroy_link(Link &link); + void _update_domain_object(Domain &new_domain); + void _detach_from_domain_raw(); void _detach_from_domain();