Refactor nic_bus service
This commit is contained in:
parent
3782a39cf3
commit
d0f73b0b6e
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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*)ð, size);
|
||||
source().submit_packet(pkt);
|
||||
}
|
||||
|
||||
void _handle_ethernet(Ethernet_frame const ð,
|
||||
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 ð = 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; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue