Add nic_bus service
This commit is contained in:
parent
201e9e97fa
commit
d23bd2c562
4
src/server/nic_bus/README
Normal file
4
src/server/nic_bus/README
Normal file
|
@ -0,0 +1,4 @@
|
|||
The nic_bus server switches packets between sessions using Ethernet headers.
|
||||
Sessions may only send and receive packets with MAC addresses assigned by
|
||||
the bus. For this reason it does not support attachment to ethernet hubs or
|
||||
switches and is therefore not intended for use with harware interfaces.
|
16
src/server/nic_bus/Tupfile
Normal file
16
src/server/nic_bus/Tupfile
Normal file
|
@ -0,0 +1,16 @@
|
|||
TARGET_NAME = nic_bus
|
||||
include_rules
|
||||
|
||||
PKGS = genode-os genode-prg
|
||||
|
||||
: foreach *.cc |> ^ CC %o^ \
|
||||
$(CC) -std=gnu++11 `pkg-config --cflags $(PKGS)` -c %f -o %o |> %B.o {objs}
|
||||
|
||||
: {objs} |> ^o LD %o^ \
|
||||
$(LD) `pkg-config --libs $(PKGS)` %f -o %o |> %d {binary}
|
||||
|
||||
: {binary} |> !collect_bin |>
|
||||
: |> !bin |>
|
||||
|
||||
PKG_DEPENDS += _/src/$(TARGET_NAME)
|
||||
: runtime |> !collect_pkg_runtime |>
|
113
src/server/nic_bus/bus.h
Normal file
113
src/server/nic_bus/bus.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* \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;
|
||||
|
||||
struct Bus;
|
||||
class Session_component;
|
||||
|
||||
Mac_address mac_address(Session_component &session);
|
||||
}
|
||||
|
||||
|
||||
struct Nic_bus::Bus
|
||||
{
|
||||
/* static array of sessions on the bus */
|
||||
enum { BUS_SIZE = 0xffU };
|
||||
Session_component *_sessions[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; }
|
||||
|
||||
Mac_address insert(Session_label const &label,
|
||||
Session_component &session)
|
||||
{
|
||||
/**
|
||||
* Derive a MAC address using the FNV-1a algorithm.
|
||||
*/
|
||||
enum {
|
||||
FNV_32_PRIME = 16777619U,
|
||||
FNV_32_OFFSET = 2166136261U,
|
||||
};
|
||||
|
||||
uint32_t hash = FNV_32_OFFSET;
|
||||
|
||||
char const *p = label.string();
|
||||
while (*p) {
|
||||
hash ^= *p++;
|
||||
hash *= FNV_32_PRIME;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* add the terminating zero */
|
||||
hash *= FNV_32_PRIME;
|
||||
|
||||
uint8_t index = hash >> 24;
|
||||
|
||||
if (_sessions[index] != nullptr)
|
||||
continue;
|
||||
/* hash until a free slot is found */
|
||||
|
||||
_sessions[index] = &session;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PROC>
|
||||
void apply_all(PROC proc)
|
||||
{
|
||||
for (auto i = 0U; i < BUS_SIZE; ++i) {
|
||||
Session_component *session = _sessions[i];
|
||||
if (session != nullptr) {
|
||||
proc(*session);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
93
src/server/nic_bus/main.cc
Normal file
93
src/server/nic_bus/main.cc
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* \brief Nic bus service
|
||||
* \author Emery Hemingway
|
||||
* \date 2019-04-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include "session_component.h"
|
||||
|
||||
/* Genode */
|
||||
#include <root/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <base/component.h>
|
||||
|
||||
namespace Nic_bus {
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
class Root;
|
||||
struct Main;
|
||||
|
||||
/* used by the bus */
|
||||
Mac_address mac_address(Session_component &session) {
|
||||
return session.mac_address(); }
|
||||
}
|
||||
|
||||
|
||||
class Nic_bus::Root : public Genode::Root_component<Nic_bus::Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
|
||||
Bus _bus { };
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
_config_rom.update();
|
||||
|
||||
Session_label label { label_from_args(args) };
|
||||
Session_policy policy { label, _config_rom.xml() };
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_env.ep(), _env.ram(), _env.rm(),
|
||||
ram_quota_from_args(args),
|
||||
cap_quota_from_args(args),
|
||||
Tx_size{Arg_string::find_arg(args, "tx_buf_size").ulong_value(0)},
|
||||
Rx_size{Arg_string::find_arg(args, "rx_buf_size").ulong_value(0)},
|
||||
_bus,
|
||||
label);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Env &env,
|
||||
Genode::Allocator &md_alloc)
|
||||
:
|
||||
Genode::Root_component<Nic_bus::Session_component>(
|
||||
env.ep(), md_alloc),
|
||||
_env(env)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
struct Nic_bus::Main
|
||||
{
|
||||
Sliced_heap _sliced_heap;
|
||||
Nic_bus::Root _root;
|
||||
|
||||
Main(Genode::Env &env)
|
||||
:
|
||||
_sliced_heap(env.ram(), env.rm()),
|
||||
_root(env, _sliced_heap)
|
||||
{
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Nic_bus::Main inst(env); }
|
5
src/server/nic_bus/runtime
Normal file
5
src/server/nic_bus/runtime
Normal file
|
@ -0,0 +1,5 @@
|
|||
<runtime ram="4M" caps="96" binary="nic_bus">
|
||||
<provides> <nic/> </provides>
|
||||
<content> <rom label="nic_bus"/> </content>
|
||||
<config> <default-policy/></config>
|
||||
</runtime>
|
169
src/server/nic_bus/session_component.h
Normal file
169
src/server/nic_bus/session_component.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* \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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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:
|
||||
|
||||
Bus &_bus;
|
||||
|
||||
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(); }
|
||||
|
||||
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());
|
||||
|
||||
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;
|
||||
|
||||
Size_guard size_guard(pkt.size());
|
||||
Ethernet_frame const ð = Ethernet_frame::cast_from(
|
||||
sink().packet_content(pkt), size_guard);
|
||||
|
||||
_handle_ethernet(eth, pkt.size());
|
||||
}
|
||||
|
||||
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,
|
||||
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(bus), _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; }
|
||||
|
||||
bool link_state() override { return true; }
|
||||
|
||||
void link_state_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SESSION_COMPONENT_H_ */
|
Loading…
Reference in New Issue
Block a user