[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-users] Custom memory management

From: Mason
Subject: Re: [lwip-users] Custom memory management
Date: Thu, 06 Oct 2011 17:23:25 +0200
User-agent: Mozilla/5.0 (Windows NT 5.1; rv:6.0.2) Gecko/20110902 Firefox/6.0.2 SeaMonkey/2.3.3

Simon wrote:

> You're right, that won't get too easy.
> For the RX side, using a *custom* PBUF_REF would be the best solution. 
> That's a pbuf that has a 'freed' callback and references external 
> memory. However, that doesn't work, yet (though I planned to add support 
> for it as I can see it's one possible solution to implement DMA MAC 
> drivers). The problem here is that pbuf_header() can't grow such pbufs 
> (as it doesn't know the original length). This would have to be fixed by 
> changing the struct pbuf (if only for PBUF_REF pbufs).

I'm concerned when you say "it doesn't work, yet" because
that's the solution I implemented ;-(

Let me describe what I did, so you can tell me where it
blows up...

I've defined a new struct packet_info_t which stores a pbuf
(for lwip) and an OS descriptor.

typedef struct { struct pbuf_custom pbuf; ethernet_async_t desc; } 

The driver manages N such structures, one per buffer in the
RX pool. A buffer's address and length are stored in desc.

For each structure, pbuf->custom_free_function points to my
custom free function -- which does not actually *free* but
returns the buffer to the RX pool.

When a packet is received, it is stuffed inside a custom pbuf
and sent to the input function:

    packet_info_t *info = WAIT_FOR_NEXT_PACKET( )
    /*** PROCESS THE PACKET ***/
    ethernet_async_t *desc = &info->desc;
    struct pbuf *pbuf = pbuf_alloced_custom(PBUF_RAW, desc->length, PBUF_RAM, 
&info->pbuf, desc->buffer, MAX_FRAME_SIZE);
    mynetif->input(pbuf, mynetif);

And when lwip wants to free the custom pbuf, it calls my
custom function. Seems to work OK. What is the problem
with this strategy?

> As to the TX side: normally, TX pbufs are allocated as PBUF_RAM, the 
> memory for that is taken from the heap by calling mem_malloc(). Now the 
> simple solution would be to just replace mem.c by your own code 
> allocating and freeing from your TX pool: with the correct settings, 
> mem_malloc() isn't used for anything else but PBUF_RAM pbufs. The only 
> problem might be that you don't know in advance how big the memory 
> blocks are (and thus how big your TX buffer entries should be), but by 
> using TCP_OVERSIZE, you can just use the maximum ethernet frame size (if 
> you don't mind wasting some RAM for smaller packets).

RX and TX buffers are large enough to store a full-sized
Ethernet frame, i.e. MAX_FRAME_SIZE is defined to 1536
(for alignment reasons).

However, I was trying to make the port as clean as possible
by making as few modifications inside lwip as possible.

I'll have to balance performance vs portability, I guess.
Maybe copying every outgoing packet is not such a big deal
after all?  ;-)



> Mason wrote:
>> Hello,
>> I've been trying to port lwip 1.4.0 to OS21/OS+ for several
>> weeks. I am very stuck on the aspect of buffer management,
>> because what lwip expects seems incompatible with the way
>> things work on this platform.
>> Here's a short description:
>> At init, I specify how many RX buffers and TX buffers I want
>> the OS to manage. The OS allocates these buffers along with
>> associated "descriptors". Thus, the OS manages an RX pool
>> and a (separate) TX pool.
>> When a packet is received, an IRQ handler grabs a buffer from
>> the RX pool, copies the packet to this buffer, then calls a
>> user-defined function. When the packet is no longer needed,
>> software is supposed to return it to the RX pool by calling
>> a particular function.
>> When software wants to send a packet, it requests a buffer from
>> the TX pool, copies its data to the buffer, then requests an
>> asynchronous TX. This function returns immediately, but the
>> packet is only sent "sometime later". When it has effectively
>> been sent, an IRQ handler calls a second user-defined function,
>> which is responsible for returning the packet to the TX pool.
>> Can someone explain how to make lwip happy with this buffer
>> management model, without using memcpy, i.e. having lwip
>> deal directly with the buffers from TX pool and RX pool?
>> I've come up with a slightly hackish solution to deal with
>> receiving, but I don't see how to make sending work?
>> (Aside from copying the pbuf to a TX pool buffer in
>> low_level_ouput, which I'm desperately trying to avoid.)
>> I would really appreciate a gentle nudge in the right direction.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]