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