zephyr/tests/bluetooth/controller/ctrl_tx_buffer_alloc/src/main.c
Andries Kruithof f023b5f611 Bluetooth: controller: push topic branch to main
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>
2021-11-16 21:24:37 -05:00

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);
}