mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
os/server: nic_dump
A tiny bump-in-the-wire tool for dumping NIC packet information. Ref #2314
This commit is contained in:
parent
995017b60c
commit
35cc020e9c
258
repos/libports/run/nic_dump.run
Normal file
258
repos/libports/run/nic_dump.run
Normal file
@ -0,0 +1,258 @@
|
||||
#
|
||||
# Build components
|
||||
#
|
||||
|
||||
proc enable_test_1 { } { return 1 }
|
||||
proc enable_test_2 { } { return 1 }
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
|
||||
proc nic_drv { } {
|
||||
if {[have_spec omap4] || [have_spec arndale] || [have_spec rpi]} { return usb_drv }
|
||||
if {!([have_spec imx53] || [have_spec riscv] || [have_spec odroid_xu] || [have_spec wand_quad])} { return nic_drv }
|
||||
}
|
||||
|
||||
proc gpio_drv { } {
|
||||
if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv }
|
||||
if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv }
|
||||
if {[have_spec gpio]} { return gpio_drv }
|
||||
}
|
||||
|
||||
if {[nic_drv] == ""} {
|
||||
puts "\n Run script is not supported on this platform. \n"; exit 0 }
|
||||
|
||||
proc nic_drv_build { } {
|
||||
if {[nic_drv] == "nic_drv"} { return drivers/nic }
|
||||
if {[nic_drv] == "usb_drv"} { return drivers/usb }
|
||||
}
|
||||
|
||||
proc gpio_drv_build { } { if {[gpio_drv] != ""} { return drivers/gpio } }
|
||||
|
||||
build "core init drivers/timer server/nic_router server/nic_bridge
|
||||
test/lwip/http_srv_static test/lwip/http_clnt test/lxip/udp_echo
|
||||
test/lxip/udp_client server/nic_dump [nic_drv_build] [gpio_drv_build]
|
||||
[platform_drv_build_components]"
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
proc gpio_drv_config { } {
|
||||
if {[have_spec gpio]} {
|
||||
append result {
|
||||
<start name="} [gpio_drv] {">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="Gpio"/></provides>
|
||||
</start>}
|
||||
return $result
|
||||
}
|
||||
}
|
||||
|
||||
proc nic_drv_config { } {
|
||||
if {[nic_drv] == "nic_drv"} {
|
||||
append result {
|
||||
<start name="nic_drv">
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
</start>}
|
||||
return $result
|
||||
}
|
||||
if {[nic_drv] == "usb_drv"} {
|
||||
append result {
|
||||
<start name="usb_drv">
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<provides>
|
||||
<service name="Nic"/>
|
||||
</provides>
|
||||
<config ehci="yes">
|
||||
<nic mac="02:00:00:00:01:01" />
|
||||
</config>
|
||||
</start>}
|
||||
return $result
|
||||
}
|
||||
}
|
||||
|
||||
proc client_bin { prot } {
|
||||
if {$prot == "udp"} { return "test-lxip_udp_client" }
|
||||
if {$prot == "http"} { return "test-http_clnt" } }
|
||||
|
||||
proc server_bin { prot } {
|
||||
if {$prot == "udp"} { return "test-lxip_udp_echo" }
|
||||
if {$prot == "http"} { return "test-lwip_httpsrv_static" } }
|
||||
|
||||
proc client_config { prot index ip_addr gateway netmask nic srv_port srv_ip } {
|
||||
append result {
|
||||
<start name="} $prot {_client_} $index {">
|
||||
<binary name="} [client_bin $prot] {" />
|
||||
<resource name="RAM" quantum="28M"/>
|
||||
<route>
|
||||
<service name="Nic"> <child name="} $nic {"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config server_ip="} $srv_ip {" server_port="} $srv_port {">
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" ip_addr="} $ip_addr {"
|
||||
gateway="} $gateway {" netmask="} $netmask {"/>
|
||||
</config>
|
||||
</start>}
|
||||
return $result
|
||||
}
|
||||
|
||||
proc server_config { prot index ip_addr gateway netmask nic port } {
|
||||
append result {
|
||||
<start name="} $prot {_server_} $index {">
|
||||
<binary name="} [server_bin $prot] {" />
|
||||
<resource name="RAM" quantum="28M"/>
|
||||
<route>
|
||||
<service name="Nic"> <child name="} $nic {"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config port="} $port {">
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" ip_addr="} $ip_addr {"
|
||||
gateway="} $gateway {" netmask="} $netmask {"/>
|
||||
</config>
|
||||
</start>}
|
||||
return $result
|
||||
}
|
||||
|
||||
proc test_1_config { } {
|
||||
if {[enable_test_1]} { return "
|
||||
[client_config udp 2 10.0.2.212 10.0.2.1 255.255.255.0 nic_bridge 1 10.0.2.55]
|
||||
[server_config udp 2 18.17.16.15 18.17.16.14 255.255.0.0 nic_router 1 ]" }
|
||||
}
|
||||
|
||||
proc test_2_config { } {
|
||||
if {[enable_test_2]} { return "
|
||||
[client_config http 1 10.0.2.201 10.0.2.1 255.255.255.0 nic_bridge 80 10.0.2.55]
|
||||
[server_config http 1 192.168.1.18 192.168.1.1 255.255.255.0 nic_router 80 ]" }
|
||||
}
|
||||
|
||||
append config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
|
||||
} [gpio_drv_config] {
|
||||
} [nic_drv_config] {
|
||||
} [platform_drv_config] {
|
||||
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="nic_dump">
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
<config uplink="bridge" downlink="router" time="yes"/>
|
||||
<route>
|
||||
<service name="Nic"> <child name="nic_bridge"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="nic_router">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
<config rtt_sec="3" verbose="no">
|
||||
|
||||
<policy label_prefix="udp_client_1" domain="udp_client_1" />
|
||||
<policy label_prefix="http_client_3" domain="http_client_3" />
|
||||
<policy label_prefix="udp_client_3" domain="udp_client_3" />
|
||||
<policy label_prefix="http_server_1" domain="http_server_1" />
|
||||
<policy label_prefix="http_server_2" domain="http_server_2" />
|
||||
<policy label_prefix="udp_server_1" domain="udp_server_1" />
|
||||
<policy label_prefix="udp_server_2" domain="udp_server_2" />
|
||||
|
||||
<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" />
|
||||
<udp-forward port="1" domain="udp_server_2" to="18.17.16.15" />
|
||||
<nat domain="http_client_3" tcp-ports="6" />
|
||||
<ip dst="217.13.192.0/24" domain="udp_client_3" />
|
||||
</domain>
|
||||
|
||||
<domain name="udp_client_1" interface="10.0.98.33/24">
|
||||
<udp-forward port="1337" domain="udp_server_1" to="10.0.99.55" />
|
||||
</domain>
|
||||
|
||||
<domain name="http_client_3" interface="100.200.0.1/24">
|
||||
<tcp dst="10.0.0.0/16">
|
||||
<permit port="2345" domain="uplink" />
|
||||
</tcp>
|
||||
</domain>
|
||||
|
||||
<domain name="udp_client_3" interface="217.13.192.1/24">
|
||||
<ip dst="10.0.2.0/24" domain="uplink" />
|
||||
</domain>
|
||||
|
||||
<domain name="http_server_1" interface="192.168.1.1/24" />
|
||||
<domain name="http_server_2" interface="192.168.2.1/24" />
|
||||
<domain name="udp_server_1" interface="10.0.99.33/24" />
|
||||
<domain name="udp_server_2" interface="18.17.16.14/24" />
|
||||
|
||||
</config>
|
||||
<route>
|
||||
<service name="Nic"> <child name="nic_dump"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="nic_bridge">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
<config>
|
||||
<policy label_prefix="nic_dump" ip_addr="10.0.2.55" />
|
||||
<policy label_prefix="http_client_1" ip_addr="10.0.2.201" />
|
||||
<policy label_prefix="http_client_2" ip_addr="10.0.2.202" />
|
||||
<policy label_prefix="http_server_3" ip_addr="10.0.2.203" />
|
||||
<policy label_prefix="udp_client_2" ip_addr="10.0.2.212" />
|
||||
<policy label_prefix="udp_server_3" ip_addr="10.0.2.213" />
|
||||
</config>
|
||||
<route>
|
||||
<service name="Nic"> <child name="} [nic_drv] {"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
} [test_1_config] {
|
||||
} [test_2_config] {
|
||||
|
||||
</config> }
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Create single image and execute
|
||||
#
|
||||
|
||||
|
||||
build_boot_image "
|
||||
core init timer nic_router nic_bridge ld.lib.so libc.lib.so libm.lib.so
|
||||
libc_resolv.lib.so lwip.lib.so lxip.lib.so test-http_clnt
|
||||
test-lwip_httpsrv_static nic_dump test-lxip_udp_echo test-lxip_udp_client
|
||||
[nic_drv] [gpio_drv] [platform_drv_boot_modules]"
|
||||
|
||||
proc nic_qemu_args { } {
|
||||
if {[have_spec x86]} { return "-net nic,model=e1000" }
|
||||
if {[have_spec lan9118]} { return "-net nic,model=lan9118" } }
|
||||
|
||||
append qemu_args "-m 384 -nographic -net user -redir udp:5555::1337 [nic_qemu_args]"
|
||||
|
||||
run_genode_until {.*Test done.*\n.*Test done.*\n} 60
|
44
repos/os/src/server/nic_dump/README
Normal file
44
repos/os/src/server/nic_dump/README
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
==================================
|
||||
Component for tracking NIC traffic
|
||||
==================================
|
||||
|
||||
|
||||
Brief
|
||||
#####
|
||||
|
||||
The 'nic_dump' component is a bump-in-the-wire component for the NIC service
|
||||
that does deep packet inspection for each passing packet and dumps the
|
||||
gathered information to the log. This includes information about Ethernet,
|
||||
ARP, IPv4, TCP, UDP, and DHCP.
|
||||
|
||||
|
||||
Basics
|
||||
######
|
||||
|
||||
The component knows three configuration attributes:
|
||||
|
||||
! <config uplink="karl" downlink="olivia" time="yes"/>
|
||||
|
||||
The values of the 'uplink' and 'downlink' attributes are used as log labels
|
||||
for the two NIC peers. These labels are only relevant for the readability of
|
||||
the log. The third attribute 'time' defines wether to print timing
|
||||
information or not.
|
||||
|
||||
An example output snippet of the component might be:
|
||||
|
||||
! (olivia <- karl) ETH ... ARP ... time 4626 (15)
|
||||
! (karl <- olivia) ETH ... ARP ... time 4639 (7)
|
||||
! (olivia <- karl) ETH ... IPV4 ... TCP ... time 4644 (5)
|
||||
! (karl <- olivia) ETH ... IPV4 ... TCP ... time 4660 (6)
|
||||
|
||||
After the NIC peer labels and the traffic direction, the unfolding of the
|
||||
protocols and their information follows. The printing order is from the lowest
|
||||
to the highest networking layer. At the end of each line there is the word
|
||||
'time' followed by two numbers if you have enabled timing information. The
|
||||
first number is the packet-arrival time (the milliseconds since 'nic_dump' was
|
||||
started). The second number is the time from the last packet that passed till
|
||||
this one (milliseconds).
|
||||
|
||||
A comprehensive example of how to use the NIC dump can be found in the test
|
||||
script 'libports/run/nic_dump.run'.
|
150
repos/os/src/server/nic_dump/component.cc
Normal file
150
repos/os/src/server/nic_dump/component.cc
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* \brief Downlink interface in form of a NIC session component
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 includes */
|
||||
#include <os/session_policy.h>
|
||||
|
||||
/* local includes */
|
||||
#include <component.h>
|
||||
#include <uplink.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**************************
|
||||
** Communication_buffer **
|
||||
**************************/
|
||||
|
||||
Communication_buffer::Communication_buffer(Ram_session &ram,
|
||||
Genode::size_t const size)
|
||||
:
|
||||
Ram_dataspace_capability(ram.alloc(size)), _ram(ram)
|
||||
{ }
|
||||
|
||||
|
||||
/****************************
|
||||
** Session_component_base **
|
||||
****************************/
|
||||
|
||||
Session_component_base::
|
||||
Session_component_base(Allocator &guarded_alloc_backing,
|
||||
size_t const guarded_alloc_amount,
|
||||
Ram_session &buf_ram,
|
||||
size_t const tx_buf_size,
|
||||
size_t const rx_buf_size)
|
||||
:
|
||||
_guarded_alloc(&guarded_alloc_backing, guarded_alloc_amount),
|
||||
_range_alloc(&_guarded_alloc), _tx_buf(buf_ram, tx_buf_size),
|
||||
_rx_buf(buf_ram, rx_buf_size)
|
||||
{ }
|
||||
|
||||
|
||||
/***********************
|
||||
** Session_component **
|
||||
***********************/
|
||||
|
||||
Net::Session_component::Session_component(Allocator &alloc,
|
||||
size_t const amount,
|
||||
Ram_session &buf_ram,
|
||||
size_t const tx_buf_size,
|
||||
size_t const rx_buf_size,
|
||||
Region_map ®ion_map,
|
||||
Uplink &uplink,
|
||||
Xml_node config,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
Entrypoint &ep)
|
||||
:
|
||||
Session_component_base(alloc, amount, buf_ram, tx_buf_size, rx_buf_size),
|
||||
Session_rpc_object(region_map, _tx_buf, _rx_buf, &_range_alloc, ep.rpc_ep()),
|
||||
Interface(ep, config.attribute_value("downlink", Interface_label()),
|
||||
timer, curr_time, config.attribute_value("time", false),
|
||||
_guarded_alloc),
|
||||
_mac(uplink.mac_address())
|
||||
{
|
||||
_tx.sigh_ready_to_ack(_sink_ack);
|
||||
_tx.sigh_packet_avail(_sink_submit);
|
||||
_rx.sigh_ack_avail(_source_ack);
|
||||
_rx.sigh_ready_to_submit(_source_submit);
|
||||
Interface::remote(uplink);
|
||||
uplink.Interface::remote(*this);
|
||||
}
|
||||
|
||||
|
||||
bool Session_component::link_state()
|
||||
{
|
||||
warning("Session_component::link_state not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Session_component::link_state_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
warning("Session_component::link_state_sigh not implemented");
|
||||
}
|
||||
|
||||
|
||||
/**********
|
||||
** Root **
|
||||
**********/
|
||||
|
||||
Net::Root::Root(Entrypoint &ep,
|
||||
Allocator &alloc,
|
||||
Uplink &uplink,
|
||||
Ram_session &buf_ram,
|
||||
Xml_node config,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
Region_map ®ion_map)
|
||||
:
|
||||
Root_component<Session_component, Genode::Single_client>(&ep.rpc_ep(),
|
||||
&alloc),
|
||||
_ep(ep), _uplink(uplink), _buf_ram(buf_ram),
|
||||
_region_map(region_map), _config(config), _timer(timer),
|
||||
_curr_time(curr_time)
|
||||
{ }
|
||||
|
||||
|
||||
Session_component *Net::Root::_create_session(char const *args)
|
||||
{
|
||||
try {
|
||||
size_t const ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
|
||||
size_t const tx_buf_size =
|
||||
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
||||
|
||||
size_t const rx_buf_size =
|
||||
Arg_string::find_arg(args, "rx_buf_size").ulong_value(0);
|
||||
|
||||
size_t const session_size =
|
||||
max((size_t)4096, sizeof(Session_component));
|
||||
|
||||
if (ram_quota < session_size) {
|
||||
throw Root::Quota_exceeded(); }
|
||||
|
||||
if (tx_buf_size > ram_quota - session_size ||
|
||||
rx_buf_size > ram_quota - session_size ||
|
||||
tx_buf_size + rx_buf_size > ram_quota - session_size)
|
||||
{
|
||||
error("insufficient 'ram_quota' for session creation");
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
return new (md_alloc())
|
||||
Session_component(*md_alloc(), ram_quota - session_size,
|
||||
_buf_ram, tx_buf_size, rx_buf_size, _region_map,
|
||||
_uplink, _config, _timer, _curr_time, _ep);
|
||||
} catch (...) {
|
||||
throw Root::Unavailable(); }
|
||||
}
|
143
repos/os/src/server/nic_dump/component.h
Normal file
143
repos/os/src/server/nic_dump/component.h
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* \brief Downlink interface in form of a NIC session component
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _COMPONENT_H_
|
||||
#define _COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_guard.h>
|
||||
#include <root/component.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <nic_session/rpc_object.h>
|
||||
|
||||
/* local includes */
|
||||
#include <interface.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Communication_buffer;
|
||||
class Session_component_base;
|
||||
class Session_component;
|
||||
class Root;
|
||||
class Uplink;
|
||||
}
|
||||
|
||||
|
||||
class Net::Communication_buffer : public Genode::Ram_dataspace_capability
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Ram_session &_ram;
|
||||
|
||||
public:
|
||||
|
||||
Communication_buffer(Genode::Ram_session &ram,
|
||||
Genode::size_t const size);
|
||||
|
||||
~Communication_buffer() { _ram.free(*this); }
|
||||
};
|
||||
|
||||
|
||||
class Net::Session_component_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Genode::Allocator_guard _guarded_alloc;
|
||||
Nic::Packet_allocator _range_alloc;
|
||||
Communication_buffer _tx_buf;
|
||||
Communication_buffer _rx_buf;
|
||||
|
||||
public:
|
||||
|
||||
Session_component_base(Genode::Allocator &guarded_alloc_backing,
|
||||
Genode::size_t const guarded_alloc_amount,
|
||||
Genode::Ram_session &buf_ram,
|
||||
Genode::size_t const tx_buf_size,
|
||||
Genode::size_t const rx_buf_size);
|
||||
};
|
||||
|
||||
|
||||
class Net::Session_component : public Session_component_base,
|
||||
public ::Nic::Session_rpc_object,
|
||||
public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
Mac_address _mac;
|
||||
|
||||
|
||||
/********************
|
||||
** Net::Interface **
|
||||
********************/
|
||||
|
||||
Packet_stream_sink &_sink() { return *_tx.sink(); }
|
||||
Packet_stream_source &_source() { return *_rx.source(); }
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Genode::Allocator &alloc,
|
||||
Genode::size_t const amount,
|
||||
Genode::Ram_session &buf_ram,
|
||||
Genode::size_t const tx_buf_size,
|
||||
Genode::size_t const rx_buf_size,
|
||||
Genode::Region_map ®ion_map,
|
||||
Uplink &uplink,
|
||||
Genode::Xml_node config,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
Genode::Entrypoint &ep);
|
||||
|
||||
|
||||
/******************
|
||||
** Nic::Session **
|
||||
******************/
|
||||
|
||||
Mac_address mac_address() { return _mac; }
|
||||
bool link_state();
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh);
|
||||
};
|
||||
|
||||
|
||||
class Net::Root : public Genode::Root_component<Session_component,
|
||||
Genode::Single_client>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Entrypoint &_ep;
|
||||
Uplink &_uplink;
|
||||
Genode::Ram_session &_buf_ram;
|
||||
Genode::Region_map &_region_map;
|
||||
Genode::Xml_node _config;
|
||||
Genode::Timer &_timer;
|
||||
unsigned &_curr_time;
|
||||
|
||||
|
||||
/********************
|
||||
** Root_component **
|
||||
********************/
|
||||
|
||||
Session_component *_create_session(char const *args);
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Entrypoint &ep,
|
||||
Genode::Allocator &alloc,
|
||||
Uplink &uplink,
|
||||
Genode::Ram_session &buf_ram,
|
||||
Genode::Xml_node config,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
Genode::Region_map ®ion_map);
|
||||
};
|
||||
|
||||
#endif /* _COMPONENT_H_ */
|
102
repos/os/src/server/nic_dump/interface.cc
Normal file
102
repos/os/src/server/nic_dump/interface.cc
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* \brief A net interface in form of a signal-driven NIC-packet handler
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <interface.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ethernet.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Interface::_handle_eth(void *const eth_base,
|
||||
size_t const eth_size,
|
||||
Packet_descriptor const &pkt)
|
||||
{
|
||||
try {
|
||||
Ethernet_frame ð = *new (eth_base) Ethernet_frame(eth_size);
|
||||
Interface &remote = _remote.deref();
|
||||
unsigned new_time = _timer.curr_time().value / 1000;
|
||||
if (_log_time) {
|
||||
log("\033[33m(", remote._label, " <- ", _label, ")\033[0m ", eth,
|
||||
" \033[33mtime ", new_time, " (", new_time - _curr_time,
|
||||
")\033[0m");
|
||||
} else {
|
||||
log("\033[33m(", remote._label, " <- ", _label, ")\033[0m ", eth);
|
||||
}
|
||||
_curr_time = new_time;
|
||||
remote._send(eth, eth_size);
|
||||
}
|
||||
catch (Ethernet_frame::No_ethernet_frame) {
|
||||
error("invalid ethernet frame"); }
|
||||
|
||||
catch (Pointer<Interface>::Invalid) {
|
||||
error("no remote interface set"); }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_send(Ethernet_frame ð, Genode::size_t const size)
|
||||
{
|
||||
try {
|
||||
Packet_descriptor const pkt = _source().alloc_packet(size);
|
||||
char *content = _source().packet_content(pkt);
|
||||
Genode::memcpy((void *)content, (void *)ð, size);
|
||||
_source().submit_packet(pkt);
|
||||
}
|
||||
catch (Packet_stream_source::Packet_alloc_failed) {
|
||||
error("Failed to allocate packet"); }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_ready_to_submit()
|
||||
{
|
||||
while (_sink().packet_avail()) {
|
||||
|
||||
Packet_descriptor const pkt = _sink().get_packet();
|
||||
if (!pkt.size()) {
|
||||
continue; }
|
||||
|
||||
_handle_eth(_sink().packet_content(pkt), pkt.size(), pkt);
|
||||
|
||||
if (!_sink().ready_to_ack()) {
|
||||
error("ack state FULL");
|
||||
return;
|
||||
}
|
||||
_sink().acknowledge_packet(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Interface::_ready_to_ack()
|
||||
{
|
||||
while (_source().ack_avail()) {
|
||||
_source().release_packet(_source().get_acked_packet()); }
|
||||
}
|
||||
|
||||
|
||||
Interface::Interface(Entrypoint &ep,
|
||||
Interface_label label,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
bool log_time,
|
||||
Allocator &alloc)
|
||||
:
|
||||
_sink_ack (ep, *this, &Interface::_ack_avail),
|
||||
_sink_submit (ep, *this, &Interface::_ready_to_submit),
|
||||
_source_ack (ep, *this, &Interface::_ready_to_ack),
|
||||
_source_submit(ep, *this, &Interface::_packet_avail),
|
||||
_alloc(alloc), _label(label), _timer(timer), _curr_time(curr_time),
|
||||
_log_time(log_time)
|
||||
{ }
|
88
repos/os/src/server/nic_dump/interface.h
Normal file
88
repos/os/src/server/nic_dump/interface.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* \brief A net interface in form of a signal-driven NIC-packet handler
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _INTERFACE_H_
|
||||
#define _INTERFACE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <pointer.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <nic_session/nic_session.h>
|
||||
#include <util/string.h>
|
||||
#include <os/timer.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
using Packet_descriptor = ::Nic::Packet_descriptor;
|
||||
using Packet_stream_sink = ::Nic::Packet_stream_sink< ::Nic::Session::Policy>;
|
||||
using Packet_stream_source = ::Nic::Packet_stream_source< ::Nic::Session::Policy>;
|
||||
class Ethernet_frame;
|
||||
class Interface;
|
||||
using Interface_label = Genode::String<64>;
|
||||
}
|
||||
|
||||
|
||||
class Net::Interface
|
||||
{
|
||||
protected:
|
||||
|
||||
using Signal_handler = Genode::Signal_handler<Interface>;
|
||||
|
||||
Signal_handler _sink_ack;
|
||||
Signal_handler _sink_submit;
|
||||
Signal_handler _source_ack;
|
||||
Signal_handler _source_submit;
|
||||
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
Pointer<Interface> _remote;
|
||||
Interface_label _label;
|
||||
Genode::Timer &_timer;
|
||||
unsigned &_curr_time;
|
||||
bool _log_time;
|
||||
|
||||
void _send(Ethernet_frame ð, Genode::size_t const eth_size);
|
||||
|
||||
void _handle_eth(void *const eth_base,
|
||||
Genode::size_t const eth_size,
|
||||
Packet_descriptor const &pkt);
|
||||
|
||||
virtual Packet_stream_sink &_sink() = 0;
|
||||
|
||||
virtual Packet_stream_source &_source() = 0;
|
||||
|
||||
|
||||
/***********************************
|
||||
** Packet-stream signal handlers **
|
||||
***********************************/
|
||||
|
||||
void _ready_to_submit();
|
||||
void _ack_avail() { }
|
||||
void _ready_to_ack();
|
||||
void _packet_avail() { }
|
||||
|
||||
public:
|
||||
|
||||
Interface(Genode::Entrypoint &ep,
|
||||
Interface_label label,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
bool log_time,
|
||||
Genode::Allocator &alloc);
|
||||
|
||||
void remote(Interface &remote) { _remote.set(remote); }
|
||||
};
|
||||
|
||||
#endif /* _INTERFACE_H_ */
|
58
repos/os/src/server/nic_dump/main.cc
Normal file
58
repos/os/src/server/nic_dump/main.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* \brief Bump-in-the-wire component to dump NIC traffic info to the log
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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/heap.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <component.h>
|
||||
#include <uplink.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
class Main
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Attached_rom_dataspace _config;
|
||||
Timer::Connection _timer_connection;
|
||||
Genode::Timer _timer;
|
||||
unsigned _curr_time { 0 };
|
||||
Genode::Heap _heap;
|
||||
Uplink _uplink;
|
||||
Net::Root _root;
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env);
|
||||
};
|
||||
|
||||
|
||||
Main::Main(Env &env)
|
||||
:
|
||||
_config(env, "config"), _timer_connection(env),
|
||||
_timer(_timer_connection, env.ep()), _heap(&env.ram(), &env.rm()),
|
||||
_uplink(env, _config.xml(), _timer, _curr_time, _heap),
|
||||
_root(env.ep(), _heap, _uplink, env.ram(), _config.xml(), _timer,
|
||||
_curr_time, env.rm())
|
||||
{
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Env &env) { static Main main(env); }
|
55
repos/os/src/server/nic_dump/pointer.h
Normal file
55
repos/os/src/server/nic_dump/pointer.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* \brief Pointer that can be dereferenced only when valid
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _POINTER_H_
|
||||
#define _POINTER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/exception.h>
|
||||
|
||||
namespace Net { template <typename> class Pointer; }
|
||||
|
||||
template <typename T>
|
||||
class Net::Pointer
|
||||
{
|
||||
private:
|
||||
|
||||
T *_ptr;
|
||||
|
||||
public:
|
||||
|
||||
struct Valid : Genode::Exception { };
|
||||
struct Invalid : Genode::Exception { };
|
||||
|
||||
Pointer() : _ptr(nullptr) { }
|
||||
|
||||
T &deref() const
|
||||
{
|
||||
if (_ptr == nullptr) {
|
||||
throw Invalid(); }
|
||||
|
||||
return *_ptr;
|
||||
}
|
||||
|
||||
void set(T &ptr)
|
||||
{
|
||||
if (_ptr != nullptr) {
|
||||
throw Valid(); }
|
||||
|
||||
_ptr = &ptr;
|
||||
}
|
||||
|
||||
void unset() { _ptr = nullptr; }
|
||||
};
|
||||
|
||||
#endif /* _POINTER_H_ */
|
7
repos/os/src/server/nic_dump/target.mk
Normal file
7
repos/os/src/server/nic_dump/target.mk
Normal file
@ -0,0 +1,7 @@
|
||||
TARGET = nic_dump
|
||||
|
||||
LIBS += base net config timeout
|
||||
|
||||
SRC_CC += component.cc main.cc uplink.cc interface.cc
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
40
repos/os/src/server/nic_dump/uplink.cc
Normal file
40
repos/os/src/server/nic_dump/uplink.cc
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Uplink interface in form of a NIC session component
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 includes */
|
||||
#include <base/env.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
/* local includes */
|
||||
#include <uplink.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Net::Uplink::Uplink(Env &env,
|
||||
Xml_node config,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
Allocator &alloc)
|
||||
:
|
||||
Nic::Packet_allocator(&alloc),
|
||||
Nic::Connection(env, this, BUF_SIZE, BUF_SIZE),
|
||||
Interface(env.ep(), config.attribute_value("uplink", Interface_label()),
|
||||
timer, curr_time, config.attribute_value("time", false), alloc)
|
||||
{
|
||||
rx_channel()->sigh_ready_to_ack(_sink_ack);
|
||||
rx_channel()->sigh_packet_avail(_sink_submit);
|
||||
tx_channel()->sigh_ack_avail(_source_ack);
|
||||
tx_channel()->sigh_ready_to_submit(_source_submit);
|
||||
}
|
54
repos/os/src/server/nic_dump/uplink.h
Normal file
54
repos/os/src/server/nic_dump/uplink.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* \brief Uplink interface in form of a NIC session component
|
||||
* \author Martin Stein
|
||||
* \date 2017-03-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _UPLINK_H_
|
||||
#define _UPLINK_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
/* local includes */
|
||||
#include <interface.h>
|
||||
|
||||
namespace Net { class Uplink; }
|
||||
|
||||
class Net::Uplink : public Nic::Packet_allocator,
|
||||
public Nic::Connection,
|
||||
public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
PKT_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
|
||||
BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE,
|
||||
};
|
||||
|
||||
/********************
|
||||
** Net::Interface **
|
||||
********************/
|
||||
|
||||
Packet_stream_sink &_sink() { return *rx(); }
|
||||
Packet_stream_source &_source() { return *tx(); }
|
||||
|
||||
public:
|
||||
|
||||
Uplink(Genode::Env &env,
|
||||
Genode::Xml_node config,
|
||||
Genode::Timer &timer,
|
||||
unsigned &curr_time,
|
||||
Genode::Allocator &alloc);
|
||||
};
|
||||
|
||||
#endif /* _UPLINK_H_ */
|
Loading…
x
Reference in New Issue
Block a user