Relationship between CONFIG_BT_CONN_TX_MAX and CONFIG_BT_L2CAP_TX_BUF_COUNT in total number of notify packets sent

Hi,

I'm having a problem with sending notify packets, I'll describe the situation I'm doing.

Problem :

I have 5 devices connected to the board and I want to send a first notify command to all 5 devices and a second notify command to 1 of those devices. The problem is that if CONFIG_BT_L2CAP_TX_BUF_COUNT <=6 then there may be an error. I understand that the total number of L2cap Tx I'm using is 5(notify 1)+1(notify 2). And I know the way to prevent this error is to increase CONFIG_BT_L2CAP_TX_BUF_COUNT but I don't understand why notify 1 ends without returning the slot for notify 2 to execute? And the second problem is why I increase CONFIG_BT_CONN_TX_MAX also has the same effect although as far as I know these 2 configurations have different effects. CONFIG_BT_L2CAP_TX_BUF_COUNT indicates the total TX buffer at the logical link layer and CONFIG_BT_CONN_TX_MAX indicates the maximum tx buffer on each connection to the board.

  • I have noticed some problems. CONFIG_BT_CONN_TX_MAX allows to increase the pending limit for each connection, CONFIG_BT_L2CAP_TX_BUF_COUNT will limit the number of shared Tx buffers to transport notifications to other layers, the reason why increasing CONFIG_BT_CONN_TX_MAX solves the problem is because if the default is not configured, CONFIG_BT_CONN_TX_MAX = CONFIG_BT_L2CAP_TX_BUF_COUNT. means with CONFIG_BT_L2CAP_TX_BUF_COUNT = 5 then CONFIG_BT_CONN_TX_MAX = 5, in fact if I notify up to 5 connections each connection takes 1 notification then it is possible but if I add 1 more notification then it cannot be put into pending because I guess the ble controller is not sure that the previous 5 notifications can be divided equally among 5 connections, if they are already in 5 pending slots of a connection then adding 1 package notify will get an error that there are no more slots in the queue so it will return an error. However I am not sure my understanding is correct, your advice is very helpful to me.

  • Hi Tai, a few things are happening here.

    1/Why notify 1 ends without returning the slot for notify 2 to execute?

    Assuming that you are using bt_gatt_notify(), the function returns once the packet is queued, not completed. So, it's likely that the slots were still occupied when you sent the 2nd notification

    2/ "why I increase CONFIG_BT_CONN_TX_MAX also has the same effect although as far as I know these 2 configurations have different effects"

    I cannot be 100% sure without seeing your full error logs, but here are some possible explanations.

    2.1 Why BT_L2CAP_TX_BUF_COUNT <=6 doesn't work?

    With 5 links you burst one notify each (5 L2CAP buffers), then you try a second notify to one link (6th one). If those first 5 buffers haven’t completed yet, all 5 L2CAP buffers are still occupied. The 6th bt_gatt_notify() tries to allocate another buffer and fails

    2.2 Why increase CONFIG_BT_CONN_TX_MAX works?

    Your 5 first notifies may already consume the global pending budget. When you try the 6th, the host rejects it because the global pending limit is reached. Raising CONFIG_BT_CONN_TX_MAX raises that global ceiling, so the 6th notify can be queued instead of failing.
    A notify packet is only freed after all its ACL fragments complete. With a larger global pending budget, the host can keep more ACL packets in flight overall, which reduces backpressure and lets earlier notifies complete sooner. That frees buffers earlier, so when you attempt the 6th allocation it’s more likely to succeed.

    Solution:
    a/ Like you mentioned, you can increase these values as it is good to have some headroom anyways
    b/ If you want to save memory, you can also use bt_gatt_notify_cb() and semaphore to block the notification command until the previous one has finished

    Note:
    CONFIG_BT_CONN_TX_MAX will likely be deprecated later Zephyr 4.2.0 (Working Draft)


    you can use the Kconfig search to see what the config does and it's default value if applicable
    Kconfig search




    Also look at your \build\zephyr\.config file to see what value the configs are set to


  • Hi DanielNG,

    Thank you for your help.

    I think your advice is useful for me. But have one problem I want to confirm about CONFIG_BT_CONN_TX_MAX .

    Before I think it is a queue for each connection like about that:

    and some package such as notify, write response, read response of each connection will be arrange in their queue and then the package be sent to L2cap TX buffer to delivery to another layer. But after I read code in zephyr\subsys\bluetooth\host\att.c in ncs 2.5.0.

    static struct bt_att_tx_meta_data tx_meta_data[CONFIG_BT_CONN_TX_MAX];
    .

    It seems this is a share queue for all connection before delivery to L2cap TX buffer.

    I didn't see more information about that in description of Kconfig.

    Thank you very much for your help.

  • Sorry for the late reply, there are not a lot of documentation on the config but yes, I can confirm that it's a global queue shared by all connections.

  • Thank you for your confirmed information, DanielNG

Related