Thanks for the detailed write-up, Will - very useful. Are there defines for these things? Ideally, if I want a payload size of N, I'd like to specify in syscfg.yml:
MSYS_1_BLOCK_SIZE: '(N + MBUF_HEADER + PKT_HEADER + LL_OVERHEAD + ...)' And magically have optimally-sized buffers. On Wed, Jan 11, 2017 at 11:00 AM, will sanfilippo <wi...@runtime.io> wrote: > Hello: > > Since this has come up on a number of different occasions I wanted to send > out an email which discusses how the nimble stack uses mbufs. This will be > a controller-centric discussion but the concepts apply to the host as well. > > A quick refresher on mbufs: Mynewt, and the nimble stack, use mbufs for > networking stack packet data. A “packet” is simply a chain of mbufs with > the first mbuf in the chain being a packet header mbuf and all others being > “normal” mbufs. A packet header mbuf contains a mbuf header, a packet > header and an optional user-defined header. > > The length of the packet (i.e. all the data contained in all the mbuf > chains) is stored in the packet header. Each individual mbuf in the chain > also contains a length which is the length of the data in that mbuf. The > sum of all the mbuf data lengths = length of packet. > > The amount of overhead in an mbuf and its size determine the amount of > data that can be carried in a mbuf. All mbufs have a 16-byte mbuf header. > Packet header mbufs have an additional 8 bytes for the packet header > structure and an optional user-data header. The nimble stack uses either an > 8-byte or 12-byte user data header. If you turn on multi-advertising > support, the user header is 12 bytes; otherwise it is 8 bytes. This means > the total packet header mbuf overhead is 32 or 36 bytes. > > The total mbuf size is defined by the various MSYS_X_BLOCK_SIZE syscfg > variables. Currently, there is one mbuf pool added to msys (MSYS_1) with a > block size of 292 bytes. > > Controller constraints: > The controller assumes that a certain minimum data size is available in a > packet header mbuf. This size is equal to the largest advertising PDU, or > 37 bytes, and must also contain the 2-byte LL PDU header (for a total of 39 > bytes). Additionally, the controller requires an additional 4 bytes at the > start of the packet header mbuf to prepend the HCI ACL data packet header. > This means that the minimum mbuf size that can be allocated in any msys > mbuf pool is: packet header overhead + 4 + 39 = 75 (79 for multi-adv). > Since memory pools are always rounded up to the nearest 4 byte boundary, > this means that the minimum size should be 76 (or 80) bytes. > > For most applications that dont use large packets, setting the mbuf size > to 80 should be fine as this will accommodate the typical BLE PDU and also > meets the minimum requirement. If your application generally uses larger > packets it might be benefical to allocate large mbufs as you dont lose the > 16-byte overhead per mbuf. > > Finally, here is an example of how many mbufs will be used by the > controller for received packets. This assumes multi-advertising enabled (36 > byte packet header overhead). > > Example 1: PDU length = 251, msys_1_block_size = 80 > > Controller needs to store 251 + 2 = 253 total bytes. > > Packet header mbuf can hold 80 - 36 - 4 bytes, or 40 bytes. > Each additional mbuf can hold 80 - 16 bytes, or 64 bytes. > Total mbufs = 5. First mbuf holds 40 bytes, the next three hold 64 bytes > while the final mbuf holds 21 bytes (40 + 64*3 + 21 = 253). > > Example 2: PDU length = 251, msys_1_block_size = 112 > Total mbufs: 3 (72 + 96 + 85) > > Hope this helps. > > > > > >