nic_bridge: use the server framework (fix #1865)

Let the Server::Entrypoint do all the work: RPC and signal handling.
Additionally get rid of the Net::Env global environment.
This commit is contained in:
Stefan Kalkowski 2016-01-27 13:46:35 +01:00 committed by Christian Helmuth
parent 71b621775b
commit 3bfd2aa3c9
12 changed files with 127 additions and 181 deletions

View File

@ -16,10 +16,7 @@
#include <net/dhcp.h>
#include <net/udp.h>
#include "env.h"
#include "component.h"
#include "nic.h"
#include "vlan.h"
#include <component.h>
using namespace Net;
@ -44,11 +41,11 @@ 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 = Env::vlan()->ip_tree()->first();
Ipv4_address_node *node = vlan().ip_tree()->first();
if (node)
node = node->find_by_address(arp->dst_ip());
if (!node) {
arp->src_mac(Net::Env::nic()->mac());
arp->src_mac(_nic.mac());
}
}
return true;
@ -80,15 +77,15 @@ 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 = Env::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);
else {
/* set our MAC as sender */
eth->src(Net::Env::nic()->mac());
Net::Env::nic()->send(eth, size);
eth->src(_nic.mac());
_nic.send(eth, size);
}
}
@ -96,14 +93,13 @@ void Session_component::finalize_packet(Ethernet_frame *eth,
void Session_component::_free_ipv4_node()
{
if (_ipv4_node) {
Env::vlan()->ip_tree()->remove(_ipv4_node);
vlan().ip_tree()->remove(_ipv4_node);
destroy(this->guarded_allocator(), _ipv4_node);
}
}
bool Session_component::link_state() {
return Net::Env::nic()->link_state(); }
bool Session_component::link_state() { return _nic.link_state(); }
void Session_component::set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr)
@ -111,7 +107,7 @@ 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);
Net::Env::vlan()->ip_tree()->insert(_ipv4_node);
vlan().ip_tree()->insert(_ipv4_node);
}
@ -120,18 +116,21 @@ Session_component::Session_component(Genode::Allocator *allocator,
Genode::size_t tx_buf_size,
Genode::size_t rx_buf_size,
Ethernet_frame::Mac_address vmac,
Genode::Rpc_entrypoint &ep,
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),
this->range_allocator(), ep.rpc_ep()),
Packet_handler(ep, nic.vlan()),
_mac_node(vmac, this),
_ipv4_node(0)
_ipv4_node(0),
_nic(nic)
{
Env::vlan()->mac_tree()->insert(&_mac_node);
Env::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)) {
@ -158,7 +157,7 @@ Session_component::Session_component(Genode::Allocator *allocator,
Session_component::~Session_component() {
Env::vlan()->mac_tree()->remove(&_mac_node);
Env::vlan()->mac_list()->remove(&_mac_node);
vlan().mac_tree()->remove(&_mac_node);
vlan().mac_list()->remove(&_mac_node);
_free_ipv4_node();
}

View File

@ -25,9 +25,10 @@
#include <base/allocator_guard.h>
#include <os/session_policy.h>
#include "address_node.h"
#include "mac.h"
#include "packet_handler.h"
#include <address_node.h>
#include <mac.h>
#include <nic.h>
#include <packet_handler.h>
namespace Net {
@ -102,9 +103,9 @@ namespace Net {
{
private:
Mac_address_node _mac_node;
Ipv4_address_node *_ipv4_node;
Mac_address_node _mac_node;
Ipv4_address_node *_ipv4_node;
Net::Nic &_nic;
Genode::Signal_context_capability _link_state_sigh;
void _free_ipv4_node();
@ -126,7 +127,8 @@ namespace Net {
Genode::size_t tx_buf_size,
Genode::size_t rx_buf_size,
Ethernet_frame::Mac_address vmac,
Genode::Rpc_entrypoint &ep,
Server::Entrypoint &ep,
Net::Nic &nic,
char *ip_addr = 0);
~Session_component();
@ -181,8 +183,9 @@ namespace Net {
enum { verbose = 1 };
Mac_allocator _mac_alloc;
Genode::Rpc_entrypoint &_ep;
Mac_allocator _mac_alloc;
Server::Entrypoint &_ep;
Net::Nic &_nic;
protected:
@ -239,6 +242,7 @@ namespace Net {
rx_buf_size,
_mac_alloc.alloc(),
_ep,
_nic,
ip_addr);
} catch(Mac_allocator::Alloc_failed) {
PWRN("Mac address allocation failed!");
@ -248,10 +252,11 @@ namespace Net {
public:
Root(Genode::Rpc_entrypoint *session_ep,
Genode::Allocator *md_alloc)
: Genode::Root_component<Session_component>(session_ep, md_alloc),
_ep(*session_ep) { }
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) { }
};
} /* namespace Net */

View File

@ -1,36 +0,0 @@
/*
* \brief Nic-bridge global environment
* \author Stefan Kalkowski
* \date 2013-05-23
*/
/*
* Copyright (C) 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.
*/
#include "env.h"
#include "nic.h"
#include "vlan.h"
Genode::Signal_receiver* Net::Env::receiver()
{
static Genode::Signal_receiver receiver;
return &receiver;
}
Net::Vlan* Net::Env::vlan()
{
static Net::Vlan vlan;
return &vlan;
}
Net::Nic* Net::Env::nic()
{
static Net::Nic nic;
return &nic;
}

View File

@ -1,36 +0,0 @@
/*
* \brief Proxy-ARP environment
* \author Stefan Kalkowski
* \date 2013-05-24
*
* A database containing all clients sorted by IP and MAC addresses.
*/
/*
* Copyright (C) 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 _SRC__SERVER__NIC_BRIDGE__ENV_H_
#define _SRC__SERVER__NIC_BRIDGE__ENV_H_
#include <base/signal.h>
namespace Net {
class Vlan;
class Nic;
class Env;
}
struct Net::Env
{
static Genode::Signal_receiver* receiver();
static Vlan *vlan();
static Net::Nic *nic();
};
#endif /* _SRC__SERVER__NIC_BRIDGE__ENV_H_ */

View File

@ -11,7 +11,7 @@
* under the terms of the GNU General Public License version 2.
*/
#include "mac.h"
#include <mac.h>
/**
* We take the range 02:02:02:02:02:XX for our MAC address allocator,

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
* Copyright (C) 2010-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.
@ -18,47 +18,62 @@
#include <nic/packet_allocator.h>
#include <nic/xml_node.h>
#include <os/config.h>
#include <os/server.h>
/* local includes */
#include "component.h"
#include "nic.h"
#include "env.h"
#include <component.h>
int main(int, char **)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
/* read MAC address prefix from config file */
try {
Nic::Mac_address mac;
Genode::config()->xml_node().attribute("mac").value(&mac);
Genode::memcpy(&Net::Mac_allocator::mac_addr_base, &mac,
sizeof(Net::Mac_allocator::mac_addr_base));
} catch(...) {}
Net::Vlan vlan;
Net::Nic nic = { ep, vlan };
Net::Root root = { ep, nic, Genode::env()->heap() };
try {
enum { STACK_SIZE = 2048*sizeof(Genode::addr_t) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nic_bridge_ep");
static Net::Root nic_root(&ep, env()->heap());
/* announce NIC service */
env()->parent()->announce(ep.manage(&nic_root));
/* connect to NIC backend to actually see incoming traffic */
Net::Ethernet_frame::Mac_address mac(Net::Env::nic()->mac());
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]);
while (true) {
Signal s = Net::Env::receiver()->wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
} catch (Parent::Service_denied) {
PERR("Could not connect to uplink NIC");
void handle_config()
{
/* read MAC address prefix from config file */
try {
Nic::Mac_address mac;
Genode::config()->xml_node().attribute("mac").value(&mac);
Genode::memcpy(&Net::Mac_allocator::mac_addr_base, &mac,
sizeof(Net::Mac_allocator::mac_addr_base));
} catch(...) {}
}
return 0;
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)
{
try {
handle_config();
read_mac();
Genode::env()->parent()->announce(ep.manage(root));
} catch (Genode::Parent::Service_denied) {
PERR("Could not connect to uplink NIC");
}
}
};
/************
** Server **
************/
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); }
}

