nic_bridge: transition to the new base API

* use Component::* instead of Server::*
* do not use old printf format anymore
* do not use old Genode::env()->heap() anymore
* avoid pointers where possible, and use references instead
* throw away the thread-safe variants of list and AVL tree,
  nic_bridge became single-threaded in the past
* introduce Ram_session_guard instead of Allocator_guard

Issue #1987
This commit is contained in:
Stefan Kalkowski 2016-06-03 16:21:45 +02:00 committed by Christian Helmuth
parent d9f33f7577
commit a145e6ad70
20 changed files with 480 additions and 536 deletions

View File

@ -66,6 +66,7 @@ append_if $use_nic_bridge config {
<start name="nic_bridge">
<resource name="RAM" quantum="2M"/>
<provides><service name="Nic"/></provides>
<config/>
<route>
<service name="Nic"> }
append_if [expr $use_nic_bridge && ([have_spec omap4] || [have_spec arndale])] config {

View File

@ -16,6 +16,7 @@
/* Genode includes */
#include <base/exception.h>
#include <base/output.h>
#include <util/string.h>
#include <util/endian.h>
@ -43,7 +44,21 @@ class Net::Ethernet_frame
ADDR_LEN = 6, /* MAC address length in bytes */
};
typedef Network_address<ADDR_LEN> Mac_address;
struct Mac_address : Network_address<ADDR_LEN>
{
using Network_address<ADDR_LEN>::Network_address;
void print(Genode::Output &output) const
{
using namespace Genode;
for (unsigned i = 0; i < ADDR_LEN; i++) {
Genode::print(output, Hex(addr[i], Hex::OMIT_PREFIX,
Hex::PAD));
if (i < ADDR_LEN-1) output.out_char(':');
}
}
};
static const Mac_address BROADCAST; /* broadcast address */

View File

@ -16,6 +16,7 @@
/* Genode */
#include <base/exception.h>
#include <base/output.h>
#include <util/string.h>
#include <util/endian.h>
@ -53,7 +54,18 @@ class Net::Ipv4_packet
ADDR_LEN = 4, /* Ip address length in bytes */
};
typedef Network_address<ADDR_LEN> Ipv4_address;
struct Ipv4_address : Network_address<ADDR_LEN>
{
using Network_address<ADDR_LEN>::Network_address;
void print(Genode::Output &output) const
{
for (unsigned i = 0; i < ADDR_LEN; i++) {
Genode::print(output, (unsigned) addr[i]);
if (i < ADDR_LEN-1) output.out_char('.');
}
}
};
static const Ipv4_address CURRENT; /* current network */
static const Ipv4_address BROADCAST; /* broadcast address */

View File

