Skip to content
Jérémie Magnette edited this page Dec 21, 2015 · 1 revision

The pico_frame structure is the most important structure in the stack. It acts like a container for buffers of data, and it has been designed to work minimizing the duplication of the actual buffer, while still being accessible from all the layers. There are many members in this structure, but the most important are:

  • buffer
  • buffer_len
  • start
  • len
  • usage_count
  • *_hdr (internal pointers) / *_len
  • notify_free
  • next

Each frame can be allocated once, and then transfer its ownership across different protocols. The size specified in the frame allocation is stored in buffer_len, and the buffer pointer itself is stored on buffer. This technically allows to have multiple frame descriptors pointing to the same buffer, in order to have multiple logical copies of the frame but without the additional overhead to actually have to store the frame content twice. This is why the usage counter of the frame buffer content is stored separately, at the beginning of the frame, and its address linked to the frame descriptor in the usage_count field. The next field keeps the relationship between the frame descriptor and the queue it is associated to. This is a single field in the frame, which basically means that a frame can only be part of one queue at every single time. If the frame needs to be enqueued in two different queues, it is good practice to create a copy of the descriptor.

This is the interface exported to all the modules to allocate, deallocate and copy the frames:

  • pico_frame_alloc - allocates a new frame and its content of a given size. The size is stored automatically in the buffer_len, and the usage_count of the frame buffer object is set to 1. From this point on, the frame can be used by any module

  • pico_frame_grow - given a frame and a new size, the buffer is reallocated to fit its new given size. All the internal pointers are updated to point to the new memory if this differs from the previously allocated one. pico_frame_copy - creates a new frame descriptor, associated to the same buffer as the original frame. Usage_count is increased by one, while all other fields are copied from the original frame.

  • pico_frame_deepcopy - creates a physical copy of the frame descriptor and its buffer. This is only useful when both frames content has to be modified. All the internal pointers of the newly created frame are adapted to the new buffer. The usage_count of the original frame is left untouched, and the one of the new frame is set to 1.

  • pico_frame_discard - informs the allocator that the specific frame descriptor is not in use any more. The descriptor itself gets freed, and the usage_count of the buffer is decreased by one. Whenever usage_count reaches zero, the frame content is not in use by any descriptor, so it gets freed automatically.

  • pico_frame_alloc_skeleton - creates a new empty frame descriptor, associated with no buffer. Creating a skeleton is only useful when we want to attach a specific, pre-existing buffer to it. An extra flag argument extbuf can be set to one to indicate that the frame content will not be automatically freed when the buffer’s usage_count reaches zero. Instead, the function associated to the notify_free function pointer will be called in this occurrence, so that the external buffer can be freed by the programmer.

  • pico_frame_skeleton_set_buffer - given a pre-allocated skeleton, associates a specific memory area as the buffer for it. Useful to associate an actual content to the frame descriptor after this one has been created using pico_frame_alloc_skeleton.

The internal pointers and lengths in the frame are used from within the stack in both directions to indicate the beginning and the end of the portion of the frame that is related with a specific protocol. For example, a UDP/IP frame being transported over Ethernet, may look like this:

Pico Frame diagram

Any frame operation that modifies the buffer address (like for instance pico_frame_grow) must take into account updating all the other internal pointers accordingly.

Clone this wiki locally