Files:
Classes:
IBuf class methods implemented in CBufImpl:
IBuf virtual methods implemented in CBufImpl:
CBufImpl private variables:
CBufImpl creator:
Sets beginning and end pointers to HEADROOM which is hard coded to rssi / packetizer size
Sets capacity to passed value, passes k to CFreeListNode creator (adding to free list?)
CBufImpl virtual protected methods:
CBufImpl virtual methods:
IBufChain class methods implemented in CBufChainImpl:
IBufChain virtual methods implemented in CBufChainImpl:
CBufChainImpl private variables:
CBufChainIml public class variables:
CBufChainImpl creator:
CBufChainImpl virtual protected methods:
CBufImpl class methods:
CBufImpl virtual methods:
Questions:
Till,
I am going through the CPSW code and have some questions and comments, starting with the CPSW buffer implementation. BTW I like the approach to the buffer chains which minimizes the number of copies to the copy from the UDP receive and the copy to user space.
1. It appears you base the buffer size constants and container variables around the assumption that we will limit each buffer element size to 64K. I am not sure if that is a safe assumption once we add support for interfaces that are not TCP/IP or UDP. With PGP or axi-stream we can have much larger buffers. Also you seem to hardcode some ethernet based constants in the .h file and I am not sure that is the best place for a generic implementation. (more notes on size later)
2. In adjPayload you have this line:
if ( delta > beg || delta > old_size )
return false;
Why do you care if the shift size is greater than the beginning payload offset? Should this be an unsigned compare to check for left shifts beyond the beginning of the buffer?
3. In getBuf(size capa, bool clip) you adjust capa based upon maxcap and clip, but the resulting variable value is not used when calling the free list allocate. It seems you are just always allocating maxcap and not using the passed variable size. Maybe this is just a sanity check for the exception? It seems that maybe the capa arg is not necessary. (see next item).
4. On the note of buffer sizes. I see the allocation size is hard coded in cpsw_buf.c and there is a uniform size for all buffers. Would it make more sense for the free list to be exposed to a higher level and using it as a argument to getBuf? This way a number of free lists can be created with a size most appropriate for where they are being used. For applications with a mix of data and command traffic, you may want large buffers for data and smaller for commands. Of course this would be for applications where the transport medium allows for larger buffers. We would still use buffer chains for really large frames (continue flag in the PGP and axi-stream drivers).
5. Why do you not pre-create the free list for the buffer chain like you do for the buffer entries. You seem to have it set externally to a public class variable.
6. unlinkCheap() seems to be a method to kill the next pointer in each buffer, which is used to clean up a buffer chain. But why is the key passed as an arg? Is it mean to used in classes that override the virtual method?
7. Why is IBufChain::take_ownership a class method instead of an instance method? Is this because it has to perform a cast to BufChainImpl?
8. In CBufChainImpl::insert. I think it is confusing to recreate a variable within a while loop with the same name as an existing variable.
Lastly a code convention question. Is it standard practice to declare classes, even internal ones, within the .cc files? It is hard to use tools such as doxygen with this approach. It is also hard to follow the code structure.
9. Additional notes on question. It seems that a public free list allocator would also make sense to set the headroom size for each buffer at creation. Different implementations will need different headroom depending on protocol. Of course one could just allocated a large enough space for all possibilities, but it is hard to anticipate that and some headroom needs may be excessive compared to the norm. 10. Perhaps the IBufChain::insert functions should include a passed value which determines the amount of space to copy to each buffer. It seems now that the max possible size is used for each buffer.