From 49a3a0e0d096af943d661294eee3f526c081ebc7 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Tue, 5 Jun 2018 18:31:40 +0200 Subject: [PATCH] nic_router: multiple uplinks Introduce the uplink tag: ! ! ! ! ! For each uplink tag, the NIC router requests a NIC session with the corresponding label or an empty label if there is no label attribute. These NIC sessions get attached to the domain that is set in their uplink tag as soon as the domain appears. This means their lifetime is not bound to the domain. Uplink NIC sessions can be safely moved from one domain to another without being closed by reconfiguring the corresponding domain attribute. Attention: This may render previously valid NIC router configurations useless. A domain named "uplink" doesn't automatically request a NIC session anymore. To fix these configurations, just add ! or ! as direct subtag of the tag. Issue #2840 --- repos/dde_linux/run/nic_router_uplinks.run | 30 ++-- repos/gems/src/app/sculpt_manager/network.cc | 70 ++++++---- repos/gems/src/app/sculpt_manager/network.h | 3 + repos/libports/run/nic_dump.run | 1 + repos/libports/run/nic_router.run | 3 + repos/libports/run/nic_router_dyn_config.run | 8 ++ repos/os/recipes/pkg/nic_router-nat/runtime | 1 + repos/os/run/nic_router_flood.run | 1 + repos/os/run/ping_nic_router.run | 2 + repos/os/src/server/nic_router/README | 63 ++++----- repos/os/src/server/nic_router/component.cc | 2 + repos/os/src/server/nic_router/config.xsd | 7 + .../os/src/server/nic_router/configuration.cc | 38 +++++- .../os/src/server/nic_router/configuration.h | 8 +- repos/os/src/server/nic_router/interface.cc | 38 +++++- repos/os/src/server/nic_router/interface.h | 6 +- repos/os/src/server/nic_router/main.cc | 86 +----------- repos/os/src/server/nic_router/uplink.cc | 115 ++++++++++++++-- repos/os/src/server/nic_router/uplink.h | 128 ++++++++++++++---- .../recipes/pkg/nic_router-nat-dns/runtime | 1 + repos/ports/run/netperf.inc | 1 + repos/ports/run/stubby.run | 6 +- repos/ports/run/virtualbox_nic_router.run | 1 + 23 files changed, 418 insertions(+), 201 deletions(-) diff --git a/repos/dde_linux/run/nic_router_uplinks.run b/repos/dde_linux/run/nic_router_uplinks.run index 51202f93a..2195a7951 100644 --- a/repos/dde_linux/run/nic_router_uplinks.run +++ b/repos/dde_linux/run/nic_router_uplinks.run @@ -125,8 +125,9 @@ append config { - - + + + @@ -140,8 +141,9 @@ append config { - - + + + @@ -167,8 +169,9 @@ append config { - - + + + @@ -182,8 +185,9 @@ append config { - - + + + @@ -209,8 +213,9 @@ append config { - - + + + @@ -224,8 +229,9 @@ append config { - - + + + diff --git a/repos/gems/src/app/sculpt_manager/network.cc b/repos/gems/src/app/sculpt_manager/network.cc index 52c22b064..e9bf1e158 100644 --- a/repos/gems/src/app/sculpt_manager/network.cc +++ b/repos/gems/src/app/sculpt_manager/network.cc @@ -15,6 +15,24 @@ #include +void Sculpt::Network::_generate_nic_router_uplink(Xml_generator &xml, + char const *label) +{ + xml.node("uplink", [&] () { + xml.attribute("label", label); + xml.attribute("domain", "uplink"); + }); + gen_named_node(xml, "domain", "uplink", [&] () { + xml.node("nat", [&] () { + xml.attribute("domain", "default"); + xml.attribute("tcp-ports", "1000"); + xml.attribute("udp-ports", "1000"); + xml.attribute("icmp-ids", "1000"); + }); + }); +} + + void Sculpt::Network::handle_key_press(Codepoint code) { enum { BACKSPACE = 8, ENTER = 10 }; @@ -70,22 +88,12 @@ void Sculpt::Network::_generate_nic_router_config() xml.node("default-policy", [&] () { xml.attribute("domain", "default"); }); - if (_nic_target.type() != Nic_target::LOCAL) { - gen_named_node(xml, "domain", "uplink", [&] () { - switch (_nic_target.type()) { - case Nic_target::WIRED: xml.attribute("label", "wired"); break; - case Nic_target::WIFI: xml.attribute("label", "wifi"); break; - default: break; - } - xml.node("nat", [&] () { - xml.attribute("domain", "default"); - xml.attribute("tcp-ports", "1000"); - xml.attribute("udp-ports", "1000"); - xml.attribute("icmp-ids", "1000"); - }); - }); + bool uplink_exists = true; + switch (_nic_target.type()) { + case Nic_target::WIRED: _generate_nic_router_uplink(xml, "wired"); break; + case Nic_target::WIFI: _generate_nic_router_uplink(xml, "wifi"); break; + default: uplink_exists = false; } - gen_named_node(xml, "domain", "default", [&] () { xml.attribute("interface", "10.0.1.1/24"); @@ -96,7 +104,7 @@ void Sculpt::Network::_generate_nic_router_config() xml.attribute("dns_server_from", "uplink"); } }); - if (_nic_target.type() != Nic_target::LOCAL) { + if (uplink_exists) { xml.node("tcp", [&] () { xml.attribute("dst", "0.0.0.0/0"); xml.node("permit-any", [&] () { @@ -171,19 +179,31 @@ void Sculpt::Network::_handle_nic_router_config(Xml_node config) if (!config.has_sub_node("domain")) target = Nic_target::OFF; - config.for_each_sub_node("domain", [&] (Xml_node domain) { + struct Break : Exception { }; + try { + config.for_each_sub_node("domain", [&] (Xml_node domain) { - /* skip non-uplink domains */ - if (domain.attribute_value("name", String<16>()) != "uplink") - return; + /* skip domains that are not called "uplink" */ + if (domain.attribute_value("name", String<16>()) != "uplink") + return; - if (domain.attribute_value("label", String<16>()) == "wired") - target = Nic_target::WIRED; + config.for_each_sub_node("uplink", [&] (Xml_node uplink) { - if (domain.attribute_value("label", String<16>()) == "wifi") - target = Nic_target::WIFI; - }); + /* skip uplinks not assigned to a domain called "uplink" */ + if (uplink.attribute_value("domain", String<16>()) != "uplink") + return; + if (uplink.attribute_value("label", String<16>()) == "wired") { + target = Nic_target::WIRED; + throw Break(); + } + if (uplink.attribute_value("label", String<16>()) == "wifi") { + target = Nic_target::WIFI; + throw Break(); + } + }); + }); + } catch (Break) { } _nic_target.manual_type = target; } diff --git a/repos/gems/src/app/sculpt_manager/network.h b/repos/gems/src/app/sculpt_manager/network.h index 3cb1c9404..96f011e69 100644 --- a/repos/gems/src/app/sculpt_manager/network.h +++ b/repos/gems/src/app/sculpt_manager/network.h @@ -63,6 +63,9 @@ struct Sculpt::Network : Network_dialog::Action void _generate_nic_router_config(); + void _generate_nic_router_uplink(Xml_generator &xml, + char const *label); + Access_points _access_points { }; Wifi_connection _wifi_connection = Wifi_connection::disconnected_wifi_connection(); diff --git a/repos/libports/run/nic_dump.run b/repos/libports/run/nic_dump.run index 75d10db34..aa188acfd 100644 --- a/repos/libports/run/nic_dump.run +++ b/repos/libports/run/nic_dump.run @@ -88,6 +88,7 @@ append config { + diff --git a/repos/libports/run/nic_router.run b/repos/libports/run/nic_router.run index 5e4b6e5d1..cca8a6f78 100644 --- a/repos/libports/run/nic_router.run +++ b/repos/libports/run/nic_router.run @@ -158,6 +158,7 @@ proc test_7_config { } { + @@ -260,6 +261,8 @@ append config { + + + + + + + + + + + + + @@ -131,6 +132,7 @@ append config { icmp_idle_timeout_sec="10"> + diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README index d1e96ba50..2c95a5c19 100644 --- a/repos/os/src/server/nic_router/README +++ b/repos/os/src/server/nic_router/README @@ -19,22 +19,35 @@ these domains. This is a brief overview of the features thereby provided: Basics ~~~~~~ -The 'nic_router' component provides multiple sessions of the 'NIC' service -(downlinks) while requesting one 'NIC' session (the uplink) itself. Through -common Genode session routing, the uplink can be connected to any other NIC -server. Inside the component, uplink and downlinks are treated the same. Its -routing algorithm is ultimately controlled through the configuration. NIC +The NIC router can act as server of multiple NIC session clients (downlinks) +and at the same time as client of multiple NIC session servers (uplinks). +Besides the decision which side initiates the NIC session and provides MAC +address respectively link state, uplinks and downlinks are equal to the NIC +router. + +The routing algorithm is ultimately controlled through the configuration. NIC sessions are assigned to domains. Each domain represents one subnet and a -corresponding routing configuration. Currently, each domain can contain -only one NIC session at a time. The assignment of sessions to domains is -controlled through the the common Genode session-policy tag: +corresponding routing configuration. The assignment of downlink NIC sessions +to domains is controlled through the policy tag that is also known from other +Genode components: -! -! +! +! +! +! -The domain name can be freely choosen but must be unique. There is no need -to have a policy for the uplink. It is automatically assigned to the domain -named "uplink". For each domain there must be a domain tag: +The domain name can be freely choosen but must be unique. +The uplink tag instructs the NIC router to create an uplink NIC session that +is assigned to the give domain: + +! +! +! + +The label is the session label that is used when requesting the uplink NIC +session. The label attribute is optional. It is perfectly fine to have a +domain with uplinks and downlinks assigned to at the same time. For each +domain there must be a domain tag: ! ! @@ -411,27 +424,6 @@ router: ! dhcp_request_timeout_sec="6"> -The uplink domain -~~~~~~~~~~~~~~~~~ - -The uplink domain is treated like every other domain wherever possible. -However, there are still some differences that are visible to the user: - -* 'policy' tags that target the uplink domain have no effect at all -* The domain tag of the uplink is the only domain tag in which the - 'label' attribute has an effect -* The uplink domain, as long as existant, has exactly one NIC session in which - the NIC router is the session client -* When the uplink 'domain' tag appears, the uplink NIC session is requested by - the NIC router using the label denoted in the 'label' attribute of the - uplink 'domain' tag (default label "") -* When the 'label' attribute of the uplink 'domain' tag changes, the NIC - router closes the uplink NIC session and requests it again with the new - label -* When the uplink 'domain' tag disappears, the NIC router closes the uplink - NIC session - - Configuring reporting functionality ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -511,6 +503,7 @@ following configuration: ! ! +! ! ! ! @@ -550,6 +543,7 @@ internet. The router would have the following configuration: ! ! +! ! ! ! @@ -588,6 +582,7 @@ following configuration: ! ! +! ! ! ! diff --git a/repos/os/src/server/nic_router/component.cc b/repos/os/src/server/nic_router/component.cc index 438eaffcb..0f41e0fdd 100644 --- a/repos/os/src/server/nic_router/component.cc +++ b/repos/os/src/server/nic_router/component.cc @@ -101,6 +101,8 @@ Net::Session_component::Session_component(Allocator &alloc, config, interfaces, *_tx.sink(), *_rx.source(), _link_state, _interface_policy } { + _interface.attach_to_domain(); + _tx.sigh_ready_to_ack (_interface.sink_ack()); _tx.sigh_packet_avail (_interface.sink_submit()); _rx.sigh_ack_avail (_interface.source_ack()); diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd index 298104eb9..573fdb746 100644 --- a/repos/os/src/server/nic_router/config.xsd +++ b/repos/os/src/server/nic_router/config.xsd @@ -112,6 +112,13 @@ + + + + + + + diff --git a/repos/os/src/server/nic_router/configuration.cc b/repos/os/src/server/nic_router/configuration.cc index 9d1460536..a1bad4356 100644 --- a/repos/os/src/server/nic_router/configuration.cc +++ b/repos/os/src/server/nic_router/configuration.cc @@ -35,6 +35,17 @@ Configuration::Configuration(Xml_node const node, { } +void Configuration::_invalid_uplink(Uplink &uplink, + char const *reason) +{ + if (_verbose) { + log("[", uplink.domain(), "] invalid uplink: ", uplink, " (", reason, ")"); } + + _uplinks.remove(uplink); + destroy(_alloc, &uplink); +} + + void Configuration::_invalid_domain(Domain &domain, char const *reason) { @@ -50,7 +61,8 @@ Configuration::Configuration(Env &env, Xml_node const node, Allocator &alloc, Timer::Connection &timer, - Configuration &old_config) + Configuration &old_config, + Interface_list &interfaces) : _alloc(alloc), _verbose (node.attribute_value("verbose", false)), @@ -129,11 +141,35 @@ Configuration::Configuration(Env &env, Report(report_node, timer, _domains, _reporter()); } catch (Genode::Xml_node::Nonexistent_sub_node) { } + + /* initialize uplinks */ + _node.for_each_sub_node("uplink", [&] (Xml_node const node) { + try { + Uplink &uplink = *new (_alloc) + Uplink { node, alloc, old_config._uplinks, env, timer, + interfaces, *this }; + + try { _uplinks.insert(uplink); } + catch (Uplink_tree::Name_not_unique exception) { + _invalid_uplink(uplink, "label not unique"); + _invalid_uplink(exception.object, "label not unique"); + } + } + catch (Uplink::Invalid) { } + }); + /* + * Destroy old uplinks to ensure that uplink interfaces that were not + * re-used are not re-attached to the new domains. + */ + old_config._uplinks.destroy_each(_alloc); } Configuration::~Configuration() { + /* destroy uplinks */ + _uplinks.destroy_each(_alloc); + /* destroy reporter */ try { destroy(_alloc, &_reporter()); } catch (Pointer::Invalid) { } diff --git a/repos/os/src/server/nic_router/configuration.h b/repos/os/src/server/nic_router/configuration.h index 6c487cfaf..3c030a007 100644 --- a/repos/os/src/server/nic_router/configuration.h +++ b/repos/os/src/server/nic_router/configuration.h @@ -17,6 +17,7 @@ /* local includes */ #include #include +#include /* Genode includes */ #include @@ -46,8 +47,12 @@ class Net::Configuration Pointer _report { }; Pointer _reporter { }; Domain_tree _domains { }; + Uplink_tree _uplinks { }; Genode::Xml_node const _node; + void _invalid_uplink(Uplink &uplink, + char const *reason); + void _invalid_domain(Domain &domain, char const *reason); @@ -69,7 +74,8 @@ class Net::Configuration Genode::Xml_node const node, Genode::Allocator &alloc, Timer::Connection &timer, - Configuration &old_config); + Configuration &old_config, + Interface_list &interfaces); ~Configuration(); diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 8ec87f7a9..0f85ea5ae 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -30,6 +30,7 @@ using Genode::uint32_t; using Genode::log; using Genode::error; using Genode::warning; +using Genode::Exception; using Genode::construct_at; using Genode::Quota_guard; using Genode::Ram_quota; @@ -256,15 +257,23 @@ void Interface::_detach_from_domain_raw() } -void Interface::_attach_to_domain(Domain_name const &domain_name) +void Interface::attach_to_domain() { - _attach_to_domain_raw(_config().domains().find_by_name(domain_name)); - attach_to_domain_finish(); + try { + _attach_to_domain_raw(_config().domains().find_by_name( + _policy.determine_domain_name())); + + attach_to_domain_finish(); + } + catch (Domain_tree::No_match) { } } void Interface::attach_to_domain_finish() { + if (!link_state()) { + return; } + /* if domain has yet no IP config, participate in requesting one */ Domain &domain = _domain(); Ipv4_config const &ip_config = domain.ip_config(); @@ -764,6 +773,27 @@ bool Interface::link_state() const } +void Interface::handle_link_state() +{ + struct Keep_ip_config : Exception { }; + try { + attach_to_domain_finish(); + + /* if the wholde domain became down, discard IP config */ + Domain &domain_ = domain(); + if (!link_state() && domain_.ip_config().valid) { + domain_.interfaces().for_each([&] (Interface &interface) { + if (interface.link_state()) { + throw Keep_ip_config(); } + }); + domain_.discard_ip_config(); + } + } + catch (Domain::Ip_config_static) { } + catch (Keep_ip_config) { } +} + + void Interface::_handle_icmp_query(Ethernet_frame ð, Size_guard &size_guard, Ipv4_packet &ip, @@ -1383,8 +1413,6 @@ Interface::Interface(Genode::Entrypoint &ep, _interfaces { interfaces } { _interfaces.insert(this); - try { _attach_to_domain(_policy.determine_domain_name()); } - catch (Domain_tree::No_match) { } } diff --git a/repos/os/src/server/nic_router/interface.h b/repos/os/src/server/nic_router/interface.h index 1984edb39..a88e61d0f 100644 --- a/repos/os/src/server/nic_router/interface.h +++ b/repos/os/src/server/nic_router/interface.h @@ -274,8 +274,6 @@ class Net::Interface : private Interface_list::Element void _detach_from_domain(); - void _attach_to_domain(Domain_name const &domain_name); - void _attach_to_domain_raw(Domain &domain); void _apply_foreign_arp(); @@ -375,6 +373,8 @@ class Net::Interface : private Interface_list::Element void handle_config_3(); + void attach_to_domain(); + void detach_from_ip_config(); void attach_to_ip_config(Domain &domain, @@ -388,6 +388,8 @@ class Net::Interface : private Interface_list::Element bool link_state() const; + void handle_link_state(); + /*************** ** Accessors ** diff --git a/repos/os/src/server/nic_router/main.cc b/repos/os/src/server/nic_router/main.cc index 9980d7d90..72dff4587 100644 --- a/repos/os/src/server/nic_router/main.cc +++ b/repos/os/src/server/nic_router/main.cc @@ -38,22 +38,12 @@ class Net::Main Timer::Connection _timer { _env }; Genode::Heap _heap { &_env.ram(), &_env.rm() }; Genode::Attached_rom_dataspace _config_rom { _env, "config" }; - Reference _config { _init_config() }; + Reference _config { *new (_heap) Configuration { _config_rom.xml(), _heap } }; Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; - Pointer _uplink { }; Root _root { _env.ep(), _timer, _heap, _config(), _env.ram(), _interfaces, _env.rm()}; void _handle_config(); - Configuration &_init_config(); - - void _deinit_uplink(Configuration &config); - - void _init_uplink(Configuration &config, - Session_label const &label); - - void _uplink_handle_config(Configuration &config); - template void _for_each_interface(FUNC && functor) { @@ -73,80 +63,22 @@ class Net::Main }; -Configuration &Net::Main::_init_config() -{ - Configuration &dummy_config = *new (_heap) - Configuration(_config_rom.xml(), _heap); - - Configuration &config = *new (_heap) - Configuration(_env, _config_rom.xml(), _heap, _timer, dummy_config); - - destroy(_heap, &dummy_config); - return config; -} - - Net::Main::Main(Env &env) : _env(env) { - _uplink_handle_config(_config()); _config_rom.sigh(_config_handler); + _handle_config(); env.parent().announce(env.ep().manage(_root)); } -void Net::Main::_init_uplink(Configuration &config, - Session_label const &label) -{ - if (config.verbose()) { - log("[uplink] request NIC session \"", label, "\""); } - - Uplink &uplink = *new (_heap) Uplink(_env, _timer, _heap, _interfaces, - config, label); - _uplink = Pointer(uplink); -} - - -void Net::Main::_deinit_uplink(Configuration &config) -{ - try { - Uplink &uplink = _uplink(); - if (config.verbose()) { - log("[uplink] close NIC session \"", uplink.label(), "\""); } - - destroy(_heap, &uplink); - _uplink = Pointer(); - } - catch (Pointer::Invalid) { } -} - - -void Net::Main::_uplink_handle_config(Configuration &config) -{ - try { - Session_label const &label = - config.domains().find_by_name("uplink").label(); - - try { - if (label == _uplink().label()) { - return; - } - _deinit_uplink(config); - _init_uplink(config, label); - } - catch (Pointer::Invalid) { _init_uplink(config, label); } - } - catch (Domain_tree::No_match) { _deinit_uplink(config); } -} - - void Net::Main::_handle_config() { _config_rom.update(); Configuration &old_config = _config(); Configuration &new_config = *new (_heap) - Configuration(_env, _config_rom.xml(), _heap, _timer, old_config); + Configuration(_env, _config_rom.xml(), _heap, _timer, old_config, + _interfaces); - _uplink_handle_config(new_config); _root.handle_config(new_config); _for_each_interface([&] (Interface &intf) { intf.handle_config_1(new_config); }); _for_each_interface([&] (Interface &intf) { intf.handle_config_2(); }); @@ -157,12 +89,4 @@ void Net::Main::_handle_config() } -void Component::construct(Env &env) -{ - try { static Net::Main main(env); } - - catch (Net::Domain_tree::No_match) { - error("failed to find configuration for domain 'uplink'"); - env.parent().exit(-1); - } -} +void Component::construct(Env &env) { static Net::Main main(env); } diff --git a/repos/os/src/server/nic_router/uplink.cc b/repos/os/src/server/nic_router/uplink.cc index b3def4d87..0ba833678 100644 --- a/repos/os/src/server/nic_router/uplink.cc +++ b/repos/os/src/server/nic_router/uplink.cc @@ -13,7 +13,6 @@ /* Genode includes */ #include -#include /* local includes */ #include @@ -23,20 +22,111 @@ using namespace Net; using namespace Genode; -Net::Uplink::Uplink(Env &env, - Timer::Connection &timer, - Genode::Allocator &alloc, - Interface_list &interfaces, - Configuration &config, - Session_label const &label) +/***************** + ** Uplink_base ** + *****************/ + +Net::Uplink_base::Uplink_base(Xml_node const &node) : + _label { node.attribute_value("label", Session_label::String()) }, + _domain { node.attribute_value("domain", Domain_name()) } +{ } + + +/************ + ** Uplink ** + ************/ + +void Uplink::_invalid(char const *reason) const +{ + if (_config.verbose()) { + log("[", domain(), "] invalid uplink: ", *this, " (", reason, ")"); } + + throw Invalid(); +} + + +Net::Uplink::Uplink(Xml_node const &node, + Allocator &alloc, + Uplink_tree &old_uplinks, + Env &env, + Timer::Connection &timer, + Interface_list &interfaces, + Configuration &config) +: + Uplink_base { node }, + Avl_string_base { label().string() }, + _alloc { alloc }, + _config { config } +{ + /* if an interface with this label already exists, reuse it */ + try { + Uplink &old_uplink = old_uplinks.find_by_name(label()); + Uplink_interface &interface = old_uplink._interface(); + old_uplink._interface = Pointer(); + interface.domain_name(domain()); + _interface = interface; + } + /* if not, create a new one */ + catch (Uplink_tree::No_match) { + if (config.verbose()) { + log("[", domain(), "] request uplink NIC session: ", *this); } + + try { + _interface = *new (_alloc) + Uplink_interface { env, timer, alloc, interfaces, config, + domain(), label() }; + } + catch (Insufficient_ram_quota) { _invalid("NIC session RAM quota"); } + catch (Insufficient_cap_quota) { _invalid("NIC session CAP quota"); } + catch (Service_denied) { _invalid("NIC session denied"); } + } +} + + +Net::Uplink::~Uplink() +{ + /* if the interface was yet not reused by another uplink, destroy it */ + try { + Uplink_interface &interface = _interface(); + if (_config.verbose()) { + log("[", domain(), "] close uplink NIC session: ", *this); } + + destroy(_alloc, &interface); + } + catch (Pointer::Invalid) { } +} + + +void Net::Uplink::print(Output &output) const +{ + if (label() == Session_label()) { + Genode::print(output, ""); } + else { + Genode::print(output, label()); } +} + + +/********************** + ** Uplink_interface ** + **********************/ + +Net::Uplink_interface::Uplink_interface(Env &env, + Timer::Connection &timer, + Genode::Allocator &alloc, + Interface_list &interfaces, + Configuration &config, + Domain_name const &domain_name, + Session_label const &label) +: + Uplink_interface_base { domain_name }, Nic::Packet_allocator { &alloc }, Nic::Connection { env, this, BUF_SIZE, BUF_SIZE, label.string() }, - _label { label }, - _link_state_handler { env.ep(), *this, &Uplink::_handle_link_state }, + _link_state_handler { env.ep(), *this, + &Uplink_interface::_handle_link_state }, _interface { env.ep(), timer, mac_address(), alloc, Mac_address(), config, interfaces, *rx(), *tx(), - _link_state, _intf_policy } + _link_state, *this } { /* install packet stream signal handlers */ rx_channel()->sigh_ready_to_ack (_interface.sink_ack()); @@ -50,9 +140,8 @@ Net::Uplink::Uplink(Env &env, } -void Net::Uplink::_handle_link_state() +void Net::Uplink_interface::_handle_link_state() { _link_state = link_state(); - try { _interface.domain().discard_ip_config(); } - catch (Domain::Ip_config_static) { } + _interface.handle_link_state(); } diff --git a/repos/os/src/server/nic_router/uplink.h b/repos/os/src/server/nic_router/uplink.h index 7fed7e33b..2347a1fff 100644 --- a/repos/os/src/server/nic_router/uplink.h +++ b/repos/os/src/server/nic_router/uplink.h @@ -19,6 +19,7 @@ #include /* local includes */ +#include #include #include @@ -27,32 +28,110 @@ namespace Net { using Domain_name = Genode::String<160>; class Uplink_base; class Uplink; + class Uplink_tree; + class Uplink_interface_base; + class Uplink_interface; } +class Net::Uplink_tree +: + public Avl_string_tree +{ }; + + class Net::Uplink_base { - protected: + private: - struct Interface_policy : Net::Interface_policy - { - /*************************** - ** Net::Interface_policy ** - ***************************/ + Genode::Session_label const _label; + Domain_name const _domain; - Domain_name determine_domain_name() const override { return Genode::Cstring("uplink"); }; - void handle_config(Configuration const &) override { } - }; + public: - Interface_policy _intf_policy { }; + Uplink_base(Genode::Xml_node const &node); virtual ~Uplink_base() { } + + + /************** + ** Acessors ** + **************/ + + Genode::Session_label const &label() const { return _label; } + Domain_name const &domain() const { return _domain; } }; -class Net::Uplink : public Uplink_base, - public Nic::Packet_allocator, - public Nic::Connection +struct Net::Uplink : public Uplink_base, + private Genode::Avl_string_base +{ + friend class Avl_string_tree; + friend class Genode::List; + + private: + + Genode::Allocator &_alloc; + Configuration const &_config; + Pointer _interface { }; + + void _invalid(char const *reason) const; + + public: + + struct Invalid : Genode::Exception { }; + + Uplink(Genode::Xml_node const &node, + Genode::Allocator &alloc, + Uplink_tree &old_uplinks, + Genode::Env &env, + Timer::Connection &timer, + Interface_list &interfaces, + Configuration &config); + + ~Uplink(); + + + /********* + ** log ** + *********/ + + void print(Genode::Output &output) const; +}; + + +class Net::Uplink_interface_base : public Interface_policy +{ + private: + + Const_reference _domain_name; + + + /*************************** + ** Net::Interface_policy ** + ***************************/ + + Domain_name determine_domain_name() const override { return _domain_name(); }; + void handle_config(Configuration const &) override { } + + public: + + Uplink_interface_base(Domain_name const &domain_name) : _domain_name(domain_name) { } + + virtual ~Uplink_interface_base() { } + + + /*************** + ** Accessors ** + ***************/ + + void domain_name(Domain_name const &v) { _domain_name = v; } +}; + + +class Net::Uplink_interface : public Uplink_interface_base, + public Nic::Packet_allocator, + public Nic::Connection { private: @@ -61,10 +140,9 @@ class Net::Uplink : public Uplink_base, BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE, }; - Genode::Session_label const &_label; - bool _link_state { false }; - Genode::Signal_handler _link_state_handler; - Net::Interface _interface; + bool _link_state { false }; + Genode::Signal_handler _link_state_handler; + Net::Interface _interface; Ipv4_address_prefix _read_interface(); @@ -72,20 +150,20 @@ class Net::Uplink : public Uplink_base, public: - Uplink(Genode::Env &env, - Timer::Connection &timer, - Genode::Allocator &alloc, - Interface_list &interfaces, - Configuration &config, - Genode::Session_label const &label); + Uplink_interface(Genode::Env &env, + Timer::Connection &timer, + Genode::Allocator &alloc, + Interface_list &interfaces, + Configuration &config, + Domain_name const &domain_name, + Genode::Session_label const &label); /*************** ** Accessors ** ***************/ - Mac_address const &router_mac() const { return _interface.router_mac(); } - Genode::Session_label const &label() const { return _label; } + Mac_address const &router_mac() const { return _interface.router_mac(); } }; #endif /* _UPLINK_H_ */ diff --git a/repos/ports/recipes/pkg/nic_router-nat-dns/runtime b/repos/ports/recipes/pkg/nic_router-nat-dns/runtime index a27aacc0e..f752d6c70 100644 --- a/repos/ports/recipes/pkg/nic_router-nat-dns/runtime +++ b/repos/ports/recipes/pkg/nic_router-nat-dns/runtime @@ -23,6 +23,7 @@ + diff --git a/repos/ports/run/netperf.inc b/repos/ports/run/netperf.inc index f3daca93b..edd36c255 100644 --- a/repos/ports/run/netperf.inc +++ b/repos/ports/run/netperf.inc @@ -149,6 +149,7 @@ append_if $use_nic_router config { + - - + + + + diff --git a/repos/ports/run/virtualbox_nic_router.run b/repos/ports/run/virtualbox_nic_router.run index 76e4fb30c..25dd3eb93 100644 --- a/repos/ports/run/virtualbox_nic_router.run +++ b/repos/ports/run/virtualbox_nic_router.run @@ -159,6 +159,7 @@ append config { dhcp_discover_timeout_sec="1"> +