169 lines
4.6 KiB
C++
169 lines
4.6 KiB
C++
/*
|
|
* \brief Nic bus session component
|
|
* \author Emery Hemingway
|
|
* \date 2019-04-14
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2019 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 _SESSION_COMPONENT_H_
|
|
#define _SESSION_COMPONENT_H_
|
|
|
|
/* local includes */
|
|
#include "bus.h"
|
|
|
|
/* Genode includes */
|
|
#include <net/ethernet.h>
|
|
#include <net/size_guard.h>
|
|
#include <nic/component.h>
|
|
#include <base/heap.h>
|
|
#include <base/session_label.h>
|
|
|
|
namespace Nic_bus {
|
|
using namespace Net;
|
|
|
|
struct Tx_size { Genode::size_t value; };
|
|
struct Rx_size { Genode::size_t value; };
|
|
|
|
class Session_resources;
|
|
class Session_component;
|
|
|
|
typedef Bus<Session_component> Session_bus;
|
|
}
|
|
|
|
|
|
/**
|
|
* Base class to manage session quotas and allocations
|
|
*/
|
|
class Nic_bus::Session_resources
|
|
{
|
|
protected:
|
|
|
|
Genode::Ram_quota_guard _ram_guard;
|
|
Genode::Cap_quota_guard _cap_guard;
|
|
Genode::Constrained_ram_allocator _ram_alloc;
|
|
Genode::Attached_ram_dataspace _tx_ds, _rx_ds;
|
|
Genode::Heap _alloc;
|
|
Nic::Packet_allocator _rx_pkt_alloc { &_alloc };
|
|
|
|
Session_resources(Genode::Ram_allocator &ram,
|
|
Genode::Region_map ®ion_map,
|
|
Genode::Ram_quota ram_quota,
|
|
Genode::Cap_quota cap_quota,
|
|
Tx_size tx_size,
|
|
Rx_size rx_size)
|
|
:
|
|
_ram_guard(ram_quota), _cap_guard(cap_quota),
|
|
_ram_alloc(ram, _ram_guard, _cap_guard),
|
|
_tx_ds(_ram_alloc, region_map, tx_size.value),
|
|
_rx_ds(_ram_alloc, region_map, rx_size.value),
|
|
_alloc(_ram_alloc, region_map)
|
|
{ }
|
|
};
|
|
|
|
|
|
class Nic_bus::Session_component : private Session_resources,
|
|
public Nic::Session_rpc_object
|
|
{
|
|
private:
|
|
|
|
Session_bus::Element _bus_elem;
|
|
|
|
Genode::Session_label const _label;
|
|
|
|
Genode::Io_signal_handler<Session_component> _packet_handler;
|
|
|
|
Nic::Packet_stream_sink<::Nic::Session::Policy> &sink() {
|
|
return *_tx.sink(); }
|
|
|
|
Nic::Packet_stream_source<::Nic::Session::Policy> &source() {
|
|
return *_rx.source(); }
|
|
|
|
void _send(Ethernet_frame const ð, Genode::size_t const size)
|
|
{
|
|
while (source().ack_avail())
|
|
source().release_packet(source().get_acked_packet());
|
|
|
|
if (!source().ready_to_submit()) return;
|
|
/* drop the packet if the queue is congested */
|
|
|
|
Nic::Packet_descriptor pkt = source().alloc_packet(size);
|
|
void *content = source().packet_content(pkt);
|
|
Genode::memcpy(content, (void*)ð, size);
|
|
source().submit_packet(pkt);
|
|
}
|
|
|
|
void _handle_packet(Nic::Packet_descriptor const &pkt)
|
|
{
|
|
if (!pkt.size() || !sink().packet_valid(pkt)) return;
|
|
|
|
Size_guard size_guard(pkt.size());
|
|
Ethernet_frame const ð = Ethernet_frame::cast_from(
|
|
sink().packet_content(pkt), size_guard);
|
|
|
|
if (eth.src() != _bus_elem.mac) {
|
|
Genode::warning(
|
|
eth.src(), " is not the managed MAC adress, "
|
|
"dropping packet from ", _label);
|
|
return;
|
|
}
|
|
|
|
auto send = [&] (Session_component &other) { other._send(eth, pkt.size()); };
|
|
|
|
if (eth.dst().addr[0] & 1) {
|
|
/* multicast */
|
|
_bus_elem.bus.apply_all(send);
|
|
} else {
|
|
/* unicast */
|
|
_bus_elem.bus.apply(eth.dst(), send);
|
|
}
|
|
}
|
|
|
|
void _handle_packets()
|
|
{
|
|
while (sink().ready_to_ack() && sink().packet_avail()) {
|
|
_handle_packet(sink().peek_packet());
|
|
sink().acknowledge_packet(sink().get_packet());
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
Session_component(Genode::Entrypoint &ep,
|
|
Genode::Ram_allocator &ram,
|
|
Genode::Region_map ®ion_map,
|
|
Genode::Ram_quota ram_quota,
|
|
Genode::Cap_quota cap_quota,
|
|
Tx_size tx_size,
|
|
Rx_size rx_size,
|
|
Session_bus &bus,
|
|
Genode::Session_label const &label)
|
|
:
|
|
Session_resources(ram, region_map,
|
|
ram_quota, cap_quota,
|
|
tx_size, rx_size),
|
|
Nic::Session_rpc_object(region_map,
|
|
_tx_ds.cap(), _rx_ds.cap(),
|
|
&_rx_pkt_alloc, ep.rpc_ep()),
|
|
_bus_elem(bus, *this, label.string()), _label(label),
|
|
_packet_handler(ep, *this, &Session_component::_handle_packets)
|
|
{
|
|
_tx.sigh_packet_avail(_packet_handler);
|
|
_tx.sigh_ready_to_ack(_packet_handler);
|
|
}
|
|
|
|
Nic::Mac_address mac_address() override { return _bus_elem.mac; }
|
|
|
|
bool link_state() override { return true; }
|
|
|
|
void link_state_sigh(Genode::Signal_context_capability) override { }
|
|
|
|
};
|
|
|
|
#endif /* _SESSION_COMPONENT_H_ */
|