os/server: nic_dump

A tiny bump-in-the-wire tool for dumping NIC packet information.

Ref #2314
This commit is contained in:
Martin Stein 2017-03-08 15:40:18 +01:00 committed by Christian Helmuth
parent 995017b60c
commit 35cc020e9c
11 changed files with 999 additions and 0 deletions

View 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

View 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'.

View 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 &region_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 &region_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(); }
}

View 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 &region_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 &region_map);
};
#endif /* _COMPONENT_H_ */

View 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 &eth = *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 &eth, 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 *)&eth, 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)
{ }

View 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 &eth, 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_ */

View 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); }

View 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_ */

View 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)

View 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);
}

View 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_ */