1 /*
2 * Copyright (c) 2020 Demant
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/types.h>
8 #include <zephyr/ztest.h>
9
10 #define ULL_LLCP_UNITTEST
11
12 #include <zephyr/bluetooth/hci.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/slist.h>
15 #include <zephyr/sys/util.h>
16 #include "hal/ccm.h"
17
18 #include "util/util.h"
19 #include "util/mem.h"
20 #include "util/memq.h"
21 #include "util/dbuf.h"
22
23 #include "pdu_df.h"
24 #include "lll/pdu_vendor.h"
25 #include "pdu.h"
26 #include "ll.h"
27 #include "ll_settings.h"
28
29 #include "lll.h"
30 #include "lll/lll_df_types.h"
31 #include "lll_conn.h"
32 #include "lll_conn_iso.h"
33
34 #include "ull_tx_queue.h"
35
36 #include "isoal.h"
37 #include "ull_iso_types.h"
38 #include "ull_conn_iso_types.h"
39
40 #include "ull_conn_types.h"
41 #include "ull_llcp.h"
42 #include "ull_conn_internal.h"
43 #include "ull_llcp_internal.h"
44
45 #include "helper_pdu.h"
46 #include "helper_util.h"
47
48
49 static struct ll_conn conn[CONFIG_BT_CTLR_LLCP_CONN];
50
alloc_setup(void * data)51 static void alloc_setup(void *data)
52 {
53 ull_conn_init();
54 for (int i = 0; i < CONFIG_BT_MAX_CONN; i++) {
55 test_setup(&conn[i]);
56 }
57 }
58
ZTEST(tx_buffer_alloc,test_tx_buffer_alloc)59 ZTEST(tx_buffer_alloc, test_tx_buffer_alloc)
60 {
61 struct proc_ctx *ctxs[CONFIG_BT_CTLR_LLCP_CONN];
62 struct node_tx *tx[CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM +
63 CONFIG_BT_CTLR_LLCP_CONN * CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM + 3];
64 uint16_t tx_alloc_idx = 0;
65 int i;
66
67 for (int ctx_idx = 0; ctx_idx < CONFIG_BT_CTLR_LLCP_CONN; ctx_idx++) {
68 ctxs[ctx_idx] = llcp_create_local_procedure(PROC_VERSION_EXCHANGE);
69 }
70
71 /* Init per conn tx_buffer_alloc count */
72 for (int j = 1; j < CONFIG_BT_CTLR_LLCP_CONN; j++) {
73 conn[j].llcp.tx_buffer_alloc = 0;
74 }
75 #if defined(LLCP_TX_CTRL_BUF_QUEUE_ENABLE)
76 /* Check alloc flow */
77 for (i = 0; i < CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM; i++) {
78 zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]));
79 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
80 zassert_equal(conn[0].llcp.tx_buffer_alloc, i + 1);
81 zassert_equal(llcp_common_tx_buffer_alloc_count(), 0);
82 zassert_not_null(tx[tx_alloc_idx], NULL);
83 tx_alloc_idx++;
84
85 }
86 for (i = 0; i < CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM; i++) {
87 zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]));
88 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
89 zassert_equal(conn[0].llcp.tx_buffer_alloc,
90 CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM + i + 1, NULL);
91 zassert_equal(llcp_common_tx_buffer_alloc_count(), i+1);
92 zassert_not_null(tx[tx_alloc_idx], NULL);
93 tx_alloc_idx++;
94
95 }
96 zassert_false(llcp_tx_alloc_peek(&conn[0], ctxs[0]));
97 zassert_equal(ctxs[0]->wait_reason, WAITING_FOR_TX_BUFFER);
98
99 for (int j = 1; j < CONFIG_BT_CTLR_LLCP_CONN; j++) {
100 /* Now global pool is exausted, but conn pool is not */
101 for (i = 0; i < CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM; i++) {
102 zassert_true(llcp_tx_alloc_peek(&conn[j], ctxs[j]));
103 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[j], ctxs[j]);
104 zassert_not_null(tx[tx_alloc_idx], NULL);
105 zassert_equal(llcp_common_tx_buffer_alloc_count(),
106 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM, NULL);
107 zassert_equal(conn[j].llcp.tx_buffer_alloc, i + 1);
108 tx_alloc_idx++;
109 }
110
111 zassert_false(llcp_tx_alloc_peek(&conn[j], ctxs[j]));
112 zassert_equal(ctxs[j]->wait_reason, WAITING_FOR_TX_BUFFER);
113 }
114 ull_cp_release_tx(&conn[0], tx[1]);
115 zassert_equal(llcp_common_tx_buffer_alloc_count(),
116 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM - 1, NULL);
117 zassert_equal(conn[0].llcp.tx_buffer_alloc, CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM +
118 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM - 1, NULL);
119
120 /* global pool is now 'open' again, but ctxs[1] is NOT next in line */
121 zassert_false(llcp_tx_alloc_peek(&conn[1], ctxs[1]));
122
123 /* ... ctxs[0] is */
124 zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]));
125 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
126 zassert_equal(llcp_common_tx_buffer_alloc_count(),
127 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM, NULL);
128 zassert_equal(conn[0].llcp.tx_buffer_alloc,
129 CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM +
130 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM, NULL);
131
132 zassert_not_null(tx[tx_alloc_idx], NULL);
133 tx_alloc_idx++;
134 ull_cp_release_tx(&conn[0], tx[tx_alloc_idx - 1]);
135 zassert_equal(llcp_common_tx_buffer_alloc_count(),
136 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM - 1, NULL);
137 zassert_equal(conn[0].llcp.tx_buffer_alloc, CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM +
138 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM - 1, NULL);
139
140 /* global pool does not allow as ctxs[2] is NOT next up */
141 zassert_false(llcp_tx_alloc_peek(&conn[2], ctxs[2]));
142
143 #if (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0)
144 /* Release conn[2] held tx, to confirm alloc is allowed after releasing pre-alloted buf */
145 zassert_true(!(conn[2].llcp.tx_buffer_alloc <
146 CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM), NULL);
147 ull_cp_release_tx(&conn[2], tx[CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM +
148 CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM +
149 CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM]);
150 zassert_true((conn[2].llcp.tx_buffer_alloc <
151 CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM), NULL);
152
153 /* global pool does not allow as ctxs[2] is not next up, but pre alloted is now avail */
154 zassert_equal(ctxs[2]->wait_reason, WAITING_FOR_TX_BUFFER);
155 zassert_not_null(ctxs[2]->wait_node.next, NULL);
156 zassert_true(llcp_tx_alloc_peek(&conn[2], ctxs[2]));
157 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[2], ctxs[2]);
158 zassert_not_null(tx[tx_alloc_idx], NULL);
159 tx_alloc_idx++;
160
161 /* No longer waiting in line */
162 zassert_equal(ctxs[2]->wait_reason, WAITING_FOR_NOTHING);
163 zassert_is_null(ctxs[2]->wait_node.next, NULL);
164 #endif /* (CONFIG_BT_CTLR_LLCP_PER_CONN_TX_CTRL_BUF_NUM > 0) */
165
166 /* now ctxs[1] is next up */
167 zassert_true(llcp_tx_alloc_peek(&conn[1], ctxs[1]));
168 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
169 zassert_not_null(tx[tx_alloc_idx], NULL);
170 tx_alloc_idx++;
171
172 #else /* LLCP_TX_CTRL_BUF_QUEUE_ENABLE */
173 /* Test that there are exactly LLCP_CONN * LLCP_TX_CTRL_BUF_NUM_MAX
174 * buffers available
175 */
176 for (i = 0;
177 i < CONFIG_BT_CTLR_LLCP_TX_PER_CONN_TX_CTRL_BUF_NUM_MAX * CONFIG_BT_CTLR_LLCP_CONN;
178 i++) {
179 zassert_true(llcp_tx_alloc_peek(&conn[0], ctxs[0]));
180 tx[tx_alloc_idx] = llcp_tx_alloc(&conn[0], ctxs[0]);
181 zassert_not_null(tx[tx_alloc_idx], NULL);
182 tx_alloc_idx++;
183 }
184 zassert_false(llcp_tx_alloc_peek(&conn[0], ctxs[0]));
185 #endif /* LLCP_TX_CTRL_BUF_QUEUE_ENABLE */
186 }
187
188 ZTEST_SUITE(tx_buffer_alloc, NULL, NULL, alloc_setup, NULL, NULL);
189