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 <report stats="yes"
  quota="yes"/> is configured. (default is yes if <report> is present)

Issue #2953
This commit is contained in:
Martin Stein 2018-09-16 14:21:38 +02:00 committed by Christian Helmuth
parent bd77bb41df
commit 304cb290d9
21 changed files with 1021 additions and 285 deletions

View File

@ -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 {
<policy label_prefix="udp_client_1" domain="udp_client_1" />
<policy label_prefix="lan_1" domain="lan_1" />
<policy label_prefix="t1_d1" domain="t1_d1" />
<policy label_prefix="t1_d2" domain="t1_d2" />
<domain name="udp_client_1" interface="10.0.98.33/24">
<udp-forward port="1337" domain="lan_1" to="10.0.99.55" />
<domain name="t1_d1" interface="10.0.98.33/24">
<udp-forward port="1337" domain="t1_d2" to="10.0.99.55" />
</domain>
<domain name="lan_1" interface="10.0.99.33/24" />} }
<domain name="t1_d2" interface="10.0.99.33/24" />} }
}
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 {
<policy label_prefix="udp_server_2" domain="udp_server_2" />
<domain name="udp_server_2" interface="18.17.16.14/24" />} }
<policy label_prefix="t2_d1" domain="t2_d1" />
<domain name="t2_d1" interface="18.17.16.14/24" />} }
}
proc test_2_router_uplink_config { } {
if {[enable_test_2]} { return {
<udp-forward port="1" domain="udp_server_2" to="18.17.16.15" />} }
<udp-forward port="1" domain="t2_d1" to="18.17.16.15" />} }
}
@ -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 {
<policy label_prefix="udp_client_3" domain="udp_client_3" />
<policy label_prefix="t3_d1" domain="t3_d1" />
<domain name="udp_client_3" interface="217.13.192.1/24">
<domain name="t3_d1" interface="217.13.192.1/24">
<ip dst="10.0.2.0/24" domain="uplink" />
</domain>} }
}
proc test_3_router_uplink_config { } {
if {[enable_test_3]} { return {
<ip dst="217.13.192.0/24" domain="udp_client_3" />} }
<ip dst="217.13.192.0/24" domain="t3_d1" />} }
}
@ -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 {
<policy label_prefix="http_server_1" domain="http_server_1" />
<domain name="http_server_1" interface="192.168.1.1/24" />} }
<policy label_prefix="t4_d1" domain="t4_d1" />
<domain name="t4_d1" interface="192.168.1.1/24" />} }
}
proc test_4_router_uplink_config { } {
if {[enable_test_4]} { return {
<tcp-forward port="80" domain="http_server_1" to="192.168.1.18" />} }
<tcp-forward port="80" domain="t4_d1" to="192.168.1.18" />} }
}
#
@ -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 {
<policy label_prefix="http_server_2" domain="http_server_2" />
<domain name="http_server_2" interface="192.168.2.1/24" />} }
<policy label_prefix="t5_d1" domain="t5_d1" />
<domain name="t5_d1" interface="192.168.2.1/24" />} }
}
proc test_5_router_uplink_config { } {
if {[enable_test_5]} { return {
<tcp-forward port="8080" domain="http_server_2" to="192.168.2.72" />} }
<tcp-forward port="8080" domain="t5_d1" to="192.168.2.72" />} }
}
@ -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 {
<policy label_prefix="http_client_3" domain="http_client_3" />
<policy label_prefix="t6_d1" domain="t6_d1" />
<domain name="http_client_3" interface="100.200.0.1/24">
<domain name="t6_d1" interface="100.200.0.1/24">
<tcp dst="10.0.0.0/16">
<permit port="2345" domain="uplink" />
</tcp>
@ -158,7 +158,7 @@ proc test_6_router_config { } {
proc test_6_router_uplink_config { } {
if {[enable_test_6]} { return {
<nat domain="http_client_3" tcp-ports="6" />} }
<nat domain="t6_d1" tcp-ports="6" />} }
}
@ -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 {
<start name="lan_2_nic_router" caps="200" priority="-1">
<start name="t7_d1_nic_router" caps="200" priority="-1">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config>
<policy label_prefix="lan_2" domain="downlink" />
<policy label_prefix="t7_d1" domain="downlink" />
<uplink domain="uplink" />
<domain name="uplink">
@ -214,23 +214,23 @@ proc test_7_config { } {
proc test_7_router_config { } {
if {[enable_test_7]} { return {
<policy label_prefix="lan_2" domain="lan_2" />
<policy label_prefix="lan_3" domain="lan_3" />
<policy label_prefix="t7_d1" domain="t7_d1" />
<policy label_prefix="t7_d2" domain="t7_d2" />
<domain name="lan_2" interface="100.200.0.1/24">
<domain name="t7_d1" interface="100.200.0.1/24">
<dhcp-server ip_first="100.200.0.32"
ip_last="100.200.0.64"
ip_lease_time_sec="3600"
dns_server="8.8.8.8"/>
<tcp dst="10.0.0.0/16">
<permit port="2345" domain="lan_3" />
<permit port="3456" domain="lan_3" />
<permit port="2345" domain="t7_d2" />
<permit port="3456" domain="t7_d2" />
</tcp>
</domain>
<domain name="lan_3" interface="10.0.2.1/24">
<nat domain="lan_2" tcp-ports="18" />
<domain name="t7_d2" interface="10.0.2.1/24">
<nat domain="t7_d1" tcp-ports="18" />
</domain>} }
}
@ -286,7 +286,11 @@ append config {
tcp_idle_timeout_sec="30"
tcp_max_segm_lifetime_sec="15">
<report bytes="yes" config="yes" interval_sec="60" />
<report bytes="yes"
config="yes"
quota="no"
stats="no"
interval_sec="60" />
<uplink domain="uplink"/>
@ -325,12 +329,12 @@ append config {
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config>
<policy label_prefix="nic_router" ip_addr="10.0.2.55" />
<policy label_prefix="http_client_1" ip_addr="10.0.2.201" />
<policy label_prefix="http_client_2" ip_addr="10.0.2.202" />
<policy label_prefix="http_server_3" ip_addr="10.0.2.203" />
<policy label_prefix="udp_client_2" ip_addr="10.0.2.212" />
<policy label_prefix="udp_server_3" ip_addr="10.0.2.213" />
<policy label_prefix="nic_router" ip_addr="10.0.2.55" />
<policy label_prefix="t2_d0_c1_udp" ip_addr="10.0.2.212" />
<policy label_prefix="t3_d0_s1_udp" ip_addr="10.0.2.213" />
<policy label_prefix="t4_d0_c1_tcp" ip_addr="10.0.2.201" />
<policy label_prefix="t5_d0_c1_tcp" ip_addr="10.0.2.202" />
<policy label_prefix="t6_d0_s1_tcp" ip_addr="10.0.2.203" />
</config>
<route>
<service name="Nic"> <child name="nic_loopback"/> </service>

View File

@ -447,15 +447,22 @@ The NIC router can be configured to send reports about its state.
Configuration example (shows default values of attributes):
<config>
<report interval_sec="5" bytes="yes" config="yes" config_triggers="no">
</config>
! <config>
! <report bytes="yes"
! stats="yes"
! quota="yes"
! config="yes"
! config_triggers="no"
! interval_sec="5">
! </config>
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

View File

@ -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);
}

View File

@ -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 &region_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 &region_map)
Quota &shared_quota,
Interface_list &interfaces)
:
Root_component<Session_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<Session_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 { 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<Session_env>(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<Session_component>(
(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)"); };
}

View File

@ -15,6 +15,7 @@
#define _COMPONENT_H_
/* Genode includes */
#include <base/heap.h>
#include <base/allocator_guard.h>
#include <root/component.h>
#include <nic/packet_allocator.h>
@ -24,6 +25,9 @@
#include <mac_allocator.h>
#include <interface.h>
#include <reference.h>
#include <report.h>
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 <typename FUNC>
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 <typename FUNC>
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<Configuration> _config;
Genode::Session_label const _label;
Const_reference<Configuration> _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 &region_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<Session_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<Configuration> _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>
********************/
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 &region_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<Configuration>(config); }
};

