lwip: packet-stream/link-state signals in recv thread

Issue #1327
This commit is contained in:
Josef Söntgen 2015-03-12 20:23:05 +01:00 committed by Christian Helmuth
parent 6c6375aa83
commit 2d469cb35c
4 changed files with 102 additions and 50 deletions

View File

@ -47,6 +47,13 @@ int lwip_nic_init(genode_int32_t ip_addr,
__SIZE_TYPE__ tx_buf_size,
__SIZE_TYPE__ rx_buf_size);
/**
* Pass on link-state changes to lwIP
*
* \param state current link-state
*/
void lwip_nic_link_state_changed(int state);
#ifdef __cplusplus
}
#endif

View File

@ -42,7 +42,8 @@
#define TCP_RCV_SCALE 2 /* receive scale factor IETF RFC 1323 */
#if LWIP_DHCP
#define LWIP_NETIF_STATUS_CALLBACK 1 /* callback function used by DHCP init */
#define LWIP_NETIF_STATUS_CALLBACK 1 /* callback function used for interface changes */
#define LWIP_NETIF_LINK_CALLBACK 1 /* callback function used for link-state changes */
#endif
/***********************************

View File

@ -32,6 +32,13 @@ extern "C" {
#include <nic/packet_allocator.h>
#include <nic_session/connection.h>
extern "C" {
static void genode_netif_input(struct netif *netif);
void lwip_nic_link_state_changed(int state);
}
/*
* Thread, that receives packets by the nic-session interface.
@ -46,6 +53,28 @@ class Nic_receiver_thread : public Genode::Thread<8192>
Packet_descriptor _rx_packet; /* actual packet received */
struct netif *_netif; /* LwIP network interface structure */
Genode::Signal_receiver _sig_rec;
Genode::Signal_dispatcher<Nic_receiver_thread> _link_state_dispatcher;
Genode::Signal_dispatcher<Nic_receiver_thread> _rx_packet_avail_dispatcher;
Genode::Signal_dispatcher<Nic_receiver_thread> _rx_ready_to_ack_dispatcher;
void _handle_rx_packet_avail(unsigned)
{
while (_nic->rx()->packet_avail() && _nic->rx()->ready_to_ack()) {
_rx_packet = _nic->rx()->get_packet();
genode_netif_input(_netif);
_nic->rx()->acknowledge_packet(_rx_packet);
}
}
void _handle_rx_read_to_ack(unsigned) { _handle_rx_packet_avail(0); }
void _handle_link_state(unsigned)
{
lwip_nic_link_state_changed(_nic->link_state());
}
void _tx_ack(bool block = false)
{
/* check for acknowledgements */
@ -59,7 +88,16 @@ class Nic_receiver_thread : public Genode::Thread<8192>
public:
Nic_receiver_thread(Nic::Connection *nic, struct netif *netif)
: Genode::Thread<8192>("nic-recv"), _nic(nic), _netif(netif) {}
:
Genode::Thread<8192>("nic-recv"), _nic(nic), _netif(netif),
_link_state_dispatcher(_sig_rec, *this, &Nic_receiver_thread::_handle_link_state),
_rx_packet_avail_dispatcher(_sig_rec, *this, &Nic_receiver_thread::_handle_rx_packet_avail),
_rx_ready_to_ack_dispatcher(_sig_rec, *this, &Nic_receiver_thread::_handle_rx_read_to_ack)
{
_nic->link_state_sigh(_link_state_dispatcher);
_nic->rx_channel()->sigh_packet_avail(_rx_packet_avail_dispatcher);
_nic->rx_channel()->sigh_ready_to_ack(_rx_ready_to_ack_dispatcher);
}
void entry();
Nic::Connection *nic() { return _nic; };
@ -95,9 +133,6 @@ class Nic_receiver_thread : public Genode::Thread<8192>
*/
extern "C" {
static void genode_netif_input(struct netif *netif);
/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
@ -192,8 +227,6 @@ extern "C" {
LINK_STATS_INC(link.drop);
}
/* Acknowledge the packet */
nic->rx()->acknowledge_packet(rx_packet);
return p;
}
@ -295,11 +328,11 @@ void Nic_receiver_thread::entry()
{
while(true)
{
/*
* Block until we receive a packet,
* then call input function.
*/
_rx_packet = _nic->rx()->get_packet();
genode_netif_input(_netif);
Genode::Signal sig = _sig_rec.wait_for_signal();
int num = sig.num();
Genode::Signal_dispatcher_base *dispatcher;
dispatcher = dynamic_cast<Genode::Signal_dispatcher_base *>(sig.context());
dispatcher->dispatch(num);
}
}

View File

@ -64,16 +64,6 @@ static Lwip::Mutex *global_mutex()
}
/**
* Returns a timed semaphore used to wait for DHCP to come up.
*/
static Genode::Timed_semaphore *dhcp_semaphore()
{
static Genode::Timed_semaphore _sem;
return &_sem;
}
/**
* Used for startup synchronization by the tcpip thread.
*/
@ -83,15 +73,6 @@ static void startup_done(void *arg)
}
/**
* Callback function used when doing dhcp requests,
* to check availability of an IP address.
*/
static void dhcp_callback(struct netif *netif)
{
dhcp_semaphore()->up();
}
using namespace Lwip;
extern "C" {
@ -115,6 +96,42 @@ extern "C" {
#error "You cannot use the Genode LwIP backend with NO_SYS!"
#endif //NO_SYS
#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL)
#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL)
static struct netif netif;
/*
* Callback function used when changing the interface state.
*/
static void status_callback(struct netif *netif)
{
static ip_addr_t ip_addr = { 0 };
if (ip_addr.addr != netif->ip_addr.addr) {
PINF("got IP address %d.%d.%d.%d",
ip4_addr1(&(netif->ip_addr)),
ip4_addr2(&(netif->ip_addr)),
ip4_addr3(&(netif->ip_addr)),
ip4_addr4(&(netif->ip_addr)));
ip_addr.addr = netif->ip_addr.addr;
}
}
/*
* Callback function used when doing a link-state change.
*/
static void link_callback(struct netif *netif)
{
/*
* We call the status callback at this point to print
* the IP address because we may have got a new one,
* e.h., we joined another wireless network.
*/
status_callback(netif);
}
/********************
** Initialization **
@ -141,7 +158,6 @@ extern "C" {
Genode::size_t tx_buf_size,
Genode::size_t rx_buf_size)
{
static struct netif netif;
struct ip_addr ip, nm, gw;
static struct netif_buf_sizes nbs;
nbs.tx_buf_size = tx_buf_size;
@ -174,25 +190,11 @@ extern "C" {
/* If no static ip was set, we do dhcp */
if (!ip_addr) {
#if LWIP_DHCP
/* Register callback function triggered, when DHCP succeeded. */
netif.status_callback = dhcp_callback;
/* Register callback functions. */
netif.status_callback = status_callback;
netif.link_callback = link_callback;
/* Start DHCP requests */
netifapi_dhcp_start(&netif);
/* Block until DHCP succeeded or a timeout was triggered */
try {
dhcp_semaphore()->down(20000);
} catch (Genode::Timeout_exception) {
PWRN("DHCP timed out!");
netifapi_dhcp_stop(&netif);
return 1;
}
PINF("got IP address %d.%d.%d.%d",
ip4_addr1(&(netif.ip_addr)),
ip4_addr2(&(netif.ip_addr)),
ip4_addr3(&(netif.ip_addr)),
ip4_addr4(&(netif.ip_addr)));
#else
/* no IP address - no networking */
return 1;
@ -208,6 +210,15 @@ extern "C" {
}
void lwip_nic_link_state_changed(int state)
{
if (state)
netifapi_netif_set_link_up(&netif);
else
netifapi_netif_set_link_down(&netif);
}
/***************
** Semaphore **
***************/