From ce7423cf4af8047db2aef149fc7871d73583edeb Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Thu, 24 Nov 2022 15:31:17 +0100 Subject: [PATCH] Bluetooth: host: update l2cap stress test Do these things: - use the proper macros for reserving the SDU header - make every L2CAP PDU fragment into 3 ACL packets - set tx data and verify rx matches the pattern - measure segment pool usage Signed-off-by: Jonathan Rico (cherry picked from commit 8bc094610c5dd69f6ba0085fb3fe7d18167164c9) --- .../bsim_bt/bsim_test_l2cap_stress/prj.conf | 26 ++++++----- .../bsim_bt/bsim_test_l2cap_stress/src/main.c | 43 +++++++++++++++++-- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/prj.conf b/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/prj.conf index dfe384cc28c0791..fcb08ee2217c142 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/prj.conf +++ b/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/prj.conf @@ -18,28 +18,32 @@ CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n # L2CAP MPS # 23+27+27=77 makes exactly three full packets CONFIG_BT_L2CAP_TX_MTU=77 -CONFIG_BT_BUF_ACL_TX_SIZE=77 + +# Use this to send L2CAP PDUs without any fragmentation. +# In this particular case, we prefer fragmenting to test that code path. +# CONFIG_BT_BUF_ACL_TX_SIZE=81 + +# L2CAP PDUs will be fragmented in 3 ACL packets. +CONFIG_BT_BUF_ACL_TX_SIZE=27 + CONFIG_BT_BUF_ACL_TX_COUNT=4 # The minimum value for this is # L2AP MPS + L2CAP header (4) CONFIG_BT_BUF_ACL_RX_SIZE=81 -# TODO: find out why we can't use 16 buffers. It should fit. - -CONFIG_BT_L2CAP_TX_BUF_COUNT=30 -# CONFIG_BT_L2CAP_TX_BUF_COUNT=100 - -CONFIG_BT_BUF_ACL_TX_COUNT=4 +# Governs BT_CONN_TX_MAX, and so must be >= than the max number of +# peers, since we attempt to send one SDU per peer. The test execution +# is a bit slowed down by having this at the very minimum, but we want +# to keep it that way as to stress the stack as much as possible. +CONFIG_BT_L2CAP_TX_BUF_COUNT=6 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=27 CONFIG_BT_CTLR_RX_BUFFERS=10 -# The ring buffer now has space for three times as much data -# (default 27, 3*27=81), so that it does not run out of data -# while waiting for new SDUs to be queued. -CONFIG_BT_CTLR_DATA_LENGTH_MAX=81 CONFIG_BT_MAX_CONN=10 CONFIG_LOG=y CONFIG_ASSERT=y CONFIG_BT_DEBUG_LOG=y +CONFIG_NET_BUF_POOL_USAGE=y diff --git a/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/src/main.c b/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/src/main.c index bbb28cf16ad4639..62871d9697c6630 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/src/main.c +++ b/tests/bluetooth/bsim_bt/bsim_test_l2cap_stress/src/main.c @@ -21,16 +21,21 @@ CREATE_FLAG(flag_l2cap_connected); #define INIT_CREDITS 10 #define SDU_NUM 20 #define SDU_LEN 1230 +#define NUM_SEGMENTS 10 /* Only one SDU per link will be transmitted at a time */ -/* FIXME: decrease size */ NET_BUF_POOL_DEFINE(sdu_tx_pool, - 100, BT_L2CAP_BUF_SIZE(SDU_LEN), + CONFIG_BT_MAX_CONN, BT_L2CAP_SDU_BUF_SIZE(SDU_LEN), + 8, NULL); + +NET_BUF_POOL_DEFINE(segment_pool, + /* MTU + 4 l2cap hdr + 4 ACL hdr */ + NUM_SEGMENTS, BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU), 8, NULL); /* Only one SDU per link will be received at a time */ NET_BUF_POOL_DEFINE(sdu_rx_pool, - CONFIG_BT_MAX_CONN, BT_L2CAP_BUF_SIZE(SDU_LEN), + CONFIG_BT_MAX_CONN, BT_L2CAP_SDU_BUF_SIZE(SDU_LEN), 8, NULL); static struct bt_l2cap_le_chan l2cap_channels[L2CAP_CHANS]; @@ -40,6 +45,7 @@ static uint8_t tx_data[SDU_LEN]; static uint8_t tx_left[L2CAP_CHANS]; static uint16_t rx_cnt; static uint8_t disconnect_counter; +static uint32_t max_seg_allocated; int l2cap_chan_send(struct bt_l2cap_chan *chan, uint8_t *data, size_t len) { @@ -52,7 +58,7 @@ int l2cap_chan_send(struct bt_l2cap_chan *chan, uint8_t *data, size_t len) return -ENOMEM; } - net_buf_reserve(buf, BT_L2CAP_CHAN_SEND_RESERVE); + net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE); net_buf_add_mem(buf, data, len); int ret = bt_l2cap_chan_send(chan, buf); @@ -66,6 +72,19 @@ int l2cap_chan_send(struct bt_l2cap_chan *chan, uint8_t *data, size_t len) return ret; } +struct net_buf *alloc_seg_cb(struct bt_l2cap_chan *chan) +{ + struct net_buf *buf = net_buf_alloc(&segment_pool, K_NO_WAIT); + + if ((NUM_SEGMENTS - segment_pool.avail_count) > max_seg_allocated) { + max_seg_allocated++; + } + + ASSERT(buf, "Ran out of segment buffers"); + + return buf; +} + struct net_buf *alloc_buf_cb(struct bt_l2cap_chan *chan) { return net_buf_alloc(&sdu_rx_pool, K_NO_WAIT); @@ -108,6 +127,9 @@ int recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf) LOG_DBG("len %d", buf->len); rx_cnt++; + /* Verify SDU data matches TX'd data. */ + ASSERT(memcmp(buf->data, tx_data, buf->len) == 0, "RX data doesn't match TX"); + return 0; } @@ -137,6 +159,7 @@ static struct bt_l2cap_chan_ops ops = { .connected = l2cap_chan_connected_cb, .disconnected = l2cap_chan_disconnected_cb, .alloc_buf = alloc_buf_cb, + .alloc_seg = alloc_seg_cb, .recv = recv_cb, .sent = sent_cb, }; @@ -253,6 +276,11 @@ static void test_peripheral_main(void) LOG_DBG("*L2CAP STRESS Peripheral started*"); int err; + /* Prepare tx_data */ + for (size_t i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (uint8_t)i; + } + err = bt_enable(NULL); if (err) { FAIL("Can't enable Bluetooth (err %d)", err); @@ -358,6 +386,11 @@ static void test_central_main(void) LOG_DBG("*L2CAP STRESS Central started*"); int err; + /* Prepare tx_data */ + for (size_t i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (uint8_t)i; + } + err = bt_enable(NULL); ASSERT(err == 0, "Can't enable Bluetooth (err %d)\n", err); LOG_DBG("Central Bluetooth initialized."); @@ -395,6 +428,8 @@ static void test_central_main(void) } LOG_DBG("All peripherals disconnected."); + LOG_DBG("Max segment pool usage: %u bufs", max_seg_allocated); + PASS("L2CAP STRESS Central passed\n"); }