View File

@ -59,6 +59,8 @@
<xs:attribute name="config" type="Boolean" />
<xs:attribute name="config_triggers" type="Boolean" />
<xs:attribute name="bytes" type="Boolean" />
<xs:attribute name="stats" type="Boolean" />
<xs:attribute name="quota" type="Boolean" />
<xs:attribute name="interval_sec" type="Seconds" />
</xs:complexType>
</xs:element><!-- report -->

View File

@ -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<Reporter>::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) { }

View File

@ -79,6 +79,7 @@ class Net::Configuration
Genode::Allocator &alloc,
Timer::Connection &timer,
Configuration &old_config,
Quota const &shared_quota,
Interface_list &interfaces);
~Configuration();

View File

@ -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);

View File

@ -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<Dhcp_allocation>;
@ -125,6 +124,8 @@ class Net::Dhcp_allocation : public Genode::Avl_node<Dhcp_allocation>,
Timer::Connection &timer,
Genode::Microseconds lifetime);
~Dhcp_allocation();
Dhcp_allocation &find_by_mac(Mac_address const &mac);
void lifetime(Genode::Microseconds lifetime);

View File

@ -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(); }
}

View File

@ -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<Domain, Domain_name> { };
@ -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_ */

View File

@ -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_TYPE *>(&link));
}
@ -74,6 +75,29 @@ static void _destroy_links(Link_list &links,
}
template <typename LINK_TYPE>
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_TYPE *>(link));
if (!--max) {
return; }
}
while (Link *link = links.first()) {
_destroy_link<LINK_TYPE>(*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<Udp_link *>(&link)->packet();
if (client) {
static_cast<Udp_link *>(&link)->client_packet();
return;
} else {
static_cast<Udp_link *>(&link)->server_packet();
return;
}
return;
case L3_protocol::ICMP:
static_cast<Icmp_link *>(&link)->packet();
if (client) {
static_cast<Icmp_link *>(&link)->client_packet();
return;
} else {
static_cast<Icmp_link *>(&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<Domain>();
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<Ram_quota>::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<Ram_quota>::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<Ram_quota>::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 &eth,
hop_ip);
});
try { new (_alloc) Arp_waiter { *this, remote_domain, hop_ip, pkt }; }
catch (Quota_guard<Ram_quota>::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 &eth,
Domain &local_domain,
Domain &remote_domain)
{
Pointer<Port_allocator_guard> 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<Port_allocator_guard> 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 &eth,
dhcp.xid(),
local_domain.ip_config().interface);
}
catch (Quota_guard<Ram_quota>::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_link> (_tcp_links, _dissolved_tcp_links, _alloc);
_destroy_links<Udp_link> (_udp_links, _dissolved_udp_links, _alloc);
_destroy_links<Icmp_link>(_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_link> (_tcp_links, _dissolved_tcp_links, _alloc, max);
_destroy_some_links<Udp_link> (_udp_links, _dissolved_udp_links, _alloc, max);
_destroy_some_links<Icmp_link>(_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"); }
}

View File

@ -21,12 +21,15 @@
#include <dhcp_client.h>
#include <dhcp_server.h>
#include <list.h>
#include <report.h>
/* Genode includes */
#include <nic_session/nic_session.h>
#include <net/dhcp.h>
#include <net/icmp.h>
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<Interface>;
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<Interface>;
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> _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);
};

View File

@ -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();
}

View File

@ -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<Genode::size_t> _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_ */

View File

@ -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<Configuration> _config { *new (_heap) Configuration { _config_rom.xml(), _heap } };
Signal_handler<Main> _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); });

View File

@ -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) {

View File

@ -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<Report> _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_ */

View File

@ -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,

View File

@ -104,7 +104,8 @@ class Net::Uplink_interface_base : public Interface_policy
{
private:
Const_reference<Domain_name> _domain_name;
Const_reference<Domain_name> _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() { }