130 lines
3.4 KiB
C++
130 lines
3.4 KiB
C++
/*
|
|
* \brief NIC connection wrapper for a more convenient interface
|
|
* \author Martin Stein
|
|
* \date 2018-04-16
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2018 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 _NIC_H_
|
|
#define _NIC_H_
|
|
|
|
/* Genode includes */
|
|
#include <nic_session/connection.h>
|
|
#include <nic/packet_allocator.h>
|
|
#include <net/ethernet.h>
|
|
|
|
namespace Genode {
|
|
|
|
class Env;
|
|
}
|
|
|
|
namespace Net {
|
|
|
|
struct Nic_handler;
|
|
class Nic;
|
|
|
|
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>;
|
|
}
|
|
|
|
|
|
struct Net::Nic_handler
|
|
{
|
|
virtual void handle_eth(Ethernet_frame ð,
|
|
Size_guard &size_guard) = 0;
|
|
|
|
virtual ~Nic_handler() { }
|
|
};
|
|
|
|
|
|
class Net::Nic
|
|
{
|
|
private:
|
|
|
|
using Signal_handler = Genode::Signal_handler<Nic>;
|
|
|
|
enum { PKT_SIZE = ::Nic::Packet_allocator::DEFAULT_PACKET_SIZE };
|
|
enum { BUF_SIZE = ::Nic::Session::QUEUE_SIZE * PKT_SIZE };
|
|
|
|
Genode::Env &_env;
|
|
Genode::Allocator &_alloc;
|
|
Nic_handler &_handler;
|
|
bool const &_verbose;
|
|
::Nic::Packet_allocator _pkt_alloc { &_alloc };
|
|
::Nic::Connection _nic { _env, &_pkt_alloc, BUF_SIZE, BUF_SIZE };
|
|
Signal_handler _sink_ack { _env.ep(), *this, &Nic::_ack_avail };
|
|
Signal_handler _sink_submit { _env.ep(), *this, &Nic::_ready_to_submit };
|
|
Signal_handler _source_ack { _env.ep(), *this, &Nic::_ready_to_ack };
|
|
Signal_handler _source_submit { _env.ep(), *this, &Nic::_packet_avail };
|
|
Mac_address const _mac { _nic.mac_address() };
|
|
|
|
Net::Packet_stream_sink &_sink() { return *_nic.rx(); }
|
|
Net::Packet_stream_source &_source() { return *_nic.tx(); }
|
|
|
|
|
|
/***********************************
|
|
** Packet-stream signal handlers **
|
|
***********************************/
|
|
|
|
void _ready_to_submit();
|
|
void _ack_avail() { }
|
|
void _ready_to_ack();
|
|
void _packet_avail() { }
|
|
|
|
public:
|
|
|
|
Nic(Genode::Env &env,
|
|
Genode::Allocator &alloc,
|
|
Nic_handler &handler,
|
|
bool const &verbose)
|
|
:
|
|
_env (env),
|
|
_alloc (alloc),
|
|
_handler (handler),
|
|
_verbose (verbose)
|
|
{
|
|
/* install packet stream signals */
|
|
_nic.rx_channel()->sigh_ready_to_ack(_sink_ack);
|
|
_nic.rx_channel()->sigh_packet_avail(_sink_submit);
|
|
_nic.tx_channel()->sigh_ack_avail(_source_ack);
|
|
_nic.tx_channel()->sigh_ready_to_submit(_source_submit);
|
|
}
|
|
|
|
template <typename FUNC>
|
|
void send(Genode::size_t pkt_size,
|
|
FUNC && write_to_pkt)
|
|
{
|
|
try {
|
|
Packet_descriptor pkt = _source().alloc_packet(pkt_size);
|
|
void *pkt_base = _source().packet_content(pkt);
|
|
Size_guard size_guard(pkt_size);
|
|
write_to_pkt(pkt_base, size_guard);
|
|
_source().submit_packet(pkt);
|
|
if (_verbose) {
|
|
Size_guard size_guard(pkt_size);
|
|
try { Genode::log("snd ", Ethernet_frame::cast_from(pkt_base, size_guard)); }
|
|
catch (Size_guard::Exceeded) { Genode::log("snd ?"); }
|
|
}
|
|
}
|
|
catch (Net::Packet_stream_source::Packet_alloc_failed) {
|
|
Genode::warning("failed to allocate packet"); }
|
|
}
|
|
|
|
|
|
/***************
|
|
** Accessors **
|
|
***************/
|
|
|
|
Mac_address const &mac() const { return _mac; }
|
|
};
|
|
|
|
|
|
#endif /* _NIC_H_ */
|