diff --git a/repos/os/recipes/src/ping/used_apis b/repos/os/recipes/src/ping/used_apis index 7b044429d1..a1972aef72 100644 --- a/repos/os/recipes/src/ping/used_apis +++ b/repos/os/recipes/src/ping/used_apis @@ -2,3 +2,4 @@ base os net nic_session +report_session diff --git a/repos/os/run/ping.run b/repos/os/run/ping.run index 07a2b9f27a..a119c3358f 100644 --- a/repos/os/run/ping.run +++ b/repos/os/run/ping.run @@ -58,6 +58,7 @@ create_boot_directory import_from_depot [depot_user]/src/[base_src] \ [depot_user]/pkg/[drivers_nic_pkg] \ [depot_user]/src/init \ + [depot_user]/src/report_rom \ [depot_user]/src/nic_router build { app/ping } @@ -114,6 +115,15 @@ append config { + + + + + + + + + @@ -168,9 +178,11 @@ append config { + diff --git a/repos/os/src/app/ping/README b/repos/os/src/app/ping/README index 4019a9b9fa..10f0bf95d4 100644 --- a/repos/os/src/app/ping/README +++ b/repos/os/src/app/ping/README @@ -16,6 +16,7 @@ value for each attribute except 'config.dst_ip' and 'config.interface': ! protocol="icmp" ! period_sec="5" ! verbose="no" +! report="yes" ! count="5" /> This is a short description of the tags and attributes: @@ -36,6 +37,9 @@ This is a short description of the tags and attributes: :config.verbose: Optional. Toggles wether the component shall log debugging information. +:config.report: + Optional. Toggles wether the component shall report results. + :config.count: Optional. After how many successful pings the component exits successfully. @@ -46,6 +50,30 @@ This is a short description of the tags and attributes: Optional. Protocol to ping with. Can be one of 'icmp', 'udp'. +Report +~~~~~~ + +If config attribute 'report' is set, the component generates a report named +"last_received" that looks like this if the expected reply was received: + +:ICMP: +! + +:UDP: +! + +When an ICMP error "destination unreachable" was received instead, the report +looks like this: + +:ICMP: +! + +:UDP: +! + +The id attribute in the report is incremented with each result. + + Sessions ~~~~~~~~ @@ -53,6 +81,7 @@ This is an overview of the sessions required and provided by the component apart from the environment sessions: * Requires one Timer session. +* Requires one Report session if config attribute report is set. Examples diff --git a/repos/os/src/app/ping/config.xsd b/repos/os/src/app/ping/config.xsd index f8c6e92b7c..5777f6fa5c 100644 --- a/repos/os/src/app/ping/config.xsd +++ b/repos/os/src/app/ping/config.xsd @@ -15,6 +15,7 @@ + diff --git a/repos/os/src/app/ping/main.cc b/repos/os/src/app/ping/main.cc index ad2c411ded..1cd9673a84 100644 --- a/repos/os/src/app/ping/main.cc +++ b/repos/os/src/app/ping/main.cc @@ -18,6 +18,7 @@ #include /* Genode includes */ +#include #include #include #include @@ -58,26 +59,29 @@ class Main : public Nic_handler, enum { DEFAULT_PERIOD_SEC = 5 }; enum { SRC_PORT = 50000 }; - Env &_env; - Attached_rom_dataspace _config_rom { _env, "config" }; - Xml_node _config { _config_rom.xml() }; - Timer::Connection _timer { _env }; - Microseconds _send_time { 0 }; - Microseconds _period_us { read_sec_attr(_config, "period_sec", (uint64_t)DEFAULT_PERIOD_SEC) }; - Constructible _period { }; - Heap _heap { &_env.ram(), &_env.rm() }; - bool const _verbose { _config.attribute_value("verbose", false) }; - Net::Nic _nic { _env, _heap, *this, _verbose }; - Ipv4_address const _dst_ip { _config.attribute_value("dst_ip", Ipv4_address()) }; - Mac_address _dst_mac { }; - uint16_t _icmp_seq { 1 }; - unsigned long _count { _config.attribute_value("count", (unsigned long)DEFAULT_COUNT) }; - Constructible _dhcp_client { }; - Reconstructible _ip_config { _config.attribute_value("interface", Ipv4_address_prefix()), - _config.attribute_value("gateway", Ipv4_address()), - Ipv4_address() }; - Protocol const _protocol { _config.attribute_value("protocol", Protocol::ICMP) }; - Port const _dst_port { _config.attribute_value("dst_port", Port(DEFAULT_DST_PORT)) }; + Env &_env; + Attached_rom_dataspace _config_rom { _env, "config" }; + Xml_node _config { _config_rom.xml() }; + Timer::Connection _timer { _env }; + Microseconds _send_time { 0 }; + Microseconds _period_us { read_sec_attr(_config, "period_sec", (uint64_t)DEFAULT_PERIOD_SEC) }; + Constructible _period { }; + Heap _heap { &_env.ram(), &_env.rm() }; + bool const _verbose { _config.attribute_value("verbose", false) }; + bool const _report { _config.attribute_value("report", false) }; + unsigned long _report_id { 0 }; + Constructible _reporter { }; + Net::Nic _nic { _env, _heap, *this, _verbose }; + Ipv4_address const _dst_ip { _config.attribute_value("dst_ip", Ipv4_address()) }; + Mac_address _dst_mac { }; + uint16_t _icmp_seq { 1 }; + unsigned long _count { _config.attribute_value("count", (unsigned long)DEFAULT_COUNT) }; + Constructible _dhcp_client { }; + Reconstructible _ip_config { _config.attribute_value("interface", Ipv4_address_prefix()), + _config.attribute_value("gateway", Ipv4_address()), + Ipv4_address() }; + Protocol const _protocol { _config.attribute_value("protocol", Protocol::ICMP) }; + Port const _dst_port { _config.attribute_value("dst_port", Port(DEFAULT_DST_PORT)) }; void _handle_ip(Ethernet_frame ð, Size_guard &size_guard); @@ -156,6 +160,9 @@ Main::Main(Env &env) : _env(env) /* else, start the DHCP client for requesting an IP config */ else { _dhcp_client.construct(_timer, _nic, *this); } + + if (_report) + _reporter.construct(env, "result", "result"); } @@ -281,6 +288,16 @@ void Main::_handle_icmp_echo_reply(Ipv4_packet &ip, ": icmp_seq=", icmp_seq, " ttl=", (uint64_t)IPV4_TIME_TO_LIVE, " time=", time_ms, ".", time_us ," ms"); + if (_report) + _reporter->generate([&] (Xml_generator &xml) { + xml.attribute("id", _report_id++); + xml.attribute("type", "reply"); + xml.attribute("bytes", ICMP_DATA_SIZE + sizeof(Icmp_packet)); + xml.attribute("from", String<32>(ip.src())); + xml.attribute("ttl", (uint64_t)IPV4_TIME_TO_LIVE); + xml.attribute("time_ms", String<32>(time_ms, ".", time_us)); + xml.attribute("icmp_seq", icmp_seq); }); + /* raise ICMP sequence number and check exit condition */ _icmp_seq++; _count--; @@ -325,6 +342,12 @@ void Main::_handle_icmp_dst_unreachbl(Ipv4_packet &ip, return; } log("From ", ip.src(), " icmp_seq=", embed_icmp_seq, " Destination Unreachable"); + if (_report) + _reporter->generate([&] (Xml_generator &xml) { + xml.attribute("id", _report_id++); + xml.attribute("type", "destination_unreachable"); + xml.attribute("from", String<32>(ip.src())); + xml.attribute("icmp_seq", embed_icmp_seq); }); break; } case Protocol::UDP: @@ -349,6 +372,11 @@ void Main::_handle_icmp_dst_unreachbl(Ipv4_packet &ip, return; } log("From ", ip.src(), " Destination Unreachable"); + if (_report) + _reporter->generate([&] (Xml_generator &xml) { + xml.attribute("id", _report_id++); + xml.attribute("type", "destination_unreachable"); + xml.attribute("from", String<32>(ip.src())); }); break; } } @@ -414,6 +442,15 @@ void Main::_handle_udp(Ipv4_packet &ip, log(udp.length(), " bytes from ", ip.src(), " ttl=", (uint64_t)IPV4_TIME_TO_LIVE, " time=", time_ms, ".", time_us ," ms"); + if (_report) + _reporter->generate([&] (Xml_generator &xml) { + xml.attribute("id", _report_id++); + xml.attribute("type", "reply"); + xml.attribute("bytes", udp.length()); + xml.attribute("from", String<32>(ip.src())); + xml.attribute("ttl", (uint64_t)IPV4_TIME_TO_LIVE); + xml.attribute("time_ms", String<32>(time_ms, ".", time_us)); }); + /* check exit condition */ _count--; if (!_count) {