mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 10:01:57 +00:00
nic_dump: configurable packet print
The nic_dump uses a wrapper for all supported protocols that takes a packet and a verbosity configuration. The wrapper object can than be used as argument for a Genode log function and prints the packet's contents according to the given configuration. The configuration is a distinct class to enable the reuse of one instance for different packets. There are currently 4 possible configurations for each protocol: * NONE (no output for this protocol) * SHORT (only the protocol name) * COMPACT (the most important information densely packed) * COMPREHENSIVE (all header information of this protocol) Ref #2490
This commit is contained in:
parent
d63c40af3e
commit
71bd9a1f10
@ -16,6 +16,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ethernet.h>
|
||||
#include <packet_log.h>
|
||||
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
@ -28,18 +29,20 @@ void Interface::_handle_eth(void *const eth_base,
|
||||
try {
|
||||
Ethernet_frame ð = *new (eth_base) Ethernet_frame(eth_size);
|
||||
Interface &remote = _remote.deref();
|
||||
Packet_log_config log_cfg;
|
||||
|
||||
if (_log_time) {
|
||||
Genode::Duration const new_time = _timer.curr_time();
|
||||
unsigned long const new_time_ms = new_time.trunc_to_plain_us().value / 1000;
|
||||
unsigned long const old_time_ms = _curr_time.trunc_to_plain_us().value / 1000;
|
||||
|
||||
log("\033[33m(", remote._label, " <- ", _label, ")\033[0m ", eth,
|
||||
" \033[33mtime ", new_time_ms, " ms (Δ ",
|
||||
new_time_ms - old_time_ms, " ms)\033[0m");
|
||||
log("\033[33m(", remote._label, " <- ", _label, ")\033[0m ",
|
||||
packet_log(eth, log_cfg), " \033[33mtime ", new_time_ms,
|
||||
" ms (Δ ", new_time_ms - old_time_ms, " ms)\033[0m");
|
||||
|
||||
_curr_time = new_time;
|
||||
} else {
|
||||
log("\033[33m(", remote._label, " <- ", _label, ")\033[0m ", eth);
|
||||
log("\033[33m(", remote._label, " <- ", _label, ")\033[0m ", packet_log(eth, log_cfg));
|
||||
}
|
||||
remote._send(eth, eth_size);
|
||||
}
|
||||
|
290
repos/os/src/server/nic_dump/packet_log.cc
Normal file
290
repos/os/src/server/nic_dump/packet_log.cc
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* \brief Configurable print functionality for network packets
|
||||
* \author Martin Stein
|
||||
* \date 2017-09-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 <packet_log.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Net;
|
||||
|
||||
|
||||
template <>
|
||||
void Packet_log<Dhcp_packet>::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
/* print header attributes */
|
||||
switch (_cfg.dhcp) {
|
||||
case Packet_log_style::COMPREHENSIVE:
|
||||
|
||||
print(output, "\033[32mDHCP\033[0m");
|
||||
print(output, " op ", _pkt.op());
|
||||
print(output, " htyp ", (uint8_t)_pkt.htype());
|
||||
print(output, " hlen ", _pkt.hlen());
|
||||
print(output, " hps ", _pkt.hops());
|
||||
print(output, " xid ", _pkt.xid());
|
||||
print(output, " sec ", _pkt.secs());
|
||||
print(output, " flg ", Hex(_pkt.flags()));
|
||||
print(output, " ci ", _pkt.ciaddr());
|
||||
print(output, " yi ", _pkt.yiaddr());
|
||||
print(output, " si ", _pkt.siaddr());
|
||||
print(output, " gi ", _pkt.giaddr());
|
||||
print(output, " ch ", _pkt.client_mac());
|
||||
print(output, " srv ", _pkt.server_name());
|
||||
print(output, " file ", _pkt.file());
|
||||
print(output, " mag ", _pkt.magic_cookie());
|
||||
print(output, " opt");
|
||||
_pkt.for_each_option([&] (Dhcp_packet::Option &opt) {
|
||||
print(output, " ", opt);
|
||||
});
|
||||
break;
|
||||
|
||||
case Packet_log_style::COMPACT:
|
||||
|
||||
print(output, _pkt);
|
||||
break;
|
||||
|
||||
case Packet_log_style::SHORT:
|
||||
|
||||
print(output, "\033[32mDHCP\033[0m");
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dhcp_packet::Option::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
print(output, _code, ":", _len);
|
||||
if (!len()) {
|
||||
return;
|
||||
}
|
||||
print(output, ":");
|
||||
for (unsigned j = 0; j < len(); j++) {
|
||||
print(output, Hex(_value[j], Hex::OMIT_PREFIX, Hex::PAD));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void Packet_log<Arp_packet>::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
/* print header attributes */
|
||||
switch (_cfg.arp) {
|
||||
case Packet_log_style::COMPREHENSIVE:
|
||||
|
||||
print(output, "\033[32mARP\033[0m");
|
||||
print(output, " hw ", _pkt.hardware_address_type());
|
||||
print(output, " prot ", _pkt.protocol_address_type());
|
||||
print(output, " hwsz ", _pkt.hardware_address_size());
|
||||
print(output, " protsz ", _pkt.protocol_address_size());
|
||||
print(output, " op ", _pkt.opcode());
|
||||
|
||||
if (_pkt.ethernet_ipv4()) {
|
||||
|
||||
print(output, " srcmac ", _pkt.src_mac());
|
||||
print(output, " srcip ", _pkt.src_ip());
|
||||
print(output, " dstmac ", _pkt.dst_mac());
|
||||
print(output, " dstip ", _pkt.dst_ip());
|
||||
|
||||
} else {
|
||||
print(output, " ...");
|
||||
}
|
||||
break;
|
||||
|
||||
case Packet_log_style::COMPACT:
|
||||
|
||||
print(output, _pkt);
|
||||
break;
|
||||
|
||||
case Packet_log_style::SHORT:
|
||||
|
||||
print(output, "\033[32mARP\033[0m");
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void Packet_log<Ethernet_frame>::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
/* print header attributes */
|
||||
switch (_cfg.eth) {
|
||||
case Packet_log_style::COMPREHENSIVE:
|
||||
|
||||
print(output, "\033[32mETH\033[0m");
|
||||
print(output, " src ", _pkt.src());
|
||||
print(output, " dst ", _pkt.dst());
|
||||
print(output, " typ ", (Genode::uint16_t)_pkt.type());
|
||||
break;
|
||||
|
||||
case Packet_log_style::COMPACT:
|
||||
|
||||
print(output, _pkt);
|
||||
break;
|
||||
|
||||
case Packet_log_style::SHORT:
|
||||
|
||||
print(output, "\033[32mETH\033[0m");
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
/* print encapsulated packet */
|
||||
switch (_pkt.type()) {
|
||||
case Ethernet_frame::Type::ARP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Arp_packet const>(), _cfg));
|
||||
break;
|
||||
|
||||
case Ethernet_frame::Type::IPV4:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Ipv4_packet const>(), _cfg));
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void Packet_log<Ipv4_packet>::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
/* print header attributes */
|
||||
switch (_cfg.ipv4) {
|
||||
case Packet_log_style::COMPREHENSIVE:
|
||||
|
||||
print(output, "\033[32mIPV4\033[0m");
|
||||
print(output, " hdrlen ", _pkt.header_length());
|
||||
print(output, " ver ", _pkt.version());
|
||||
print(output, " dsrv ", _pkt.diff_service());
|
||||
print(output, " ecn ", _pkt.ecn());
|
||||
print(output, " len ", _pkt.total_length());
|
||||
print(output, " id ", _pkt.identification());
|
||||
print(output, " flg ", _pkt.flags());
|
||||
print(output, " frgoff ", _pkt.fragment_offset());
|
||||
print(output, " ttl ", _pkt.time_to_live());
|
||||
print(output, " prot ", (uint8_t)_pkt.protocol());
|
||||
print(output, " crc ", _pkt.checksum());
|
||||
print(output, " src ", _pkt.src());
|
||||
print(output, " dst ", _pkt.dst());
|
||||
break;
|
||||
|
||||
case Packet_log_style::COMPACT:
|
||||
|
||||
print(output, _pkt);
|
||||
break;
|
||||
|
||||
case Packet_log_style::SHORT:
|
||||
|
||||
print(output, "\033[32mIPV4\033[0m");
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
/* print encapsulated packet */
|
||||
switch (_pkt.protocol()) {
|
||||
case Ipv4_packet::Protocol::TCP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Tcp_packet const>(), _cfg));
|
||||
break;
|
||||
|
||||
case Ipv4_packet::Protocol::UDP:
|
||||
|
||||
print(output, " ", packet_log(*_pkt.data<Udp_packet const>(), _cfg));
|
||||
break;
|
||||
|
||||
default: ; }
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void Packet_log<Tcp_packet>::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
/* print header attributes */
|
||||
switch (_cfg.tcp) {
|
||||
case Packet_log_style::COMPREHENSIVE:
|
||||
|
||||
print(output, "\033[32mTCP\033[0m");
|
||||
print(output, " src ", _pkt.src_port());
|
||||
print(output, " dst ", _pkt.dst_port());
|
||||
print(output, " seqn ", _pkt.seq_nr());
|
||||
print(output, " ackn ", _pkt.ack_nr());
|
||||
print(output, " doff ", _pkt.data_offset());
|
||||
print(output, " flg ", _pkt.flags());
|
||||
print(output, " winsz ", _pkt.window_size());
|
||||
print(output, " crc ", _pkt.checksum());
|
||||
print(output, " urgp ", _pkt.urgent_ptr());
|
||||
break;
|
||||
|
||||
case Packet_log_style::COMPACT:
|
||||
|
||||
print(output, _pkt);
|
||||
break;
|
||||
|
||||
case Packet_log_style::SHORT:
|
||||
|
||||
print(output, "\033[32mTCP\033[0m");
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void Packet_log<Udp_packet>::print(Output &output) const
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
/* print header attributes */
|
||||
switch (_cfg.udp) {
|
||||
case Packet_log_style::COMPREHENSIVE:
|
||||
|
||||
print(output, "\033[32mUDP\033[0m");
|
||||
print(output, " src ", _pkt.src_port());
|
||||
print(output, " dst ", _pkt.dst_port());
|
||||
print(output, " len ", _pkt.length());
|
||||
print(output, " crc ", _pkt.checksum());
|
||||
break;
|
||||
|
||||
case Packet_log_style::COMPACT:
|
||||
|
||||
print(output, _pkt);
|
||||
break;
|
||||
|
||||
case Packet_log_style::SHORT:
|
||||
|
||||
print(output, "\033[32mUDP\033[0m");
|
||||
break;
|
||||
|
||||
default: ;
|
||||
}
|
||||
/* print encapsulated packet */
|
||||
if (Dhcp_packet::is_dhcp(&_pkt)) {
|
||||
print(output, " ", packet_log(*_pkt.data<Dhcp_packet const>(), _cfg));
|
||||
}
|
||||
}
|
119
repos/os/src/server/nic_dump/packet_log.h
Normal file
119
repos/os/src/server/nic_dump/packet_log.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* \brief Configurable print functionality for network packets
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2017-09-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 _PACKET_LOG_H_
|
||||
#define _PACKET_LOG_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
#include <net/arp.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/dhcp.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/ipv4.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
enum class Packet_log_style : Genode::uint8_t
|
||||
{
|
||||
NONE, SHORT, COMPACT, COMPREHENSIVE,
|
||||
};
|
||||
|
||||
struct Packet_log_config;
|
||||
|
||||
template <typename PKT>
|
||||
struct Packet_log;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configuration for the print functionality of network packets
|
||||
*/
|
||||
struct Net::Packet_log_config
|
||||
{
|
||||
using Style = Packet_log_style;
|
||||
|
||||
Style eth, arp, ipv4, dhcp, udp, tcp;
|
||||
|
||||
Packet_log_config(Style def = Style::COMPACT)
|
||||
: eth(def), arp(def), ipv4(def), dhcp(def), udp(def), tcp(def) { }
|
||||
|
||||
Packet_log_config(Style eth,
|
||||
Style arp,
|
||||
Style ipv4,
|
||||
Style dhcp,
|
||||
Style udp,
|
||||
Style tcp)
|
||||
: eth(eth), arp(arp), ipv4(ipv4), dhcp(dhcp), udp(udp), tcp(tcp) { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for network packets to configure their print functionality
|
||||
*/
|
||||
template <typename PKT>
|
||||
class Net::Packet_log
|
||||
{
|
||||
private:
|
||||
|
||||
PKT const &_pkt;
|
||||
Packet_log_config const &_cfg;
|
||||
|
||||
public:
|
||||
|
||||
Packet_log(PKT const &pkt, Packet_log_config const &cfg)
|
||||
: _pkt(pkt), _cfg(cfg) { }
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
};
|
||||
|
||||
|
||||
namespace Net {
|
||||
|
||||
/* getting an instances via a function enables template-arg deduction */
|
||||
template <typename PKT>
|
||||
Packet_log<PKT> packet_log(PKT const &pkt, Packet_log_config const &cfg) {
|
||||
return Packet_log<PKT>(pkt, cfg); }
|
||||
|
||||
|
||||
/************************************************************
|
||||
** Packet log specializations for all supported protocols **
|
||||
************************************************************/
|
||||
|
||||
template <>
|
||||
void Packet_log<Arp_packet>::print(Genode::Output &output) const;
|
||||
|
||||
template <>
|
||||
void Packet_log<Ethernet_frame>::print(Genode::Output &output) const;
|
||||
|
||||
template <>
|
||||
void Packet_log<Dhcp_packet>::print(Genode::Output &output) const;
|
||||
|
||||
template <>
|
||||
void Packet_log<Ipv4_packet>::print(Genode::Output &output) const;
|
||||
|
||||
template <>
|
||||
void Packet_log<Tcp_packet>::print(Genode::Output &output) const;
|
||||
|
||||
template <>
|
||||
void Packet_log<Udp_packet>::print(Genode::Output &output) const;
|
||||
}
|
||||
|
||||
#endif /* _PACKET_LOG_H_ */
|
@ -2,6 +2,6 @@ TARGET = nic_dump
|
||||
|
||||
LIBS += base net
|
||||
|
||||
SRC_CC += component.cc main.cc uplink.cc interface.cc
|
||||
SRC_CC += component.cc main.cc packet_log.cc uplink.cc interface.cc
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
||||
|
Loading…
x
Reference in New Issue
Block a user