From 304cb290d90dbad0c05864db8fb58b445a22e60c Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Sun, 16 Sep 2018 14:21:38 +0200 Subject: [PATCH] nic_router: rework quota accounting * Account all RAM/CAP quota of a session except quota for metadata used in core. The latter is considered when asking if a session can afford to make an operation but it does not get accounted to always be able to pay back all quota when a session closes. The general accounting mechanism is moved from atop of the allocators down to the level of RAM/RM session operations. * report statistics about session objects and quota if is configured. (default is yes if is present) Issue #2953 --- repos/libports/run/nic_router.run | 112 +++---- repos/os/src/server/nic_router/README | 13 +- repos/os/src/server/nic_router/arp_waiter.cc | 3 + repos/os/src/server/nic_router/component.cc | 202 ++++++++----- repos/os/src/server/nic_router/component.h | 281 +++++++++++++++--- repos/os/src/server/nic_router/config.xsd | 2 + .../os/src/server/nic_router/configuration.cc | 38 +-- .../os/src/server/nic_router/configuration.h | 1 + repos/os/src/server/nic_router/dhcp_server.cc | 8 + repos/os/src/server/nic_router/dhcp_server.h | 3 +- repos/os/src/server/nic_router/domain.cc | 71 ++++- repos/os/src/server/nic_router/domain.h | 34 +++ repos/os/src/server/nic_router/interface.cc | 231 +++++++++++--- repos/os/src/server/nic_router/interface.h | 76 ++++- repos/os/src/server/nic_router/link.cc | 105 ++++++- repos/os/src/server/nic_router/link.h | 34 ++- repos/os/src/server/nic_router/main.cc | 5 +- repos/os/src/server/nic_router/report.cc | 41 ++- repos/os/src/server/nic_router/report.h | 25 +- repos/os/src/server/nic_router/uplink.cc | 14 +- repos/os/src/server/nic_router/uplink.h | 7 +- 21 files changed, 1021 insertions(+), 285 deletions(-) diff --git a/repos/libports/run/nic_router.run b/repos/libports/run/nic_router.run index bdfc6ac153..8556cc18c1 100644 --- a/repos/libports/run/nic_router.run +++ b/repos/libports/run/nic_router.run @@ -25,21 +25,21 @@ create_boot_directory proc test_1_config { } { if {[enable_test_1]} { return " - [client_config udp_client_1 udp 10.0.98.55 10.0.98.33 255.255.255.0 nic_router 1337 10.0.98.33] - [client_config lan_1_udp_client_1 udp 10.0.99.56 10.0.99.33 255.255.255.0 nic_router 1337 10.0.99.55] - [server_config lan_1_udp_server_1 udp 10.0.99.55 10.0.99.33 255.255.255.0 nic_router 1337 ]" } + [client_config t1_d1_c1_udp udp 10.0.98.55 10.0.98.33 255.255.255.0 nic_router 1337 10.0.98.33] + [client_config t1_d2_c1_udp udp 10.0.99.56 10.0.99.33 255.255.255.0 nic_router 1337 10.0.99.55] + [server_config t1_d2_s1_udp udp 10.0.99.55 10.0.99.33 255.255.255.0 nic_router 1337 ]" } } proc test_1_router_config { } { if {[enable_test_1]} { return { - - + + - - + + - } } + } } } proc test_1_router_uplink_config { } { } @@ -51,19 +51,19 @@ proc test_1_router_uplink_config { } { } proc test_2_config { } { if {[enable_test_2]} { return " - [client_config udp_client_2 udp 10.0.2.212 10.0.2.1 255.255.255.0 nic_bridge 1 10.0.2.55] - [server_config udp_server_2 udp 18.17.16.15 18.17.16.14 255.255.0.0 nic_router 1 ]" } + [client_config t2_d0_c1_udp udp 10.0.2.212 10.0.2.1 255.255.255.0 nic_bridge 1 10.0.2.55] + [server_config t2_d1_s1_udp udp 18.17.16.15 18.17.16.14 255.255.0.0 nic_router 1 ]" } } proc test_2_router_config { } { if {[enable_test_2]} { return { - - } } + + } } } proc test_2_router_uplink_config { } { if {[enable_test_2]} { return { - } } + } } } @@ -73,22 +73,22 @@ proc test_2_router_uplink_config { } { proc test_3_config { } { if {[enable_test_3]} { return " - [client_config udp_client_3 udp 217.13.192.2 217.13.192.1 255.255.192.0 nic_router 65535 10.0.2.213] - [server_config udp_server_3 udp 10.0.2.213 10.0.2.55 255.255.255.0 nic_bridge 65535 ]" } + [client_config t3_d1_c1_udp udp 217.13.192.2 217.13.192.1 255.255.192.0 nic_router 65535 10.0.2.213] + [server_config t3_d0_s1_udp udp 10.0.2.213 10.0.2.55 255.255.255.0 nic_bridge 65535 ]" } } proc test_3_router_config { } { if {[enable_test_3]} { return { - + - + } } } proc test_3_router_uplink_config { } { if {[enable_test_3]} { return { - } } + } } } @@ -98,19 +98,19 @@ proc test_3_router_uplink_config { } { proc test_4_config { } { if {[enable_test_4]} { return " - [client_config http_client_1 http 10.0.2.201 10.0.2.1 255.255.255.0 nic_bridge 80 10.0.2.55] - [server_config http_server_1 http 192.168.1.18 192.168.1.1 255.255.255.0 nic_router 80 ]" } + [client_config t4_d0_c1_tcp http 10.0.2.201 10.0.2.1 255.255.255.0 nic_bridge 80 10.0.2.55] + [server_config t4_d1_s1_tcp http 192.168.1.18 192.168.1.1 255.255.255.0 nic_router 80 ]" } } proc test_4_router_config { } { if {[enable_test_4]} { return { - - } } + + } } } proc test_4_router_uplink_config { } { if {[enable_test_4]} { return { - } } + } } } # @@ -119,19 +119,19 @@ proc test_4_router_uplink_config { } { proc test_5_config { } { if {[enable_test_5]} { return " - [client_config http_client_2 http 10.0.2.202 10.0.2.1 255.255.255.0 nic_bridge 8080 10.0.2.55] - [server_config http_server_2 http 192.168.2.72 192.168.2.1 255.255.255.0 nic_router 8080 ]" } + [client_config t5_d0_c1_tcp http 10.0.2.202 10.0.2.1 255.255.255.0 nic_bridge 8080 10.0.2.55] + [server_config t5_d1_s1_tcp http 192.168.2.72 192.168.2.1 255.255.255.0 nic_router 8080 ]" } } proc test_5_router_config { } { if {[enable_test_5]} { return { - - } } + + } } } proc test_5_router_uplink_config { } { if {[enable_test_5]} { return { - } } + } } } @@ -141,15 +141,15 @@ proc test_5_router_uplink_config { } { proc test_6_config { } { if {[enable_test_6]} { return " - [client_config http_client_3 http 100.200.0.128 100.200.0.1 255.255.0.0 nic_router 2345 10.0.2.203] - [server_config http_server_3 http 10.0.2.203 10.0.2.1 255.255.255.0 nic_bridge 2345 ]" } + [client_config t6_d1_c1_tcp http 100.200.0.128 100.200.0.1 255.255.0.0 nic_router 2345 10.0.2.203] + [server_config t6_d0_s1_tcp http 10.0.2.203 10.0.2.1 255.255.255.0 nic_bridge 2345 ]" } } proc test_6_router_config { } { if {[enable_test_6]} { return { - + - + @@ -158,7 +158,7 @@ proc test_6_router_config { } { proc test_6_router_uplink_config { } { if {[enable_test_6]} { return { - } } + } } } @@ -170,20 +170,20 @@ proc test_7_config { } { if {[enable_test_7]} { append config " - [client_config lan_2_client_1 http dhcp dhcp dhcp lan_2_nic_router 2345 10.0.2.204] - [client_config lan_2_client_2 http dhcp dhcp dhcp nic_router 3456 10.0.2.240] - [client_config lan_2_client_3 http dhcp dhcp dhcp nic_router 3456 10.0.2.240] - [server_config lan_3_server_1 http 10.0.2.204 10.0.2.1 255.255.255.0 nic_router 2345 ] - [server_config lan_3_server_2 http 10.0.2.240 10.0.2.1 255.255.255.0 nic_router 3456 ]" + [client_config t7_d1_c1_tcp http dhcp dhcp dhcp t7_d1_nic_router 2345 10.0.2.204] + [client_config t7_d1_c2_tcp http dhcp dhcp dhcp nic_router 3456 10.0.2.240] + [client_config t7_d1_c3_tcp http dhcp dhcp dhcp nic_router 3456 10.0.2.240] + [server_config t7_d2_s1_tcp http 10.0.2.204 10.0.2.1 255.255.255.0 nic_router 2345 ] + [server_config t7_d2_s2_tcp http 10.0.2.240 10.0.2.1 255.255.255.0 nic_router 3456 ]" append config { - + - + @@ -214,23 +214,23 @@ proc test_7_config { } { proc test_7_router_config { } { if {[enable_test_7]} { return { - - + + - + - - + + - - + + } } } @@ -286,7 +286,11 @@ append config { tcp_idle_timeout_sec="30" tcp_max_segm_lifetime_sec="15"> - + @@ -325,12 +329,12 @@ append config { - - - - - - + + + + + + diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README index f4bf5ae831..044bb8d9f0 100644 --- a/repos/os/src/server/nic_router/README +++ b/repos/os/src/server/nic_router/README @@ -447,15 +447,22 @@ The NIC router can be configured to send reports about its state. Configuration example (shows default values of attributes): - - - +! +! +! If the 'report' tag is not available, no reports are send. The attributes of the 'report' tag: 'bytes' : Boolean : Whether to report sent bytes and received bytes per domain +'stats' : Boolean : Whether to report statistics about session objects +'quota' : Boolean : Whether to report quota and its utilization 'config' : Boolean : Whether to report IPv4 interface and gateway per domain 'config_triggers' : Boolean : Wether to force a report each time the IPv4 diff --git a/repos/os/src/server/nic_router/arp_waiter.cc b/repos/os/src/server/nic_router/arp_waiter.cc index d790ef55a5..992e59c2b8 100644 --- a/repos/os/src/server/nic_router/arp_waiter.cc +++ b/repos/os/src/server/nic_router/arp_waiter.cc @@ -28,6 +28,7 @@ Arp_waiter::Arp_waiter(Interface &src, _src_le(this), _src(src), _dst_le(this), _dst(dst), _ip(ip), _packet(packet) { + _src.arp_stats().alive++; _src.own_arp_waiters().insert(&_src_le); _dst().foreign_arp_waiters().insert(&_dst_le); } @@ -35,6 +36,8 @@ Arp_waiter::Arp_waiter(Interface &src, Arp_waiter::~Arp_waiter() { + _src.arp_stats().alive--; + _src.arp_stats().destroyed++; _src.own_arp_waiters().remove(&_src_le); _dst().foreign_arp_waiters().remove(&_dst_le); } diff --git a/repos/os/src/server/nic_router/component.cc b/repos/os/src/server/nic_router/component.cc index b2fa0d4322..ee1b875098 100644 --- a/repos/os/src/server/nic_router/component.cc +++ b/repos/os/src/server/nic_router/component.cc @@ -26,10 +26,11 @@ using namespace Genode; ** Communication_buffer ** **************************/ -Communication_buffer::Communication_buffer(Ram_session &ram, - Genode::size_t const size) +Communication_buffer::Communication_buffer(Ram_allocator &ram_alloc, + size_t const size) : - Ram_dataspace_capability(ram.alloc(size)), _ram(ram) + _ram_alloc { ram_alloc }, + _ram_ds { ram_alloc.alloc(size) } { } @@ -38,15 +39,15 @@ Communication_buffer::Communication_buffer(Ram_session &ram, ****************************/ Session_component_base:: -Session_component_base(Allocator &guarded_alloc_backing, - size_t const guarded_alloc_amount, - Ram_session &buf_ram, - size_t const tx_buf_size, - size_t const rx_buf_size) +Session_component_base(Session_env &session_env, + size_t const tx_buf_size, + size_t const rx_buf_size) : - _guarded_alloc(&guarded_alloc_backing, guarded_alloc_amount), - _range_alloc(&_guarded_alloc), _tx_buf(buf_ram, tx_buf_size), - _rx_buf(buf_ram, rx_buf_size) + _session_env { session_env }, + _alloc { _session_env, _session_env }, + _packet_alloc { &_alloc }, + _tx_buf { _session_env, tx_buf_size }, + _rx_buf { _session_env, rx_buf_size } { } @@ -56,8 +57,13 @@ Session_component_base(Allocator &guarded_alloc_backing, Net::Session_component:: Interface_policy::Interface_policy(Genode::Session_label const &label, + Session_env const &session_env, Configuration const &config) -: _label(label), _config(config) { } +: + _label { label }, + _config { config }, + _session_env { session_env } +{ } Domain_name @@ -86,28 +92,25 @@ Net::Session_component::Interface_policy::determine_domain_name() const ** Session_component ** ***********************/ -Net::Session_component::Session_component(Allocator &alloc, - Timer::Connection &timer, - size_t const amount, - Ram_session &buf_ram, - size_t const tx_buf_size, - size_t const rx_buf_size, - Region_map ®ion_map, - Mac_address const mac, - Entrypoint &ep, - Mac_address const &router_mac, - Session_label const &label, - Interface_list &interfaces, - Configuration &config) +Net::Session_component::Session_component(Session_env &session_env, + size_t const tx_buf_size, + size_t const rx_buf_size, + Timer::Connection &timer, + Mac_address const mac, + Mac_address const &router_mac, + Session_label const &label, + Interface_list &interfaces, + Configuration &config, + Ram_dataspace_capability const ram_ds) : - Session_component_base { alloc, amount, buf_ram, tx_buf_size, - rx_buf_size }, - Session_rpc_object { region_map, _tx_buf, _rx_buf, &_range_alloc, - ep.rpc_ep() }, - _interface_policy { label, config }, - _interface { ep, timer, router_mac, _guarded_alloc, mac, - config, interfaces, *_tx.sink(), *_rx.source(), - _link_state, _interface_policy } + Session_component_base { session_env, tx_buf_size,rx_buf_size }, + Session_rpc_object { _session_env, _tx_buf.ds(), _rx_buf.ds(), + &_packet_alloc, _session_env.ep().rpc_ep() }, + _interface_policy { label, _session_env, config }, + _interface { _session_env.ep(), timer, router_mac, _alloc, + mac, config, interfaces, *_tx.sink(), + *_rx.source(), _link_state, _interface_policy }, + _ram_ds { ram_ds } { _interface.attach_to_domain(); @@ -122,58 +125,123 @@ Net::Session_component::Session_component(Allocator &alloc, ** Root ** **********/ -Net::Root::Root(Entrypoint &ep, +Net::Root::Root(Env &env, Timer::Connection &timer, Allocator &alloc, Configuration &config, - Ram_session &buf_ram, - Interface_list &interfaces, - Region_map ®ion_map) + Quota &shared_quota, + Interface_list &interfaces) : - Root_component(&ep.rpc_ep(), &alloc), _timer(timer), - _mac_alloc(MAC_ALLOC_BASE), _ep(ep), _router_mac(_mac_alloc.alloc()), - _config(config), _buf_ram(buf_ram), _region_map(region_map), - _interfaces(interfaces) + Root_component { &env.ep().rpc_ep(), &alloc }, + _env { env }, + _timer { timer }, + _mac_alloc { MAC_ALLOC_BASE }, + _router_mac { _mac_alloc.alloc() }, + _config { config }, + _shared_quota { shared_quota }, + _interfaces { interfaces } { } Session_component *Net::Root::_create_session(char const *args) { try { - size_t const ram_quota = - Arg_string::find_arg(args, "ram_quota").ulong_value(0); + /* create session environment temporarily on the stack */ + Session_env session_env_tmp { _env, _shared_quota, + Ram_quota { Arg_string::find_arg(args, "ram_quota").ulong_value(0) }, + Cap_quota { Arg_string::find_arg(args, "cap_quota").ulong_value(0) } }; + Reference session_env { session_env_tmp }; - size_t const tx_buf_size = - Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); + /* alloc/attach RAM block and move session env to base of the block */ + Ram_dataspace_capability ram_ds { + session_env().alloc(sizeof(Session_env) + + sizeof(Session_component), CACHED) }; + try { + void * const ram_ptr { session_env().attach(ram_ds) }; + session_env = *construct_at(ram_ptr, session_env()); - size_t const rx_buf_size = - Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); - - size_t const session_size = - max((size_t)4096, sizeof(Session_component)); - - if (ram_quota < session_size) { + /* create new session object behind session env in the RAM block */ + try { + Session_label const label { label_from_args(args) }; + return construct_at( + (void*)((addr_t)ram_ptr + sizeof(Session_env)), + session_env(), + Arg_string::find_arg(args, "tx_buf_size").ulong_value(0), + Arg_string::find_arg(args, "rx_buf_size").ulong_value(0), + _timer, _mac_alloc.alloc(), _router_mac, label, + _interfaces, _config(), ram_ds); + } + catch (Mac_allocator::Alloc_failed) { + session_env().detach(ram_ptr); + session_env().free(ram_ds); + _invalid_downlink("failed to allocate MAC address"); + throw Service_denied(); + } + catch (Out_of_ram) { + session_env().detach(ram_ptr); + session_env().free(ram_ds); + _invalid_downlink("NIC session RAM quota"); + throw Insufficient_ram_quota(); + } + catch (Out_of_caps) { + session_env().detach(ram_ptr); + session_env().free(ram_ds); + _invalid_downlink("NIC session CAP quota"); + throw Insufficient_cap_quota(); + } + } + catch (Region_map::Invalid_dataspace) { + session_env().free(ram_ds); + _invalid_downlink("Failed to attach RAM"); + throw Service_denied(); + } + catch (Region_map::Region_conflict) { + session_env().free(ram_ds); + _invalid_downlink("Failed to attach RAM"); + throw Service_denied(); + } + catch (Out_of_ram) { + session_env().free(ram_ds); _invalid_downlink("NIC session RAM quota"); throw Insufficient_ram_quota(); } - if (tx_buf_size > ram_quota - session_size || - rx_buf_size > ram_quota - session_size || - tx_buf_size + rx_buf_size > ram_quota - session_size) - { - _invalid_downlink("NIC session RAM quota for buffers)"); - throw Insufficient_ram_quota(); + catch (Out_of_caps) { + session_env().free(ram_ds); + _invalid_downlink("NIC session CAP quota"); + throw Insufficient_cap_quota(); } - Session_label const label(label_from_args(args)); - return new (md_alloc()) - Session_component(*md_alloc(), _timer, ram_quota - session_size, - _buf_ram, tx_buf_size, rx_buf_size, _region_map, - _mac_alloc.alloc(), _ep, _router_mac, label, - _interfaces, _config()); } - catch (Mac_allocator::Alloc_failed) { - _invalid_downlink("failed to allocate MAC address"); } + catch (Out_of_ram) { + _invalid_downlink("NIC session RAM quota"); + throw Insufficient_ram_quota(); + } + catch (Out_of_caps) { + _invalid_downlink("NIC session CAP quota"); + throw Insufficient_cap_quota(); + } +} - throw Service_denied(); +void Net::Root::_destroy_session(Session_component *session) +{ + /* read out initial dataspace and session env and destruct session */ + Ram_dataspace_capability ram_ds { session->ram_ds() }; + Session_env const &session_env { session->session_env() }; + Session_label const session_label { session->interface_policy().label() }; + session->~Session_component(); + + /* copy session env to stack and detach/free all session data */ + Session_env session_env_stack { session_env }; + session_env_stack.detach(session); + session_env_stack.detach(&session_env); + session_env_stack.free(ram_ds); + + /* check for leaked quota */ + if (session_env_stack.ram_guard().used().value) { + error("NIC session component \"", session_label, "\" leaks RAM quota of ", + session_env_stack.ram_guard().used().value, " byte(s)"); }; + if (session_env_stack.cap_guard().used().value) { + error("NIC session component \"", session_label, "\" leaks CAP quota of ", + session_env_stack.cap_guard().used().value, " cap(s)"); }; } diff --git a/repos/os/src/server/nic_router/component.h b/repos/os/src/server/nic_router/component.h index 8707d33423..7fc65982ef 100644 --- a/repos/os/src/server/nic_router/component.h +++ b/repos/os/src/server/nic_router/component.h @@ -15,6 +15,7 @@ #define _COMPONENT_H_ /* Genode includes */ +#include #include #include #include @@ -24,6 +25,9 @@ #include #include #include +#include + +namespace Genode { class Session_env; } namespace Net { @@ -34,18 +38,200 @@ namespace Net { } -class Net::Communication_buffer : public Genode::Ram_dataspace_capability +class Genode::Session_env : public Ram_allocator, + public Region_map { private: - Genode::Ram_session &_ram; + Env &_env; + Net::Quota &_shared_quota; + Ram_quota_guard _ram_guard; + Cap_quota_guard _cap_guard; + + template + void _consume(size_t own_ram, + size_t max_shared_ram, + size_t own_cap, + size_t max_shared_cap, + FUNC && functor) + { + size_t const max_ram_consumpt { own_ram + max_shared_ram }; + size_t const max_cap_consumpt { own_cap + max_shared_cap }; + size_t ram_consumpt { _env.pd().used_ram().value }; + size_t cap_consumpt { _env.pd().used_caps().value }; + { + Ram_quota_guard::Reservation ram_reserv { _ram_guard, Ram_quota { max_ram_consumpt } }; + Cap_quota_guard::Reservation cap_reserv { _cap_guard, Cap_quota { max_cap_consumpt } }; + + functor(); + + ram_reserv.acknowledge(); + cap_reserv.acknowledge(); + } + ram_consumpt = _env.pd().used_ram().value - ram_consumpt; + cap_consumpt = _env.pd().used_caps().value - cap_consumpt; + + if (ram_consumpt > max_ram_consumpt) { + error("Session_env: more RAM quota consumed than expected"); } + if (cap_consumpt > max_cap_consumpt) { + error("Session_env: more CAP quota consumed than expected"); } + if (ram_consumpt < own_ram) { + error("Session_env: less RAM quota consumed than expected"); } + if (cap_consumpt < own_cap) { + error("Session_env: less CAP quota consumed than expected"); } + + _shared_quota.ram += ram_consumpt - own_ram; + _shared_quota.cap += cap_consumpt - own_cap; + + _ram_guard.replenish( Ram_quota { max_shared_ram } ); + _cap_guard.replenish( Cap_quota { max_shared_cap } ); + } + + template + void _replenish(size_t accounted_ram, + size_t accounted_cap, + FUNC && functor) + { + size_t ram_replenish { _env.pd().used_ram().value }; + size_t cap_replenish { _env.pd().used_caps().value }; + functor(); + ram_replenish = ram_replenish - _env.pd().used_ram().value; + cap_replenish = cap_replenish - _env.pd().used_caps().value; + + if (ram_replenish < accounted_ram) { + error("Session_env: less RAM quota replenished than expected"); } + if (cap_replenish < accounted_cap) { + error("Session_env: less CAP quota replenished than expected"); } + + _shared_quota.ram -= ram_replenish - accounted_ram; + _shared_quota.cap -= cap_replenish - accounted_cap; + + _ram_guard.replenish( Ram_quota { accounted_ram } ); + _cap_guard.replenish( Cap_quota { accounted_cap } ); + + } public: - Communication_buffer(Genode::Ram_session &ram, - Genode::size_t const size); + Session_env(Env &env, + Net::Quota &shared_quota, + Ram_quota const &ram_quota, + Cap_quota const &cap_quota) + : + _env { env }, + _shared_quota { shared_quota }, + _ram_guard { ram_quota }, + _cap_guard { cap_quota } + { } - ~Communication_buffer() { _ram.free(*this); } + Entrypoint &ep() { return _env.ep(); } + + + /******************* + ** Ram_allocator ** + *******************/ + + Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override + { + enum { MAX_SHARED_CAP = 1 }; + enum { MAX_SHARED_RAM = 4096 }; + enum { DS_SIZE_GRANULARITY_LOG2 = 12 }; + + size_t const ds_size = align_addr(size, DS_SIZE_GRANULARITY_LOG2); + Ram_dataspace_capability ds; + _consume(ds_size, MAX_SHARED_RAM, 1, MAX_SHARED_CAP, [&] () { + ds = _env.pd().alloc(ds_size, cached); + }); + return ds; + } + + + void free(Ram_dataspace_capability ds) override + { + _replenish(_env.pd().dataspace_size(ds), 1, [&] () { + _env.pd().free(ds); + }); + } + + size_t dataspace_size(Ram_dataspace_capability ds) const override { return _env.pd().dataspace_size(ds); } + + + /**************** + ** Region_map ** + ****************/ + + Local_addr attach(Dataspace_capability ds, + size_t size = 0, + off_t offset = 0, + bool use_local_addr = false, + Local_addr local_addr = (void *)0, + bool executable = false, + bool writeable = true) override + { + enum { MAX_SHARED_CAP = 2 }; + enum { MAX_SHARED_RAM = 4 * 4096 }; + + void *ptr; + _consume(0, MAX_SHARED_RAM, 0, MAX_SHARED_CAP, [&] () { + ptr = _env.rm().attach(ds, size, offset, use_local_addr, + local_addr, executable, writeable); + }); + return ptr; + }; + + void report(Genode::Xml_generator &xml) const + { + xml.node("ram-quota", [&] () { + xml.attribute("used", _ram_guard.used().value); + xml.attribute("limit", _ram_guard.limit().value); + xml.attribute("avail", _ram_guard.avail().value); + }); + xml.node("cap-quota", [&] () { + xml.attribute("used", _cap_guard.used().value); + xml.attribute("limit", _cap_guard.limit().value); + xml.attribute("avail", _cap_guard.avail().value); + }); + } + + void detach(Local_addr local_addr) override + { + _replenish(0, 0, [&] () { _env.rm().detach(local_addr); }); + } + + void fault_handler(Signal_context_capability handler) override { _env.rm().fault_handler(handler); } + State state() override { return _env.rm().state(); } + Dataspace_capability dataspace() override { return _env.rm().dataspace(); } + + + /*************** + ** Accessors ** + ***************/ + + Ram_quota_guard const &ram_guard() const { return _ram_guard; }; + Cap_quota_guard const &cap_guard() const { return _cap_guard; }; +}; + + +class Net::Communication_buffer +{ + private: + + Genode::Ram_allocator &_ram_alloc; + Genode::Ram_dataspace_capability _ram_ds; + + public: + + Communication_buffer(Genode::Ram_allocator &ram_alloc, + Genode::size_t const size); + + ~Communication_buffer() { _ram_alloc.free(_ram_ds); } + + + /*************** + ** Accessors ** + ***************/ + + Genode::Dataspace_capability ds() const { return _ram_ds; } }; @@ -53,18 +239,17 @@ class Net::Session_component_base { protected: - Genode::Allocator_guard _guarded_alloc; - Nic::Packet_allocator _range_alloc; - Communication_buffer _tx_buf; - Communication_buffer _rx_buf; + Genode::Session_env &_session_env; + Genode::Heap _alloc; + Nic::Packet_allocator _packet_alloc; + Communication_buffer _tx_buf; + Communication_buffer _rx_buf; public: - Session_component_base(Genode::Allocator &guarded_alloc_backing, - Genode::size_t const guarded_alloc_amount, - Genode::Ram_session &buf_ram, - Genode::size_t const tx_buf_size, - Genode::size_t const rx_buf_size); + Session_component_base(Genode::Session_env &session_env, + Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size); }; @@ -77,12 +262,14 @@ class Net::Session_component : private Session_component_base, { private: - Genode::Session_label const _label; - Const_reference _config; + Genode::Session_label const _label; + Const_reference _config; + Genode::Session_env const &_session_env; public: Interface_policy(Genode::Session_label const &label, + Genode::Session_env const &session_env, Configuration const &config); @@ -92,27 +279,27 @@ class Net::Session_component : private Session_component_base, Domain_name determine_domain_name() const override; void handle_config(Configuration const &config) override { _config = config; } + Genode::Session_label const &label() const override { return _label; } + void report(Genode::Xml_generator &xml) const override { _session_env.report(xml); }; }; - bool _link_state { true }; - Interface_policy _interface_policy; - Interface _interface; + bool _link_state { true }; + Interface_policy _interface_policy; + Interface _interface; + Genode::Ram_dataspace_capability const _ram_ds; public: - Session_component(Genode::Allocator &alloc, - Timer::Connection &timer, - Genode::size_t const amount, - Genode::Ram_session &buf_ram, - Genode::size_t const tx_buf_size, - Genode::size_t const rx_buf_size, - Genode::Region_map ®ion_map, - Mac_address const mac, - Genode::Entrypoint &ep, - Mac_address const &router_mac, - Genode::Session_label const &label, - Interface_list &interfaces, - Configuration &config); + Session_component(Genode::Session_env &session_env, + Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Timer::Connection &timer, + Mac_address const mac, + Mac_address const &router_mac, + Genode::Session_label const &label, + Interface_list &interfaces, + Configuration &config, + Genode::Ram_dataspace_capability const ram_ds); /****************** @@ -123,6 +310,15 @@ class Net::Session_component : private Session_component_base, bool link_state() override { return _interface.link_state(); } void link_state_sigh(Genode::Signal_context_capability sigh) override { _interface.session_link_state_sigh(sigh); } + + + /*************** + ** Accessors ** + ***************/ + + Interface_policy const &interface_policy() const { return _interface_policy; } + Genode::Ram_dataspace_capability ram_ds() const { return _ram_ds; }; + Genode::Session_env const &session_env() const { return _session_env; }; }; @@ -132,13 +328,12 @@ class Net::Root : public Genode::Root_component enum { MAC_ALLOC_BASE = 0x02 }; + Genode::Env &_env; Timer::Connection &_timer; Mac_allocator _mac_alloc; - Genode::Entrypoint &_ep; - Mac_address const _router_mac; + Mac_address const _router_mac; Reference _config; - Genode::Ram_session &_buf_ram; - Genode::Region_map &_region_map; + Quota &_shared_quota; Interface_list &_interfaces; void _invalid_downlink(char const *reason); @@ -149,16 +344,16 @@ class Net::Root : public Genode::Root_component ********************/ Session_component *_create_session(char const *args) override; + void _destroy_session(Session_component *session) override; public: - Root(Genode::Entrypoint &ep, - Timer::Connection &timer, - Genode::Allocator &alloc, - Configuration &config, - Genode::Ram_session &buf_ram, - Interface_list &interfaces, - Genode::Region_map ®ion_map); + Root(Genode::Env &env, + Timer::Connection &timer, + Genode::Allocator &alloc, + Configuration &config, + Quota &shared_quota, + Interface_list &interfaces); void handle_config(Configuration &config) { _config = Reference(config); } }; diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd index b322953a1d..8c64b50be0 100644 --- a/repos/os/src/server/nic_router/config.xsd +++ b/repos/os/src/server/nic_router/config.xsd @@ -59,6 +59,8 @@ + + diff --git a/repos/os/src/server/nic_router/configuration.cc b/repos/os/src/server/nic_router/configuration.cc index b7a920c340..3211335b15 100644 --- a/repos/os/src/server/nic_router/configuration.cc +++ b/repos/os/src/server/nic_router/configuration.cc @@ -58,27 +58,28 @@ void Configuration::_invalid_domain(Domain &domain, Configuration::Configuration(Env &env, - Xml_node const node, + Xml_node const node, Allocator &alloc, Timer::Connection &timer, Configuration &old_config, + Quota const &shared_quota, Interface_list &interfaces) : - _alloc(alloc), - _max_packets_per_signal(node.attribute_value("max_packets_per_signal", (unsigned long)DEFAULT_MAX_PACKETS_PER_SIGNAL)), - _verbose (node.attribute_value("verbose", false)), - _verbose_packets (node.attribute_value("verbose_packets", false)), - _verbose_packet_drop (node.attribute_value("verbose_packet_drop", false)), - _verbose_domain_state (node.attribute_value("verbose_domain_state", false)), - _icmp_echo_server (node.attribute_value("icmp_echo_server", true)), - _dhcp_discover_timeout (read_sec_attr(node, "dhcp_discover_timeout_sec", DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC)), - _dhcp_request_timeout (read_sec_attr(node, "dhcp_request_timeout_sec", DEFAULT_DHCP_REQUEST_TIMEOUT_SEC )), - _dhcp_offer_timeout (read_sec_attr(node, "dhcp_offer_timeout_sec", DEFAULT_DHCP_OFFER_TIMEOUT_SEC )), - _icmp_idle_timeout (read_sec_attr(node, "icmp_idle_timeout_sec", DEFAULT_ICMP_IDLE_TIMEOUT_SEC )), - _udp_idle_timeout (read_sec_attr(node, "udp_idle_timeout_sec", DEFAULT_UDP_IDLE_TIMEOUT_SEC )), - _tcp_idle_timeout (read_sec_attr(node, "tcp_idle_timeout_sec", DEFAULT_TCP_IDLE_TIMEOUT_SEC )), - _tcp_max_segm_lifetime (read_sec_attr(node, "tcp_max_segm_lifetime_sec", DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC)), - _node(node) + _alloc { alloc }, + _max_packets_per_signal { node.attribute_value("max_packets_per_signal", (unsigned long)DEFAULT_MAX_PACKETS_PER_SIGNAL) }, + _verbose { node.attribute_value("verbose", false) }, + _verbose_packets { node.attribute_value("verbose_packets", false) }, + _verbose_packet_drop { node.attribute_value("verbose_packet_drop", false) }, + _verbose_domain_state { node.attribute_value("verbose_domain_state", false) }, + _icmp_echo_server { node.attribute_value("icmp_echo_server", true) }, + _dhcp_discover_timeout { read_sec_attr(node, "dhcp_discover_timeout_sec", DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC) }, + _dhcp_request_timeout { read_sec_attr(node, "dhcp_request_timeout_sec", DEFAULT_DHCP_REQUEST_TIMEOUT_SEC ) }, + _dhcp_offer_timeout { read_sec_attr(node, "dhcp_offer_timeout_sec", DEFAULT_DHCP_OFFER_TIMEOUT_SEC ) }, + _icmp_idle_timeout { read_sec_attr(node, "icmp_idle_timeout_sec", DEFAULT_ICMP_IDLE_TIMEOUT_SEC ) }, + _udp_idle_timeout { read_sec_attr(node, "udp_idle_timeout_sec", DEFAULT_UDP_IDLE_TIMEOUT_SEC ) }, + _tcp_idle_timeout { read_sec_attr(node, "tcp_idle_timeout_sec", DEFAULT_TCP_IDLE_TIMEOUT_SEC ) }, + _tcp_max_segm_lifetime { read_sec_attr(node, "tcp_max_segm_lifetime_sec", DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC) }, + _node { node } { /* do parts of domain initialization that do not lookup other domains */ node.for_each_sub_node("domain", [&] (Xml_node const node) { @@ -137,11 +138,12 @@ Configuration::Configuration(Env &env, catch (Pointer::Invalid) { /* there is no reporter by now, create a new one */ - _reporter = *new (_alloc) Reporter(env, "state"); + _reporter = *new (_alloc) Reporter(env, "state", nullptr, 4096 * 4); } /* create report generator */ _report = *new (_alloc) - Report(_verbose, report_node, timer, _domains, _reporter()); + Report(_verbose, report_node, timer, _domains, shared_quota, + env.pd(), _reporter()); } catch (Genode::Xml_node::Nonexistent_sub_node) { } diff --git a/repos/os/src/server/nic_router/configuration.h b/repos/os/src/server/nic_router/configuration.h index 747d410983..a40389fb14 100644 --- a/repos/os/src/server/nic_router/configuration.h +++ b/repos/os/src/server/nic_router/configuration.h @@ -79,6 +79,7 @@ class Net::Configuration Genode::Allocator &alloc, Timer::Connection &timer, Configuration &old_config, + Quota const &shared_quota, Interface_list &interfaces); ~Configuration(); diff --git a/repos/os/src/server/nic_router/dhcp_server.cc b/repos/os/src/server/nic_router/dhcp_server.cc index 0f8b2211cd..7ac397c6f8 100644 --- a/repos/os/src/server/nic_router/dhcp_server.cc +++ b/repos/os/src/server/nic_router/dhcp_server.cc @@ -163,10 +163,18 @@ Dhcp_allocation::Dhcp_allocation(Interface &interface, _interface(interface), _ip(ip), _mac(mac), _timeout(timer, *this, &Dhcp_allocation::_handle_timeout) { + _interface.dhcp_stats().alive++; _timeout.schedule(lifetime); } +Dhcp_allocation::~Dhcp_allocation() +{ + _interface.dhcp_stats().alive--; + _interface.dhcp_stats().destroyed++; +} + + void Dhcp_allocation::lifetime(Microseconds lifetime) { _timeout.schedule(lifetime); diff --git a/repos/os/src/server/nic_router/dhcp_server.h b/repos/os/src/server/nic_router/dhcp_server.h index 8a34dfc94c..6aedab3013 100644 --- a/repos/os/src/server/nic_router/dhcp_server.h +++ b/repos/os/src/server/nic_router/dhcp_server.h @@ -31,7 +31,6 @@ namespace Net { class Configuration; class Dhcp_server; class Dhcp_allocation; - class Dhcp_allocation; class Dhcp_allocation_tree; using Dhcp_allocation_list = List; @@ -125,6 +124,8 @@ class Net::Dhcp_allocation : public Genode::Avl_node, Timer::Connection &timer, Genode::Microseconds lifetime); + ~Dhcp_allocation(); + Dhcp_allocation &find_by_mac(Mac_address const &mac); void lifetime(Genode::Microseconds lifetime); diff --git a/repos/os/src/server/nic_router/domain.cc b/repos/os/src/server/nic_router/domain.cc index 3f87848844..34c54b1e8a 100644 --- a/repos/os/src/server/nic_router/domain.cc +++ b/repos/os/src/server/nic_router/domain.cc @@ -357,21 +357,78 @@ void Domain::detach_interface(Interface &interface) void Domain::report(Xml_generator &xml) { - bool const bytes = _config.report().bytes(); - bool const config = _config.report().config(); - if (!bytes && !config) { - return; - } xml.node("domain", [&] () { + bool empty = true; xml.attribute("name", _name); - if (bytes) { + if (_config.report().bytes()) { xml.attribute("rx_bytes", _tx_bytes); xml.attribute("tx_bytes", _rx_bytes); + empty = false; } - if (config) { + if (_config.report().config()) { xml.attribute("ipv4", String<19>(ip_config().interface)); xml.attribute("gw", String<16>(ip_config().gateway)); xml.attribute("dns", String<16>(ip_config().dns_server)); + empty = false; } + if (_config.report().stats()) { + try { xml.node("tcp-links", [&] () { _tcp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("udp-links", [&] () { _udp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("icmp-links", [&] () { _icmp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("arp-waiters", [&] () { _arp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("dhcp-allocations", [&] () { _dhcp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + } + _interfaces.for_each([&] (Interface &interface) { + try { + interface.report(xml); + empty = false; + } catch (Report::Empty) { } + }); + if (empty) { + throw Report::Empty(); } }); } + + +/*********************** + ** Domain_link_stats ** + ***********************/ + +void +Domain_link_stats::dissolve_interface(Interface_link_stats const &stats) +{ + refused_for_ram += stats.refused_for_ram; + refused_for_ports += stats.refused_for_ports; + destroyed += stats.destroyed; +} + + +void Domain_link_stats::report(Genode::Xml_generator &xml) +{ + bool empty = true; + + if (refused_for_ram) { xml.node("refused_for_ram", [&] () { xml.attribute("value", refused_for_ram); }); empty = false; } + if (refused_for_ports) { xml.node("refused_for_ports", [&] () { xml.attribute("value", refused_for_ports); }); empty = false; } + if (destroyed) { xml.node("destroyed", [&] () { xml.attribute("value", destroyed); }); empty = false; } + + if (empty) { throw Report::Empty(); } +} + + +/************************* + ** Domain_object_stats ** + *************************/ + +void +Domain_object_stats::dissolve_interface(Interface_object_stats const &stats) +{ + destroyed += stats.destroyed; +} + + +void Domain_object_stats::report(Genode::Xml_generator &xml) +{ + bool empty = true; + if (destroyed) { xml.node("destroyed", [&] () { xml.attribute("value", destroyed); }); empty = false; } + if (empty) { throw Report::Empty(); } +} diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h index f68cfb5f24..50cdad8182 100644 --- a/repos/os/src/server/nic_router/domain.h +++ b/repos/os/src/server/nic_router/domain.h @@ -44,9 +44,33 @@ namespace Net { class Domain; using Domain_name = Genode::String<160>; class Domain_tree; + class Domain_link_stats; + class Domain_object_stats; } +struct Net::Domain_object_stats +{ + Genode::size_t destroyed { 0 }; + + void dissolve_interface(Interface_object_stats const &stats); + + void report(Genode::Xml_generator &xml); +}; + + +struct Net::Domain_link_stats : Domain_object_stats +{ + Genode::size_t refused_for_ram { 0 }; + Genode::size_t refused_for_ports { 0 }; + Genode::size_t destroyed { 0 }; + + void dissolve_interface(Interface_link_stats const &stats); + + void report(Genode::Xml_generator &xml); +}; + + class Net::Domain_tree : public Avl_string_tree { }; @@ -96,6 +120,11 @@ class Net::Domain : public Domain_base, bool const _verbose_packet_drop; bool const _icmp_echo_server; Genode::Session_label const _label; + Domain_link_stats _udp_stats { }; + Domain_link_stats _tcp_stats { }; + Domain_link_stats _icmp_stats { }; + Domain_object_stats _arp_stats { }; + Domain_object_stats _dhcp_stats { }; void _read_forward_rules(Genode::Cstring const &protocol, Domain_tree &domains, @@ -190,6 +219,11 @@ class Net::Domain : public Domain_base, Link_side_tree &tcp_links() { return _tcp_links; } Link_side_tree &udp_links() { return _udp_links; } Link_side_tree &icmp_links() { return _icmp_links; } + Domain_link_stats &udp_stats() { return _udp_stats; } + Domain_link_stats &tcp_stats() { return _tcp_stats; } + Domain_link_stats &icmp_stats() { return _icmp_stats; } + Domain_object_stats &arp_stats() { return _arp_stats; } + Domain_object_stats &dhcp_stats() { return _dhcp_stats; } }; #endif /* _DOMAIN_H_ */ diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 042351d673..df4a8c7bd1 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -27,11 +27,12 @@ using namespace Net; using Genode::Deallocator; using Genode::size_t; using Genode::uint32_t; +using Genode::addr_t; using Genode::log; +using Genode::error; using Genode::Exception; -using Genode::construct_at; -using Genode::Quota_guard; -using Genode::Ram_quota; +using Genode::Out_of_ram; +using Genode::Out_of_caps; using Genode::Constructible; using Genode::Signal_context_capability; using Genode::Signal_transmitter; @@ -57,7 +58,7 @@ static void _destroy_link(Link &link, Link_list &links, Deallocator &dealloc) { - link.dissolve(); + link.dissolve(false); links.remove(&link); destroy(dealloc, static_cast(&link)); } @@ -74,6 +75,29 @@ static void _destroy_links(Link_list &links, } +template +static void _destroy_some_links(Link_list &links, + Link_list &dissolved_links, + Deallocator &dealloc, + unsigned long &max) +{ + if (!max) { + return; } + + while (Link *link = dissolved_links.first()) { + dissolved_links.remove(link); + destroy(dealloc, static_cast(link)); + if (!--max) { + return; } + } + while (Link *link = links.first()) { + _destroy_link(*link, links, dealloc); + if (!--max) { + return; } + } +} + + static void _link_packet(L3_protocol const prot, void *const prot_base, Link &link, @@ -89,10 +113,22 @@ static void _link_packet(L3_protocol const prot, return; } case L3_protocol::UDP: - static_cast(&link)->packet(); + if (client) { + static_cast(&link)->client_packet(); + return; + } else { + static_cast(&link)->server_packet(); + return; + } return; case L3_protocol::ICMP: - static_cast(&link)->packet(); + if (client) { + static_cast(&link)->client_packet(); + return; + } else { + static_cast(&link)->server_packet(); + return; + } return; default: throw Interface::Bad_transport_protocol(); } } @@ -179,6 +215,49 @@ static void *_prot_base(L3_protocol const prot, } +/************************** + ** Interface_link_stats ** + **************************/ + +void Interface_link_stats::report(Genode::Xml_generator &xml) +{ + bool empty = true; + + if (refused_for_ram) { xml.node("refused_for_ram", [&] () { xml.attribute("value", refused_for_ram); }); empty = false; } + if (refused_for_ports) { xml.node("refused_for_ports", [&] () { xml.attribute("value", refused_for_ports); }); empty = false; } + + if (opening) { xml.node("opening", [&] () { xml.attribute("value", opening); }); empty = false; } + if (open) { xml.node("open", [&] () { xml.attribute("value", open); }); empty = false; } + if (closing) { xml.node("closing", [&] () { xml.attribute("value", closing); }); empty = false; } + if (closed) { xml.node("closed", [&] () { xml.attribute("value", closed); }); empty = false; } + + if (dissolved_timeout_opening) { xml.node("dissolved_timeout_opening", [&] () { xml.attribute("value", dissolved_timeout_opening); }); empty = false; } + if (dissolved_timeout_open) { xml.node("dissolved_timeout_open", [&] () { xml.attribute("value", dissolved_timeout_open); }); empty = false; } + if (dissolved_timeout_closing) { xml.node("dissolved_timeout_closing", [&] () { xml.attribute("value", dissolved_timeout_closing); }); empty = false; } + if (dissolved_timeout_closed) { xml.node("dissolved_timeout_closed", [&] () { xml.attribute("value", dissolved_timeout_closed); }); empty = false; } + if (dissolved_no_timeout) { xml.node("dissolved_no_timeout", [&] () { xml.attribute("value", dissolved_no_timeout); }); empty = false; } + + if (destroyed) { xml.node("destroyed", [&] () { xml.attribute("value", destroyed); }); empty = false; } + + if (empty) { throw Report::Empty(); } +} + + +/**************************** + ** Interface_object_stats ** + ****************************/ + +void Interface_object_stats::report(Genode::Xml_generator &xml) +{ + bool empty = true; + + if (alive) { xml.node("alive", [&] () { xml.attribute("value", alive); }); empty = false; } + if (destroyed) { xml.node("destroyed", [&] () { xml.attribute("value", destroyed); }); empty = false; } + + if (empty) { throw Report::Empty(); } +} + + /*************** ** Interface ** ***************/ @@ -252,6 +331,12 @@ void Interface::_detach_from_domain_raw() _interfaces.insert(this); _domain = Pointer(); Signal_transmitter(_session_link_state_sigh).submit(); + + domain.tcp_stats().dissolve_interface(_tcp_stats); + domain.udp_stats().dissolve_interface(_udp_stats); + domain.icmp_stats().dissolve_interface(_icmp_stats); + domain.arp_stats().dissolve_interface(_arp_stats); + domain.dhcp_stats().dissolve_interface(_dhcp_stats); } @@ -359,30 +444,30 @@ Interface::_new_link(L3_protocol const protocol, try { new (_alloc) Tcp_link { *this, local, remote_port_alloc, remote_domain, - remote, _timer, _config(), protocol }; + remote, _timer, _config(), protocol, _tcp_stats }; } - catch (Quota_guard::Limit_exceeded) { - throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(L3_protocol::TCP); } + catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(L3_protocol::TCP); } break; case L3_protocol::UDP: try { new (_alloc) Udp_link { *this, local, remote_port_alloc, remote_domain, - remote, _timer, _config(), protocol }; + remote, _timer, _config(), protocol, _udp_stats }; } - catch (Quota_guard::Limit_exceeded) { - throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(L3_protocol::UDP); } + catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(L3_protocol::UDP); } break; case L3_protocol::ICMP: try { new (_alloc) Icmp_link { *this, local, remote_port_alloc, remote_domain, - remote, _timer, _config(), protocol }; + remote, _timer, _config(), protocol, _icmp_stats }; } - catch (Quota_guard::Limit_exceeded) { - throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(L3_protocol::ICMP); } + catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(L3_protocol::ICMP); } break; default: throw Bad_transport_protocol(); } @@ -433,9 +518,8 @@ void Interface::_adapt_eth(Ethernet_frame ð, hop_ip); }); try { new (_alloc) Arp_waiter { *this, remote_domain, hop_ip, pkt }; } - catch (Quota_guard::Limit_exceeded) { - throw Free_resources_and_retry_handle_eth(); } - + catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(); } throw Packet_postponed(); } } @@ -451,23 +535,31 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð, Domain &local_domain, Domain &remote_domain) { - Pointer remote_port_alloc; try { - Nat_rule &nat = remote_domain.nat_rules().find_by_domain(local_domain); - if(_config().verbose()) { - log("[", local_domain, "] using NAT rule: ", nat); } + Pointer remote_port_alloc; + try { + Nat_rule &nat = remote_domain.nat_rules().find_by_domain(local_domain); + if(_config().verbose()) { + log("[", local_domain, "] using NAT rule: ", nat); } - _src_port(prot, prot_base, nat.port_alloc(prot).alloc()); - ip.src(remote_domain.ip_config().interface.address); - remote_port_alloc = nat.port_alloc(prot); + _src_port(prot, prot_base, nat.port_alloc(prot).alloc()); + ip.src(remote_domain.ip_config().interface.address); + remote_port_alloc = nat.port_alloc(prot); + } + catch (Nat_rule_tree::No_match) { } + Link_side_id const remote_id = { ip.dst(), _dst_port(prot, prot_base), + ip.src(), _src_port(prot, prot_base) }; + _new_link(prot, local_id, remote_port_alloc, remote_domain, remote_id); + remote_domain.interfaces().for_each([&] (Interface &interface) { + interface._pass_prot(eth, size_guard, ip, prot, prot_base, prot_size); + }); + } catch (Port_allocator_guard::Out_of_indices) { + switch (prot) { + case L3_protocol::TCP: _tcp_stats.refused_for_ports++; break; + case L3_protocol::UDP: _udp_stats.refused_for_ports++; break; + case L3_protocol::ICMP: _icmp_stats.refused_for_ports++; break; + default: throw Bad_transport_protocol(); } } - catch (Nat_rule_tree::No_match) { } - Link_side_id const remote_id = { ip.dst(), _dst_port(prot, prot_base), - ip.src(), _src_port(prot, prot_base) }; - _new_link(prot, local_id, remote_port_alloc, remote_domain, remote_id); - remote_domain.interfaces().for_each([&] (Interface &interface) { - interface._pass_prot(eth, size_guard, ip, prot, prot_base, prot_size); - }); } @@ -572,8 +664,8 @@ void Interface::_new_dhcp_allocation(Ethernet_frame ð, dhcp.xid(), local_domain.ip_config().interface); } - catch (Quota_guard::Limit_exceeded) { - throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(); } } @@ -1395,15 +1487,29 @@ void Interface::_handle_eth(void *const eth_base, if (_config().verbose()) { log("[", local_domain, "] free resources and retry to handle packet"); } - /* resources do not suffice, destroy all links */ - _destroy_links (_tcp_links, _dissolved_tcp_links, _alloc); - _destroy_links (_udp_links, _dissolved_udp_links, _alloc); - _destroy_links(_icmp_links, _dissolved_icmp_links, _alloc); + /* + * Resources do not suffice, destroy some links + * + * Limit number of links to destroy because otherwise, + * this could block the router for a significant + * amount of time. + */ + unsigned long max = MAX_FREE_OPS_PER_EMERGENCY; + _destroy_some_links (_tcp_links, _dissolved_tcp_links, _alloc, max); + _destroy_some_links (_udp_links, _dissolved_udp_links, _alloc, max); + _destroy_some_links(_icmp_links, _dissolved_icmp_links, _alloc, max); /* retry to handle ethernet frame */ _handle_eth(eth, size_guard, pkt, local_domain); } - catch (Free_resources_and_retry_handle_eth) { + catch (Free_resources_and_retry_handle_eth exception) { + if (exception.prot != (L3_protocol)0) { + switch (exception.prot) { + case L3_protocol::TCP: _tcp_stats.refused_for_ram++; break; + case L3_protocol::UDP: _udp_stats.refused_for_ram++; break; + case L3_protocol::ICMP: _icmp_stats.refused_for_ram++; break; + default: throw Bad_transport_protocol(); } + } /* give up if the resources still not suffice */ throw Drop_packet("insufficient resources"); @@ -1875,3 +1981,50 @@ Interface::~Interface() _detach_from_domain(); _interfaces.remove(this); } + + +void Interface::report(Genode::Xml_generator &xml) +{ + bool const stats = _config().report().stats(); + if (stats) { + xml.node("interface", [&] () { + bool empty = true; + xml.attribute("label", _policy.label()); + try { _policy.report(xml); empty = false; } catch (Report::Empty) { } + + try { xml.node("tcp-links", [&] () { _tcp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("udp-links", [&] () { _udp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("icmp-links", [&] () { _icmp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("arp-waiters", [&] () { _arp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + try { xml.node("dhcp-allocations", [&] () { _dhcp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } + if (empty) { throw Report::Empty(); } + }); + } +} + + +/************************** + ** Interface_link_stats ** + **************************/ + +Interface_link_stats::~Interface_link_stats() +{ + if (opening || + open || + closing || + closed) + { + error("closing interface has dangling links"); + } +} + + +/**************************** + ** Interface_object_stats ** + ****************************/ + +Interface_object_stats::~Interface_object_stats() +{ + if (alive) { + error("closing interface has dangling links"); } +} diff --git a/repos/os/src/server/nic_router/interface.h b/repos/os/src/server/nic_router/interface.h index 742717468d..1a1f8f233e 100644 --- a/repos/os/src/server/nic_router/interface.h +++ b/repos/os/src/server/nic_router/interface.h @@ -21,12 +21,15 @@ #include #include #include +#include /* Genode includes */ #include #include #include +namespace Genode { class Xml_generator; } + namespace Net { using Packet_descriptor = ::Nic::Packet_descriptor; @@ -41,18 +44,56 @@ namespace Net { class Interface_policy; class Interface; using Interface_list = List; + class Interface_link_stats; + class Interface_object_stats; class Dhcp_server; class Configuration; class Domain; } +struct Net::Interface_object_stats +{ + Genode::size_t alive { 0 }; + Genode::size_t destroyed { 0 }; + + void report(Genode::Xml_generator &xml); + + ~Interface_object_stats(); +}; + + +struct Net::Interface_link_stats +{ + Genode::size_t refused_for_ram { 0 }; + Genode::size_t refused_for_ports { 0 }; + Genode::size_t opening { 0 }; + Genode::size_t open { 0 }; + Genode::size_t closing { 0 }; + Genode::size_t closed { 0 }; + Genode::size_t dissolved_timeout_opening { 0 }; + Genode::size_t dissolved_timeout_open { 0 }; + Genode::size_t dissolved_timeout_closing { 0 }; + Genode::size_t dissolved_timeout_closed { 0 }; + Genode::size_t dissolved_no_timeout { 0 }; + Genode::size_t destroyed { 0 }; + + void report(Genode::Xml_generator &xml); + + ~Interface_link_stats(); +}; + + struct Net::Interface_policy { virtual Domain_name determine_domain_name() const = 0; virtual void handle_config(Configuration const &config) = 0; + virtual Genode::Session_label const &label() const = 0; + + virtual void report(Genode::Xml_generator &) const { throw Report::Empty(); } + virtual ~Interface_policy() { } }; @@ -67,7 +108,8 @@ class Net::Interface : private Interface_list::Element using Signal_handler = Genode::Signal_handler; using Signal_context_capability = Genode::Signal_context_capability; - enum { IPV4_TIME_TO_LIVE = 64 }; + enum { IPV4_TIME_TO_LIVE = 64 }; + enum { MAX_FREE_OPS_PER_EMERGENCY = 1024 }; struct Dismiss_link : Genode::Exception { }; struct Dismiss_arp_waiter : Genode::Exception { }; @@ -112,6 +154,11 @@ class Net::Interface : private Interface_list::Element Dhcp_client _dhcp_client { _alloc, _timer, *this }; Interface_list &_interfaces; Genode::Constructible _update_domain { }; + Interface_link_stats _udp_stats { }; + Interface_link_stats _tcp_stats { }; + Interface_link_stats _icmp_stats { }; + Interface_object_stats _arp_stats { }; + Interface_object_stats _dhcp_stats { }; void _new_link(L3_protocol const protocol, Link_side_id const &local_id, @@ -314,7 +361,7 @@ class Net::Interface : private Interface_list::Element public: - struct Free_resources_and_retry_handle_eth : Genode::Exception { }; + struct Free_resources_and_retry_handle_eth : Genode::Exception { L3_protocol prot; Free_resources_and_retry_handle_eth(L3_protocol prot = (L3_protocol)0) : prot(prot) { } }; struct Bad_send_dhcp_args : Genode::Exception { }; struct Bad_transport_protocol : Genode::Exception { }; struct Bad_network_protocol : Genode::Exception { }; @@ -397,20 +444,27 @@ class Net::Interface : private Interface_list::Element void handle_link_state(); + void report(Genode::Xml_generator &xml); + /*************** ** Accessors ** ***************/ - Configuration const &config() const { return _config(); } - Domain &domain() { return _domain(); } - Mac_address const &router_mac() const { return _router_mac; } - Mac_address const &mac() const { return _mac; } - Arp_waiter_list &own_arp_waiters() { return _own_arp_waiters; } - Signal_handler &sink_ack() { return _sink_ack; } - Signal_handler &sink_submit() { return _sink_submit; } - Signal_handler &source_ack() { return _source_ack; } - Signal_handler &source_submit() { return _source_submit; } + Configuration const &config() const { return _config(); } + Domain &domain() { return _domain(); } + Mac_address const &router_mac() const { return _router_mac; } + Mac_address const &mac() const { return _mac; } + Arp_waiter_list &own_arp_waiters() { return _own_arp_waiters; } + Signal_handler &sink_ack() { return _sink_ack; } + Signal_handler &sink_submit() { return _sink_submit; } + Signal_handler &source_ack() { return _source_ack; } + Signal_handler &source_submit() { return _source_submit; } + Interface_link_stats &udp_stats() { return _udp_stats; } + Interface_link_stats &tcp_stats() { return _tcp_stats; } + Interface_link_stats &icmp_stats() { return _icmp_stats; } + Interface_object_stats &arp_stats() { return _arp_stats; } + Interface_object_stats &dhcp_stats() { return _dhcp_stats; } void session_link_state_sigh(Genode::Signal_context_capability sigh); }; diff --git a/repos/os/src/server/nic_router/link.cc b/repos/os/src/server/nic_router/link.cc index 707d039f3b..33636d5546 100644 --- a/repos/os/src/server/nic_router/link.cc +++ b/repos/os/src/server/nic_router/link.cc @@ -121,7 +121,8 @@ Link::Link(Interface &cln_interface, Timer::Connection &timer, Configuration &config, L3_protocol const protocol, - Microseconds const dissolve_timeout) + Microseconds const dissolve_timeout, + Interface_link_stats &stats) : _config(config), _client_interface(cln_interface), @@ -130,8 +131,11 @@ Link::Link(Interface &cln_interface, _dissolve_timeout_us(dissolve_timeout), _protocol(protocol), _client(cln_interface.domain(), cln_id, *this), - _server(srv_domain, srv_id, *this) + _server(srv_domain, srv_id, *this), + _stats(stats), + _stats_curr(stats.opening) { + _stats_curr()++; _client_interface.links(_protocol).insert(this); _client.domain().links(_protocol).insert(&_client); _server.domain().links(_protocol).insert(&_server); @@ -139,16 +143,31 @@ Link::Link(Interface &cln_interface, } +Link::~Link() { _stats.destroyed++; } + + void Link::_handle_dissolve_timeout(Duration) { - dissolve(); + dissolve(true); _client_interface.links(_protocol).remove(this); _client_interface.dissolved_links(_protocol).insert(this); } -void Link::dissolve() +void Link::dissolve(bool timeout) { + + _stats_curr()--; + if (timeout) { + if (&_stats_curr() == &_stats.opening) { _stats_curr = _stats.dissolved_timeout_opening; } + if (&_stats_curr() == &_stats.open) { _stats_curr = _stats.dissolved_timeout_open; } + if (&_stats_curr() == &_stats.closing) { _stats_curr = _stats.dissolved_timeout_closing; } + if (&_stats_curr() == &_stats.closed) { _stats_curr = _stats.dissolved_timeout_closed; } + } else { + _stats_curr = _stats.dissolved_no_timeout; + } + _stats_curr()++; + _client.domain().links(_protocol).remove(&_client); _server.domain().links(_protocol).remove(&_server); if (_config().verbose()) { @@ -211,13 +230,32 @@ Tcp_link::Tcp_link(Interface &cln_interface, Link_side_id const &srv_id, Timer::Connection &timer, Configuration &config, - L3_protocol const protocol) + L3_protocol const protocol, + Interface_link_stats &stats) : Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer, - config, protocol, config.tcp_idle_timeout()) + config, protocol, config.tcp_idle_timeout(), stats) { } +void Tcp_link::_closing() +{ + _state = State::CLOSING; + _stats_curr()--; + _stats_curr = _stats.closing; + _stats_curr()++; +} + + +void Tcp_link::_closed() +{ + _state = State::CLOSED; + _stats_curr()--; + _stats_curr = _stats.closed; + _stats_curr()++; +} + + void Tcp_link::_tcp_packet(Tcp_packet &tcp, Peer &sender, Peer &receiver) @@ -226,18 +264,19 @@ void Tcp_link::_tcp_packet(Tcp_packet &tcp, return; } if (tcp.rst()) { - _state = State::CLOSED; + _closed(); } else { if (tcp.fin()) { sender.fin = true; - _state = State::CLOSING; + _closing(); } if (receiver.fin && tcp.ack()) { receiver.fin_acked = true; if (sender.fin_acked) { - _state = State::CLOSED; } + _closed(); } else { - _state = State::CLOSING; } + _closing(); + } } } if (_state == State::OPEN) { @@ -249,6 +288,18 @@ void Tcp_link::_tcp_packet(Tcp_packet &tcp, } +void Tcp_link::server_packet(Tcp_packet &tcp) +{ + if (_opening) { + _opening = false; + _stats_curr()--; + if (&_stats_curr() == &_stats.opening) { _stats_curr = _stats.open; } + _stats_curr()++; + } + _tcp_packet(tcp, _server, _client); +} + + /************** ** Udp_link ** **************/ @@ -260,13 +311,26 @@ Udp_link::Udp_link(Interface &cln_interface, Link_side_id const &srv_id, Timer::Connection &timer, Configuration &config, - L3_protocol const protocol) + L3_protocol const protocol, + Interface_link_stats &stats) : Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer, - config, protocol, config.udp_idle_timeout()) + config, protocol, config.udp_idle_timeout(), stats) { } +void Udp_link::server_packet() +{ + if (_opening) { + _opening = false; + _stats_curr()--; + if (&_stats_curr() == &_stats.opening) { _stats_curr = _stats.open; } + _stats_curr()++; + } + _packet(); +} + + /*************** ** Icmp_link ** ***************/ @@ -278,8 +342,21 @@ Icmp_link::Icmp_link(Interface &cln_interface, Link_side_id const &srv_id, Timer::Connection &timer, Configuration &config, - L3_protocol const protocol) + L3_protocol const protocol, + Interface_link_stats &stats) : Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer, - config, protocol, config.icmp_idle_timeout()) + config, protocol, config.icmp_idle_timeout(), stats) { } + + +void Icmp_link::server_packet() +{ + if (_opening) { + _opening = false; + _stats_curr()--; + if (&_stats_curr() == &_stats.opening) { _stats_curr = _stats.open; } + _stats_curr()++; + } + _packet(); +} diff --git a/repos/os/src/server/nic_router/link.h b/repos/os/src/server/nic_router/link.h index e531200068..f46d3509cb 100644 --- a/repos/os/src/server/nic_router/link.h +++ b/repos/os/src/server/nic_router/link.h @@ -45,6 +45,7 @@ namespace Net { + class Interface_link_stats; class Configuration; class Port_allocator_guard; class Tcp_packet; @@ -152,6 +153,9 @@ class Net::Link : public Link_list::Element L3_protocol const _protocol; Link_side _client; Link_side _server; + bool _opening { true }; + Interface_link_stats &_stats; + Reference _stats_curr; void _handle_dissolve_timeout(Genode::Duration); @@ -169,9 +173,12 @@ class Net::Link : public Link_list::Element Timer::Connection &timer, Configuration &config, L3_protocol const protocol, - Genode::Microseconds const dissolve_timeout); + Genode::Microseconds const dissolve_timeout, + Interface_link_stats &stats); - void dissolve(); + ~Link(); + + void dissolve(bool timeout); void handle_config(Domain &cln_domain, Domain &srv_domain, @@ -216,6 +223,10 @@ class Net::Tcp_link : public Link Peer &sender, Peer &receiver); + void _closing(); + + void _closed(); + public: Tcp_link(Interface &cln_interface, @@ -225,11 +236,12 @@ class Net::Tcp_link : public Link Link_side_id const &srv_id, Timer::Connection &timer, Configuration &config, - L3_protocol const protocol); + L3_protocol const protocol, + Interface_link_stats &stats); void client_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _client, _server); } - void server_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _server, _client); } + void server_packet(Tcp_packet &tcp); }; @@ -242,9 +254,12 @@ struct Net::Udp_link : Link Link_side_id const &srv_id, Timer::Connection &timer, Configuration &config, - L3_protocol const protocol); + L3_protocol const protocol, + Interface_link_stats &stats); - void packet() { _packet(); } + void client_packet() { _packet(); } + + void server_packet(); }; @@ -257,9 +272,12 @@ struct Net::Icmp_link : Link Link_side_id const &srv_id, Timer::Connection &timer, Configuration &config, - L3_protocol const protocol); + L3_protocol const protocol, + Interface_link_stats &stats); - void packet() { _packet(); } + void client_packet() { _packet(); } + + void server_packet(); }; #endif /* _LINK_H_ */ diff --git a/repos/os/src/server/nic_router/main.cc b/repos/os/src/server/nic_router/main.cc index 72dff4587f..7d902d88e4 100644 --- a/repos/os/src/server/nic_router/main.cc +++ b/repos/os/src/server/nic_router/main.cc @@ -34,13 +34,14 @@ class Net::Main private: Genode::Env &_env; + Quota _shared_quota { }; Interface_list _interfaces { }; Timer::Connection _timer { _env }; Genode::Heap _heap { &_env.ram(), &_env.rm() }; Genode::Attached_rom_dataspace _config_rom { _env, "config" }; Reference _config { *new (_heap) Configuration { _config_rom.xml(), _heap } }; Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; - Root _root { _env.ep(), _timer, _heap, _config(), _env.ram(), _interfaces, _env.rm()}; + Root _root { _env, _timer, _heap, _config(), _shared_quota, _interfaces }; void _handle_config(); @@ -77,7 +78,7 @@ void Net::Main::_handle_config() Configuration &old_config = _config(); Configuration &new_config = *new (_heap) Configuration(_env, _config_rom.xml(), _heap, _timer, old_config, - _interfaces); + _shared_quota, _interfaces); _root.handle_config(new_config); _for_each_interface([&] (Interface &intf) { intf.handle_config_1(new_config); }); diff --git a/repos/os/src/server/nic_router/report.cc b/repos/os/src/server/nic_router/report.cc index ad25d29f75..236d5ade61 100644 --- a/repos/os/src/server/nic_router/report.cc +++ b/repos/os/src/server/nic_router/report.cc @@ -20,20 +20,26 @@ using namespace Net; using namespace Genode; -Net::Report::Report(bool const &verbose, - Xml_node const node, +Net::Report::Report(bool const &verbose, + Xml_node const node, Timer::Connection &timer, Domain_tree &domains, + Quota const &shared_quota, + Pd_session &pd, Reporter &reporter) : - _verbose(verbose), - _config(node.attribute_value("config", true)), - _config_triggers(node.attribute_value("config_triggers", false)), - _bytes(node.attribute_value("bytes", true)), - _reporter(reporter), - _domains(domains), - _timeout(timer, *this, &Report::_handle_report_timeout, - read_sec_attr(node, "interval_sec", 5)) + _verbose { verbose }, + _config { node.attribute_value("config", true) }, + _config_triggers { node.attribute_value("config_triggers", false) }, + _bytes { node.attribute_value("bytes", true) }, + _stats { node.attribute_value("stats", true) }, + _quota { node.attribute_value("quota", true) }, + _shared_quota { shared_quota }, + _pd { pd }, + _reporter { reporter }, + _domains { domains }, + _timeout { timer, *this, &Report::_handle_report_timeout, + read_sec_attr(node, "interval_sec", 5) } { _reporter.enabled(true); } @@ -43,8 +49,21 @@ void Net::Report::_report() { try { Reporter::Xml_generator xml(_reporter, [&] () { + if (_quota) { + xml.node("ram", [&] () { + xml.attribute("quota", _pd.ram_quota().value); + xml.attribute("used", _pd.used_ram().value); + xml.attribute("shared", _shared_quota.ram); + }); + xml.node("cap", [&] () { + xml.attribute("quota", _pd.cap_quota().value); + xml.attribute("used", _pd.used_caps().value); + xml.attribute("shared", _shared_quota.cap); + }); + } _domains.for_each([&] (Domain &domain) { - domain.report(xml); + try { domain.report(xml); } + catch (Empty) { } }); }); } catch (Xml_generator::Buffer_exceeded) { diff --git a/repos/os/src/server/nic_router/report.h b/repos/os/src/server/nic_router/report.h index e025d7a281..1a7bc6a123 100644 --- a/repos/os/src/server/nic_router/report.h +++ b/repos/os/src/server/nic_router/report.h @@ -28,17 +28,29 @@ namespace Net { class Domain_tree; class Report; + class Quota; } +struct Net::Quota +{ + Genode::size_t ram { 0 }; + Genode::size_t cap { 0 }; +}; + + class Net::Report { private: - bool const &_verbose; - bool const _config; - bool const _config_triggers; - bool const _bytes; + bool const &_verbose; + bool const _config; + bool const _config_triggers; + bool const _bytes; + bool const _stats; + bool const _quota; + Quota const &_shared_quota; + Genode::Pd_session &_pd; Genode::Reporter &_reporter; Domain_tree &_domains; Timer::Periodic_timeout _timeout; @@ -49,10 +61,14 @@ class Net::Report public: + struct Empty : Genode::Exception { }; + Report(bool const &verbose, Genode::Xml_node const node, Timer::Connection &timer, Domain_tree &domains, + Quota const &shared_quota, + Genode::Pd_session &pd, Genode::Reporter &reporter); void handle_config(); @@ -64,6 +80,7 @@ class Net::Report bool config() const { return _config; } bool bytes() const { return _bytes; } + bool stats() const { return _stats; } }; #endif /* _REPORT_H_ */ diff --git a/repos/os/src/server/nic_router/uplink.cc b/repos/os/src/server/nic_router/uplink.cc index c00a234a0a..4d2ede07c6 100644 --- a/repos/os/src/server/nic_router/uplink.cc +++ b/repos/os/src/server/nic_router/uplink.cc @@ -107,6 +107,18 @@ void Net::Uplink::print(Output &output) const } +/*************************** + ** Uplink_interface_base ** + ***************************/ + +Net::Uplink_interface_base::Uplink_interface_base(Domain_name const &domain_name, + Session_label const &label) +: + _domain_name { domain_name }, + _label { label } +{ } + + /********************** ** Uplink_interface ** **********************/ @@ -119,7 +131,7 @@ Net::Uplink_interface::Uplink_interface(Env &env, Domain_name const &domain_name, Session_label const &label) : - Uplink_interface_base { domain_name }, + Uplink_interface_base { domain_name, label }, Nic::Packet_allocator { &alloc }, Nic::Connection { env, this, BUF_SIZE, BUF_SIZE, label.string() }, _link_state_handler { env.ep(), *this, diff --git a/repos/os/src/server/nic_router/uplink.h b/repos/os/src/server/nic_router/uplink.h index 2347a1fffc..0faeaf1897 100644 --- a/repos/os/src/server/nic_router/uplink.h +++ b/repos/os/src/server/nic_router/uplink.h @@ -104,7 +104,8 @@ class Net::Uplink_interface_base : public Interface_policy { private: - Const_reference _domain_name; + Const_reference _domain_name; + Genode::Session_label const &_label; /*************************** @@ -113,10 +114,12 @@ class Net::Uplink_interface_base : public Interface_policy Domain_name determine_domain_name() const override { return _domain_name(); }; void handle_config(Configuration const &) override { } + Genode::Session_label const &label() const override { return _label; } public: - Uplink_interface_base(Domain_name const &domain_name) : _domain_name(domain_name) { } + Uplink_interface_base(Domain_name const &domain_name, + Genode::Session_label const &label); virtual ~Uplink_interface_base() { }