@ -25,49 +25,47 @@ namespace Net { template <unsigned> class Network_address; }
* Generic form of a network address.
*/
template <unsigned LEN>
class Net::Network_address
struct Net::Network_address
{
public:
Genode::uint8_t addr[LEN];
Genode::uint8_t addr[LEN];
/******************
** Constructors **
******************/
/******************
** Constructors **
******************/
Network_address(Genode::uint8_t value = 0) {
Genode::memset(&addr, value, LEN); }
Network_address(Genode::uint8_t value = 0) {
Genode::memset(&addr, value, LEN); }
Network_address(void *src) {
Genode::memcpy(&addr, src, LEN); }
Network_address(void *src) {
Genode::memcpy(&addr, src, LEN); }
/*********************
** Helper methods **
*********************/
/*********************
** Helper methods **
*********************/
void copy(void *dst) { Genode::memcpy(dst, addr, LEN); }
void copy(void *dst) { Genode::memcpy(dst, addr, LEN); }
/***************
** Operators **
***************/
/***************
** Operators **
***************/
bool operator==(const Network_address &other) const {
bool operator==(const Network_address &other) const {
/*
* We compare from lowest address segment to highest
* one, because in a local context, the higher segments
* of two addresses normally don't distinguish.
* (e.g. in an IPv4 local subnet)
*/
for (int i = LEN-1; i >= 0; --i) {
if (addr[i] != other.addr[i])
return false;
}
return true;
/*
* We compare from lowest address segment to highest
* one, because in a local context, the higher segments
* of two addresses normally don't distinguish.
* (e.g. in an IPv4 local subnet)
*/
for (int i = LEN-1; i >= 0; --i) {
if (addr[i] != other.addr[i])
return false;
}
return true;
}
};
#endif /* _NET__NETADDRESS_H_ */

View File

@ -33,71 +33,72 @@ namespace Net {
* a list and/or avl-tree, whereby the network-address (MAC or IP)
* acts as a key.
*/
template <unsigned LEN>
class Address_node : public Genode::Avl_node<Address_node<LEN> >,
public Genode::List<Address_node<LEN> >::Element
{
public:
template <typename ADDRESS> class Address_node;
typedef Network_address<LEN> Address;
private:
Address _addr; /* MAC or IP address */
Session_component *_component; /* client's component */
public:
/**
* Constructor
*
* \param addr Network address acting as sorting criteria.
* \param component pointer to client's session component.
*/
Address_node(Address addr, Session_component *component)
: _addr(addr), _component(component) { }
/***************
** Accessors **
***************/
Address addr() { return _addr; }
Session_component *component() { return _component; }
/************************
** Avl node interface **
************************/
bool higher(Address_node *c)
{
using namespace Genode;
return (memcmp(&c->_addr.addr, &_addr.addr,
sizeof(_addr.addr)) > 0);
}
/**
* Find by address
*/
Address_node *find_by_address(Address addr)
{
using namespace Genode;
if (addr == _addr)
return this;
bool side = memcmp(&addr.addr, _addr.addr,
sizeof(_addr.addr)) > 0;
Address_node *c = Avl_node<Address_node>::child(side);
return c ? c->find_by_address(addr) : 0;
}
};
typedef Address_node<Ipv4_packet::ADDR_LEN> Ipv4_address_node;
typedef Address_node<Ethernet_frame::ADDR_LEN> Mac_address_node;
using Ipv4_address_node = Address_node<Ipv4_packet::Ipv4_address>;
using Mac_address_node = Address_node<Ethernet_frame::Mac_address>;
}
template <typename ADDRESS>
class Net::Address_node : public Genode::Avl_node<Address_node<ADDRESS> >,
public Genode::List<Address_node<ADDRESS> >::Element
{
private:
ADDRESS _addr; /* MAC or IP address */
Session_component &_component; /* client's component */
public:
using Address = ADDRESS;
/**
* Constructor
*
* \param component reference to client's session component.
*/
Address_node(Session_component &component,
Address addr = Address())
: _addr(addr), _component(component) { }
/***************
** Accessors **
***************/
void addr(Address addr) { _addr = addr; }
Address addr() { return _addr; }
Session_component &component() { return _component; }
/************************
** Avl node interface **
************************/
bool higher(Address_node *c)
{
using namespace Genode;
return (memcmp(&c->_addr.addr, &_addr.addr,
sizeof(_addr.addr)) > 0);
}
/**
* Find by address
*/
Address_node *find_by_address(Address addr)
{
using namespace Genode;
if (addr == _addr)
return this;
bool side = memcmp(&addr.addr, _addr.addr,
sizeof(_addr.addr)) > 0;
Address_node *c = Avl_node<Address_node>::child(side);
return c ? c->find_by_address(addr) : 0;
}
};
#endif /* _ADDRESS_NODE_H_ */

View File

@ -1,47 +0,0 @@
/*
* \brief Thread-safe Avl_tree implementation
* \author Stefan Kalkowski
* \date 2010-08-20
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _AVL_SAFE_H_
#define _AVL_SAFE_H_
/* Genode */
#include <base/lock.h>
#include <base/lock_guard.h>
#include <util/avl_tree.h>
/**
* Lock-guarded avl-tree implementation.
*/
template <typename NT>
class Avl_tree_safe : public Genode::Avl_tree<NT>
{
private:
Genode::Lock _lock;
public:
void insert(Genode::Avl_node<NT> *node)
{
Genode::Lock::Guard lock_guard(_lock);
Genode::Avl_tree<NT>::insert(node);
}
void remove(Genode::Avl_node<NT> *node)
{
Genode::Lock::Guard lock_guard(_lock);
Genode::Avl_tree<NT>::remove(node);
}
};
#endif /* _AVL_SAFE_H_ */

View File

@ -20,9 +20,6 @@
using namespace Net;
static const int verbose = 1;
bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
{
Arp_packet *arp =
@ -41,7 +38,7 @@ bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
if (arp->src_ip() == arp->dst_ip())
return false;
Ipv4_address_node *node = vlan().ip_tree()->first();
Ipv4_address_node *node = vlan().ip_tree.first();
if (node)
node = node->find_by_address(arp->dst_ip());
if (!node) {
@ -77,11 +74,11 @@ bool Session_component::handle_ip(Ethernet_frame *eth, Genode::size_t size)
void Session_component::finalize_packet(Ethernet_frame *eth,
Genode::size_t size)
{
Mac_address_node *node = vlan().mac_tree()->first();
Mac_address_node *node = vlan().mac_tree.first();
if (node)
node = node->find_by_address(eth->dst());
if (node)
node->component()->send(eth, size);
node->component().send(eth, size);
else {
/* set our MAC as sender */
eth->src(_nic.mac());
@ -90,12 +87,12 @@ void Session_component::finalize_packet(Ethernet_frame *eth,
}
void Session_component::_free_ipv4_node()
void Session_component::_unset_ipv4_node()
{
if (_ipv4_node) {
vlan().ip_tree()->remove(_ipv4_node);
destroy(this->guarded_allocator(), _ipv4_node);
}
Ipv4_address_node * first = vlan().ip_tree.first();
if (!first) return;
if (first->find_by_address(_ipv4_node.addr()))
vlan().ip_tree.remove(&_ipv4_node);
}
@ -104,48 +101,43 @@ bool Session_component::link_state() { return _nic.link_state(); }
void Session_component::set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr)
{
_free_ipv4_node();
_ipv4_node = new (this->guarded_allocator())
Ipv4_address_node(ip_addr, this);
vlan().ip_tree()->insert(_ipv4_node);
_unset_ipv4_node();
_ipv4_node.addr(ip_addr);
vlan().ip_tree.insert(&_ipv4_node);
}
Session_component::Session_component(Genode::Allocator *allocator,
Session_component::Session_component(Genode::Ram_session &ram,
Genode::Region_map &rm,
Genode::Entrypoint &ep,
Genode::size_t amount,
Genode::size_t tx_buf_size,
Genode::size_t rx_buf_size,
Ethernet_frame::Mac_address vmac,
Server::Entrypoint &ep,
Net::Nic &nic,
char *ip_addr)
: Guarded_range_allocator(allocator, amount),
Tx_rx_communication_buffers(tx_buf_size, rx_buf_size),
Session_rpc_object(Tx_rx_communication_buffers::tx_ds(),
Tx_rx_communication_buffers::rx_ds(),
this->range_allocator(), ep.rpc_ep()),
: Stream_allocator(ram, rm, amount),
Stream_dataspaces(ram, tx_buf_size, rx_buf_size),
Session_rpc_object(Stream_dataspaces::tx_ds,
Stream_dataspaces::rx_ds,
Stream_allocator::range_allocator(), ep.rpc_ep()),
Packet_handler(ep, nic.vlan()),
_mac_node(vmac, this),
_ipv4_node(0),
_mac_node(*this, vmac),
_ipv4_node(*this),
_nic(nic)
{
vlan().mac_tree()->insert(&_mac_node);
vlan().mac_list()->insert(&_mac_node);
vlan().mac_tree.insert(&_mac_node);
vlan().mac_list.insert(&_mac_node);
/* static ip parsing */
if (ip_addr != 0 && Genode::strlen(ip_addr)) {
Ipv4_packet::Ipv4_address ip = Ipv4_packet::ip_from_string(ip_addr);
if (ip == Ipv4_packet::Ipv4_address()) {
PWRN("Empty or error ip address. Skipped.");
Genode::warning("Empty or error ip address. Skipped.");
} else {
set_ipv4_address(ip);
if (verbose)
PLOG("vmac=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d",
vmac.addr[0], vmac.addr[1], vmac.addr[2],
vmac.addr[3], vmac.addr[4], vmac.addr[5],
ip.addr[0], ip.addr[1], ip.addr[2], ip.addr[3]);
Genode::log("vmac = ", vmac, " ip = ", ip);
}
}
@ -157,7 +149,7 @@ Session_component::Session_component(Genode::Allocator *allocator,
Session_component::~Session_component() {
vlan().mac_tree()->remove(&_mac_node);
vlan().mac_list()->remove(&_mac_node);
_free_ipv4_node();
vlan().mac_tree.remove(&_mac_node);
vlan().mac_list.remove(&_mac_node);
_unset_ipv4_node();
}

View File

@ -15,250 +15,225 @@
#define _COMPONENT_H_
/* Genode */
#include <base/lock.h>
#include <root/component.h>
#include <util/arg_string.h>
#include <base/log.h>
#include <base/heap.h>
#include <nic/packet_allocator.h>
#include <nic_session/rpc_object.h>
#include <nic_session/connection.h>
#include <net/ipv4.h>
#include <base/allocator_guard.h>
#include <os/session_policy.h>
#include <root/component.h>
#include <util/arg_string.h>
#include <address_node.h>
#include <mac.h>
#include <nic.h>
#include <packet_handler.h>
#include <ram_session_guard.h>
namespace Net {
/**
* Helper class.
*
*/
class Guarded_range_allocator
{
private:
Genode::Allocator_guard _guarded_alloc;
::Nic::Packet_allocator _range_alloc;
public:
Guarded_range_allocator(Genode::Allocator *backing_store,
Genode::size_t amount)
: _guarded_alloc(backing_store, amount),
_range_alloc(&_guarded_alloc) {}
Genode::Allocator_guard *guarded_allocator() {
return &_guarded_alloc; }
Genode::Range_allocator *range_allocator() {
return static_cast<Genode::Range_allocator *>(&_range_alloc); }
};
class Stream_allocator;
class Stream_dataspace;
class Stream_dataspaces;
class Session_component;
class Root;
}
class Communication_buffer : Genode::Ram_dataspace_capability
{
public:
/********************
** Helper classes **
********************/
Communication_buffer(Genode::size_t size)
: Genode::Ram_dataspace_capability(Genode::env()->ram_session()->alloc(size))
{ }
class Net::Stream_allocator
{
protected:
~Communication_buffer() { Genode::env()->ram_session()->free(*this); }
Genode::Ram_session_guard _ram;
Genode::Heap _heap;
::Nic::Packet_allocator _range_alloc;
Genode::Dataspace_capability dataspace() { return *this; }
};
public:
Stream_allocator(Genode::Ram_session &ram,
Genode::Region_map &rm,
Genode::size_t amount)
: _ram(ram, amount),
_heap(ram, rm),
_range_alloc(&_heap) {}
Genode::Range_allocator *range_allocator() {
return static_cast<Genode::Range_allocator *>(&_range_alloc); }
};
class Tx_rx_communication_buffers
{
private:
struct Net::Stream_dataspace : Genode::Ram_dataspace_capability
{
Genode::Ram_session &ram;
Communication_buffer _tx_buf, _rx_buf;
Stream_dataspace(Genode::Ram_session &ram, Genode::size_t size)
: Genode::Ram_dataspace_capability(ram.alloc(size)), ram(ram) { }
public:
Tx_rx_communication_buffers(Genode::size_t tx_size,
Genode::size_t rx_size)
: _tx_buf(tx_size), _rx_buf(rx_size) { }
Genode::Dataspace_capability tx_ds() { return _tx_buf.dataspace(); }
Genode::Dataspace_capability rx_ds() { return _rx_buf.dataspace(); }
};
~Stream_dataspace() { ram.free(*this); }
};
/**
* Nic-session component class
*
* We must inherit here from Guarded_range_allocator, although aggregation
* would be more convinient, because the range-allocator needs to be initialized
* before base-class Session_rpc_object.
*/
class Session_component : public Guarded_range_allocator,
private Tx_rx_communication_buffers,
public ::Nic::Session_rpc_object,
public Packet_handler
{
private:
struct Net::Stream_dataspaces
{
Stream_dataspace tx_ds, rx_ds;
Mac_address_node _mac_node;
Ipv4_address_node *_ipv4_node;
Net::Nic &_nic;
Genode::Signal_context_capability _link_state_sigh;
void _free_ipv4_node();
public:
/**
* Constructor
*
* \param allocator backing store for guarded allocator
* \param amount amount of memory managed by guarded allocator
* \param tx_buf_size buffer size for tx channel
* \param rx_buf_size buffer size for rx channel
* \param vmac virtual mac address
* \param ep entry point used for packet stream
*/
Session_component(Genode::Allocator *allocator,
Genode::size_t amount,
Genode::size_t tx_buf_size,
Genode::size_t rx_buf_size,
Ethernet_frame::Mac_address vmac,
Server::Entrypoint &ep,
Net::Nic &nic,
char *ip_addr = 0);
~Session_component();
::Nic::Mac_address mac_address()
{
::Nic::Mac_address m;
Mac_address_node::Address mac = _mac_node.addr();
Genode::memcpy(&m, mac.addr, sizeof(m.addr));
return m;
}
void link_state_changed()
{
if (_link_state_sigh.valid())
Genode::Signal_transmitter(_link_state_sigh).submit();
}
void set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr);
/****************************************
** Nic::Driver notification interface **
****************************************/
bool link_state();
void link_state_sigh(Genode::Signal_context_capability sigh) {
_link_state_sigh = sigh; }
/******************************
** Packet_handler interface **
******************************/
Packet_stream_sink< ::Nic::Session::Policy> * sink() {
return _tx.sink(); }
Packet_stream_source< ::Nic::Session::Policy> * source() {
return _rx.source(); }
bool handle_arp(Ethernet_frame *eth, Genode::size_t size);
bool handle_ip(Ethernet_frame *eth, Genode::size_t size);
void finalize_packet(Ethernet_frame *eth, Genode::size_t size);
};
Stream_dataspaces(Genode::Ram_session &ram, Genode::size_t tx_size,
Genode::size_t rx_size)
: tx_ds(ram, tx_size), rx_ds(ram, rx_size) { }
};
/*
* Root component, handling new session requests.
*/
class Root : public Genode::Root_component<Session_component>
{
private:
/**
* Nic-session component class
*
* We must inherit here from Stream_allocator, although aggregation
* would be more convinient, because the allocator needs to be initialized
* before base-class Session_rpc_object.
*/
class Net::Session_component : public Net::Stream_allocator,
private Net::Stream_dataspaces,
public ::Nic::Session_rpc_object,
public Net::Packet_handler
{
private:
enum { verbose = 1 };
Mac_address_node _mac_node;
Ipv4_address_node _ipv4_node;
Net::Nic &_nic;
Genode::Signal_context_capability _link_state_sigh;
Mac_allocator _mac_alloc;
Server::Entrypoint &_ep;
Net::Nic &_nic;
void _unset_ipv4_node();
protected:
public:
/**
* Constructor
*
* \param ram ram session
* \param rm region map of this component
* \param ep entry point this session component is handled by
* \param amount amount of memory managed by guarded allocator
* \param tx_buf_size buffer size for tx channel
* \param rx_buf_size buffer size for rx channel
* \param vmac virtual mac address
*/
Session_component(Genode::Ram_session &ram,
Genode::Region_map &rm,
Genode::Entrypoint &ep,
Genode::size_t amount,
Genode::size_t tx_buf_size,
Genode::size_t rx_buf_size,
Ethernet_frame::Mac_address vmac,
Net::Nic &nic,
char *ip_addr = 0);
~Session_component();
::Nic::Mac_address mac_address()
{
::Nic::Mac_address m;
Mac_address_node::Address mac = _mac_node.addr();
Genode::memcpy(&m, mac.addr, sizeof(m.addr));
return m;
}
void link_state_changed()
{
if (_link_state_sigh.valid())
Genode::Signal_transmitter(_link_state_sigh).submit();
}
void set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr);
/****************************************
** Nic::Driver notification interface **
****************************************/
bool link_state();
void link_state_sigh(Genode::Signal_context_capability sigh) {
_link_state_sigh = sigh; }
/******************************
** Packet_handler interface **
******************************/
Packet_stream_sink< ::Nic::Session::Policy> * sink() {
return _tx.sink(); }
Packet_stream_source< ::Nic::Session::Policy> * source() {
return _rx.source(); }
bool handle_arp(Ethernet_frame *eth, Genode::size_t size);
bool handle_ip(Ethernet_frame *eth, Genode::size_t size);
void finalize_packet(Ethernet_frame *eth, Genode::size_t size);
};
/*
* Root component, handling new session requests.
*/
class Net::Root : public Genode::Root_component<Net::Session_component>
{
private:
Mac_allocator _mac_alloc;
Genode::Env &_env;
Net::Nic &_nic;
Genode::Xml_node _config;
protected:
Session_component *_create_session(const char *args)
{
using namespace Genode;
enum { MAX_IP_ADDR_LENGTH = 16, };
char ip_addr[MAX_IP_ADDR_LENGTH];
memset(ip_addr, 0, MAX_IP_ADDR_LENGTH);
Session_component *_create_session(const char *args)
{
using namespace Genode;
memset(ip_addr, 0, MAX_IP_ADDR_LENGTH);
try {
Session_label label(args);
Session_policy policy(label);
policy.attribute("ip_addr").value(ip_addr, sizeof(ip_addr));
if (verbose) PLOG("policy: %s ip_addr = %s", label.string(), ip_addr);
} catch (Xml_node::Nonexistent_attribute) {
if (verbose) PLOG("Missing \"ip_addr\" attribute in policy definition");
} catch (Session_policy::No_policy_defined) {
if (verbose) PLOG("Invalid session request, no matching policy");;
}
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
size_t tx_buf_size =
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
size_t rx_buf_size =
Arg_string::find_arg(args, "rx_buf_size").ulong_value(0);
/* delete ram quota by the memory needed for the session */
size_t session_size = max((size_t)4096, sizeof(Session_component));
if (ram_quota < session_size)
throw Root::Quota_exceeded();
/*
* Check if donated ram quota suffices for both
* communication buffers. Also check both sizes separately
* to handle a possible overflow of the sum of both sizes.
*/
if (tx_buf_size > ram_quota - session_size
|| rx_buf_size > ram_quota - session_size
|| tx_buf_size + rx_buf_size > ram_quota - session_size) {
PERR("insufficient 'ram_quota', got %zd, need %zd",
ram_quota, tx_buf_size + rx_buf_size + session_size);
throw Root::Quota_exceeded();
}
try {
return new (md_alloc()) Session_component(env()->heap(),
ram_quota - session_size,
tx_buf_size,
rx_buf_size,
_mac_alloc.alloc(),
_ep,
_nic,
ip_addr);
} catch(Mac_allocator::Alloc_failed) {
PWRN("Mac address allocation failed!");
return (Session_component*) 0;
}
try {
Session_label label(args);
Session_policy policy(label, _config);
policy.attribute("ip_addr").value(ip_addr, sizeof(ip_addr));
} catch (Xml_node::Nonexistent_attribute) {
Genode::log("Missing \"ip_addr\" attribute in policy definition");
} catch (Session_policy::No_policy_defined) {
Genode::log("Invalid session request, no matching policy");;
}
public:
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
size_t tx_buf_size =
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
size_t rx_buf_size =
Arg_string::find_arg(args, "rx_buf_size").ulong_value(0);
Root(Server::Entrypoint &ep,
Net::Nic &nic,
Genode::Allocator *md_alloc)
: Genode::Root_component<Session_component>(&ep.rpc_ep(), md_alloc),
_ep(ep), _nic(nic) { }
};
try {
return new (md_alloc())
Session_component(_env.ram(), _env.rm(), _env.ep(),
ram_quota, tx_buf_size, rx_buf_size,
_mac_alloc.alloc(), _nic, ip_addr);
} catch(Mac_allocator::Alloc_failed) {
Genode::warning("Mac address allocation failed!");
throw Root::Unavailable();
} catch(Ram_session::Quota_exceeded) {
Genode::warning("insufficient 'ram_quota'");
throw Root::Quota_exceeded();
}
}
} /* namespace Net */
public:
Root(Genode::Env &env, Net::Nic &nic, Genode::Allocator &md_alloc,
Genode::Xml_node config)
: Genode::Root_component<Session_component>(env.ep(), md_alloc),
_env(env), _nic(nic), _config(config) { }
};
#endif /* _COMPONENT_H_ */

View File

@ -1,45 +0,0 @@
/*
* \brief Thread-safe list implementation
* \author Stefan Kalkowski
* \date 2010-08-23
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _LIST_SAFE_H_
#define _LIST_SAFE_H_
#include <base/lock_guard.h>
#include <util/list.h>
/**
* Lock-guarded avl-tree implementation.
*/
template <typename LE>
class List_safe : public Genode::List<LE>
{
private:
Genode::Lock _lock;
public:
void insert(LE *item)
{
Genode::Lock::Guard lock_guard(_lock);
Genode::List<LE>::insert(item);
}
void remove(LE *item)
{
Genode::Lock::Guard lock_guard(_lock);
Genode::List<LE>::remove(item);
}
};
#endif /* _LIST_SAFE_H_ */

View File

@ -12,13 +12,14 @@
*/
/* Genode */
#include <nic/xml_node.h> /* ugly template dependency forces us
to include this before xml_node.h */
#include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/env.h>
#include <cap_session/connection.h>
#include <base/log.h>
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
#include <nic/xml_node.h>
#include <os/config.h>
#include <os/server.h>
/* local includes */
#include <component.h>
@ -26,54 +27,47 @@
struct Main
{
Server::Entrypoint &ep;
Net::Vlan vlan;
Net::Nic nic = { ep, vlan };
Net::Root root = { ep, nic, Genode::env()->heap() };
Genode::Env &env;
Genode::Entrypoint &ep { env.ep() };
Genode::Heap heap { env.ram(), env.rm() };
Genode::Attached_rom_dataspace config { env, "config" };
Net::Vlan vlan;
Net::Nic nic { ep, heap, vlan };
Net::Root root { env, nic, heap, config.xml() };
void handle_config()
{
/* read MAC address prefix from config file */
try {
Nic::Mac_address mac;
Genode::config()->xml_node().attribute("mac").value(&mac);
config.xml().attribute("mac").value(&mac);
Genode::memcpy(&Net::Mac_allocator::mac_addr_base, &mac,
sizeof(Net::Mac_allocator::mac_addr_base));
} catch(...) {}
}
void read_mac()
{
Net::Ethernet_frame::Mac_address mac(nic.mac());
Genode::printf("--- NIC bridge started "
"(mac=%02x:%02x:%02x:%02x:%02x:%02x) ---\n",
mac.addr[0], mac.addr[1], mac.addr[2],
mac.addr[3], mac.addr[4], mac.addr[5]);
}
Main(Server::Entrypoint &ep) : ep(ep)
Main(Genode::Env &e) : env(e)
{
try {
/* read configuration file */
handle_config();
read_mac();
Genode::env()->parent()->announce(ep.manage(root));
/* show MAC address to use */
Net::Ethernet_frame::Mac_address mac(nic.mac());
Genode::log("--- NIC bridge started (mac=", mac, ") ---");
/* announce at parent */
env.parent().announce(ep.manage(root));
} catch (Genode::Parent::Service_denied) {
PERR("Could not connect to uplink NIC");
Genode::error("Could not connect to uplink NIC");
}
}
};
/************
** Server **
************/
Genode::size_t Component::stack_size() {
return 2048*sizeof(Genode::addr_t); }
namespace Server {
char const *name() { return "nic_bridge_ep"; }
size_t stack_size() { return 2048*sizeof(Genode::addr_t); }
void construct(Entrypoint &ep) { static Main nic_bridge(ep); }
}
void Component::construct(Genode::Env &env) {
static Main nic_bridge(env); }

View File

@ -32,7 +32,7 @@ bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
return true;
/* look whether the IP address is one of our client's */
Ipv4_address_node *node = vlan().ip_tree()->first();
Ipv4_address_node *node = vlan().ip_tree.first();
if (node)
node = node->find_by_address(arp->dst_ip());
if (node) {
@ -55,9 +55,9 @@ bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
send(eth, size);
} else {
/* overwrite destination MAC */
arp->dst_mac(node->component()->mac_address().addr);
eth->dst(node->component()->mac_address().addr);
node->component()->send(eth, size);
arp->dst_mac(node->component().mac_address().addr);
eth->dst(node->component().mac_address().addr);
node->component().send(eth, size);
}
return false;
}
@ -91,11 +91,11 @@ bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
Genode::uint8_t *msg_type = (Genode::uint8_t*) ext->value();
if (*msg_type == Dhcp_packet::DHCP_ACK) {
Mac_address_node *node =
vlan().mac_tree()->first();
vlan().mac_tree.first();
if (node)
node = node->find_by_address(dhcp->client_mac());
if (node)
node->component()->set_ipv4_address(dhcp->yiaddr());
node->component().set_ipv4_address(dhcp->yiaddr());
}
}
}
@ -104,15 +104,15 @@ bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
/* is it an unicast message to one of our clients ? */
if (eth->dst() == mac()) {
Ipv4_address_node *node = vlan().ip_tree()->first();
Ipv4_address_node *node = vlan().ip_tree.first();
if (node) {
node = node->find_by_address(ip->dst());
if (node) {
/* overwrite destination MAC */
eth->dst(node->component()->mac_address().addr);
eth->dst(node->component().mac_address().addr);
/* deliver the packet to the client */
node->component()->send(eth, size);
node->component().send(eth, size);
return false;
}
}
@ -121,9 +121,9 @@ bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
}
Net::Nic::Nic(Server::Entrypoint &ep, Net::Vlan &vlan)
Net::Nic::Nic(Genode::Entrypoint &ep, Genode::Heap &heap, Net::Vlan &vlan)
: Packet_handler(ep, vlan),
_tx_block_alloc(Genode::env()->heap()),
_tx_block_alloc(&heap),
_nic(&_tx_block_alloc, BUF_SIZE, BUF_SIZE),
_mac(_nic.mac_address().addr)
{

View File

@ -37,7 +37,7 @@ class Net::Nic : public Net::Packet_handler
public:
Nic(Server::Entrypoint&, Vlan&);
Nic(Genode::Entrypoint&, Genode::Heap&, Vlan&);
::Nic::Connection *nic() { return &_nic; }
Ethernet_frame::Mac_address mac() { return _mac; }

View File

@ -11,7 +11,7 @@
* under the terms of the GNU General Public License version 2.
*/
#include <base/lock.h>
#include <base/log.h>
#include <net/arp.h>
#include <net/dhcp.h>
#include <net/ethernet.h>
@ -23,9 +23,7 @@
using namespace Net;
static const bool verbose = true;
void Packet_handler::_ready_to_submit(unsigned)
void Packet_handler::_ready_to_submit()
{
/* as long as packets are available, and we can ack them */
while (sink()->packet_avail()) {
@ -34,8 +32,7 @@ void Packet_handler::_ready_to_submit(unsigned)
handle_ethernet(sink()->packet_content(_packet), _packet.size());
if (!sink()->ready_to_ack()) {
if (verbose)
PWRN("ack state FULL");
Genode::warning("ack state FULL");
return;
}
@ -44,7 +41,7 @@ void Packet_handler::_ready_to_submit(unsigned)
}
void Packet_handler::_ready_to_ack(unsigned)
void Packet_handler::_ready_to_ack()
{
/* check for acknowledgements */
while (source()->ack_avail())
@ -52,11 +49,11 @@ void Packet_handler::_ready_to_ack(unsigned)
}
void Packet_handler::_link_state(unsigned)
void Packet_handler::_link_state()
{
Mac_address_node *node = _vlan.mac_list()->first();
Mac_address_node *node = _vlan.mac_list.first();
while (node) {
node->component()->link_state_changed();
node->component().link_state_changed();
node = node->next();
}
}
@ -68,10 +65,10 @@ void Packet_handler::broadcast_to_clients(Ethernet_frame *eth, Genode::size_t si
if (eth->dst() == Ethernet_frame::BROADCAST) {
/* iterate through the list of clients */
Mac_address_node *node =
_vlan.mac_list()->first();
_vlan.mac_list.first();
while (node) {
/* deliver packet */
node->component()->send(eth, size);
node->component().send(eth, size);
node = node->next();
}
}
@ -97,15 +94,15 @@ void Packet_handler::handle_ethernet(void* src, Genode::size_t size)
broadcast_to_clients(eth, size);
finalize_packet(eth, size);
} catch(Arp_packet::No_arp_packet) {
PWRN("Invalid ARP packet!");
Genode::warning("Invalid ARP packet!");
} catch(Ethernet_frame::No_ethernet_frame) {
PWRN("Invalid ethernet frame");
Genode::warning("Invalid ethernet frame");
} catch(Dhcp_packet::No_dhcp_packet) {
PWRN("Invalid IPv4 packet!");
Genode::warning("Invalid IPv4 packet!");
} catch(Ipv4_packet::No_ip_packet) {
PWRN("Invalid IPv4 packet!");
Genode::warning("Invalid IPv4 packet!");
} catch(Udp_packet::No_udp_packet) {
PWRN("Invalid UDP packet!");
Genode::warning("Invalid UDP packet!");
}
}
@ -119,13 +116,12 @@ void Packet_handler::send(Ethernet_frame *eth, Genode::size_t size)
Genode::memcpy((void*)content, (void*)eth, size);
source()->submit_packet(packet);
} catch(Packet_stream_source< ::Nic::Session::Policy>::Packet_alloc_failed) {
if (verbose)
PWRN("Packet dropped");
Genode::warning("Packet dropped");
}
}
Packet_handler::Packet_handler(Server::Entrypoint &ep, Vlan &vlan)
Packet_handler::Packet_handler(Genode::Entrypoint &ep, Vlan &vlan)
: _vlan(vlan),
_sink_ack(ep, *this, &Packet_handler::_ack_avail),
_sink_submit(ep, *this, &Packet_handler::_ready_to_submit),

View File

@ -46,7 +46,7 @@ class Net::Packet_handler
/**
* submit queue not empty anymore
*/
void _ready_to_submit(unsigned);
void _ready_to_submit();
/**
* acknoledgement queue not full anymore
@ -54,12 +54,12 @@ class Net::Packet_handler
* TODO: by now, we assume ACK and SUBMIT queue to be equally
* dimensioned. That's why we ignore this signal by now.
*/
void _ack_avail(unsigned) { }
void _ack_avail() { }
/**
* acknoledgement queue not empty anymore
*/
void _ready_to_ack(unsigned);
void _ready_to_ack();
/**
* submit queue not full anymore
@ -67,24 +67,24 @@ class Net::Packet_handler
* TODO: by now, we just drop packets that cannot be transferred
* to the other side, that's why we ignore this signal.
*/
void _packet_avail(unsigned) { }
void _packet_avail() { }
/**
* the link-state of changed
*/
void _link_state(unsigned);
void _link_state();
protected:
Genode::Signal_rpc_member<Packet_handler> _sink_ack;
Genode::Signal_rpc_member<Packet_handler> _sink_submit;
Genode::Signal_rpc_member<Packet_handler> _source_ack;
Genode::Signal_rpc_member<Packet_handler> _source_submit;
Genode::Signal_rpc_member<Packet_handler> _client_link_state;
Genode::Signal_handler<Packet_handler> _sink_ack;
Genode::Signal_handler<Packet_handler> _sink_submit;
Genode::Signal_handler<Packet_handler> _source_ack;
Genode::Signal_handler<Packet_handler> _source_submit;
Genode::Signal_handler<Packet_handler> _client_link_state;
public:
Packet_handler(Server::Entrypoint&, Vlan&);
Packet_handler(Genode::Entrypoint&, Vlan&);
virtual Packet_stream_sink< ::Nic::Session::Policy> * sink() = 0;
virtual Packet_stream_source< ::Nic::Session::Policy> * source() = 0;

View File

@ -0,0 +1,63 @@
/*
* \brief RAM session guard
* \author Stefan Kalkowski
* \date 2016-06-03
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _RAM_SESSION_GUARD_H_
#define _RAM_SESSION_GUARD_H_
#include <dataspace/client.h>
#include <ram_session/ram_session.h>
#include <ram_session/capability.h>
namespace Genode { struct Ram_session_guard; }
class Genode::Ram_session_guard : public Genode::Ram_session
{
private:
Ram_session &_session;
size_t _quota;
size_t _used;
public:
Ram_session_guard(Ram_session &session, size_t quota)
: _session(session) { }
Ram_dataspace_capability alloc(size_t size,
Cache_attribute cached = CACHED) override
{
if (_used + size > _used) throw Quota_exceeded();
_used += size;
return _session.alloc(size, cached);
}
void free(Ram_dataspace_capability ds) override
{
size_t size = Dataspace_client(ds).size();
_used -= size;
_session.free(ds);
}
int ref_account(Ram_session_capability ram_session) override {
return -1; }
int transfer_quota(Ram_session_capability ram_session, size_t amount) override {
return -1; }
size_t quota() override { return _quota; }
size_t used() override { return _used; }
};
#endif /* _RAM_SESSION_GUARD_H_ */

View File

@ -1,6 +1,4 @@
TARGET = nic_bridge
LIBS = base net config server
SRC_CC = component.cc mac.cc main.cc nic.cc packet_handler.cc
INC_DIR += $(PRG_DIR)
vpath *.cc $(REP_DIR)/src/server/proxy_arp
TARGET = nic_bridge
LIBS = base net
SRC_CC = component.cc mac.cc main.cc nic.cc packet_handler.cc
INC_DIR += $(PRG_DIR)

View File

@ -16,9 +16,9 @@
#ifndef _VLAN_H_
#define _VLAN_H_
#include <util/avl_tree.h>
#include <util/list.h>
#include <address_node.h>
#include <avl_safe.h>
#include <list_safe.h>
namespace Net {
@ -26,27 +26,15 @@ namespace Net {
* The Vlan is a database containing all clients
* sorted by IP and MAC addresses.
*/
class Vlan
struct Vlan
{
public:
using Mac_address_tree = Genode::Avl_tree<Mac_address_node>;
using Ipv4_address_tree = Genode::Avl_tree<Ipv4_address_node>;
using Mac_address_list = Genode::List<Mac_address_node>;
typedef Avl_tree_safe<Mac_address_node> Mac_address_tree;
typedef Avl_tree_safe<Ipv4_address_node> Ipv4_address_tree;
typedef List_safe<Mac_address_node> Mac_address_list;
private:
Mac_address_tree _mac_tree;
Mac_address_list _mac_list;
Ipv4_address_tree _ip_tree;
public:
Vlan() {}
Mac_address_tree *mac_tree() { return &_mac_tree; }
Mac_address_list *mac_list() { return &_mac_list; }
Ipv4_address_tree *ip_tree() { return &_ip_tree; }
Mac_address_tree mac_tree;
Mac_address_list mac_list;
Ipv4_address_tree ip_tree;
};
}

View File

@ -138,6 +138,7 @@ append config {
<start name="nic_bridge">
<resource name="RAM" quantum="6M"/>
<provides><service name="Nic"/></provides>
<config/>
<route>
<service name="Nic"> <child name="usb_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>

View File

@ -90,6 +90,7 @@ append config {
<start name="nic_bridge">
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
<config/>
<route>}
append_if $use_nic_driver config {
<service name="Nic"> <child name="nic_drv"/></service>}

View File

@ -222,6 +222,7 @@ append_if [expr $use_nic_session && $use_nic_bridge] config {
<start name="nic_bridge" priority="-3">
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
<config/>
<route>
<service name="Nic"><child name="nic_drv"/></service>
<any-service><parent/></any-service>