From 7ca7b4417d27199d79430675474b45b32618a32d Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Wed, 5 Sep 2012 12:04:00 +0200 Subject: [PATCH] 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 --- libports/run/lwip.run | 32 +++++++--- libports/src/lib/lwip/platform/nic.cc | 90 +++++++++++++++++---------- ports/run/genode_org.run | 2 + 3 files changed, 85 insertions(+), 39 deletions(-) diff --git a/libports/run/lwip.run b/libports/run/lwip.run index 9723825f3..76e304f45 100644 --- a/libports/run/lwip.run +++ b/libports/run/lwip.run @@ -28,12 +28,16 @@ requires_installation_of lynx # Build # -build { +set build_components { core init drivers/pci drivers/timer drivers/nic test/lwip/http_srv } +lappend_if [have_spec omap4] build_components drivers/usb + +build $build_components + create_boot_directory # @@ -62,14 +66,27 @@ set config { - - - - } +append_if [have_spec omap4] config { + + + + + + + + + } + +append_if [expr ![have_spec omap4]] config { + + + + } + append_if [have_spec pci] config { @@ -89,12 +106,13 @@ install_config $config # generic modules set boot_modules { core init timer - nic_drv ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so test-lwip_httpsrv } # 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 diff --git a/libports/src/lib/lwip/platform/nic.cc b/libports/src/lib/lwip/platform/nic.cc index e6d6bbd04..bdbd03d6b 100644 --- a/libports/src/lib/lwip/platform/nic.cc +++ b/libports/src/lib/lwip/platform/nic.cc @@ -28,7 +28,7 @@ extern "C" { /* Genode includes */ #include #include -#include +#include #include @@ -43,6 +43,16 @@ class Nic_receiver_thread : public Genode::Thread<8192> Packet_descriptor _rx_packet; /* actual packet received */ 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: Nic_receiver_thread(Nic::Connection *nic, struct netif *netif) @@ -51,6 +61,29 @@ class Nic_receiver_thread : public Genode::Thread<8192> void entry(); Nic::Connection *nic() { return _nic; }; 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,39 +114,26 @@ extern "C" { low_level_output(struct netif *netif, struct pbuf *p) { Nic_receiver_thread *th = reinterpret_cast(netif->state); - Nic::Connection *nic = th->nic(); #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif - try { - Packet_descriptor tx_packet = nic->tx()->alloc_packet(p->tot_len); - char *tx_content = nic->tx()->packet_content(tx_packet); + Packet_descriptor tx_packet = th->alloc_tx_packet(p->tot_len); + char *tx_content = th->content(tx_packet); - /* - * Iterate through all pbufs and - * copy payload into packet's payload - */ - for(struct pbuf *q = p; q != NULL; q = q->next) { - char *src = (char*) q->payload; - for (unsigned i = 0; i < q->len; i++) - tx_content[i] = src[i]; - tx_content += q->len; - } - - /* Submit packet */ - nic->tx()->submit_packet(tx_packet); - } catch(Nic::Session::Tx::Source::Packet_alloc_failed) - { - PWRN("Packets to NIC were dropped!"); - return ERR_MEM; + /* + * Iterate through all pbufs and + * copy payload into packet's payload + */ + for(struct pbuf *q = p; q != NULL; q = q->next) { + char *src = (char*) q->payload; + Genode::memcpy(tx_content, src, q->len); + tx_content += q->len; } - /* Check for acknowledgements */ - while (nic->tx()->ack_avail()) { - Packet_descriptor acked_packet = nic->tx()->get_acked_packet(); - nic->tx()->release_packet(acked_packet); - } + /* Submit packet */ + th->submit_tx_packet(tx_packet); + #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif @@ -156,10 +176,10 @@ extern "C" { */ for(struct pbuf *q = p; q != 0; q = q->next) { char *dst = (char*)q->payload; - for(unsigned i=0; i < q->len; ++i) - dst[i] = rx_content[i]; + Genode::memcpy(dst, rx_content, q->len); rx_content += q->len; } + #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif @@ -222,12 +242,18 @@ extern "C" { LWIP_ASSERT("netif != NULL", (netif != NULL)); /* Initialize nic-session */ - Allocator_avl *tx_block_alloc = new (env()->heap()) - Allocator_avl(env()->heap()); + enum { + 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; 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) { destroy(env()->heap(), tx_block_alloc); return ERR_IF; diff --git a/ports/run/genode_org.run b/ports/run/genode_org.run index 209d3d7fb..ab2c8e6c6 100644 --- a/ports/run/genode_org.run +++ b/ports/run/genode_org.run @@ -18,6 +18,8 @@ set build_components { app/lighttpd } +lappend_if [have_spec omap4] build_components drivers/usb + build $build_components create_boot_directory