[ell-i-developers] A small architectural question about the UDP/IP stack

  • From: Pekka Nikander <pekka.nikander@xxxxxx>
  • To: "ell-i-developers@xxxxxxxxxxxxx" <ell-i-developers@xxxxxxxxxxxxx>
  • Date: Fri, 28 Feb 2014 14:48:57 +0200

I'm now writing the upper layer part of the CoAP, handling data etc.

As I wrote before, the stack has been designed to use a single buffer for both 
input and output data.  However, at the uppermost APIs I am changing the 
practise and passing separately input and output buffers, allowing for changing 
the underlying structures without having to touch the user code above the API.

Now, at some point I need to start passing the size of the "output buffer", 
i.e. how much total size there is in the underlying buffer.  In the "input 
path", i.e. eth_input, ip_input, udp_input and coap_input we don't need that 
information, as all of those just parse the data without changing it (other 
than replacing the source and destination addresses on each field and fixing 
checksums).  However, once we get to coap_handle, which actually need to know 
how much space there is, as the reply may be larger than the request.  And of 
course, after that the length needs to be passed downwards, from coap_handle 
back, then to udp_output, ip_output and eth_output, so that udp_output and 
ip_output can update the length and eth_output knows how much to send.

Hence, the question is:  Where to store and how to pass the information about 
the total buffer size?

I see at least three options:

1. Have a compile time constant.  Always assume that the buffer is of the given 
   PROS: Easy, uses the least amount of memory.
   CONS: All packets must be of an equal size.

2. Pass the buffer size all the way along the packet, from the lowest layer, as 
an additional parameter. 
   PROS: Each packet can easily be of a different size.
   CONS: Uses an extra register at every non-inlined function call.

3. Include the size in the underlying data structure, i.e. create a "network 
packet" data structure that not only contains the actual packet, but also some 
metadata about it.
   PROS: Each packet can be of different size.
   CONS: Requires extra macros to handle the underlying data structure.  Takes 
a few bytes more RAM.

There are probably other alternatives.

I don't have strong opinions on what is the best.  I think I'm gradually 
leaning to the third one anyway, but that will require larger restructuring of 
the whole APIs in the stack.  I presume such restructuring will be needed in 
the end of the day anyway when we want to optimise the implementation by 
inlining all functions that are only called from one place etc.  

However, at the moment the first one appears easiest to implement, so I will 
probably go that way for now anyway.  That also means that the structure is 
unlikely to change in the near future, unless someone else wants to take the 
initiative of streamlining the stack.



Other related posts:

  • » [ell-i-developers] A small architectural question about the UDP/IP stack - Pekka Nikander