Pushes all work done in the topic-ble-llcp branch into main branch This is a refactoring of the LL control procedures; the refactored control procedures are hidden behind a KConfig option and per default disabled Goal of the refactoring: close issue Link Layer Control Procedure overhaul #15256 make it easier to add/update control procedures Refactoring consists in principal of writing explicit state machines for the control procedures. To reduce the risk of regression errors unit-tests have been added Following control procedures are implemented: Connection update procedure Channel map update procedure Encryption procedure Feature exchange procedure Version exchange procedure ACL termination procedure Connection parameters request procedure LE Ping procedure Data Length Update procedure PHY update procedure Min. nr. Of channels used procedure Constant Tone extension request procedure This is a joined work by the people listed in the signed-off-by list (in alphabetical order) Signed-off-by: Andries Kruithof Andries.Kruithof@nordicsemi.no Signed-off-by: Erik Brockhoff erbr@oticon.com Signed-off-by: Piotr Pryga piotr.pryga@nordicsemi.no Signed-off-by: Szymon Janc szymon.janc@codecoup.pl Signed-off-by: Thomas Ebert Hansen thoh@oticon.com Signed-off-by: Tommie Skriver tosk@demant.com Signed-off-by: Andries Kruithof <Andries.Kruithof@nordicsemi.no>
159 lines
4.9 KiB
C
159 lines
4.9 KiB
C
/*
|
|
* Copyright (c) 2020 Demant
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/types.h>
|
|
#include <ztest.h>
|
|
#include "kconfig.h"
|
|
|
|
#define ULL_LLCP_UNITTEST
|
|
|
|
#include <bluetooth/hci.h>
|
|
#include <sys/byteorder.h>
|
|
#include <sys/slist.h>
|
|
#include <sys/util.h>
|
|
#include "hal/ccm.h"
|
|
|
|
#include "util/util.h"
|
|
#include "util/mem.h"
|
|
#include "util/memq.h"
|
|
|
|
#include "pdu.h"
|
|
#include "ll.h"
|
|
#include "ll_settings.h"
|
|
|
|
#include "lll.h"
|
|
#include "lll/lll_df_types.h"
|
|
#include "lll_conn.h"
|
|
|
|
#include "ull_tx_queue.h"
|
|
|
|
#include "ull_conn_types.h"
|
|
#include "ull_llcp.h"
|
|
#include "ull_conn_internal.h"
|
|
#include "ull_llcp_internal.h"
|
|
|
|
#include "helper_pdu.h"
|
|
#include "helper_util.h"
|
|
|
|
|
|
static struct ll_conn conn[CONFIG_BT_CTLR_LLCP_CONN];
|
|
|
|
static void setup(void)
|
|
{
|
|
ull_conn_init();
|
|
test_setup(&conn[0]);
|
|
}
|
|
void test_tx_buffer_alloc(void)
|
|
{
|
|
struct proc_ctx *ctxs[CONFIG_BT_CTLR_LLCP_CONN];
|
|
struct node_tx *tx[CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM +
|
|
CONFIG_BT_CTLR_LLCP_CONN * CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM + 3];
|
|
uint16_t tx_alloc_idx = 0;
|
|
int i;
|
|
|
|
for (int ctx_idx = 0; ctx_idx < CONFIG_BT_CTLR_LLCP_CONN; ctx_idx++) {
|
|
ctxs[ctx_idx] = llcp_create_local_procedure(PROC_VERSION_EXCHANGE);
|
|
}
|
|
|
|
#if defined(LLCP_TX_CTRL_BUF_QUEUE_ENABLE)
|
|
/* Check alloc flow */
|
|
for (i = 0; i < CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM; i++) {
|
|
zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
}
|
|
for (i = 0; i < CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM; i++) {
|
|
zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
}
|
|
zassert_false(llcp_tx_alloc_peek(&conn[0], ctxs[0]), NULL);
|
|
zassert_equal(ctxs[0]->wait_reason, WAITING_FOR_TX_BUFFER, NULL);
|
|
|
|
for (int j = 1; j < CONFIG_BT_CTLR_LLCP_CONN; j++) {
|
|
/* Now global pool is exausted, but conn pool is not */
|
|
for (i = 0; i < CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM; i++) {
|
|
zassert_true(llcp_tx_alloc_peek(&conn[j], ctxs[j]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[j], ctxs[j]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
}
|
|
|
|
zassert_false(llcp_tx_alloc_peek(&conn[j], ctxs[j]), NULL);
|
|
zassert_equal(ctxs[j]->wait_reason, WAITING_FOR_TX_BUFFER, NULL);
|
|
}
|
|
|
|
ull_cp_release_tx(&conn[0], tx[1]);
|
|
|
|
/* global pool is now 'open' again, but ctxs[1] is NOT next in line */
|
|
zassert_false(llcp_tx_alloc_peek(&conn[1], ctxs[1]), NULL);
|
|
|
|
/* ... ctxs[0] is */
|
|
zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
ull_cp_release_tx(&conn[0], tx[tx_alloc_idx - 1]);
|
|
|
|
/* global pool does not allow as ctxs[2] is NOT next up */
|
|
zassert_false(llcp_tx_alloc_peek(&conn[2], ctxs[2]), NULL);
|
|
|
|
#if (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0)
|
|
/* Release conn[2] held tx, to confirm alloc is allowed after releasing pre-alloted buf */
|
|
zassert_true(!(conn[2].llcp.tx_buffer_alloc <
|
|
CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM), NULL);
|
|
ull_cp_release_tx(&conn[2], tx[CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM +
|
|
CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM +
|
|
CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM]);
|
|
zassert_true((conn[2].llcp.tx_buffer_alloc <
|
|
CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM), NULL);
|
|
|
|
/* global pool does not allow as ctxs[2] is not next up, but pre alloted is now avail */
|
|
zassert_equal(ctxs[2]->wait_reason, WAITING_FOR_TX_BUFFER, NULL);
|
|
zassert_not_null(ctxs[2]->wait_node.next, NULL);
|
|
zassert_true(llcp_tx_alloc_peek(&conn[2], ctxs[2]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[2], ctxs[2]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
|
|
/* No longer waiting in line */
|
|
zassert_equal(ctxs[2]->wait_reason, WAITING_FOR_NOTHING, NULL);
|
|
zassert_is_null(ctxs[2]->wait_node.next, NULL);
|
|
#endif /* (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0) */
|
|
|
|
/* now ctxs[1] is next up */
|
|
zassert_true(llcp_tx_alloc_peek(&conn[1], ctxs[1]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
|
|
#else /* LLCP_TX_CTRL_BUF_QUEUE_ENABLE */
|
|
/* Test that there are excactly LLCP_CONN * LLCP_TX_CTRL_BUF_NUM_MAX
|
|
* buffers available
|
|
*/
|
|
for (i = 0;
|
|
i < CONFIG_BT_CTLR_LLCP_TX_PER_CONN_TX_CTRL_BUF_NUM_MAX * CONFIG_BT_CTLR_LLCP_CONN;
|
|
i++) {
|
|
zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]), NULL);
|
|
tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
|
|
zassert_not_null(tx[tx_alloc_idx], NULL);
|
|
tx_alloc_idx++;
|
|
}
|
|
zassert_false(llcp_tx_alloc_peek(&conn[0], ctxs[0]), NULL);
|
|
#endif /* LLCP_TX_CTRL_BUF_QUEUE_ENABLE */
|
|
}
|
|
|
|
void test_main(void)
|
|
{
|
|
ztest_test_suite(
|
|
tx_buffer_alloc, ztest_unit_test_setup_teardown(test_tx_buffer_alloc, setup,
|
|
unit_test_noop));
|
|
|
|
ztest_run_test_suite(tx_buffer_alloc);
|
|
}
|