Refactor nic_bus service

This commit is contained in:
Ehmry - 2019-04-14 18:56:47 +02:00
parent 3782a39cf3
commit d0f73b0b6e
3 changed files with 68 additions and 63 deletions

View File

@ -23,56 +23,54 @@ namespace Nic_bus {
using namespace Net;
using namespace Genode;
template <typename T>
struct Bus;
class Session_component;
Mac_address mac_address(Session_component &session);
}
template <typename T>
struct Nic_bus::Bus
{
struct Element;
/* static array of sessions on the bus */
enum { BUS_SIZE = 0xffU };
Session_component *_sessions[BUS_SIZE] { nullptr };
Element *_elements[BUS_SIZE] { nullptr };
static uint8_t _index(Mac_address const &mac) { return mac.addr[1]; };
Bus() { }
void remove(Mac_address const mac) {
_sessions[_index(mac)] = nullptr; }
_elements[_index(mac)] = nullptr; }
Mac_address insert(Session_label const &label,
Session_component &session)
Mac_address insert(Element &elem, char const *label)
{
/**
* Derive a MAC address using the FNV-1a algorithm.
*/
enum {
FNV_32_PRIME = 16777619U,
FNV_32_OFFSET = 2166136261U,
FNV_64_PRIME = 1099511628211U,
FNV_64_OFFSET = 14695981039346656037U,
};
uint32_t hash = FNV_32_OFFSET;
uint64_t hash = FNV_64_OFFSET;
char const *p = label.string();
char const *p = label;
while (*p) {
hash ^= *p++;
hash *= FNV_32_PRIME;
hash *= FNV_64_PRIME;
}
for (;;) {
/* add the terminating zero */
hash *= FNV_32_PRIME;
hash *= FNV_64_PRIME;
uint8_t index = hash >> 24;
uint8_t index = hash >> 32;
if (_sessions[index] != nullptr)
if (_elements[index] != nullptr)
continue;
/* hash until a free slot is found */
_sessions[index] = &session;
_elements[index] = &elem;
Mac_address mac;
mac.addr[0] = 0x02;
@ -86,14 +84,29 @@ struct Nic_bus::Bus
}
}
struct Element
{
Bus &bus;
T &obj;
Mac_address const mac;
Element(Bus &b, T &o, char const *label)
: bus(b), obj(o), mac(bus.insert(*this, label)) { }
~Element() { bus.remove(mac); }
};
Bus() { }
template<typename PROC>
void apply(Mac_address mac, PROC proc)
{
uint8_t const index = _index(mac);
Session_component *session = _sessions[index];
if (session != nullptr) {
if (mac_address(*session) == mac) {
proc(*session);
Element *elem = _elements[index];
if (elem != nullptr) {
if (elem->mac == mac) {
proc(elem->obj);
}
}
}
@ -102,9 +115,9 @@ struct Nic_bus::Bus
void apply_all(PROC proc)
{
for (auto i = 0U; i < BUS_SIZE; ++i) {
Session_component *session = _sessions[i];
if (session != nullptr) {
proc(*session);
Element *elem = _elements[i];
if (elem != nullptr) {
proc(elem->obj);
}
}
}

View File

@ -25,10 +25,6 @@ namespace Nic_bus {
using namespace Genode;
class Root;
struct Main;
/* used by the bus */
Mac_address mac_address(Session_component &session) {
return session.mac_address(); }
}
@ -40,7 +36,7 @@ class Nic_bus::Root : public Genode::Root_component<Nic_bus::Session_component>
Attached_rom_dataspace _config_rom { _env, "config" };
Bus _bus { };
Session_bus _bus { };
protected:
@ -67,10 +63,8 @@ class Nic_bus::Root : public Genode::Root_component<Nic_bus::Session_component>
Root(Genode::Env &env,
Genode::Allocator &md_alloc)
:
Genode::Root_component<Nic_bus::Session_component>(
env.ep(), md_alloc),
_env(env)
: Genode::Root_component<Nic_bus::Session_component>(env.ep(), md_alloc),
_env(env)
{ }
};
@ -81,9 +75,8 @@ struct Nic_bus::Main
Nic_bus::Root _root;
Main(Genode::Env &env)
:
_sliced_heap(env.ram(), env.rm()),
_root(env, _sliced_heap)
: _sliced_heap(env.ram(), env.rm()),
_root(env, _sliced_heap)
{
env.parent().announce(env.ep().manage(_root));
}

View File

@ -32,6 +32,8 @@ namespace Nic_bus {
class Session_resources;
class Session_component;
typedef Bus<Session_component> Session_bus;
}
@ -70,14 +72,12 @@ class Nic_bus::Session_component : private Session_resources,
{
private:
Bus &_bus;
Session_bus::Element _bus_elem;
Genode::Session_label const _label;
Genode::Io_signal_handler<Session_component> _packet_handler;
Mac_address const _mac { _bus.insert(_label, *this) };
Nic::Packet_stream_sink<::Nic::Session::Policy> &sink() {
return *_tx.sink(); }
@ -89,31 +89,15 @@ class Nic_bus::Session_component : private Session_resources,
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*)&eth, size);
source().submit_packet(pkt);
}
void _handle_ethernet(Ethernet_frame const &eth,
Genode::size_t const size)
{
if (eth.src() != _mac) {
Genode::warning(
eth.src(), " is not the managed MAC adress, "
"dropping packet from ", _label);
return;
}
auto send = [&] (Session_component &other) { other._send(eth, size); };
if (eth.dst().addr[0] & 1) {
_bus.apply_all(send);
} else {
_bus.apply(eth.dst(), send);
}
}
void _handle_packet(Nic::Packet_descriptor const &pkt)
{
if (!pkt.size() || !sink().packet_valid(pkt)) return;
@ -122,7 +106,22 @@ class Nic_bus::Session_component : private Session_resources,
Ethernet_frame const &eth = Ethernet_frame::cast_from(
sink().packet_content(pkt), size_guard);
_handle_ethernet(eth, pkt.size());
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()
@ -142,7 +141,7 @@ class Nic_bus::Session_component : private Session_resources,
Genode::Cap_quota cap_quota,
Tx_size tx_size,
Rx_size rx_size,
Bus &bus,
Session_bus &bus,
Genode::Session_label const &label)
:
Session_resources(ram, region_map,
@ -151,14 +150,14 @@ class Nic_bus::Session_component : private Session_resources,
Nic::Session_rpc_object(region_map,
_tx_ds.cap(), _rx_ds.cap(),
&_rx_pkt_alloc, ep.rpc_ep()),
_bus(bus), _label(label),
_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 _mac; }
Nic::Mac_address mac_address() override { return _bus_elem.mac; }
bool link_state() override { return true; }