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() { }