View File

@ -18,11 +18,7 @@
#include <net/udp.h>
#include <net/dhcp.h>
#include "address_node.h"
#include "component.h"
#include "env.h"
#include "nic.h"
#include "vlan.h"
#include <component.h>
using namespace Net;
@ -36,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 = Env::vlan()->ip_tree()->first();
Ipv4_address_node *node = vlan().ip_tree()->first();
if (node)
node = node->find_by_address(arp->dst_ip());
if (node) {
@ -95,7 +91,7 @@ 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 =
Env::vlan()->mac_tree()->first();
vlan().mac_tree()->first();
if (node)
node = node->find_by_address(dhcp->client_mac());
if (node)
@ -107,8 +103,8 @@ 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() == Net::Env::nic()->mac()) {
Ipv4_address_node *node = Env::vlan()->ip_tree()->first();
if (eth->dst() == mac()) {
Ipv4_address_node *node = vlan().ip_tree()->first();
if (node) {
node = node->find_by_address(ip->dst());
if (node) {
@ -125,8 +121,9 @@ bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
}
Net::Nic::Nic()
: _tx_block_alloc(Genode::env()->heap()),
Net::Nic::Nic(Server::Entrypoint &ep, Net::Vlan &vlan)
: Packet_handler(ep, vlan),
_tx_block_alloc(Genode::env()->heap()),
_nic(&_tx_block_alloc, BUF_SIZE, BUF_SIZE),
_mac(_nic.mac_address().addr)
{

View File

@ -17,12 +17,9 @@
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
#include "env.h"
#include "packet_handler.h"
#include <packet_handler.h>
namespace Net {
class Nic;
}
namespace Net { class Nic; }
class Net::Nic : public Net::Packet_handler
@ -40,7 +37,7 @@ class Net::Nic : public Net::Packet_handler
public:
Nic();
Nic(Server::Entrypoint&, Vlan&);
::Nic::Connection *nic() { return &_nic; }
Ethernet_frame::Mac_address mac() { return _mac; }

View File

@ -18,10 +18,8 @@
#include <net/ipv4.h>
#include <net/udp.h>
#include "env.h"
#include "component.h"
#include "packet_handler.h"
#include "vlan.h"
#include <component.h>
#include <packet_handler.h>
using namespace Net;
@ -56,7 +54,7 @@ void Packet_handler::_ready_to_ack(unsigned)
void Packet_handler::_link_state(unsigned)
{
Mac_address_node *node = Env::vlan()->mac_list()->first();
Mac_address_node *node = _vlan.mac_list()->first();
while (node) {
node->component()->link_state_changed();
node = node->next();
@ -70,7 +68,7 @@ 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 =
Env::vlan()->mac_list()->first();
_vlan.mac_list()->first();
while (node) {
/* deliver packet */
node->component()->send(eth, size);
@ -127,10 +125,11 @@ void Packet_handler::send(Ethernet_frame *eth, Genode::size_t size)
}
Packet_handler::Packet_handler()
: _sink_ack(*Net::Env::receiver(), *this, &Packet_handler::_ack_avail),
_sink_submit(*Net::Env::receiver(), *this, &Packet_handler::_ready_to_submit),
_source_ack(*Net::Env::receiver(), *this, &Packet_handler::_ready_to_ack),
_source_submit(*Net::Env::receiver(), *this, &Packet_handler::_packet_avail),
_client_link_state(*Net::Env::receiver(), *this, &Packet_handler::_link_state)
Packet_handler::Packet_handler(Server::Entrypoint &ep, Vlan &vlan)
: _vlan(vlan),
_sink_ack(ep, *this, &Packet_handler::_ack_avail),
_sink_submit(ep, *this, &Packet_handler::_ready_to_submit),
_source_ack(ep, *this, &Packet_handler::_ready_to_ack),
_source_submit(ep, *this, &Packet_handler::_packet_avail),
_client_link_state(ep, *this, &Packet_handler::_link_state)
{ }

View File

@ -18,9 +18,12 @@
#include <base/semaphore.h>
#include <base/thread.h>
#include <nic_session/connection.h>
#include <os/server.h>
#include <net/ethernet.h>
#include <net/ipv4.h>
#include <vlan.h>
namespace Net {
class Packet_handler;
@ -38,6 +41,7 @@ class Net::Packet_handler
private:
Packet_descriptor _packet;
Net::Vlan &_vlan;
/**
* submit queue not empty anymore
@ -72,19 +76,20 @@ class Net::Packet_handler
protected:
Genode::Signal_dispatcher<Packet_handler> _sink_ack;
Genode::Signal_dispatcher<Packet_handler> _sink_submit;
Genode::Signal_dispatcher<Packet_handler> _source_ack;
Genode::Signal_dispatcher<Packet_handler> _source_submit;
Genode::Signal_dispatcher<Packet_handler> _client_link_state;
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;
public:
Packet_handler();
Packet_handler(Server::Entrypoint&, Vlan&);
virtual Packet_stream_sink< ::Nic::Session::Policy> * sink() = 0;
virtual Packet_stream_source< ::Nic::Session::Policy> * source() = 0;
Net::Vlan & vlan() { return _vlan; }
/**
* Broadcasts ethernet frame to all clients,

View File

@ -1,5 +1,6 @@
TARGET = nic_bridge
LIBS = base net config
SRC_CC = component.cc env.cc mac.cc main.cc nic.cc packet_handler.cc
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

View File

@ -16,9 +16,9 @@
#ifndef _VLAN_H_
#define _VLAN_H_
#include "address_node.h"
#include "avl_safe.h"
#include "list_safe.h"
#include <address_node.h>
#include <avl_safe.h>
#include <list_safe.h>
namespace Net {