genode-ehmry/src/nic_bus/bus.h

127 lines
2.3 KiB
C
Raw Permalink Normal View History

2019-04-14 18:56:47 +02:00
/*
* \brief Nic session bus
* \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 _NETWORK_STATE_H_
#define _NETWORK_STATE_H_
/* Genode includes */
#include <net/ethernet.h>
#include <base/session_label.h>
#include <util/xml_node.h>
namespace Nic_bus {
using namespace Net;
using namespace Genode;
2019-04-14 18:56:47 +02:00
template <typename T>
2019-04-14 18:56:47 +02:00
struct Bus;
}
2019-04-14 18:56:47 +02:00
template <typename T>
2019-04-14 18:56:47 +02:00
struct Nic_bus::Bus
{
2019-04-14 18:56:47 +02:00
struct Element;
2019-04-14 18:56:47 +02:00
/* static array of sessions on the bus */
enum { BUS_SIZE = 0xffU };
2019-04-14 18:56:47 +02:00
Element *_elements[BUS_SIZE] { nullptr };
2019-04-14 18:56:47 +02:00
static uint8_t _index(Mac_address const &mac) { return mac.addr[1]; };
void remove(Mac_address const mac) {
2019-04-14 18:56:47 +02:00
_elements[_index(mac)] = nullptr; }
2019-04-14 18:56:47 +02:00
2019-04-14 18:56:47 +02:00
Mac_address insert(Element &elem, char const *label)
2019-04-14 18:56:47 +02:00
{
/**
* Derive a MAC address using the FNV-1a algorithm.
*/
enum {
2019-04-14 18:56:47 +02:00
FNV_64_PRIME = 1099511628211U,
FNV_64_OFFSET = 14695981039346656037U,
2019-04-14 18:56:47 +02:00
};
2019-04-14 18:56:47 +02:00
uint64_t hash = FNV_64_OFFSET;
2019-04-14 18:56:47 +02:00
2019-04-14 18:56:47 +02:00
char const *p = label;
2019-04-14 18:56:47 +02:00
while (*p) {
hash ^= *p++;
2019-04-14 18:56:47 +02:00
hash *= FNV_64_PRIME;
2019-04-14 18:56:47 +02:00
}
for (;;) {
/* add the terminating zero */
2019-04-14 18:56:47 +02:00
hash *= FNV_64_PRIME;
2019-04-14 18:56:47 +02:00
2019-04-14 18:56:47 +02:00
uint8_t index = hash >> 32;
2019-04-14 18:56:47 +02:00
2019-04-14 18:56:47 +02:00
if (_elements[index] != nullptr)
2019-04-14 18:56:47 +02:00
continue;
/* hash until a free slot is found */
2019-04-14 18:56:47 +02:00
_elements[index] = &elem;
2019-04-14 18:56:47 +02:00
Mac_address mac;
mac.addr[0] = 0x02;
mac.addr[1] = index;
mac.addr[2] = hash >> 24;
mac.addr[3] = hash >> 16;
mac.addr[4] = hash >> 8;
mac.addr[5] = hash;
return mac;
}
}
2019-04-14 18:56:47 +02:00
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() { }
2019-04-14 18:56:47 +02:00
template<typename PROC>
void apply(Mac_address mac, PROC proc)
{
uint8_t const index = _index(mac);
2019-04-14 18:56:47 +02:00
Element *elem = _elements[index];
if (elem != nullptr) {
if (elem->mac == mac) {
proc(elem->obj);
2019-04-14 18:56:47 +02:00
}
}
}
template<typename PROC>
void apply_all(PROC proc)
{
for (auto i = 0U; i < BUS_SIZE; ++i) {
2019-04-14 18:56:47 +02:00
Element *elem = _elements[i];
if (elem != nullptr) {
proc(elem->obj);
2019-04-14 18:56:47 +02:00
}
}
}
};
#endif