Bluetooth: L2CAP: stop stealing buffers from SDU pool

It seems like a nice idea at first, but leads to hard-to-debug
situations for the application.

The previous behavior can be implemented by the app by defining
`alloc_seg` and allocating from the same pool as `buf`.

Signed-off-by: Jonathan Rico <jonathan.rico@nordicsemi.no>
This commit is contained in:
Jonathan Rico 2024-01-11 10:47:22 +01:00 committed by Carles Cufí
commit 75c2aeb8bd
3 changed files with 16 additions and 12 deletions

View file

@ -241,6 +241,10 @@ Bluetooth
Any pointer to a UUID must be prefixed with `const`, otherwise there will be a compilation warning. Any pointer to a UUID must be prefixed with `const`, otherwise there will be a compilation warning.
For example change ``struct bt_uuid *uuid = BT_UUID_DECLARE_16(xx)`` to For example change ``struct bt_uuid *uuid = BT_UUID_DECLARE_16(xx)`` to
``const struct bt_uuid *uuid = BT_UUID_DECLARE_16(xx)``. (:github:`66136`) ``const struct bt_uuid *uuid = BT_UUID_DECLARE_16(xx)``. (:github:`66136`)
* The :c:func:`bt_l2cap_chan_send` API no longer allocates buffers from the same pool as its `buf`
parameter when segmenting SDUs into PDUs. In order to reproduce the previous behavior, the
application should register the `alloc_seg` channel callback and allocate from the same pool as
`buf`.
* Mesh * Mesh

View file

@ -587,9 +587,10 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan);
* If the application is reserving the bytes it should use the * If the application is reserving the bytes it should use the
* BT_L2CAP_BUF_SIZE() helper to correctly size the buffers for the for the * BT_L2CAP_BUF_SIZE() helper to correctly size the buffers for the for the
* outgoing buffer pool. * outgoing buffer pool.
* When segmenting an L2CAP SDU into L2CAP PDUs the stack will first attempt * When segmenting an L2CAP SDU into L2CAP PDUs the stack will first attempt to
* to allocate buffers from the original buffer pool of the L2CAP SDU before * allocate buffers from the channel's `alloc_seg` callback and will fallback
* using the stacks own buffer pool. * on the stack's global buffer pool (sized
* @kconfig{CONFIG_BT_L2CAP_TX_BUF_COUNT}).
* *
* @note Buffer ownership is transferred to the stack in case of success, in * @note Buffer ownership is transferred to the stack in case of success, in
* case of an error the caller retains the ownership of the buffer. * case of an error the caller retains the ownership of the buffer.

View file

@ -1818,25 +1818,24 @@ static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
static inline struct net_buf *l2cap_alloc_seg(struct net_buf *buf, struct bt_l2cap_le_chan *ch) static inline struct net_buf *l2cap_alloc_seg(struct net_buf *buf, struct bt_l2cap_le_chan *ch)
{ {
struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id); struct net_buf *seg = NULL;
struct net_buf *seg;
/* Use the dedicated segment callback if registered */ /* Use the user-defined allocator */
if (ch->chan.ops->alloc_seg) { if (ch->chan.ops->alloc_seg) {
seg = ch->chan.ops->alloc_seg(&ch->chan); seg = ch->chan.ops->alloc_seg(&ch->chan);
__ASSERT_NO_MSG(seg); __ASSERT_NO_MSG(seg);
} else { }
/* Try to use original pool if possible */
seg = net_buf_alloc(pool, K_NO_WAIT); /* Fallback to using global connection tx pool */
if (!seg) {
seg = bt_l2cap_create_pdu_timeout(NULL, 0, K_NO_WAIT);
} }
if (seg) { if (seg) {
net_buf_reserve(seg, BT_L2CAP_CHAN_SEND_RESERVE); net_buf_reserve(seg, BT_L2CAP_CHAN_SEND_RESERVE);
return seg;
} }
/* Fallback to using global connection tx pool */ return seg;
return bt_l2cap_create_pdu_timeout(NULL, 0, K_NO_WAIT);
} }
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,