run/nic_router_uplinks: use test component

So far, this test used dynamic_rom for the re-configuration of the nic router
and tested for the expected ping results by inspecting the log with the run
tool. However, this approach had two issues:

* Timing differs significantly on different targets and so the dynamic_rom had
  the difficult task of compensating with heuristics without bloating the test
  duration too much.

* In case of a failing test, it was difficult to determine the cause as the
  test kept running and produced output for quite some time and there was also
  no specific error message but only a generic timeout.

These two issues are now fixed by introducing a test component that listens to
the ping-result report and manages the nic router configuration. The new
component exits early on failure and provides information on the error
circumstances. Furthermore, the component advances to the next test step only
after having seen the expected result of the active test step and thereby
removes the need for heuristics about target timing.

Fixes #5192
This commit is contained in:
Martin Stein 2024-06-14 11:07:17 +02:00 committed by Norman Feske
parent a935a733ab
commit a450110b97
4 changed files with 246 additions and 272 deletions

View File

@ -7,18 +7,6 @@ proc wifi_ssid {} {
proc wifi_psk {} {
return "$::env(GENODE_WIFI_PSK2)" }
proc router_verbose {} {
return "no" }
proc router_verbose_packet_drop {} {
return "no" }
proc router_verbose_packets {} {
return "no" }
proc router_verbose_domain_state {} {
return "yes" }
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \
[depot_user]/pkg/pc_wifi \
@ -32,7 +20,7 @@ import_from_depot [depot_user]/src/[base_src] \
[depot_user]/src/report_rom \
[depot_user]/src/pc_rtc
build { app/ping }
build { app/ping server/nic_router test/nic_router_uplinks }
install_config {
<config prio_levels="4">
@ -52,14 +40,16 @@ install_config {
<default caps="100"/>
<start name="report_rom" caps="200">
<resource name="RAM" quantum="1M"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="ROM" />
<service name="Report" />
</provides>
<config>
<policy label="pci_decode -> system" report="acpi -> acpi"/>
<policy label="platform -> devices" report="pci_decode -> devices"/>
<policy label="platform -> devices" report="pci_decode -> devices"/>
<policy label="router -> config" report="test -> router_config"/>
<policy label="test -> ping_result" report="ping -> result"/>
</config>
</start>
@ -110,7 +100,7 @@ install_config {
</route>
</start>
<start name="wifi" caps="300" priority="-1">
<start name="wifi" caps="600" priority="-1">
<resource name="RAM" quantum="32M"/>
<config ld_verbose="no">
<vfs>
@ -140,7 +130,7 @@ install_config {
<binary name="dynamic_rom"/>
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/></provides>
<config verbose="no">
<config>
<rom name="wifi_config">
<inline description="CONNECT">
<wifi_config connected_scan_interval="0" scan_interval="5" rfkill="no" verbose="no" verbose_state="no">
@ -152,221 +142,6 @@ install_config {
</config>
</start>
<start name="dynamic_rom" priority="-1">
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/> </provides>
<config verbose="yes">
<rom name="router.config">
<!-- give the drivers time to come up -->
<inline> <config/> </inline>
<sleep milliseconds="15000"/>
<!-- start the actual test -->
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<policy label_prefix="nic" domain="uplink" />
<domain name="uplink">
<nat domain="downlink" icmp-ids="999"/>
</domain>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5001"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<policy label_prefix="wifi" domain="uplink" />
<domain name="uplink">
<nat domain="downlink" icmp-ids="999"/>
</domain>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5002"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="yes"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5003"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<policy label_prefix="nic" domain="uplink" />
<domain name="uplink">
<nat domain="downlink" icmp-ids="999"/>
</domain>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5004"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<policy label_prefix="nic" domain="uplink" />
<domain name="uplink">
<nat domain="downlink" icmp-ids="999"/>
</domain>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5005"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="yes"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5006"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<policy label_prefix="wifi" domain="uplink" />
<domain name="uplink">
<nat domain="downlink" icmp-ids="999"/>
</domain>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5007"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<policy label_prefix="nic" domain="uplink" />
<domain name="uplink">
<nat domain="downlink" icmp-ids="999"/>
</domain>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
<icmp dst="0.0.0.0/0" domain="uplink" />
</domain>
</config>
</inline>
<sleep milliseconds="5008"/>
<inline>
<config dhcp_discover_timeout_sec="1"
verbose="} [router_verbose] {"
verbose_packet_drop="} [router_verbose_packet_drop] {"
verbose_domain_state="} [router_verbose_domain_state] {"
verbose_packets="} [router_verbose_packets] {">
<policy label_prefix="ping" domain="downlink"/>
<domain name="downlink" interface="10.0.1.79/24">
<dhcp-server ip_first="10.0.1.80" ip_last="10.0.1.100"/>
</domain>
</config>
</inline>
<sleep milliseconds="600000"/>
</rom>
</config>
</start>
<start name="router" caps="200" priority="-2">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
@ -375,9 +150,17 @@ install_config {
<service name="Uplink"/>
</provides>
<route>
<service name="ROM" label="config">
<child name="dynamic_rom" label="router.config"/>
</service>
<service name="ROM" label="config"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="test" caps="200" priority="-2">
<binary name="test-nic_router_uplinks"/>
<resource name="RAM" quantum="1M"/>
<route>
<service name="Report"> <child name="report_rom"/> </service>
<service name="ROM" label="ping_result"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
@ -386,8 +169,10 @@ install_config {
<resource name="RAM" quantum="8M"/>
<config dst_ip="1.1.1.1"
period_sec="1"
report="yes"
count="999"/>
<route>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Nic"> <child name="router"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
@ -396,42 +181,10 @@ install_config {
</config>
}
append qemu_args " -nographic "
build_boot_image [build_artifacts]
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5001 milliseconds"
append done_string ".*64 bytes from 1.1.1.1: icmp_seq="
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5002 milliseconds"
append done_string ".*64 bytes from 1.1.1.1: icmp_seq="
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5003 milliseconds"
append done_string ".*downlink.*invalid domain.*invalid ICMP rule"
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5004 milliseconds"
append done_string ".*64 bytes from 1.1.1.1: icmp_seq="
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5005 milliseconds"
append done_string ".*64 bytes from 1.1.1.1: icmp_seq="
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5006 milliseconds"
append done_string ".*downlink.*invalid domain.*invalid ICMP rule"
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5007 milliseconds"
append done_string ".*64 bytes from 1.1.1.1: icmp_seq="
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 5008 milliseconds"
append done_string ".*64 bytes from 1.1.1.1: icmp_seq="
append done_string ".*router.config: change"
append done_string ".*router.config: sleep 600000 milliseconds"
append done_string ".*From 10.0.1.79 icmp_seq=.* Destination Unreachable"
run_genode_until $done_string 90
run_genode_until "child \"test\" exited with exit value.*\n" 300
grep_output {\[init\] child "test" exited with exit value}
compare_output_to {[init] child "test" exited with exit value 0}

View File

@ -0,0 +1,35 @@
/*
* \brief Assertion macros
* \author Martin Stein
* \date 2023-06-09
*/
/*
* Copyright (C) 2023 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.
*/
#ifndef _TRESOR__ASSERTION_H_
#define _TRESOR__ASSERTION_H_
/* base includes */
#include <base/log.h>
#include <base/sleep.h>
#define ASSERT(condition) \
do { \
if (!(condition)) { \
Genode::error(__FILE__, ":", __LINE__, ": ", " assertion \"", #condition, "\" failed "); \
Genode::sleep_forever(); \
} \
} while (false)
#define ASSERT_NEVER_REACHED \
do { \
Genode::error(__FILE__, ":", __LINE__, ": ", " should have never been reached"); \
Genode::sleep_forever(); \
} while (false)
#endif /* _TRESOR__ASSERTION_H_ */

View File

@ -0,0 +1,172 @@
/*
* \brief Server component for Network Address Translation on NIC sessions
* \author Martin Stein
* \date 2016-08-24
*/
/*
* Copyright (C) 2016-2017 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 */
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <timer_session/connection.h>
/* local */
#include <assertion.h>
using namespace Genode;
enum { STEP_TIMEOUT_US = 60*1000*1000 };
using Driver = String<16>;
struct Result
{
enum { INVALID_ID = ~0U };
enum Type { REPLY, DESTINATION_UNREACHABLE, INVALID };
using Type_string = String<32>;
unsigned id;
Type type;
static Type string_to_type(Type_string const &string)
{
if (string == "reply") return REPLY;
if (string == "destination_unreachable") return DESTINATION_UNREACHABLE;
return INVALID;
}
Result(Xml_node const &node)
:
id(node.attribute_value("id", (unsigned)INVALID_ID)),
type(string_to_type(node.attribute_value("type", Type_string())))
{
ASSERT(id != INVALID_ID && type != INVALID);
}
};
struct Goal
{
Result::Type result_type;
unsigned count;
};
struct Main
{
Env &env;
Expanding_reporter router_config_reporter { env, "config", "router_config" };
Attached_rom_dataspace result_rom { env, "ping_result" };
Signal_handler<Main> result_handler { env.ep(), *this, &Main::handle_result };
unsigned last_result_id = Result::INVALID_ID;
Constructible<Goal> goal { };
Timer::Connection timer { env };
Timer::One_shot_timeout<Main> timeout { timer, *this, &Main::handle_timeout };
unsigned step { 0UL };
Constructible<Driver> driver { };
void handle_result()
{
if (!goal.constructed()) {
step_succeeded();
return;
}
result_rom.update();
Result result(result_rom.xml());
if (result.id != last_result_id) {
if (result.type == goal->result_type) {
ASSERT(goal->count);
if (!--goal->count) {
goal.destruct();
step_succeeded();
}
} else
warning("test step ", step, " observed unexpected result");
last_result_id = result.id;
}
}
void handle_timeout(Duration)
{
error("test step ", step, " timed out");
env.parent().exit(-1);
}
void update_router_config()
{
router_config_reporter.generate([&] (Xml_generator &xml) {
xml.attribute("dhcp_discover_timeout_sec", "1");
xml.node("policy", [&] {
xml.attribute("label_prefix", "ping");
xml.attribute("domain", "downlink"); });
xml.node("policy", [&] {
xml.attribute("label_prefix", "dhcp");
xml.attribute("domain", "uplink"); });
if (driver.constructed()) {
xml.node("policy", [&] {
xml.attribute("label_prefix", *driver);
xml.attribute("domain", "uplink"); });
xml.node("domain", [&] {
xml.attribute("name", "uplink");
xml.node("nat", [&] {
xml.attribute("domain", "downlink");
xml.attribute("icmp-ids", "999"); }); });
}
xml.node("domain", [&] {
xml.attribute("name", "downlink");
xml.attribute("interface", "10.0.1.79/24");
xml.node("dhcp-server", [&] {
xml.attribute("ip_first", "10.0.1.80");
xml.attribute("ip_last", "10.0.1.100"); });
if (driver.constructed())
xml.node("icmp", [&] {
xml.attribute("dst", "0.0.0.0/0");
xml.attribute("domain", "uplink"); }); }); });
}
void start_step(unsigned step_arg, Driver driver_arg = Driver())
{
if (driver_arg == Driver()) {
driver.destruct();
goal.construct(Result::DESTINATION_UNREACHABLE, 3);
} else {
driver.construct(driver_arg);
goal.construct(Result::REPLY, 3);
}
timeout.schedule(Microseconds(STEP_TIMEOUT_US));
update_router_config();
step = step_arg;
log("test step ", step, " started");
}
void step_succeeded()
{
log("test step ", step, " succeeded");
switch (step) {
case 0: start_step(1, "nic"); break;
case 1: start_step(2, "wifi"); break;
case 2: start_step(3); break;
case 3: start_step(4, "nic"); break;
case 4: start_step(5, "nic"); break;
case 5: start_step(6); break;
case 6: start_step(7, "wifi"); break;
case 7: start_step(8, "nic"); break;
case 8: env.parent().exit(0); break;
}
}
Main(Env &env) : env(env)
{
result_rom.sigh(result_handler);
handle_result();
}
};
void Component::construct(Env &env) { static Main main(env); }

View File

@ -0,0 +1,14 @@
TARGET = test-nic_router_uplinks
LIBS += base
NIC_ROUTER_DIR := $(call select_from_repositories,src/server/nic_router)
SRC_CC += main.cc dns.cc xml_node.cc
INC_DIR += $(PRG_DIR) $(NIC_ROUTER_DIR)
vpath dns.cc $(NIC_ROUTER_DIR)
vpath xml_node.cc $(NIC_ROUTER_DIR)
CC_CXX_WARN_STRICT_CONVERSION =