lwIP: Rewrite NIC packet allocation

Use 'Nic::Packet_allocator', wait for acknowledgements if packet allocation
fails. Updated 'lwip.run' and 'genode_org.run' to support OMAP4 correctly. Use
memcpy to copy PBUFs

May resolve issue #347
This commit is contained in:
Sebastian Sumpf 2012-09-05 12:04:00 +02:00 committed by Norman Feske
parent 5c36639031
commit 7ca7b4417d
3 changed files with 85 additions and 39 deletions

View File

@ -28,12 +28,16 @@ requires_installation_of lynx
# Build # Build
# #
build { set build_components {
core init core init
drivers/pci drivers/timer drivers/nic drivers/pci drivers/timer drivers/nic
test/lwip/http_srv test/lwip/http_srv
} }
lappend_if [have_spec omap4] build_components drivers/usb
build $build_components
create_boot_directory create_boot_directory
# #
@ -62,14 +66,27 @@ set config {
<resource name="RAM" quantum="1M"/> <resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides> <provides> <service name="Timer"/> </provides>
</start> </start>
<start name="nic_drv">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Nic"/> </provides>
</start>
<start name="test-lwip_httpsrv"> <start name="test-lwip_httpsrv">
<resource name="RAM" quantum="2M"/> <resource name="RAM" quantum="2M"/>
</start> } </start> }
append_if [have_spec omap4] config {
<start name="usb_drv" priority="-1">
<resource name="RAM" quantum="12M"/>
<provides>
<service name="Nic"/>
</provides>
<config>
<nic mac="2e:60:90:0c:4e:01" />
</config>
</start>}
append_if [expr ![have_spec omap4]] config {
<start name="nic_drv">
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
</start>}
append_if [have_spec pci] config { append_if [have_spec pci] config {
<start name="pci_drv"> <start name="pci_drv">
<resource name="RAM" quantum="1M"/> <resource name="RAM" quantum="1M"/>
@ -89,12 +106,13 @@ install_config $config
# generic modules # generic modules
set boot_modules { set boot_modules {
core init timer core init timer
nic_drv
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so test-lwip_httpsrv ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so test-lwip_httpsrv
} }
# platform-specific modules # platform-specific modules
lappend_if [have_spec pci] boot_modules pci_drv lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec omap4] boot_modules usb_drv
lappend_if [expr ![have_spec omap4]] boot_modules nic_drv
build_boot_image $boot_modules build_boot_image $boot_modules

View File

@ -28,7 +28,7 @@ extern "C" {
/* Genode includes */ /* Genode includes */
#include <base/thread.h> #include <base/thread.h>
#include <base/printf.h> #include <base/printf.h>
#include <base/allocator_avl.h> #include <nic/packet_allocator.h>
#include <nic_session/connection.h> #include <nic_session/connection.h>
@ -43,6 +43,16 @@ class Nic_receiver_thread : public Genode::Thread<8192>
Packet_descriptor _rx_packet; /* actual packet received */ Packet_descriptor _rx_packet; /* actual packet received */
struct netif *_netif; /* LwIP network interface structure */ struct netif *_netif; /* LwIP network interface structure */
void _tx_ack(bool block = false)
{
/* check for acknowledgements */
while (nic()->tx()->ack_avail() || block) {
Packet_descriptor acked_packet = nic()->tx()->get_acked_packet();
nic()->tx()->release_packet(acked_packet);
block = false;
}
}
public: public:
Nic_receiver_thread(Nic::Connection *nic, struct netif *netif) Nic_receiver_thread(Nic::Connection *nic, struct netif *netif)
@ -51,6 +61,29 @@ class Nic_receiver_thread : public Genode::Thread<8192>
void entry(); void entry();
Nic::Connection *nic() { return _nic; }; Nic::Connection *nic() { return _nic; };
Packet_descriptor rx_packet() { return _rx_packet; }; Packet_descriptor rx_packet() { return _rx_packet; };
Packet_descriptor alloc_tx_packet(Genode::size_t size)
{
while (true) {
try {
Packet_descriptor packet = nic()->tx()->alloc_packet(size);
return packet;
} catch(Nic::Session::Tx::Source::Packet_alloc_failed) {
/* packet allocator exhausted, wait for acknowledgements */
_tx_ack(true);
}
}
}
void submit_tx_packet(Packet_descriptor packet)
{
nic()->tx()->submit_packet(packet);
/* check for acknowledgements */
_tx_ack();
}
char *content(Packet_descriptor packet) {
return nic()->tx()->packet_content(packet); }
}; };
@ -81,14 +114,12 @@ extern "C" {
low_level_output(struct netif *netif, struct pbuf *p) low_level_output(struct netif *netif, struct pbuf *p)
{ {
Nic_receiver_thread *th = reinterpret_cast<Nic_receiver_thread*>(netif->state); Nic_receiver_thread *th = reinterpret_cast<Nic_receiver_thread*>(netif->state);
Nic::Connection *nic = th->nic();
#if ETH_PAD_SIZE #if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif #endif
try { Packet_descriptor tx_packet = th->alloc_tx_packet(p->tot_len);
Packet_descriptor tx_packet = nic->tx()->alloc_packet(p->tot_len); char *tx_content = th->content(tx_packet);
char *tx_content = nic->tx()->packet_content(tx_packet);
/* /*
* Iterate through all pbufs and * Iterate through all pbufs and
@ -96,24 +127,13 @@ extern "C" {
*/ */
for(struct pbuf *q = p; q != NULL; q = q->next) { for(struct pbuf *q = p; q != NULL; q = q->next) {
char *src = (char*) q->payload; char *src = (char*) q->payload;
for (unsigned i = 0; i < q->len; i++) Genode::memcpy(tx_content, src, q->len);
tx_content[i] = src[i];
tx_content += q->len; tx_content += q->len;
} }
/* Submit packet */ /* Submit packet */
nic->tx()->submit_packet(tx_packet); th->submit_tx_packet(tx_packet);
} catch(Nic::Session::Tx::Source::Packet_alloc_failed)
{
PWRN("Packets to NIC were dropped!");
return ERR_MEM;
}
/* Check for acknowledgements */
while (nic->tx()->ack_avail()) {
Packet_descriptor acked_packet = nic->tx()->get_acked_packet();
nic->tx()->release_packet(acked_packet);
}
#if ETH_PAD_SIZE #if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif #endif
@ -156,10 +176,10 @@ extern "C" {
*/ */
for(struct pbuf *q = p; q != 0; q = q->next) { for(struct pbuf *q = p; q != 0; q = q->next) {
char *dst = (char*)q->payload; char *dst = (char*)q->payload;
for(unsigned i=0; i < q->len; ++i) Genode::memcpy(dst, rx_content, q->len);
dst[i] = rx_content[i];
rx_content += q->len; rx_content += q->len;
} }
#if ETH_PAD_SIZE #if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif #endif
@ -222,12 +242,18 @@ extern "C" {
LWIP_ASSERT("netif != NULL", (netif != NULL)); LWIP_ASSERT("netif != NULL", (netif != NULL));
/* Initialize nic-session */ /* Initialize nic-session */
Allocator_avl *tx_block_alloc = new (env()->heap()) enum {
Allocator_avl(env()->heap()); PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
RX_BUF_SIZE = Nic::Session::RX_QUEUE_SIZE * PACKET_SIZE,
TX_BUF_SIZE = Nic::Session::TX_QUEUE_SIZE * PACKET_SIZE,
};
Nic::Packet_allocator *tx_block_alloc = new (env()->heap())
Nic::Packet_allocator(env()->heap());
Nic::Connection *nic = 0; Nic::Connection *nic = 0;
try { try {
nic = new (env()->heap()) Nic::Connection(tx_block_alloc); nic = new (env()->heap()) Nic::Connection(tx_block_alloc, TX_BUF_SIZE, RX_BUF_SIZE);
} catch (Parent::Service_denied) { } catch (Parent::Service_denied) {
destroy(env()->heap(), tx_block_alloc); destroy(env()->heap(), tx_block_alloc);
return ERR_IF; return ERR_IF;

View File

@ -18,6 +18,8 @@ set build_components {
app/lighttpd app/lighttpd
} }
lappend_if [have_spec omap4] build_components drivers/usb
build $build_components build $build_components
create_boot_directory create_boot_directory