nic_router: report some useful information

The NIC router can now be configured to periodically send reports.
Configuration example (shows default values):

<config>
	<report interval_sec="5" bytes="yes" config="yes">
</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
'config'       : Boolean : Whether to report ipv4 interface and gateway per
                           domain
'interval_sec' : 1..3600 : Interval of sending reports in seconds

Issue #2614
This commit is contained in:
Martin Stein 2017-12-14 16:24:42 +01:00 committed by Christian Helmuth
parent 4d6fcbb8b6
commit edf1f9d849
15 changed files with 274 additions and 24 deletions

View File

@ -12,6 +12,8 @@ proc enable_test_7 { } { return 0 }
source ${genode_dir}/repos/libports/run/nic_router.inc
lappend targets server/report_rom
build $targets
create_boot_directory
@ -210,6 +212,8 @@ append config {
tcp_idle_timeout_sec="30"
tcp_max_segm_lifetime_sec="15">
<report bytes="yes" config="yes" interval_sec="60" />
<domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
<tcp-forward port="80" domain="http_server_1" to="192.168.1.18" />
<tcp-forward port="8080" domain="http_server_2" to="192.168.2.72" />
@ -229,6 +233,7 @@ append config {
</config>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
@ -245,11 +250,17 @@ append config {
<policy label_prefix="udp_server_3" ip_addr="10.0.2.213" />
</config>
<route>
<service name="Nic"> <child name="} [nic_drv] {"/> </service>
<service name="Nic"> <child name="} [nic_drv] {"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="yes"/>
</start>
} [test_1_config] {
} [test_2_config] {
} [test_3_config] {
@ -262,6 +273,8 @@ append config {
install_config $config
lappend boot_modules report_rom
build_boot_image $boot_modules
for {set i 0} {$i < $nr_of_clients} {incr i 1} {

View File

@ -2,3 +2,4 @@ base
os
nic_session
timer_session
report_session

View File

@ -336,6 +336,27 @@ router:
! dhcp_request_timeout_sec="6">
Configuring reporting functionality
###################################
The NIC router can be configured to periodically send reports.
Configuration example (shows default values of attributes):
<config>
<report interval_sec="5" bytes="yes" config="yes">
</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
'config' : Boolean : Whether to report ipv4 interface and gateway per
domain
'interval_sec' : 1..3600 : Interval of sending reports in seconds
Examples
########

View File

@ -89,6 +89,14 @@
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="report">
<xs:complexType>
<xs:attribute name="config" type="Boolean" />
<xs:attribute name="bytes" type="Boolean" />
<xs:attribute name="interval_sec" type="Seconds" />
</xs:complexType>
</xs:element><!-- report -->
<xs:element name="policy">
<xs:complexType>
<xs:attribute name="label_prefix" type="Session_label" />

View File

@ -13,9 +13,9 @@
/* local includes */
#include <configuration.h>
#include <xml_node.h>
/* Genode includes */
#include <util/xml_node.h>
#include <base/allocator.h>
#include <base/log.h>
@ -23,28 +23,14 @@ using namespace Net;
using namespace Genode;
/***************
** Utilities **
***************/
Microseconds read_sec_attr(Xml_node const node,
char const *name,
unsigned long const default_sec)
{
unsigned long sec = node.attribute_value(name, 0UL);
if (!sec) {
sec = default_sec;
}
return Microseconds(sec * 1000 * 1000);
}
/*******************
** Configuration **
*******************/
Configuration::Configuration(Xml_node const node,
Allocator &alloc)
Configuration::Configuration(Env &env,
Xml_node const node,
Allocator &alloc,
Timer::Connection &timer)
:
_alloc(alloc), _verbose(node.attribute_value("verbose", false)),
_verbose_domain_state(node.attribute_value("verbose_domain_state", false)),
@ -56,6 +42,7 @@ Configuration::Configuration(Xml_node const node,
_tcp_max_segm_lifetime(read_sec_attr(node, "tcp_max_segm_lifetime_sec", DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC)),
_node(node)
{
/* read domains */
node.for_each_sub_node("domain", [&] (Xml_node const node) {
try { _domains.insert(*new (_alloc) Domain(*this, node, _alloc)); }
@ -68,4 +55,9 @@ Configuration::Configuration(Xml_node const node,
domain.create_rules(_domains);
});
/* if configured, create a report generator */
try {
_report.set(*new (_alloc) Report(env, node.sub_node("report"), timer,
_domains));
} catch (Genode::Xml_node::Nonexistent_sub_node) { }
}

View File

@ -16,6 +16,7 @@
/* local includes */
#include <domain.h>
#include <report.h>
/* Genode includes */
#include <os/duration.h>
@ -38,11 +39,13 @@ class Net::Configuration
Genode::Microseconds const _udp_idle_timeout;
Genode::Microseconds const _tcp_idle_timeout;
Genode::Microseconds const _tcp_max_segm_lifetime;
Pointer<Report> _report;
Domain_tree _domains;
Genode::Xml_node const _node;
public:
enum { DEFAULT_REPORT_INTERVAL_SEC = 5 };
enum { DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC = 10 };
enum { DEFAULT_DHCP_REQUEST_TIMEOUT_SEC = 10 };
enum { DEFAULT_DHCP_OFFER_TIMEOUT_SEC = 10 };
@ -50,7 +53,10 @@ class Net::Configuration
enum { DEFAULT_TCP_IDLE_TIMEOUT_SEC = 600 };
enum { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC = 30 };
Configuration(Genode::Xml_node const node, Genode::Allocator &alloc);
Configuration(Genode::Env &env,
Genode::Xml_node const node,
Genode::Allocator &alloc,
Timer::Connection &timer);
/***************
@ -66,6 +72,7 @@ class Net::Configuration
Genode::Microseconds tcp_idle_timeout() const { return _tcp_idle_timeout; }
Genode::Microseconds tcp_max_segm_lifetime() const { return _tcp_max_segm_lifetime; }
Domain_tree &domains() { return _domains; }
Report &report() { return _report.deref(); }
Genode::Xml_node node() const { return _node; }
};

View File

@ -17,6 +17,7 @@
#include <interface.h>
/* Genode includes */
#include <util/xml_generator.h>
#include <util/xml_node.h>
#include <base/allocator.h>
#include <base/log.h>
@ -233,6 +234,26 @@ void Domain::dissolve_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", [&] () {
xml.attribute("name", _name);
if (bytes) {
xml.attribute("rx_bytes", _tx_bytes);
xml.attribute("tx_bytes", _rx_bytes);
}
if (config) {
xml.attribute("ipv4", String<19>(ip_config().interface));
xml.attribute("gw", String<16>(ip_config().gateway));
}
});
}
/*****************
** Domain_tree **

View File

@ -30,7 +30,11 @@
#include <util/avl_string.h>
#include <util/reconstructible.h>
namespace Genode { class Allocator; }
namespace Genode {
class Xml_generator;
class Allocator;
}
namespace Net {
@ -98,6 +102,8 @@ class Net::Domain : public Domain_base
Arp_waiter_list _foreign_arp_waiters;
Link_side_tree _tcp_links;
Link_side_tree _udp_links;
Genode::size_t _tx_bytes { 0 };
Genode::size_t _rx_bytes { 0 };
void _read_forward_rules(Genode::Cstring const &protocol,
Domain_tree &domains,
@ -140,6 +146,12 @@ class Net::Domain : public Domain_base
void dissolve_interface(Interface &interface);
void raise_rx_bytes(Genode::size_t bytes) { _rx_bytes += bytes; }
void raise_tx_bytes(Genode::size_t bytes) { _tx_bytes += bytes; }
void report(Genode::Xml_generator &xml);
/*********
** log **

View File

@ -862,6 +862,8 @@ void Interface::_handle_eth(void *const eth_base,
size_t const eth_size,
Packet_descriptor const &pkt)
{
_domain.raise_rx_bytes(eth_size);
/* do garbage collection over transport-layer links and DHCP allocations */
_destroy_dissolved_links<Udp_link>(_dissolved_udp_links, _alloc);
_destroy_dissolved_links<Tcp_link>(_dissolved_tcp_links, _alloc);
@ -936,6 +938,7 @@ void Interface::send(Ethernet_frame &eth, Genode::size_t const size)
char *content = _source().packet_content(pkt);
Genode::memcpy((void *)content, (void *)&eth, size);
_source().submit_packet(pkt);
_domain.raise_tx_bytes(size);
}
catch (Packet_stream_source::Packet_alloc_failed) {
if (_config().verbose()) {

View File

@ -47,7 +47,8 @@ class Main
Main::Main(Env &env)
:
_timer(env), _heap(&env.ram(), &env.rm()), _config_rom(env, "config"),
_config(_config_rom.xml(), _heap), _uplink(env, _timer, _heap, _config),
_config(env, _config_rom.xml(), _heap, _timer),
_uplink(env, _timer, _heap, _config),
_root(env.ep(), _timer, _heap, _uplink.router_mac(), _config,
env.ram(), env.rm())
{

View File

@ -0,0 +1,51 @@
/*
* \brief Report generation unit
* \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.
*/
/* local includes */
#include <report.h>
#include <xml_node.h>
#include <domain.h>
using namespace Net;
using namespace Genode;
Net::Report::Report(Env &env,
Xml_node const node,
Timer::Connection &timer,
Domain_tree &domains)
:
_config(node.attribute_value("config", true)),
_bytes (node.attribute_value("bytes", true)),
_reporter(env, "state"),
_domains(domains),
_timeout(timer, *this, &Report::_handle_report_timeout,
read_sec_attr(node, "interval_sec", 5))
{
_reporter.enabled(true);
}
void Net::Report::_handle_report_timeout(Duration)
{
try {
Reporter::Xml_generator xml(_reporter, [&] () {
_domains.for_each([&] (Domain &domain) {
domain.report(xml);
});
});
} catch (Xml_generator::Buffer_exceeded) {
Genode::warning("Failed to generate report");
}
}

View File

@ -0,0 +1,62 @@
/*
* \brief Report generation unit
* \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.
*/
#ifndef _REPORT_H_
#define _REPORT_H_
/* Genode */
#include <timer_session/connection.h>
#include <os/reporter.h>
namespace Genode {
class Xml_node;
class Env;
}
namespace Net {
class Domain_tree;
class Report;
}
class Net::Report
{
private:
bool const _config;
bool const _bytes;
Genode::Reporter _reporter;
Domain_tree &_domains;
Timer::Periodic_timeout<Report> _timeout;
void _handle_report_timeout(Genode::Duration);
public:
Report(Genode::Env &env,
Genode::Xml_node const node,
Timer::Connection &timer,
Domain_tree &domains);
/***************
** Accessors **
***************/
bool config() const { return _config; }
bool bytes() const { return _bytes; }
};
#endif /* _REPORT_H_ */

View File

@ -8,7 +8,7 @@ SRC_CC += nat_rule.cc mac_allocator.cc main.cc ipv4_config.cc
SRC_CC += uplink.cc interface.cc arp_cache.cc configuration.cc
SRC_CC += domain.cc l3_protocol.cc direct_rule.cc link.cc
SRC_CC += transport_rule.cc leaf_rule.cc permit_rule.cc
SRC_CC += dhcp_client.cc dhcp_server.cc
SRC_CC += dhcp_client.cc dhcp_server.cc report.cc xml_node.cc
INC_DIR += $(PRG_DIR)

View File

@ -0,0 +1,29 @@
/*
* \brief Genode XML nodes plus local utilities
* \author Martin Stein
* \date 2016-08-19
*/
/*
* 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.
*/
/* local includes */
#include <xml_node.h>
using namespace Genode;
Microseconds Genode::read_sec_attr(Xml_node const node,
char const *name,
unsigned long const default_sec)
{
unsigned long sec = node.attribute_value(name, 0UL);
if (!sec) {
sec = default_sec;
}
return Microseconds(sec * 1000 * 1000);
}

View File

@ -0,0 +1,29 @@
/*
* \brief Genode XML nodes plus local utilities
* \author Martin Stein
* \date 2016-08-19
*/
/*
* 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.
*/
#ifndef _XML_NODE_H_
#define _XML_NODE_H_
/* Genode includes */
#include <util/xml_node.h>
#include <os/duration.h>
namespace Genode {
Microseconds read_sec_attr(Xml_node const node,
char const *name,
unsigned long const default_sec);
}
#endif /* _XML_NODE_H_ */