ccollins476ad commented on issue #686: [DO NOT MERGE] BLE Host flow control
URL: https://github.com/apache/mynewt-core/pull/686#issuecomment-348375749
 
 
   ## Overview
   
   Controller to host flow control (hereon called "flow control") stops the 
controller from sending more ACL data packets than the host can accommodate.  
Briefly, this feature is implemented as follows:
   
   * On startup, host tells controller:
       * That flow control is being used.
       * About its ACL data buffer supply:
           * Total number of buffers.
           * Size of each buffer.
   
   * After startup, host sends updates to controller containing: The number of 
ACL data buffers it has freed since the last update, and which connection 
handle each buffer was associated with.
   
   * Host provides updates periodically (default: once per second).
   
   * Host sends an immediate update if the number of buffers freed since the 
last update exceeds a threshold (default: `total_buffers - 2`).
   
   * Host does not send an update if the number of buffers freed since the last 
update is 0.
   
   * If a connection with unfreed buffers is terminated, the controller can 
assume that all buffers are freed (i.e., no host update required).
   
   This feature prevents a buffer overrun as long as the controller keeps track 
of the host's free buffer count.
   
   ## Complications
   
   Flow control is quite simple as described above.  Unfortunately, there is 
one feature of the nimble host that really complicates things.  When the host 
tells the application about an incoming data packet, such as a write-attribute 
command, the application can keep the mbuf for later processing.  If the 
application keeps the mbuf, then it is the application's responsibility to free 
the mbuf when it is done with it.  This is a problem because the flow control 
implementation needs to know when a buffer is freed to properly update the 
controller.
   
   The solution I chose is to add a callback that gets called when a block is 
freed back to the ACL buffer pool.  The callback would increment the 
appropriate freed buffer count, and possibly schedule a host update.  Because 
the ACL buffer pool is an mbuf pool, there were two ways to implement this:
   
       1. Add the callback to `struct os_mbuf_pool`.
       2. Add the callback to the underlying `struct os_mempool`.
   
   I thought this functionality might be useful to others, so I chose the more 
generic option 2.  First, here is how this is implemented:
   
   ```
       struct os_mempool_ext;
       typedef void os_mempool_put_fn(struct os_mempool_ext *ome, void *data);
   
       struct os_mempool_ext {
           struct os_mempool mpe_mp;
   
           /* Callback that is executed immediately before a block is freed. */
           os_mempool_put_fn *mpe_pre_put_cb;
   
           /* Callback that is executed immediately after a block is freed.  The
            * contents of the block are indeterminate and should not be 
inspected.
            */
           os_mempool_put_fn *mpe_post_put_cb;
       };
   ```
   
   And a new `flags` field was added to `struct os_mempool`:
   
   ```
       struct os_mempool {
           // ...
           uint8_t mp_flags;           /* Bitmap of OS_MEMPOOL_F_[...] values. 
*/
           // ...
       };
   
       /**
        * Indicates an extended mempool.  Address can be safely cast to
        * (struct os_mempool_ext *).
        */
       #define OS_MEMPOOL_F_EXT        0x01
   ```
   
   When a block is freed back to a mempool, the free function uses the flags 
field to determine if it should cast to `struct os_mempool_ext *` and call the 
callbacks.
   
   What I don't like about this is the need for two callbacks.  We need two 
because the user might need to know two separate things:
   
   * The contents of the block being freed, and
   * That the block is fully freed and ready to be reallocated.
   
   The contents of the block can only be inspected before it is freed, hence 
the need for two callbacks.  I just worry that this mechanism is too 
complicated for people to understand and use.
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to