lwip-users
[Top][All Lists]
Advanced

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

Re: [lwip-users] proper pbuf usage for TCP -> real-time in raw API NO_SY


From: Sergio R. Caprile
Subject: Re: [lwip-users] proper pbuf usage for TCP -> real-time in raw API NO_SYS=1
Date: Mon, 31 Mar 2014 22:17:30 -0300
User-agent: Mozilla/5.0 (Windows NT 5.1; rv:24.0) Gecko/20100101 Thunderbird/24.4.0

...
so, if you get here by searching the list for an answer to this very
same question, before browsing the source files, as I did, here is what
I've found.

There is also an example of pbuf handling in tcpecho_raw

We all know telling the other end to shut up is not the fastest way, but
if we don't have enough memory to buffer incoming data, we must. So,
delaying tcp_recvd() will have this effect, be ready to have some
"external" (to the lwIP stack) way to revive and call tcp_recvd()
because the lwIP won't call your receiving function again unless there
is new data.

lwIP is zero-copy, so, if your link level driver allocates pbufs as
PBUF_POOL (as in the ethernetif example and my DM9000 driver), then your
receiving functions will get pbuf chains of PBUF_POOL_BUFSIZE (plus some
possible alignment overhead), unless received data is (of course) smaller...

So, once you are done with some part of the data you received (and
called tcp_recvd()), either if you manually concatenated two pbufs or
not, if the amount of data you have just processed is >= chunk size, you
are ready to free pbuf chunks one by one by moving through the chain.
To get rid of one pbuf in the chain, you have to reference the next one
by calling pbuf_ref(q=p->next), and then pbuf_free(p). Then, p is freed
and q is your new pbuf holding the rest of the data. (This is true if
"you" are the only one using those pbufs, that is, no other task is also
referencing them).
To hide any remaining data at the beginning of the pbuf (for example
after the former process or when you have just processed < chunk size),
you can call pbuf_header().
Assuming you have a valid p chain, holding more data than you just
processed (because you have just done that from that chain), the former
text explanation resumes to something like this:
            while(p->len <= processed_data) {
              struct pbuf *q;
              processed_data -= p->len;
              q = p->next;
              pbuf_ref(q);
              pbuf_free(p);
              p = q;
            }
            pbuf_header(p, -(s16_t)processed_data);

Add any safety checks that make you feel safer, and you are done.
In a NO_SYS=1 environment, there is a shortcut by manually manipulating
the pbuf fields instead of referencing, but you know that may break
future compatibility and violates some good practices, don't you ? ;^)

You must return ERR_OK to the lwIP functions once you have freed the
whole pbuf yourself.

-- 




reply via email to

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