LwIP: manage Nic pbufs with a slab allocator
LwIP skips a packet copy by wrapping Nic stream buffer regions in LwIP pbuf objects. Move from a fixed size array to a potentially unbounded slab allocator for managing this buffer metadata. Ref #2335
This commit is contained in:
parent
4bb5046e1f
commit
22ef3ed474
|
@ -47,21 +47,27 @@ extern "C" {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
/**
|
|
||||||
* Metadata for packet backed pbufs
|
|
||||||
*/
|
|
||||||
struct nic_netif_pbuf
|
|
||||||
{
|
|
||||||
struct pbuf_custom p { };
|
|
||||||
Nic_netif *netif = nullptr;
|
|
||||||
Nic::Packet_descriptor packet { };
|
|
||||||
};
|
|
||||||
|
|
||||||
static void nic_netif_pbuf_free(pbuf *p);
|
static void nic_netif_pbuf_free(pbuf *p);
|
||||||
static err_t nic_netif_init(struct netif *netif);
|
static err_t nic_netif_init(struct netif *netif);
|
||||||
static err_t nic_netif_linkoutput(struct netif *netif, struct pbuf *p);
|
static err_t nic_netif_linkoutput(struct netif *netif, struct pbuf *p);
|
||||||
static void nic_netif_status_callback(struct netif *netif);
|
static void nic_netif_status_callback(struct netif *netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata for packet backed pbufs
|
||||||
|
*/
|
||||||
|
struct Nic_netif_pbuf
|
||||||
|
{
|
||||||
|
struct pbuf_custom p { };
|
||||||
|
Nic_netif &netif;
|
||||||
|
Nic::Packet_descriptor packet;
|
||||||
|
|
||||||
|
Nic_netif_pbuf(Nic_netif &nic, Nic::Packet_descriptor &pkt)
|
||||||
|
: netif(nic), packet(pkt)
|
||||||
|
{
|
||||||
|
p.custom_free_function = nic_netif_pbuf_free;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,15 +76,11 @@ class Lwip::Nic_netif
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PBUFS_QUEUE_SIZE = 128,
|
PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
|
||||||
NIC_BUF_SIZE =
|
BUF_SIZE = 128 * PACKET_SIZE,
|
||||||
Nic::Packet_allocator::DEFAULT_PACKET_SIZE *
|
|
||||||
PBUFS_QUEUE_SIZE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nic_netif_pbuf _pbufs[PBUFS_QUEUE_SIZE];
|
Genode::Tslab<struct Nic_netif_pbuf, 128> _pbuf_alloc;
|
||||||
unsigned _pbufs_next = 0;
|
|
||||||
unsigned _alloced = 0;
|
|
||||||
|
|
||||||
Nic::Packet_allocator _nic_tx_alloc;
|
Nic::Packet_allocator _nic_tx_alloc;
|
||||||
Nic::Connection _nic;
|
Nic::Connection _nic;
|
||||||
|
@ -94,14 +96,14 @@ class Lwip::Nic_netif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void free_pbuf(nic_netif_pbuf &pbuf)
|
void free_pbuf(Nic_netif_pbuf &pbuf)
|
||||||
{
|
{
|
||||||
if (!_nic.rx()->ready_to_ack()) {
|
if (!_nic.rx()->ready_to_ack()) {
|
||||||
Genode::error("Nic rx acknowledgement queue congested, blocking to free pbuf");
|
Genode::error("Nic rx acknowledgement queue congested, blocking to free pbuf");
|
||||||
}
|
}
|
||||||
|
|
||||||
_nic.rx()->acknowledge_packet(pbuf.packet);
|
_nic.rx()->acknowledge_packet(pbuf.packet);
|
||||||
pbuf.packet = Nic::Packet_descriptor();
|
destroy(_pbuf_alloc, &pbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,30 +131,17 @@ class Lwip::Nic_netif
|
||||||
auto &rx = *_nic.rx();
|
auto &rx = *_nic.rx();
|
||||||
|
|
||||||
while (rx.packet_avail() && rx.ready_to_ack()) {
|
while (rx.packet_avail() && rx.ready_to_ack()) {
|
||||||
unsigned const initial_index = _pbufs_next;
|
|
||||||
|
|
||||||
while (_pbufs[_pbufs_next].packet.size()) {
|
Nic::Packet_descriptor packet = rx.get_packet();
|
||||||
_pbufs_next = (_pbufs_next+1) % PBUFS_QUEUE_SIZE;
|
|
||||||
if (_pbufs_next == initial_index) {
|
|
||||||
/* internal pbuf queue congested */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Nic::Packet_descriptor const packet = rx.get_packet();
|
Nic_netif_pbuf *nic_pbuf = new (_pbuf_alloc)
|
||||||
|
Nic_netif_pbuf(*this, packet);
|
||||||
nic_netif_pbuf &nic_pbuf = _pbufs[_pbufs_next];
|
|
||||||
_pbufs_next = (_pbufs_next+1) % PBUFS_QUEUE_SIZE;
|
|
||||||
|
|
||||||
nic_pbuf.p.custom_free_function = nic_netif_pbuf_free;
|
|
||||||
nic_pbuf.netif = this;
|
|
||||||
nic_pbuf.packet = packet;
|
|
||||||
|
|
||||||
pbuf* p = pbuf_alloced_custom(
|
pbuf* p = pbuf_alloced_custom(
|
||||||
PBUF_RAW,
|
PBUF_RAW,
|
||||||
packet.size(),
|
packet.size(),
|
||||||
PBUF_REF,
|
PBUF_REF,
|
||||||
&nic_pbuf.p,
|
&nic_pbuf->p,
|
||||||
rx.packet_content(packet),
|
rx.packet_content(packet),
|
||||||
packet.size());
|
packet.size());
|
||||||
LINK_STATS_INC(link.recv);
|
LINK_STATS_INC(link.recv);
|
||||||
|
@ -217,9 +206,10 @@ class Lwip::Nic_netif
|
||||||
Genode::Allocator &alloc,
|
Genode::Allocator &alloc,
|
||||||
Genode::Xml_node config)
|
Genode::Xml_node config)
|
||||||
:
|
:
|
||||||
_nic_tx_alloc(&alloc),
|
_pbuf_alloc(alloc), _nic_tx_alloc(&alloc),
|
||||||
_nic(env, &_nic_tx_alloc, NIC_BUF_SIZE, NIC_BUF_SIZE,
|
_nic(env, &_nic_tx_alloc,
|
||||||
config.attribute_value("label", Genode::String<160>("lwip")).string()),
|
BUF_SIZE, BUF_SIZE,
|
||||||
|
config.attribute_value("label", Genode::String<160>("lwip")).string()),
|
||||||
_link_state_handler(env.ep(), *this, &Nic_netif::handle_link_state),
|
_link_state_handler(env.ep(), *this, &Nic_netif::handle_link_state),
|
||||||
_rx_packet_handler( env.ep(), *this, &Nic_netif::handle_rx_packets)
|
_rx_packet_handler( env.ep(), *this, &Nic_netif::handle_rx_packets)
|
||||||
{
|
{
|
||||||
|
@ -359,8 +349,8 @@ namespace Lwip {
|
||||||
*/
|
*/
|
||||||
static void nic_netif_pbuf_free(pbuf *p)
|
static void nic_netif_pbuf_free(pbuf *p)
|
||||||
{
|
{
|
||||||
nic_netif_pbuf *nic_pbuf = (nic_netif_pbuf*)(p);
|
Nic_netif_pbuf *nic_pbuf = reinterpret_cast<Nic_netif_pbuf*>(p);
|
||||||
nic_pbuf->netif->free_pbuf(*nic_pbuf);
|
nic_pbuf->netif.free_pbuf(*nic_pbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user