mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
Let the nic_bridge work event driven (fix #749)
This commit is contained in:
parent
153429268e
commit
853d541340
@ -57,6 +57,8 @@ namespace Net {
|
||||
static const Ipv4_address CURRENT; /* current network */
|
||||
static const Ipv4_address BROADCAST; /* broadcast address */
|
||||
|
||||
static Ipv4_address ip_from_string(const char *ip);
|
||||
|
||||
private:
|
||||
|
||||
/************************
|
||||
|
@ -1,3 +1,3 @@
|
||||
SRC_CC = ethernet.cc
|
||||
SRC_CC = ethernet.cc ipv4.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/net
|
@ -11,7 +11,57 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <util/token.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include <net/ipv4.h>
|
||||
|
||||
const Net::Ipv4_packet::Ipv4_address Net::Ipv4_packet::CURRENT(0x00);
|
||||
const Net::Ipv4_packet::Ipv4_address Net::Ipv4_packet::BROADCAST(0xFF);
|
||||
using namespace Net;
|
||||
|
||||
struct Scanner_policy_number
|
||||
{
|
||||
static bool identifier_char(char c, unsigned i ) {
|
||||
return Genode::is_digit(c) && c !='.'; }
|
||||
};
|
||||
|
||||
typedef ::Genode::Token<Scanner_policy_number> Token;
|
||||
|
||||
|
||||
Ipv4_packet::Ipv4_address Ipv4_packet::ip_from_string(const char *ip)
|
||||
{
|
||||
Ipv4_address ip_addr;
|
||||
Token t(ip);
|
||||
char tmpstr[4];
|
||||
int cnt = 0;
|
||||
unsigned char ipb[4] = {0};
|
||||
|
||||
while(t) {
|
||||
if (t.type() == Token::WHITESPACE || t[0] == '.') {
|
||||
t = t.next();
|
||||
continue;
|
||||
}
|
||||
t.string(tmpstr, sizeof(tmpstr));
|
||||
|
||||
unsigned long tmpc = 0;
|
||||
Genode::ascii_to(tmpstr, &tmpc, 10);
|
||||
ipb[cnt] = tmpc & 0xFF;
|
||||
t = t.next();
|
||||
|
||||
if (cnt == 4)
|
||||
break;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (cnt == 4) {
|
||||
ip_addr.addr[0] = ipb[0];
|
||||
ip_addr.addr[1] = ipb[1];
|
||||
ip_addr.addr[2] = ipb[2];
|
||||
ip_addr.addr[3] = ipb[3];
|
||||
}
|
||||
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
|
||||
const Ipv4_packet::Ipv4_address Ipv4_packet::CURRENT((Genode::uint8_t)0x00);
|
||||
const Ipv4_packet::Ipv4_address Ipv4_packet::BROADCAST((Genode::uint8_t)0xFF);
|
||||
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* \brief Address-node holds a client-specific session-component.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <base/lock_guard.h>
|
||||
|
||||
#include "address_node.h"
|
||||
#include "component.h"
|
||||
|
||||
/**
|
||||
* Let the client a receive a network packet.
|
||||
*
|
||||
* \param addr start address network packet.
|
||||
* \param size size of network packet.
|
||||
*/
|
||||
template <unsigned LEN>
|
||||
void Net::Address_node<LEN>::receive_packet(void *addr, Genode::size_t size)
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(*_component->rx_lock());
|
||||
|
||||
Nic::Session::Rx::Source *source = _component->rx_source();
|
||||
|
||||
while (true) {
|
||||
/* flush remaining acknowledgements */
|
||||
while (source->ack_avail())
|
||||
source->release_packet(source->get_acked_packet());
|
||||
|
||||
try {
|
||||
/* allocate packet in rx channel */
|
||||
Packet_descriptor rx_packet = source->alloc_packet(size);
|
||||
|
||||
Genode::memcpy((void*)source->packet_content(rx_packet),
|
||||
(void*)addr, size);
|
||||
source->submit_packet(rx_packet);
|
||||
return;
|
||||
} catch (Nic::Session::Rx::Source::Packet_alloc_failed) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Let the compiler know, for which template instances this implementation
|
||||
* is used for.
|
||||
*/
|
||||
template void Net::Ipv4_address_node::receive_packet(void *addr, Genode::size_t size);
|
||||
template void Net::Mac_address_node::receive_packet(void *addr, Genode::size_t size);
|
@ -65,14 +65,6 @@ namespace Net {
|
||||
Address addr() { return _addr; }
|
||||
Session_component *component() { return _component; }
|
||||
|
||||
/**
|
||||
* Let this client node, receive a network-packet
|
||||
*
|
||||
* \param addr start address of network packet
|
||||
* \param size size of network packet
|
||||
*/
|
||||
void receive_packet(void *addr, Genode::size_t size);
|
||||
|
||||
|
||||
/************************
|
||||
** Avl node interface **
|
||||
|
@ -16,44 +16,17 @@
|
||||
#include <net/dhcp.h>
|
||||
#include <net/udp.h>
|
||||
|
||||
#include <util/token.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "component.h"
|
||||
#include "nic.h"
|
||||
#include "vlan.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
const int Session_component::verbose = 1;
|
||||
|
||||
void Session_component::Tx_handler::acknowledge_last_one()
|
||||
{
|
||||
if (!_tx_packet.valid())
|
||||
return;
|
||||
|
||||
if (!_component->tx_sink()->ready_to_ack())
|
||||
PDBG("need to wait until ready-for-ack");
|
||||
_component->tx_sink()->acknowledge_packet(_tx_packet);
|
||||
}
|
||||
static const int verbose = 1;
|
||||
|
||||
|
||||
void Session_component::Tx_handler::next_packet(void** src, Genode::size_t *size)
|
||||
{
|
||||
while (true) {
|
||||
/* block for a new packet */
|
||||
_tx_packet = _component->tx_sink()->get_packet();
|
||||
if (!_tx_packet.valid()) {
|
||||
PWRN("received invalid packet");
|
||||
continue;
|
||||
}
|
||||
*src = _component->tx_sink()->packet_content(_tx_packet);
|
||||
*size = _tx_packet.size();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Session_component::Tx_handler::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
bool Session_component::handle_arp(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
Arp_packet *arp =
|
||||
new (eth->data()) Arp_packet(size - sizeof(Ethernet_frame));
|
||||
@ -71,18 +44,18 @@ bool Session_component::Tx_handler::handle_arp(Ethernet_frame *eth, Genode::size
|
||||
if (arp->src_ip() == arp->dst_ip())
|
||||
return false;
|
||||
|
||||
Ipv4_address_node *node = Vlan::vlan()->ip_tree()->first();
|
||||
Ipv4_address_node *node = Env::vlan()->ip_tree()->first();
|
||||
if (node)
|
||||
node = node->find_by_address(arp->dst_ip());
|
||||
if (!node) {
|
||||
arp->src_mac(_mac);
|
||||
arp->src_mac(Net::Env::nic()->mac());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Session_component::Tx_handler::handle_ip(Ethernet_frame *eth, Genode::size_t size)
|
||||
bool Session_component::handle_ip(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
Ipv4_packet *ip =
|
||||
new (eth->data()) Ipv4_packet(size - sizeof(Ethernet_frame));
|
||||
@ -104,137 +77,84 @@ bool Session_component::Tx_handler::handle_ip(Ethernet_frame *eth, Genode::size_
|
||||
}
|
||||
|
||||
|
||||
void Session_component::Tx_handler::finalize_packet(Ethernet_frame *eth,
|
||||
void Session_component::finalize_packet(Ethernet_frame *eth,
|
||||
Genode::size_t size)
|
||||
{
|
||||
Mac_address_node *node = Vlan::vlan()->mac_tree()->first();
|
||||
Mac_address_node *node = Env::vlan()->mac_tree()->first();
|
||||
if (node)
|
||||
node = node->find_by_address(eth->dst());
|
||||
if (node)
|
||||
node->receive_packet((void*) eth, size);
|
||||
else
|
||||
send_to_nic(eth, size);
|
||||
node->component()->send(eth, size);
|
||||
else {
|
||||
/* set our MAC as sender */
|
||||
eth->src(Net::Env::nic()->mac());
|
||||
Net::Env::nic()->send(eth, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Session_component::_free_ipv4_node()
|
||||
{
|
||||
if (_ipv4_node) {
|
||||
Vlan::vlan()->ip_tree()->remove(_ipv4_node);
|
||||
Env::vlan()->ip_tree()->remove(_ipv4_node);
|
||||
destroy(this->guarded_allocator(), _ipv4_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Scanner_policy_number
|
||||
{
|
||||
static bool identifier_char(char c, unsigned i )
|
||||
{
|
||||
return Genode::is_digit(c) && c !='.';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef ::Genode::Token<Scanner_policy_number> Token;
|
||||
|
||||
|
||||
Ipv4_packet::Ipv4_address Session_component::ip_from_string(const char *ip)
|
||||
{
|
||||
Ipv4_packet::Ipv4_address ip_addr;
|
||||
|
||||
Token t(ip);
|
||||
char tmpstr[4];
|
||||
int cnt = 0;
|
||||
unsigned char ipb[4] = {0};
|
||||
|
||||
while(t) {
|
||||
|
||||
if (t.type() == Token::WHITESPACE || t[0] == '.') {
|
||||
t = t.next();
|
||||
continue;
|
||||
}
|
||||
t.string(tmpstr, sizeof(tmpstr));
|
||||
|
||||
unsigned long tmpc = 0;
|
||||
Genode::ascii_to(tmpstr, &tmpc, 10);
|
||||
|
||||
ipb[cnt] = tmpc & 0xFF;
|
||||
|
||||
t = t.next();
|
||||
|
||||
if (cnt == 4)
|
||||
break;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (cnt == 4) {
|
||||
ip_addr.addr[0] = ipb[0];
|
||||
ip_addr.addr[1] = ipb[1];
|
||||
ip_addr.addr[2] = ipb[2];
|
||||
ip_addr.addr[3] = ipb[3];
|
||||
}
|
||||
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Session_component::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,
|
||||
Nic::Connection *session,
|
||||
Genode::Rpc_entrypoint &ep,
|
||||
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),
|
||||
_tx_handler(session, this),
|
||||
_mac_node(vmac, this),
|
||||
_ipv4_node(0)
|
||||
{
|
||||
Vlan::vlan()->mac_tree()->insert(&_mac_node);
|
||||
Vlan::vlan()->mac_list()->insert(&_mac_node);
|
||||
|
||||
/* start handler */
|
||||
_tx_handler.start();
|
||||
_tx_handler.wait_for_startup();
|
||||
|
||||
/* static ip parsing */
|
||||
if (ip_addr != 0 && Genode::strlen(ip_addr)) {
|
||||
|
||||
Ipv4_packet::Ipv4_address ip = ip_from_string(ip_addr);
|
||||
|
||||
if (ip == Ipv4_packet::Ipv4_address()) {
|
||||
PDBG("Empty or error ip address. Skipped.");
|
||||
} else {
|
||||
|
||||
set_ipv4_address(ip);
|
||||
|
||||
if (verbose)
|
||||
PDBG("\nmac=%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]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Session_component::~Session_component() {
|
||||
Vlan::vlan()->mac_tree()->remove(&_mac_node);
|
||||
Vlan::vlan()->mac_list()->remove(&_mac_node);
|
||||
_free_ipv4_node();
|
||||
}
|
||||
|
||||
|
||||
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::vlan()->ip_tree()->insert(_ipv4_node);
|
||||
Net::Env::vlan()->ip_tree()->insert(_ipv4_node);
|
||||
}
|
||||
|
||||
|
||||
Session_component::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,
|
||||
Genode::Rpc_entrypoint &ep,
|
||||
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),
|
||||
_mac_node(vmac, this),
|
||||
_ipv4_node(0)
|
||||
{
|
||||
Env::vlan()->mac_tree()->insert(&_mac_node);
|
||||
Env::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.");
|
||||
} else {
|
||||
set_ipv4_address(ip);
|
||||
|
||||
if (verbose)
|
||||
PDBG("\nmac=%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]);
|
||||
}
|
||||
}
|
||||
|
||||
_tx.sigh_ready_to_ack(_sink_ack);
|
||||
_tx.sigh_packet_avail(_sink_submit);
|
||||
_rx.sigh_ack_avail(_source_ack);
|
||||
_rx.sigh_ready_to_submit(_source_submit);
|
||||
}
|
||||
|
||||
|
||||
Session_component::~Session_component() {
|
||||
Env::vlan()->mac_tree()->remove(&_mac_node);
|
||||
Env::vlan()->mac_list()->remove(&_mac_node);
|
||||
_free_ipv4_node();
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace Net {
|
||||
private:
|
||||
|
||||
Genode::Allocator_guard _guarded_alloc;
|
||||
Nic::Packet_allocator _range_alloc;
|
||||
::Nic::Packet_allocator _range_alloc;
|
||||
|
||||
public:
|
||||
|
||||
@ -97,41 +97,15 @@ namespace Net {
|
||||
*/
|
||||
class Session_component : public Guarded_range_allocator,
|
||||
private Tx_rx_communication_buffers,
|
||||
public Nic::Session_rpc_object
|
||||
public ::Nic::Session_rpc_object,
|
||||
public Packet_handler
|
||||
{
|
||||
private:
|
||||
|
||||
class Tx_handler : public Packet_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Packet_descriptor _tx_packet;
|
||||
Session_component *_component;
|
||||
|
||||
void acknowledge_last_one();
|
||||
void next_packet(void** src, Genode::size_t *size);
|
||||
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);
|
||||
|
||||
public:
|
||||
|
||||
Tx_handler(Nic::Connection *session,
|
||||
Session_component *component)
|
||||
: Packet_handler(session), _component(component) {}
|
||||
};
|
||||
|
||||
|
||||
Tx_handler _tx_handler;
|
||||
Mac_address_node _mac_node;
|
||||
Ipv4_address_node *_ipv4_node;
|
||||
Genode::Lock _rx_lock;
|
||||
|
||||
static const int verbose;
|
||||
|
||||
void _free_ipv4_node();
|
||||
|
||||
Ipv4_packet::Ipv4_address ip_from_string(const char *ip);
|
||||
|
||||
public:
|
||||
|
||||
@ -150,25 +124,34 @@ namespace Net {
|
||||
Genode::size_t tx_buf_size,
|
||||
Genode::size_t rx_buf_size,
|
||||
Ethernet_frame::Mac_address vmac,
|
||||
Nic::Connection *session,
|
||||
Genode::Rpc_entrypoint &ep,
|
||||
char *ip_addr = 0);
|
||||
|
||||
~Session_component();
|
||||
|
||||
Nic::Session::Tx::Sink* tx_sink() { return _tx.sink(); }
|
||||
Nic::Session::Rx::Source* rx_source() { return _rx.source(); }
|
||||
Genode::Lock* rx_lock() { return &_rx_lock; }
|
||||
|
||||
Nic::Mac_address mac_address()
|
||||
::Nic::Mac_address mac_address()
|
||||
{
|
||||
Nic::Mac_address m;
|
||||
::Nic::Mac_address m;
|
||||
Mac_address_node::Address mac = _mac_node.addr();
|
||||
Genode::memcpy(&m, mac.addr, sizeof(m.addr));
|
||||
return m;
|
||||
}
|
||||
|
||||
void set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr);
|
||||
|
||||
/******************************
|
||||
** 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);
|
||||
};
|
||||
|
||||
|
||||
@ -182,7 +165,6 @@ namespace Net {
|
||||
enum { verbose = 1 };
|
||||
|
||||
Mac_allocator _mac_alloc;
|
||||
Nic::Connection *_session;
|
||||
Genode::Rpc_entrypoint &_ep;
|
||||
|
||||
protected:
|
||||
@ -240,10 +222,8 @@ namespace Net {
|
||||
tx_buf_size,
|
||||
rx_buf_size,
|
||||
_mac_alloc.alloc(),
|
||||
_session,
|
||||
_ep,
|
||||
ip_addr
|
||||
);
|
||||
ip_addr);
|
||||
} catch(Mac_allocator::Alloc_failed) {
|
||||
PWRN("Mac address allocation failed!");
|
||||
return (Session_component*) 0;
|
||||
@ -253,10 +233,9 @@ namespace Net {
|
||||
public:
|
||||
|
||||
Root(Genode::Rpc_entrypoint *session_ep,
|
||||
Genode::Allocator *md_alloc,
|
||||
Nic::Connection *session)
|
||||
Genode::Allocator *md_alloc)
|
||||
: Genode::Root_component<Session_component>(session_ep, md_alloc),
|
||||
_session(session), _ep(*session_ep) { }
|
||||
_ep(*session_ep) { }
|
||||
};
|
||||
|
||||
} /* namespace Net */
|
||||
|
36
os/src/server/nic_bridge/env.cc
Normal file
36
os/src/server/nic_bridge/env.cc
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* \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;
|
||||
}
|
36
os/src/server/nic_bridge/env.h
Normal file
36
os/src/server/nic_bridge/env.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* \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_ */
|
@ -13,32 +13,21 @@
|
||||
|
||||
/* Genode */
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <nic/xml_node.h>
|
||||
#include <os/config.h>
|
||||
|
||||
#include "packet_handler.h"
|
||||
/* local includes */
|
||||
#include "component.h"
|
||||
#include "env.h"
|
||||
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static Cap_connection cap;
|
||||
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nic_bridge_ep");
|
||||
|
||||
static Nic::Packet_allocator tx_block_alloc(env()->heap());
|
||||
|
||||
enum {
|
||||
PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
|
||||
BUF_SIZE = Nic::Session::QUEUE_SIZE * PACKET_SIZE,
|
||||
};
|
||||
|
||||
/* read MAC address prefix from config file */
|
||||
try {
|
||||
Nic::Mac_address mac;
|
||||
@ -47,23 +36,22 @@ int main(int, char **)
|
||||
sizeof(Net::Mac_allocator::mac_addr_base));
|
||||
} catch(...) {}
|
||||
|
||||
Root_capability nic_root_cap;
|
||||
try {
|
||||
static Nic::Connection nic(&tx_block_alloc, BUF_SIZE, BUF_SIZE);
|
||||
static Net::Rx_handler rx_handler(&nic);
|
||||
static Net::Root nic_root(&ep, env()->heap(), &nic);
|
||||
|
||||
/* start receiver thread handling packets from the NIC driver */
|
||||
rx_handler.start();
|
||||
rx_handler.wait_for_startup();
|
||||
enum { STACK_SIZE = 4096 };
|
||||
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));
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
sleep_forever();
|
||||
return 0;
|
||||
}
|
||||
|
136
os/src/server/nic_bridge/nic.cc
Normal file
136
os/src/server/nic_bridge/nic.cc
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* \brief NIC handler
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-05-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <base/env.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/arp.h>
|
||||
#include <net/ipv4.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/dhcp.h>
|
||||
|
||||
#include "address_node.h"
|
||||
#include "component.h"
|
||||
#include "env.h"
|
||||
#include "nic.h"
|
||||
#include "vlan.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
|
||||
bool Net::Nic::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Arp_packet *arp = new (eth->data())
|
||||
Arp_packet(size - sizeof(Ethernet_frame));
|
||||
|
||||
/* ignore broken packets */
|
||||
if (!arp->ethernet_ipv4())
|
||||
return true;
|
||||
|
||||
/* look whether the IP address is one of our client's */
|
||||
Ipv4_address_node *node = Env::vlan()->ip_tree()->first();
|
||||
if (node)
|
||||
node = node->find_by_address(arp->dst_ip());
|
||||
if (node) {
|
||||
if (arp->opcode() == Arp_packet::REQUEST) {
|
||||
/*
|
||||
* The ARP packet gets re-written, we interchange source
|
||||
* and destination MAC and IP addresses, and set the opcode
|
||||
* to reply, and then push the packet back to the NIC driver.
|
||||
*/
|
||||
Ipv4_packet::Ipv4_address old_src_ip = arp->src_ip();
|
||||
arp->opcode(Arp_packet::REPLY);
|
||||
arp->dst_mac(arp->src_mac());
|
||||
arp->src_mac(mac());
|
||||
arp->src_ip(arp->dst_ip());
|
||||
arp->dst_ip(old_src_ip);
|
||||
eth->dst(arp->dst_mac());
|
||||
|
||||
/* set our MAC as sender */
|
||||
eth->src(mac());
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Net::Nic::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Ipv4_packet *ip = new (eth->data())
|
||||
Ipv4_packet(size - sizeof(Ethernet_frame));
|
||||
|
||||
/* is it an UDP packet ? */
|
||||
if (ip->protocol() == Udp_packet::IP_ID)
|
||||
{
|
||||
Udp_packet *udp = new (ip->data())
|
||||
Udp_packet(size - sizeof(Ipv4_packet));
|
||||
|
||||
/* is it a DHCP packet ? */
|
||||
if (Dhcp_packet::is_dhcp(udp)) {
|
||||
Dhcp_packet *dhcp = new (udp->data())
|
||||
Dhcp_packet(size - sizeof(Ipv4_packet) - sizeof(Udp_packet));
|
||||
|
||||
/* check for DHCP ACKs containing new client ips */
|
||||
if (dhcp->op() == Dhcp_packet::REPLY) {
|
||||
Dhcp_packet::Option *ext = dhcp->option(Dhcp_packet::MSG_TYPE);
|
||||
if (ext) {
|
||||
/*
|
||||
* extract the IP address and set it in the
|
||||
* client's session-component
|
||||
*/
|
||||
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();
|
||||
if (node)
|
||||
node = node->find_by_address(dhcp->client_mac());
|
||||
if (node)
|
||||
node->component()->set_ipv4_address(dhcp->yiaddr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (node) {
|
||||
node = node->find_by_address(ip->dst());
|
||||
if (node) {
|
||||
/* overwrite destination MAC */
|
||||
eth->dst(node->component()->mac_address().addr);
|
||||
|
||||
/* deliver the packet to the client */
|
||||
node->component()->send(eth, size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Net::Nic::Nic()
|
||||
: _tx_block_alloc(Genode::env()->heap()),
|
||||
_nic(&_tx_block_alloc, BUF_SIZE, BUF_SIZE)
|
||||
{
|
||||
_nic.rx_channel()->sigh_ready_to_ack(_sink_ack);
|
||||
_nic.rx_channel()->sigh_packet_avail(_sink_submit);
|
||||
_nic.tx_channel()->sigh_ack_avail(_source_ack);
|
||||
_nic.tx_channel()->sigh_ready_to_submit(_source_submit);
|
||||
}
|
64
os/src/server/nic_bridge/nic.h
Normal file
64
os/src/server/nic_bridge/nic.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* \brief Proxy-ARP NIC session handler
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-18
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _SRC__SERVER__NIC_BRIDGE__NIC_H_
|
||||
#define _SRC__SERVER__NIC_BRIDGE__NIC_H_
|
||||
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "packet_handler.h"
|
||||
|
||||
namespace Net {
|
||||
class Nic;
|
||||
}
|
||||
|
||||
|
||||
class Net::Nic : public Net::Packet_handler
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
PACKET_SIZE = ::Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
|
||||
BUF_SIZE = ::Nic::Session::QUEUE_SIZE * PACKET_SIZE,
|
||||
};
|
||||
|
||||
::Nic::Packet_allocator _tx_block_alloc;
|
||||
::Nic::Connection _nic;
|
||||
|
||||
public:
|
||||
|
||||
Nic();
|
||||
|
||||
::Nic::Connection *nic() { return &_nic; }
|
||||
|
||||
Ethernet_frame::Mac_address mac() { return _nic.mac_address().addr; }
|
||||
|
||||
|
||||
/******************************
|
||||
** Packet_handler interface **
|
||||
******************************/
|
||||
|
||||
Packet_stream_sink< ::Nic::Session::Policy> * sink() {
|
||||
return _nic.rx(); }
|
||||
|
||||
Packet_stream_source< ::Nic::Session::Policy> * source() {
|
||||
return _nic.tx(); }
|
||||
|
||||
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) {}
|
||||
};
|
||||
|
||||
#endif /* _SRC__SERVER__NIC_BRIDGE__NIC_H_ */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Thread implementations handling network packets.
|
||||
* \brief Packet handler handling network packets.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-18
|
||||
*/
|
||||
@ -18,14 +18,40 @@
|
||||
#include <net/ipv4.h>
|
||||
#include <net/udp.h>
|
||||
|
||||
#include "env.h"
|
||||
#include "component.h"
|
||||
#include "packet_handler.h"
|
||||
#include "vlan.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
static const bool verbose = true;
|
||||
|
||||
static Genode::Lock _nic_lock;
|
||||
void Packet_handler::_ready_to_submit(unsigned)
|
||||
{
|
||||
/* as long as packets are available, and we can ack them */
|
||||
while (sink()->packet_avail()) {
|
||||
_packet = sink()->get_packet();
|
||||
if (!_packet.valid()) continue;
|
||||
handle_ethernet(sink()->packet_content(_packet), _packet.size());
|
||||
|
||||
if (!sink()->ready_to_ack()) {
|
||||
if (verbose)
|
||||
PWRN("ack state FULL");
|
||||
return;
|
||||
}
|
||||
|
||||
sink()->acknowledge_packet(_packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Packet_handler::_ready_to_ack(unsigned)
|
||||
{
|
||||
/* check for acknowledgements */
|
||||
while (source()->ack_avail())
|
||||
source()->release_packet(source()->get_acked_packet());
|
||||
}
|
||||
|
||||
|
||||
void Packet_handler::broadcast_to_clients(Ethernet_frame *eth, Genode::size_t size)
|
||||
@ -34,202 +60,66 @@ 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::vlan()->mac_list()->first();
|
||||
Env::vlan()->mac_list()->first();
|
||||
while (node) {
|
||||
/* deliver packet */
|
||||
node->receive_packet((void*) eth, size);
|
||||
node->component()->send(eth, size);
|
||||
node = node->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Packet_handler::send_to_nic(Ethernet_frame *eth, Genode::size_t size)
|
||||
void Packet_handler::handle_ethernet(void* src, Genode::size_t size)
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_nic_lock);
|
||||
|
||||
while (true) {
|
||||
/* check for acknowledgements */
|
||||
while (_session->tx()->ack_avail()) {
|
||||
Packet_descriptor p =
|
||||
_session->tx()->get_acked_packet();
|
||||
_session->tx()->release_packet(p);
|
||||
try {
|
||||
/* parse ethernet frame header */
|
||||
Ethernet_frame *eth = new (src) Ethernet_frame(size);
|
||||
switch (eth->type()) {
|
||||
case Ethernet_frame::ARP:
|
||||
if (!handle_arp(eth, size)) return;
|
||||
break;
|
||||
case Ethernet_frame::IPV4:
|
||||
if(!handle_ip(eth, size)) return;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
try {
|
||||
/* set our MAC as sender */
|
||||
eth->src(_mac);
|
||||
|
||||
/* allocate packet to NIC driver */
|
||||
Packet_descriptor tx_packet = _session->tx()->alloc_packet(size);
|
||||
char *tx_content = _session->tx()->packet_content(tx_packet);
|
||||
|
||||
/* copy and submit packet */
|
||||
Genode::memcpy((void*)tx_content, (void*)eth, size);
|
||||
_session->tx()->submit_packet(tx_packet);
|
||||
return;
|
||||
} catch(Nic::Session::Tx::Source::Packet_alloc_failed) { }
|
||||
broadcast_to_clients(eth, size);
|
||||
finalize_packet(eth, size);
|
||||
} catch(Arp_packet::No_arp_packet) {
|
||||
PWRN("Invalid ARP packet!");
|
||||
} catch(Ethernet_frame::No_ethernet_frame) {
|
||||
PWRN("Invalid ethernet frame");
|
||||
} catch(Dhcp_packet::No_dhcp_packet) {
|
||||
PWRN("Invalid IPv4 packet!");
|
||||
} catch(Ipv4_packet::No_ip_packet) {
|
||||
PWRN("Invalid IPv4 packet!");
|
||||
} catch(Udp_packet::No_udp_packet) {
|
||||
PWRN("Invalid UDP packet!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Packet_handler::entry()
|
||||
void Packet_handler::send(Ethernet_frame *eth, Genode::size_t size)
|
||||
{
|
||||
void* src;
|
||||
Genode::size_t eth_sz;
|
||||
|
||||
/* signal preparedness */
|
||||
_startup_sem.up();
|
||||
|
||||
/* loop for new packets */
|
||||
while (true) {
|
||||
try {
|
||||
acknowledge_last_one();
|
||||
next_packet(&src, ð_sz);
|
||||
|
||||
/* parse ethernet frame header */
|
||||
Ethernet_frame *eth = new (src) Ethernet_frame(eth_sz);
|
||||
switch (eth->type()) {
|
||||
case Ethernet_frame::ARP:
|
||||
{
|
||||
if (!handle_arp(eth, eth_sz))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case Ethernet_frame::IPV4:
|
||||
{
|
||||
if(!handle_ip(eth, eth_sz))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
/* broadcast packet ? */
|
||||
broadcast_to_clients(eth, eth_sz);
|
||||
|
||||
finalize_packet(eth, eth_sz);
|
||||
} catch(Arp_packet::No_arp_packet) {
|
||||
PWRN("Invalid ARP packet!");
|
||||
} catch(Ethernet_frame::No_ethernet_frame) {
|
||||
PWRN("Invalid ethernet frame");
|
||||
} catch(Dhcp_packet::No_dhcp_packet) {
|
||||
PWRN("Invalid IPv4 packet!");
|
||||
} catch(Ipv4_packet::No_ip_packet) {
|
||||
PWRN("Invalid IPv4 packet!");
|
||||
} catch(Udp_packet::No_udp_packet) {
|
||||
PWRN("Invalid UDP packet!");
|
||||
}
|
||||
try {
|
||||
/* copy and submit packet */
|
||||
Packet_descriptor packet = source()->alloc_packet(size);
|
||||
char *content = source()->packet_content(packet);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Rx_handler::acknowledge_last_one() {
|
||||
/* acknowledge packet to NIC driver */
|
||||
if(_rx_packet.valid())
|
||||
_session->rx()->acknowledge_packet(_rx_packet);
|
||||
}
|
||||
|
||||
|
||||
void Rx_handler::next_packet(void** src, Genode::size_t *size) {
|
||||
/* get next packet from NIC driver */
|
||||
_rx_packet = _session->rx()->get_packet();
|
||||
*src = _session->rx()->packet_content(_rx_packet);
|
||||
*size = _rx_packet.size();
|
||||
}
|
||||
|
||||
|
||||
bool Rx_handler::handle_arp(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Arp_packet *arp = new (eth->data())
|
||||
Arp_packet(size - sizeof(Ethernet_frame));
|
||||
|
||||
/* ignore broken packets */
|
||||
if (!arp->ethernet_ipv4())
|
||||
return true;
|
||||
|
||||
/* look whether the IP address is one of our client's */
|
||||
Ipv4_address_node *node = Vlan::vlan()->ip_tree()->first();
|
||||
if (node)
|
||||
node = node->find_by_address(arp->dst_ip());
|
||||
if (node) {
|
||||
if (arp->opcode() == Arp_packet::REQUEST) {
|
||||
/*
|
||||
* The ARP packet gets re-written, we interchange source
|
||||
* and destination MAC and IP addresses, and set the opcode
|
||||
* to reply, and then push the packet back to the NIC driver.
|
||||
*/
|
||||
Ipv4_packet::Ipv4_address old_src_ip = arp->src_ip();
|
||||
arp->opcode(Arp_packet::REPLY);
|
||||
arp->dst_mac(arp->src_mac());
|
||||
arp->src_mac(_mac);
|
||||
arp->src_ip(arp->dst_ip());
|
||||
arp->dst_ip(old_src_ip);
|
||||
eth->dst(arp->dst_mac());
|
||||
send_to_nic(eth, size);
|
||||
} else {
|
||||
/* overwrite destination MAC */
|
||||
arp->dst_mac(node->component()->mac_address().addr);
|
||||
eth->dst(node->component()->mac_address().addr);
|
||||
node->receive_packet((void*) eth, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Rx_handler::handle_ip(Ethernet_frame *eth, Genode::size_t size) {
|
||||
Ipv4_packet *ip = new (eth->data())
|
||||
Ipv4_packet(size - sizeof(Ethernet_frame));
|
||||
|
||||
/* is it an UDP packet ? */
|
||||
if (ip->protocol() == Udp_packet::IP_ID)
|
||||
{
|
||||
Udp_packet *udp = new (ip->data())
|
||||
Udp_packet(size - sizeof(Ipv4_packet));
|
||||
|
||||
/* is it a DHCP packet ? */
|
||||
if (Dhcp_packet::is_dhcp(udp)) {
|
||||
Dhcp_packet *dhcp = new (udp->data())
|
||||
Dhcp_packet(size - sizeof(Ipv4_packet) - sizeof(Udp_packet));
|
||||
|
||||
/* check for DHCP ACKs containing new client ips */
|
||||
if (dhcp->op() == Dhcp_packet::REPLY) {
|
||||
Dhcp_packet::Option *ext = dhcp->option(Dhcp_packet::MSG_TYPE);
|
||||
if (ext) {
|
||||
/*
|
||||
* extract the IP address and set it in the
|
||||
* client's session-component
|
||||
*/
|
||||
Genode::uint8_t *msg_type = (Genode::uint8_t*) ext->value();
|
||||
if (*msg_type == Dhcp_packet::DHCP_ACK) {
|
||||
Mac_address_node *node =
|
||||
Vlan::vlan()->mac_tree()->first();
|
||||
if (node)
|
||||
node = node->find_by_address(dhcp->client_mac());
|
||||
if (node)
|
||||
node->component()->set_ipv4_address(dhcp->yiaddr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* is it an unicast message to one of our clients ? */
|
||||
if (eth->dst() == _mac) {
|
||||
Ipv4_address_node *node = Vlan::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);
|
||||
|
||||
/* deliver the packet to the client */
|
||||
node->receive_packet((void*) eth, size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
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)
|
||||
{ }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Thread implementations handling network packets.
|
||||
* \brief Signal driven NIC packet handler
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-18
|
||||
*/
|
||||
@ -22,147 +22,111 @@
|
||||
#include <net/ipv4.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
/**
|
||||
* Generic thread-implementation used as base for
|
||||
* global receiver thread and client's transmit-threads.
|
||||
*/
|
||||
class Packet_handler : public Genode::Thread<8192>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Semaphore _startup_sem; /* thread startup sync */
|
||||
|
||||
protected:
|
||||
|
||||
Nic::Connection *_session; /* session to nic driver */
|
||||
Ethernet_frame::Mac_address _mac; /* real nic's mac */
|
||||
|
||||
/**
|
||||
* Broadcasts ethernet frame to all clients,
|
||||
* as long as its really a broadcast packtet.
|
||||
*
|
||||
* \param eth ethernet frame to send.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
void inline broadcast_to_clients(Ethernet_frame *eth,
|
||||
Genode::size_t size);
|
||||
|
||||
/**
|
||||
* Send ethernet frame to NIC driver.
|
||||
*
|
||||
* \param eth ethernet frame to send.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
void send_to_nic(Ethernet_frame *eth, Genode::size_t size);
|
||||
|
||||
/**
|
||||
* Acknowledge the last processed packet.
|
||||
*/
|
||||
virtual void acknowledge_last_one() = 0;
|
||||
|
||||
/**
|
||||
* Block for the next packet to process.
|
||||
*/
|
||||
virtual void next_packet(void** src,
|
||||
Genode::size_t *size) = 0;
|
||||
|
||||
/*
|
||||
* Handle an ARP packet
|
||||
*
|
||||
* \param eth ethernet frame containing the ARP packet.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
virtual bool handle_arp(Ethernet_frame *eth,
|
||||
Genode::size_t size) = 0;
|
||||
|
||||
/*
|
||||
* Handle an IP packet
|
||||
*
|
||||
* \param eth ethernet frame containing the IP packet.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
virtual bool handle_ip(Ethernet_frame *eth,
|
||||
Genode::size_t size) = 0;
|
||||
|
||||
/*
|
||||
* Finalize handling of ethernet frame.
|
||||
*
|
||||
* \param eth ethernet frame to handle.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
virtual void finalize_packet(Ethernet_frame *eth,
|
||||
Genode::size_t size) {}
|
||||
|
||||
public:
|
||||
|
||||
Packet_handler(Nic::Connection *session)
|
||||
: _session(session), _mac(session->mac_address().addr) {}
|
||||
|
||||
/*
|
||||
* Thread's entry code.
|
||||
*/
|
||||
void entry();
|
||||
|
||||
/*
|
||||
* Block until thread is ready to execute.
|
||||
*/
|
||||
void wait_for_startup() { _startup_sem.down(); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receiver thread handling network packets from the NIC driver
|
||||
*/
|
||||
class Rx_handler : public Packet_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Packet_descriptor _rx_packet; /* actual processed packet */
|
||||
|
||||
/**
|
||||
* Acknowledge the last processed packet.
|
||||
*/
|
||||
void acknowledge_last_one();
|
||||
|
||||
/**
|
||||
* Block for the next packet to process.
|
||||
*
|
||||
* \param src buffer the network packet gets written to.
|
||||
* \param size size of packet gets written to.
|
||||
*/
|
||||
void next_packet(void** src, Genode::size_t *size);
|
||||
|
||||
/*
|
||||
* Handle an ARP packet.
|
||||
* If it's an ARP request for an IP of one of our client's,
|
||||
* reply directly with the NIC's MAC address.
|
||||
*
|
||||
* \param eth ethernet frame containing the ARP packet.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
bool handle_arp(Ethernet_frame *eth, Genode::size_t size);
|
||||
|
||||
/*
|
||||
* Handle an IP packet.
|
||||
* IP packets have to be inspected for DHCP replies.
|
||||
* If an reply contains a new IP address for one of our
|
||||
* client's, the client's database needs to be updated.
|
||||
*
|
||||
* \param eth ethernet frame containing the IP packet.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
bool handle_ip(Ethernet_frame *eth, Genode::size_t size);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param session session to NIC driver.
|
||||
*/
|
||||
Rx_handler(Nic::Connection *session) : Packet_handler(session) {}
|
||||
};
|
||||
class Packet_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic packet handler used as base for NIC and client packet handlers.
|
||||
*/
|
||||
class Net::Packet_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Packet_descriptor _packet;
|
||||
|
||||
/**
|
||||
* submit queue not empty anymore
|
||||
*/
|
||||
void _ready_to_submit(unsigned);
|
||||
|
||||
/**
|
||||
* acknoledgement queue not full anymore
|
||||
*
|
||||
* 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) { }
|
||||
|
||||
/**
|
||||
* acknoledgement queue not empty anymore
|
||||
*/
|
||||
void _ready_to_ack(unsigned);
|
||||
|
||||
/**
|
||||
* submit queue not full anymore
|
||||
*
|
||||
* 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) { }
|
||||
|
||||
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;
|
||||
|
||||
public:
|
||||
|
||||
Packet_handler();
|
||||
|
||||
virtual Packet_stream_sink< ::Nic::Session::Policy> * sink() = 0;
|
||||
virtual Packet_stream_source< ::Nic::Session::Policy> * source() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Broadcasts ethernet frame to all clients,
|
||||
* as long as its really a broadcast packtet.
|
||||
*
|
||||
* \param eth ethernet frame to send.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
void inline broadcast_to_clients(Ethernet_frame *eth,
|
||||
Genode::size_t size);
|
||||
|
||||
/**
|
||||
* Send ethernet frame
|
||||
*
|
||||
* \param eth ethernet frame to send.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
void send(Ethernet_frame *eth, Genode::size_t size);
|
||||
|
||||
/**
|
||||
* Handle an ethernet packet
|
||||
*
|
||||
* \param src ethernet frame's address
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
void handle_ethernet(void* src, Genode::size_t size);
|
||||
|
||||
/*
|
||||
* Handle an ARP packet
|
||||
*
|
||||
* \param eth ethernet frame containing the ARP packet.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
virtual bool handle_arp(Ethernet_frame *eth,
|
||||
Genode::size_t size) = 0;
|
||||
|
||||
/*
|
||||
* Handle an IP packet
|
||||
*
|
||||
* \param eth ethernet frame containing the IP packet.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
virtual bool handle_ip(Ethernet_frame *eth,
|
||||
Genode::size_t size) = 0;
|
||||
|
||||
/*
|
||||
* Finalize handling of ethernet frame.
|
||||
*
|
||||
* \param eth ethernet frame to handle.
|
||||
* \param size ethernet frame's size.
|
||||
*/
|
||||
virtual void finalize_packet(Ethernet_frame *eth,
|
||||
Genode::size_t size) = 0;
|
||||
};
|
||||
|
||||
#endif /* _PACKET_HANDLER_H_ */
|
||||
|
@ -1,6 +1,5 @@
|
||||
TARGET = nic_bridge
|
||||
LIBS = base net
|
||||
SRC_CC = address_node.cc component.cc mac.cc \
|
||||
main.cc packet_handler.cc vlan.cc
|
||||
SRC_CC = component.cc env.cc mac.cc main.cc nic.cc packet_handler.cc
|
||||
|
||||
vpath *.cc $(REP_DIR)/src/server/proxy_arp
|
||||
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* \brief Virtual local network.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-08-18
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "vlan.h"
|
||||
|
||||
Net::Vlan* Net::Vlan::vlan()
|
||||
{
|
||||
static Net::Vlan vlan;
|
||||
return &vlan;
|
||||
}
|
@ -40,17 +40,14 @@ namespace Net {
|
||||
Mac_address_list _mac_list;
|
||||
Ipv4_address_tree _ip_tree;
|
||||
|
||||
Vlan() {}
|
||||
|
||||
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; }
|
||||
|
||||
static Vlan *vlan();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _VLAN_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user