diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README
index 942d6ab578..3f37f74e38 100644
--- a/repos/os/src/server/nic_router/README
+++ b/repos/os/src/server/nic_router/README
@@ -743,7 +743,7 @@ Whether to log router decisions and optional hints.
!
!
-!
+!
Whether to log most important protocol header fields of each packet that is
received or sent (ETH, IPv4, ARP, UDP, TCP, DHCP, ICMP). The value
@@ -751,7 +751,7 @@ affects all domains without a local value.
!
!
-!
+!
Whether to log each packet drop and the rational behind it. The value
affects all domains without a local value.
@@ -762,6 +762,28 @@ Whether to log most important changes in the state of a domain (number of
interfaces assigned, current IPv4 config).
+Tracing
+~~~~~~~
+
+You can use Genode's TRACE service to capture all packets that traverse the
+router. This requires a monitor component such as the trace-recorder component
+that provides and activates a corresponding trace buffer and trace policy.
+More precisely, packet tracing is realised via the 'trace_eth_packet()' hook
+that needs to be implemented by the trace policy. Note that packet tracing must
+also be enabled in the router configuration.
+
+This is how you can configure whether to trace packets (default values shown):
+
+!
+!
+!
+
+If enabled, 'trace_eth_packet()' is called for every packet received or sent by
+the router. The attribute in the tag applies only for packets
+received and sent by that domain. The attribute in the tag sets the
+default value for all tags without a local setting.
+
+
Other configuration attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd
index 35fc2975bb..3b46a1d104 100644
--- a/repos/os/src/server/nic_router/config.xsd
+++ b/repos/os/src/server/nic_router/config.xsd
@@ -171,6 +171,7 @@
+
@@ -182,6 +183,7 @@
+
diff --git a/repos/os/src/server/nic_router/configuration.cc b/repos/os/src/server/nic_router/configuration.cc
index 2c54344b6e..388930f922 100644
--- a/repos/os/src/server/nic_router/configuration.cc
+++ b/repos/os/src/server/nic_router/configuration.cc
@@ -36,6 +36,7 @@ Configuration::Configuration(Xml_node const node,
_verbose_packets { false },
_verbose_packet_drop { false },
_verbose_domain_state { false },
+ _trace_packets { false },
_icmp_echo_server { false },
_icmp_type_3_code_on_fragm_ipv4 { 0 },
_dhcp_discover_timeout { 0 },
@@ -116,6 +117,7 @@ Configuration::Configuration(Env &env,
_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) },
+ _trace_packets { node.attribute_value("trace_packets", false) },
_icmp_echo_server { node.attribute_value("icmp_echo_server", true) },
_icmp_type_3_code_on_fragm_ipv4 { _init_icmp_type_3_code_on_fragm_ipv4(node) },
_dhcp_discover_timeout { read_sec_attr(node, "dhcp_discover_timeout_sec", 10) },
diff --git a/repos/os/src/server/nic_router/configuration.h b/repos/os/src/server/nic_router/configuration.h
index aa332a3f96..2f157d8bbe 100644
--- a/repos/os/src/server/nic_router/configuration.h
+++ b/repos/os/src/server/nic_router/configuration.h
@@ -39,6 +39,7 @@ class Net::Configuration
bool const _verbose_packets;
bool const _verbose_packet_drop;
bool const _verbose_domain_state;
+ bool const _trace_packets;
bool const _icmp_echo_server;
Icmp_packet::Code const _icmp_type_3_code_on_fragm_ipv4;
Genode::Microseconds const _dhcp_discover_timeout;
@@ -92,6 +93,7 @@ class Net::Configuration
bool verbose_packets() const { return _verbose_packets; }
bool verbose_packet_drop() const { return _verbose_packet_drop; }
bool verbose_domain_state() const { return _verbose_domain_state; }
+ bool trace_packets() const { return _trace_packets; }
bool icmp_echo_server() const { return _icmp_echo_server; }
Icmp_packet::Code icmp_type_3_code_on_fragm_ipv4() const { return _icmp_type_3_code_on_fragm_ipv4; }
Genode::Microseconds dhcp_discover_timeout() const { return _dhcp_discover_timeout; }
diff --git a/repos/os/src/server/nic_router/domain.cc b/repos/os/src/server/nic_router/domain.cc
index 2cede36955..a162527c44 100644
--- a/repos/os/src/server/nic_router/domain.cc
+++ b/repos/os/src/server/nic_router/domain.cc
@@ -196,6 +196,8 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
config.verbose_packets()) },
_verbose_packet_drop { node.attribute_value("verbose_packet_drop",
config.verbose_packet_drop()) },
+ _trace_packets { node.attribute_value("trace_packets",
+ config.trace_packets()) },
_icmp_echo_server { node.attribute_value("icmp_echo_server",
config.icmp_echo_server()) },
_use_arp { _node.attribute_value("use_arp", true) },
diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h
index 376fd582ee..2dfa4f234a 100644
--- a/repos/os/src/server/nic_router/domain.h
+++ b/repos/os/src/server/nic_router/domain.h
@@ -142,6 +142,7 @@ class Net::Domain : public Domain_base,
Genode::size_t _rx_bytes { 0 };
bool const _verbose_packets;
bool const _verbose_packet_drop;
+ bool const _trace_packets;
bool const _icmp_echo_server;
bool const _use_arp;
Genode::Session_label const _label;
@@ -236,6 +237,7 @@ class Net::Domain : public Domain_base,
bool verbose_packets() const { return _verbose_packets; }
bool verbose_packet_drop() const { return _verbose_packet_drop; }
+ bool trace_packets() const { return _trace_packets; }
bool icmp_echo_server() const { return _icmp_echo_server; }
bool use_arp() const { return _use_arp; }
Genode::Session_label const &label() const { return _label; }
diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc
index c471a30653..77df57ff0d 100644
--- a/repos/os/src/server/nic_router/interface.cc
+++ b/repos/os/src/server/nic_router/interface.cc
@@ -1756,6 +1756,12 @@ void Interface::_handle_eth(void *const eth_base,
if (local_domain.verbose_packets()) {
log("[", local_domain, "] rcv ", eth); }
+ if (local_domain.trace_packets())
+ Genode::Trace::Ethernet_packet(local_domain.name().string(),
+ Genode::Trace::Ethernet_packet::Direction::RECV,
+ eth_base,
+ size_guard.total_size());
+
/* try to handle ethernet frame */
try { _handle_eth(eth, size_guard, pkt, local_domain); }
catch (Free_resources_and_retry_handle_eth) {
@@ -1871,6 +1877,13 @@ void Interface::_send_submit_pkt(Packet_descriptor &pkt,
}
catch (Size_guard::Exceeded) { log("[", local_domain, "] snd ?"); }
}
+
+ if (local_domain.trace_packets())
+ Genode::Trace::Ethernet_packet(local_domain.name().string(),
+ Genode::Trace::Ethernet_packet::Direction::SENT,
+ pkt_base,
+ pkt_size);
+
_source.try_submit_packet(pkt);
}