diff --git a/repos/os/run/nic_bridge_stress.run b/repos/os/run/nic_bridge_stress.run new file mode 100644 index 0000000000..b7e6714526 --- /dev/null +++ b/repos/os/run/nic_bridge_stress.run @@ -0,0 +1,2 @@ +set type "nic_bridge" +source ${genode_dir}/repos/os/run/nic_stress.inc diff --git a/repos/os/run/nic_router_stress.run b/repos/os/run/nic_router_stress.run new file mode 100644 index 0000000000..0a5cbc371b --- /dev/null +++ b/repos/os/run/nic_router_stress.run @@ -0,0 +1,2 @@ +set type "nic_router" +source ${genode_dir}/repos/os/run/nic_stress.inc diff --git a/repos/os/run/nic_stress.inc b/repos/os/run/nic_stress.inc new file mode 100644 index 0000000000..fe47cbd38d --- /dev/null +++ b/repos/os/run/nic_stress.inc @@ -0,0 +1,167 @@ +append build_components { + core init timer + server/nic_router + test/nic_stress +} + +append_if [string equal $type "nic_bridge"] build_components { server/nic_bridge } + +proc exit_support {} { + if {[have_spec fiasco]} { + return "no" + } + return "yes" +} + +proc done_string {} { + set done_string "" + if {[have_spec fiasco]} { + append done_string {.*?finished NIC stress test} + append done_string {.*?\n} + append done_string {.*?finished NIC stress test} + append done_string {.*?\n} + } else { + append done_string {.*?"nic_stress_." exited with exit value 0} + append done_string {.*?\n} + append done_string {.*?"nic_stress_." exited with exit value 0} + append done_string {.*?\n} + } + return $done_string +} + +proc nr_of_rounds { test_id } { + if {[have_spec sel4]} { + switch $test_id { + 1 { return 19 } + 2 { return 12 } + } + } else { + switch $test_id { + 1 { return 22 } + 2 { return 16 } + } + } + return 0 +} + +proc nr_of_sessions { test_id } { + switch $test_id { + 1 { return 11 } + 2 { return 17 } + } + return 0 +} + +build $build_components + +create_boot_directory + +append config { + + + + + + + + + + + + + + + + + + + + + } + +append_if [string equal $type "nic_router"] config { + + + + + + + + + + + + } + +append_if [string equal $type "nic_bridge"] config { + + + + + + + + + + + + + + + + + + + + + + + + } + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +append boot_modules { + core init timer + nic_router + test-nic_stress + ld.lib.so +} + +append_if [string equal $type "nic_bridge"] boot_modules { nic_bridge } + +build_boot_image $boot_modules + +append qemu_args " -nographic " + +run_genode_until [done_string] 300 diff --git a/repos/os/src/server/nic_bridge/address_node.h b/repos/os/src/server/nic_bridge/address_node.h index bfb0637136..c084c964cb 100644 --- a/repos/os/src/server/nic_bridge/address_node.h +++ b/repos/os/src/server/nic_bridge/address_node.h @@ -68,7 +68,7 @@ class Net::Address_node : public Genode::Avl_node >, ***************/ void addr(Address addr) { _addr = addr; } - Address addr() { return _addr; } + Address addr() const { return _addr; } Session_component &component() { return _component; } diff --git a/repos/os/src/server/nic_bridge/component.h b/repos/os/src/server/nic_bridge/component.h index 957a211982..42170f829b 100644 --- a/repos/os/src/server/nic_bridge/component.h +++ b/repos/os/src/server/nic_bridge/component.h @@ -191,6 +191,8 @@ class Net::Session_component : private Net::Stream_allocator, Size_guard &size_guard) override; void finalize_packet(Ethernet_frame *, Genode::size_t) override; + + Mac_address vmac() const { return _mac_node.addr(); } }; @@ -240,6 +242,13 @@ class Net::Root : public Genode::Root_component policy.attribute_value("ip_addr", Session_component::Ip_addr())); } + + void _destroy_session(Session_component *session) override + { + _mac_alloc.free(session->vmac()); + Genode::destroy(md_alloc(), session); + } + public: Root(Genode::Env &env, diff --git a/repos/os/src/server/nic_router/component.cc b/repos/os/src/server/nic_router/component.cc index ee1b875098..c1ac984d5b 100644 --- a/repos/os/src/server/nic_router/component.cc +++ b/repos/os/src/server/nic_router/component.cc @@ -223,6 +223,8 @@ Session_component *Net::Root::_create_session(char const *args) void Net::Root::_destroy_session(Session_component *session) { + Mac_address const mac = session->mac_address(); + /* 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() }; @@ -235,6 +237,8 @@ void Net::Root::_destroy_session(Session_component *session) session_env_stack.detach(&session_env); session_env_stack.free(ram_ds); + _mac_alloc.free(mac); + /* check for leaked quota */ if (session_env_stack.ram_guard().used().value) { error("NIC session component \"", session_label, "\" leaks RAM quota of ", diff --git a/repos/os/src/test/nic_stress/config.xsd b/repos/os/src/test/nic_stress/config.xsd new file mode 100644 index 0000000000..4a73bf1286 --- /dev/null +++ b/repos/os/src/test/nic_stress/config.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repos/os/src/test/nic_stress/main.cc b/repos/os/src/test/nic_stress/main.cc new file mode 100644 index 0000000000..c65469368d --- /dev/null +++ b/repos/os/src/test/nic_stress/main.cc @@ -0,0 +1,149 @@ +/* + * \brief Stress test for low level NIC interactions + * \author Martin Stein + * \date 2019-03-15 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +namespace Local { + + using namespace Genode; + struct Construct_destruct_test; + struct Main; +} + + +struct Local::Construct_destruct_test +{ + enum { DEFAULT_NR_OF_ROUNDS = 10 }; + enum { DEFAULT_NR_OF_SESSIONS = 10 }; + enum { PKT_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE }; + enum { BUF_SIZE = 100 * PKT_SIZE }; + + using Nic_slot = Constructible; + + Env &_env; + Allocator &_alloc; + Signal_context_capability &_completed_sigh; + Xml_node const &_config; + Nic::Packet_allocator _pkt_alloc { &_alloc }; + bool const _config_exists { _config.has_sub_node("construct_destruct") }; + + unsigned long const _nr_of_rounds { + _config_exists ? + _config.sub_node("construct_destruct"). + attribute_value("nr_of_rounds", + (unsigned long)DEFAULT_NR_OF_ROUNDS) : + (unsigned long)DEFAULT_NR_OF_ROUNDS }; + + unsigned long const _nr_of_sessions { + _config_exists ? + _config.sub_node("construct_destruct"). + attribute_value("nr_of_sessions", + (unsigned long)DEFAULT_NR_OF_SESSIONS) : + (unsigned long)DEFAULT_NR_OF_SESSIONS }; + + void construct_all(Nic_slot *const nic, + unsigned const round) + { + for (unsigned idx = 0; idx < _nr_of_sessions; idx++) { + try { + nic[idx].construct(_env, &_pkt_alloc, BUF_SIZE, BUF_SIZE); + log("round ", round + 1, "/", _nr_of_rounds, " nic ", idx + 1, + "/", _nr_of_sessions, " mac ", nic[idx]->mac_address()); + } + catch (...) { + for (unsigned destruct_idx = 0; destruct_idx < idx; destruct_idx++) { + nic[destruct_idx].destruct(); + throw; + } + } + } + } + + void destruct_all(Nic_slot *const nic) + { + for (unsigned idx = 0; idx < _nr_of_sessions; idx++) { + nic[idx].destruct(); + } + } + + Construct_destruct_test(Env &env, + Allocator &alloc, + Signal_context_capability completed_sigh, + Xml_node const &config) + : + _env { env }, + _alloc { alloc }, + _completed_sigh { completed_sigh }, + _config { config } + { + if (!_nr_of_rounds && !_nr_of_sessions) { + Signal_transmitter(_completed_sigh).submit(); } + + size_t const ram_size { _nr_of_sessions * sizeof(Nic_slot) }; + Attached_ram_dataspace ram_ds { _env.ram(), _env.rm(), ram_size }; + Nic_slot *const nic { ram_ds.local_addr() }; + + try { + for (unsigned round = 0; round < _nr_of_rounds; round++) { + construct_all(nic, round); + destruct_all(nic); + } + Signal_transmitter(_completed_sigh).submit(); + } + catch (...) { + error("Construct_destruct_test failed"); } + } +}; + + +struct Local::Main +{ + Env &_env; + Heap _heap { &_env.ram(), &_env.rm() }; + Attached_rom_dataspace _config_rom { _env, "config" }; + Xml_node const _config { _config_rom.xml() }; + Constructible _test_1 { }; + + bool const _exit_support { + _config.attribute_value("exit_support", true) }; + + Signal_handler
_test_completed_handler { + _env.ep(), *this, &Main::_handle_test_completed }; + + void _handle_test_completed() + { + if (_test_1.constructed()) { + _test_1.destruct(); + log("--- finished NIC stress test ---"); + if (_exit_support) { + _env.parent().exit(0); } + return; + } + } + + Main(Env &env) : _env(env) + { + log("--- NIC stress test ---"); + _test_1.construct(_env, _heap, _test_completed_handler, _config); + } +}; + + +void Component::construct(Genode::Env &env) { static Local::Main main(env); } diff --git a/repos/os/src/test/nic_stress/target.mk b/repos/os/src/test/nic_stress/target.mk new file mode 100644 index 0000000000..0a26a14e98 --- /dev/null +++ b/repos/os/src/test/nic_stress/target.mk @@ -0,0 +1,4 @@ +TARGET = test-nic_stress +SRC_CC = main.cc +LIBS = base +CONFIG_XSD = config.xsd diff --git a/tool/autopilot.list b/tool/autopilot.list index aa0076903a..8d4dd6b3ce 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -33,9 +33,11 @@ netperf_lxip_router netperf_lxip_usb30 netperf_lxip_wifi nic_bridge +nic_bridge_stress nic_dump nic_router nic_router_flood +nic_router_stress nic_router_uplinks noux noux_tool_chain_auto