diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README
index c125ebb485..20b3141c72 100644
--- a/repos/os/src/server/nic_router/README
+++ b/repos/os/src/server/nic_router/README
@@ -411,6 +411,27 @@ 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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd
index 10bfaca339..530425c429 100644
--- a/repos/os/src/server/nic_router/config.xsd
+++ b/repos/os/src/server/nic_router/config.xsd
@@ -147,6 +147,7 @@
+
diff --git a/repos/os/src/server/nic_router/domain.cc b/repos/os/src/server/nic_router/domain.cc
index a213a331e2..78b48c3791 100644
--- a/repos/os/src/server/nic_router/domain.cc
+++ b/repos/os/src/server/nic_router/domain.cc
@@ -115,7 +115,8 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
_node.attribute_value("gateway", Ipv4_address()),
Ipv4_address()),
_verbose_packets(_node.attribute_value("verbose_packets", false) ||
- _config.verbose_packets())
+ _config.verbose_packets()),
+ _label(_node.attribute_value("label", String<160>()).string())
{
if (_name == Domain_name()) {
log("[?] Missing name attribute in domain node");
diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h
index fd8154396f..005fcf5ef3 100644
--- a/repos/os/src/server/nic_router/domain.h
+++ b/repos/os/src/server/nic_router/domain.h
@@ -110,6 +110,7 @@ class Net::Domain : public Domain_base,
Genode::size_t _tx_bytes { 0 };
Genode::size_t _rx_bytes { 0 };
bool const _verbose_packets { false };
+ Genode::Session_label const _label;
void _read_forward_rules(Genode::Cstring const &protocol,
Domain_tree &domains,
@@ -173,26 +174,27 @@ class Net::Domain : public Domain_base,
** Accessors **
***************/
- bool verbose_packets() const { return _verbose_packets; }
- Ipv4_config const &ip_config() const { return *_ip_config; }
- List &ip_config_dependents() { return _ip_config_dependents; }
- Domain_name const &name() const { return _name; }
- Ip_rule_list &ip_rules() { return _ip_rules; }
- Forward_rule_tree &tcp_forward_rules() { return _tcp_forward_rules; }
- Forward_rule_tree &udp_forward_rules() { return _udp_forward_rules; }
- Transport_rule_list &tcp_rules() { return _tcp_rules; }
- Transport_rule_list &udp_rules() { return _udp_rules; }
- Ip_rule_list &icmp_rules() { return _icmp_rules; }
- Nat_rule_tree &nat_rules() { return _nat_rules; }
- Interface_list &interfaces() { return _interfaces; }
- Configuration &config() const { return _config; }
- Domain_avl_member &avl_member() { return _avl_member; }
- Dhcp_server &dhcp_server();
- Arp_cache &arp_cache() { return _arp_cache; }
- Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
- Link_side_tree &tcp_links() { return _tcp_links; }
- Link_side_tree &udp_links() { return _udp_links; }
- Link_side_tree &icmp_links() { return _icmp_links; }
+ bool verbose_packets() const { return _verbose_packets; }
+ Genode::Session_label const &label() const { return _label; }
+ Ipv4_config const &ip_config() const { return *_ip_config; }
+ List &ip_config_dependents() { return _ip_config_dependents; }
+ Domain_name const &name() const { return _name; }
+ Ip_rule_list &ip_rules() { return _ip_rules; }
+ Forward_rule_tree &tcp_forward_rules() { return _tcp_forward_rules; }
+ Forward_rule_tree &udp_forward_rules() { return _udp_forward_rules; }
+ Transport_rule_list &tcp_rules() { return _tcp_rules; }
+ Transport_rule_list &udp_rules() { return _udp_rules; }
+ Ip_rule_list &icmp_rules() { return _icmp_rules; }
+ Nat_rule_tree &nat_rules() { return _nat_rules; }
+ Interface_list &interfaces() { return _interfaces; }
+ Configuration &config() const { return _config; }
+ Domain_avl_member &avl_member() { return _avl_member; }
+ Dhcp_server &dhcp_server();
+ Arp_cache &arp_cache() { return _arp_cache; }
+ Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
+ Link_side_tree &tcp_links() { return _tcp_links; }
+ Link_side_tree &udp_links() { return _udp_links; }
+ Link_side_tree &icmp_links() { return _icmp_links; }
};
diff --git a/repos/os/src/server/nic_router/main.cc b/repos/os/src/server/nic_router/main.cc
index 78c1691589..a0b1840e72 100644
--- a/repos/os/src/server/nic_router/main.cc
+++ b/repos/os/src/server/nic_router/main.cc
@@ -47,7 +47,12 @@ class Net::Main
Configuration &_init_config();
- void _try_init_uplink(Configuration &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)
@@ -83,21 +88,55 @@ Configuration &Net::Main::_init_config()
Net::Main::Main(Env &env) : _env(env)
{
- _try_init_uplink(_config());
+ _uplink_handle_config(_config());
_config_rom.sigh(_config_handler);
env.parent().announce(env.ep().manage(_root));
}
-void Net::Main::_try_init_uplink(Configuration &config)
+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);
+ uplink.init();
+}
+
+
+void Net::Main::_deinit_uplink(Configuration &config)
{
try {
- config.domains().find_by_name("uplink");
- Uplink &uplink = *new (_heap) Uplink(_env, _timer, _heap, _interfaces, config);
- _uplink = Pointer(uplink);
- uplink.init();
+ Uplink &uplink = _uplink();
+ if (config.verbose()) {
+ log("[uplink] close NIC session \"", uplink.label(), "\""); }
+
+ destroy(_heap, &uplink);
+ _uplink = Pointer();
}
- catch (Domain_tree::No_match) { }
+ 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); }
}
@@ -107,16 +146,7 @@ void Net::Main::_handle_config()
Configuration &config = *new (_heap)
Configuration(_env, _config_rom.xml(), _heap, _timer, _config());
- try {
- Uplink &uplink = _uplink();
- try { config.domains().find_by_name("uplink"); }
- catch (Domain_tree::No_match) {
- destroy(_heap, &uplink);
- _uplink = Pointer();
- }
- }
- catch (Pointer::Invalid) { _try_init_uplink(config); }
-
+ _uplink_handle_config(config);
_root.handle_config(config);
_for_each_interface([&] (Interface &intf) { intf.handle_config(config); });
_for_each_interface([&] (Interface &intf) { intf.handle_config_aftermath(); });
diff --git a/repos/os/src/server/nic_router/uplink.cc b/repos/os/src/server/nic_router/uplink.cc
index 97b8f602a9..4160c49136 100644
--- a/repos/os/src/server/nic_router/uplink.cc
+++ b/repos/os/src/server/nic_router/uplink.cc
@@ -23,16 +23,18 @@ using namespace Net;
using namespace Genode;
-Net::Uplink::Uplink(Env &env,
- Timer::Connection &timer,
- Genode::Allocator &alloc,
- Interface_list &interfaces,
- Configuration &config)
+Net::Uplink::Uplink(Env &env,
+ Timer::Connection &timer,
+ Genode::Allocator &alloc,
+ Interface_list &interfaces,
+ Configuration &config,
+ Session_label const &label)
:
Nic::Packet_allocator(&alloc),
- Nic::Connection(env, this, BUF_SIZE, BUF_SIZE),
+ Nic::Connection(env, this, BUF_SIZE, BUF_SIZE, label.string()),
Net::Interface(env.ep(), timer, mac_address(), alloc, Mac_address(),
- config, interfaces, _intf_policy)
+ config, interfaces, _intf_policy),
+ _label(label)
{
rx_channel()->sigh_ready_to_ack(_sink_ack);
rx_channel()->sigh_packet_avail(_sink_submit);
diff --git a/repos/os/src/server/nic_router/uplink.h b/repos/os/src/server/nic_router/uplink.h
index 30a1375a14..b23b3c0301 100644
--- a/repos/os/src/server/nic_router/uplink.h
+++ b/repos/os/src/server/nic_router/uplink.h
@@ -62,6 +62,8 @@ class Net::Uplink : public Uplink_base,
BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE,
};
+ Genode::Session_label const &_label;
+
Ipv4_address_prefix _read_interface();
@@ -74,18 +76,20 @@ class Net::Uplink : public Uplink_base,
public:
- Uplink(Genode::Env &env,
- Timer::Connection &timer,
- Genode::Allocator &alloc,
- Interface_list &interfaces,
- Configuration &config);
+ Uplink(Genode::Env &env,
+ Timer::Connection &timer,
+ Genode::Allocator &alloc,
+ Interface_list &interfaces,
+ Configuration &config,
+ Genode::Session_label const &label);
/***************
** Accessors **
***************/
- Mac_address const &router_mac() const { return _router_mac; }
+ Mac_address const &router_mac() const { return _router_mac; }
+ Genode::Session_label const &label() const { return _label; }
};
#endif /* _UPLINK_H_ */