1 /*
2  * Copyright (c) 2022 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * SAR stress test
7  */
8 
9 #include "mesh_test.h"
10 #include <string.h>
11 #include <zephyr/logging/log.h>
12 
13 LOG_MODULE_REGISTER(test_sar, LOG_LEVEL_INF);
14 
15 #define CLI_ADDR    0x7728
16 #define SRV_ADDR    0x18f8
17 #define WAIT_TIME   60 /* seconds */
18 #define SEM_TIMEOUT K_SECONDS(25)
19 #define RAND_SEED 1
20 
21 #define DUMMY_VND_MOD_GET_OP	BT_MESH_MODEL_OP_3(0xDC, TEST_VND_COMPANY_ID)
22 #define DUMMY_VND_MOD_STATUS_OP BT_MESH_MODEL_OP_3(0xCD, TEST_VND_COMPANY_ID)
23 
24 #define MAX_SDU_MSG_LEN                                                                            \
25 	BT_MESH_TX_SDU_MAX - BT_MESH_MIC_SHORT - BT_MESH_MODEL_OP_LEN(DUMMY_VND_MOD_GET_OP)
26 
27 static struct k_sem inst_suspend_sem;
28 static const uint8_t dev_key[16] = {0xaa};
29 
30 static uint8_t dummy_msg[MAX_SDU_MSG_LEN] = {0};
31 
32 static struct bt_mesh_msg_ctx test_ctx = {
33 	.net_idx = 0,
34 	.app_idx = 0,
35 	.addr = SRV_ADDR,
36 };
37 
38 /* Segment Interval Step for both Transmitter and Receiver Configuration states must be at least 1,
39  * or else network buffers run out.
40  */
41 static struct bt_mesh_sar_tx test_sar_tx = {
42 	.seg_int_step = 1,
43 	.unicast_retrans_count = 15,
44 	.unicast_retrans_without_prog_count = 15,
45 	.unicast_retrans_int_step = 0,
46 	.unicast_retrans_int_inc = 0,
47 };
48 
49 static struct bt_mesh_sar_rx test_sar_rx = {
50 	.seg_thresh = 0,
51 	.ack_delay_inc = 0,
52 	.discard_timeout = 15,
53 	.rx_seg_int_step = 1,
54 	.ack_retrans_count = 3,
55 };
56 
57 static struct bt_mesh_sar_tx test_sar_slow_tx = {
58 	.seg_int_step = 15,
59 	.unicast_retrans_count = CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_COUNT,
60 	.unicast_retrans_without_prog_count =
61 		CONFIG_BT_MESH_SAR_TX_UNICAST_RETRANS_WITHOUT_PROG_COUNT,
62 	.unicast_retrans_int_step = 15,
63 	.unicast_retrans_int_inc = 15,
64 };
65 
66 static struct bt_mesh_sar_rx test_sar_slow_rx = {
67 	.seg_thresh = 0x1f,
68 	.ack_delay_inc = 7,
69 	.discard_timeout = CONFIG_BT_MESH_SAR_RX_DISCARD_TIMEOUT,
70 	.rx_seg_int_step = 15,
71 	.ack_retrans_count = CONFIG_BT_MESH_SAR_RX_ACK_RETRANS_COUNT,
72 };
73 
74 static struct bt_mesh_prov prov;
75 static struct bt_mesh_cfg_cli cfg_cli;
76 static struct bt_mesh_sar_cfg_cli sar_cli;
77 
78 /* Assert that buffer length and data corresponds with test dummy message.
79  * Buffer state is saved.
80  */
data_integrity_check(struct net_buf_simple * buf)81 static void data_integrity_check(struct net_buf_simple *buf)
82 {
83 	struct net_buf_simple_state state = {0};
84 
85 	ASSERT_EQUAL(buf->len, MAX_SDU_MSG_LEN);
86 	net_buf_simple_save(buf, &state);
87 
88 	/* Note: Using ASSERT_TRUE since ASSERT_EQUAL would call cond twise if not true. */
89 	ASSERT_TRUE(memcmp(net_buf_simple_pull_mem(buf, MAX_SDU_MSG_LEN), dummy_msg,
90 			   MAX_SDU_MSG_LEN) == 0);
91 	net_buf_simple_restore(buf, &state);
92 }
93 
get_handler(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)94 static int get_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
95 		       struct net_buf_simple *buf)
96 {
97 	data_integrity_check(buf);
98 	BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_VND_MOD_STATUS_OP, MAX_SDU_MSG_LEN);
99 	bt_mesh_model_msg_init(&msg, DUMMY_VND_MOD_STATUS_OP);
100 	net_buf_simple_add_mem(&msg, buf->data, buf->len);
101 
102 	k_sem_give(&inst_suspend_sem);
103 
104 	return bt_mesh_model_send(model, ctx, &msg, NULL, NULL);
105 }
106 
status_handler(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)107 static int status_handler(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
108 			  struct net_buf_simple *buf)
109 {
110 	data_integrity_check(buf);
111 	k_sem_give(&inst_suspend_sem);
112 	return 0;
113 }
114 
dummy_vnd_mod_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,uint8_t msg[])115 static int dummy_vnd_mod_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
116 			     uint8_t msg[])
117 {
118 	BT_MESH_MODEL_BUF_DEFINE(buf, DUMMY_VND_MOD_GET_OP, MAX_SDU_MSG_LEN);
119 
120 	bt_mesh_model_msg_init(&buf, DUMMY_VND_MOD_GET_OP);
121 	net_buf_simple_add_mem(&buf, msg, MAX_SDU_MSG_LEN);
122 
123 	return bt_mesh_model_send(model, ctx, &buf, NULL, NULL);
124 }
125 
126 static const struct bt_mesh_model_op _dummy_vnd_mod_op[] = {
127 	{DUMMY_VND_MOD_GET_OP, MAX_SDU_MSG_LEN, get_handler},
128 	{DUMMY_VND_MOD_STATUS_OP, MAX_SDU_MSG_LEN, status_handler},
129 	BT_MESH_MODEL_OP_END,
130 };
131 
132 uint16_t dummy_keys[CONFIG_BT_MESH_MODEL_KEY_COUNT] = { 0 };
133 
134 static struct bt_mesh_elem elements[] = {BT_MESH_ELEM(
135 	0,
136 	MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
137 		   BT_MESH_MODEL_CFG_CLI(&cfg_cli),
138 		   BT_MESH_MODEL_SAR_CFG_CLI(&sar_cli),
139 		   BT_MESH_MODEL_SAR_CFG_SRV),
140 	MODEL_LIST(BT_MESH_MODEL_VND_CB(TEST_VND_COMPANY_ID, TEST_VND_MOD_ID, _dummy_vnd_mod_op,
141 					NULL, NULL, NULL)))};
142 
143 static const struct bt_mesh_comp comp = {
144 	.cid = TEST_VND_COMPANY_ID,
145 	.elem = elements,
146 	.elem_count = ARRAY_SIZE(elements),
147 };
148 
prov_and_conf(uint16_t addr,struct bt_mesh_sar_rx * sar_rx_config,struct bt_mesh_sar_tx * sar_tx_config)149 static void prov_and_conf(uint16_t addr,
150 			  struct bt_mesh_sar_rx *sar_rx_config,
151 			  struct bt_mesh_sar_tx *sar_tx_config)
152 {
153 	int err;
154 	uint8_t status;
155 	struct bt_mesh_sar_tx tx_rsp;
156 	struct bt_mesh_sar_rx rx_rsp;
157 
158 	ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, addr, dev_key));
159 
160 	err = bt_mesh_cfg_cli_app_key_add(0, addr, 0, 0, test_app_key, &status);
161 	if (err || status) {
162 		FAIL("AppKey add failed (err %d, status %u)", err, status);
163 	}
164 
165 	err = bt_mesh_cfg_cli_mod_app_bind_vnd(0, addr, addr, 0, TEST_VND_MOD_ID,
166 					       TEST_VND_COMPANY_ID, &status);
167 	if (err || status) {
168 		FAIL("Failed to bind Dummy vnd model to application (err %d, status %u)", err,
169 		     status);
170 	}
171 
172 	ASSERT_OK(bt_mesh_sar_cfg_cli_transmitter_set(0, addr, sar_tx_config, &tx_rsp));
173 	ASSERT_OK(bt_mesh_sar_cfg_cli_receiver_set(0, addr, sar_rx_config, &rx_rsp));
174 }
175 
array_random_fill(uint8_t array[],uint16_t len,int seed)176 static void array_random_fill(uint8_t array[], uint16_t len, int seed)
177 {
178 	/* Ensures that the same random numbers are used for both client and server instances. */
179 	srand(seed);
180 	for (uint16_t i = 0; i < len; i++) {
181 		array[i] = rand() % 100;
182 	}
183 }
184 
cli_max_len_sdu_send(struct bt_mesh_sar_rx * sar_rx_config,struct bt_mesh_sar_tx * sar_tx_config)185 static void cli_max_len_sdu_send(struct bt_mesh_sar_rx *sar_rx_config,
186 				 struct bt_mesh_sar_tx *sar_tx_config)
187 {
188 	struct bt_mesh_model *dummy_vnd_mod = &elements[0].vnd_models[0];
189 
190 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
191 	bt_mesh_device_setup(&prov, &comp);
192 	prov_and_conf(CLI_ADDR, sar_rx_config, sar_tx_config);
193 
194 	ASSERT_OK(k_sem_init(&inst_suspend_sem, 0, 1));
195 	array_random_fill(dummy_msg, ARRAY_SIZE(dummy_msg), RAND_SEED);
196 
197 	for (int i = 0; i < 2; i++) {
198 		ASSERT_OK(dummy_vnd_mod_get(dummy_vnd_mod, &test_ctx, dummy_msg));
199 		/* Wait for message response */
200 		if (k_sem_take(&inst_suspend_sem, SEM_TIMEOUT)) {
201 			FAIL("Client suspension timed out.");
202 		}
203 		k_sem_reset(&inst_suspend_sem);
204 	}
205 
206 	PASS();
207 }
208 
srv_max_len_sdu_receive(struct bt_mesh_sar_rx * sar_rx_config,struct bt_mesh_sar_tx * sar_tx_config)209 static void srv_max_len_sdu_receive(struct bt_mesh_sar_rx *sar_rx_config,
210 				    struct bt_mesh_sar_tx *sar_tx_config)
211 {
212 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
213 	bt_mesh_device_setup(&prov, &comp);
214 	prov_and_conf(SRV_ADDR, sar_rx_config, sar_tx_config);
215 
216 	ASSERT_OK(k_sem_init(&inst_suspend_sem, 0, 1));
217 	array_random_fill(dummy_msg, ARRAY_SIZE(dummy_msg), RAND_SEED);
218 
219 	/* Wait for message to be received */
220 	if (k_sem_take(&inst_suspend_sem, SEM_TIMEOUT)) {
221 		FAIL("Server suspension timed out.");
222 	}
223 
224 	PASS();
225 }
226 
test_cli_max_len_sdu_send(void)227 static void test_cli_max_len_sdu_send(void)
228 {
229 	cli_max_len_sdu_send(&test_sar_rx, &test_sar_tx);
230 
231 	PASS();
232 }
233 
test_srv_max_len_sdu_receive(void)234 static void test_srv_max_len_sdu_receive(void)
235 {
236 	srv_max_len_sdu_receive(&test_sar_rx, &test_sar_tx);
237 
238 	PASS();
239 }
240 
test_cli_max_len_sdu_slow_send(void)241 static void test_cli_max_len_sdu_slow_send(void)
242 {
243 	cli_max_len_sdu_send(&test_sar_slow_rx, &test_sar_slow_tx);
244 
245 	PASS();
246 }
247 
test_srv_max_len_sdu_slow_receive(void)248 static void test_srv_max_len_sdu_slow_receive(void)
249 {
250 	srv_max_len_sdu_receive(&test_sar_slow_rx, &test_sar_slow_tx);
251 
252 	PASS();
253 }
254 
255 #if CONFIG_BT_SETTINGS
test_srv_cfg_store(void)256 static void test_srv_cfg_store(void)
257 {
258 	struct bt_mesh_sar_rx rx_cfg;
259 	struct bt_mesh_sar_tx tx_cfg;
260 
261 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
262 	bt_mesh_device_setup(&prov, &comp);
263 	prov_and_conf(SRV_ADDR, &test_sar_rx, &test_sar_tx);
264 
265 	bt_mesh_sar_cfg_cli_receiver_get(0, SRV_ADDR, &rx_cfg);
266 	bt_mesh_sar_cfg_cli_transmitter_get(0, SRV_ADDR, &tx_cfg);
267 
268 	ASSERT_EQUAL(0, memcmp(&rx_cfg, &test_sar_rx, sizeof(test_sar_rx)));
269 	ASSERT_EQUAL(0, memcmp(&tx_cfg, &test_sar_tx, sizeof(test_sar_tx)));
270 
271 	PASS();
272 }
273 
test_srv_cfg_restore(void)274 static void test_srv_cfg_restore(void)
275 {
276 	struct bt_mesh_sar_rx rx_cfg;
277 	struct bt_mesh_sar_tx tx_cfg;
278 
279 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
280 	bt_mesh_device_setup(&prov, &comp);
281 
282 	bt_mesh_sar_cfg_cli_receiver_get(0, SRV_ADDR, &rx_cfg);
283 	bt_mesh_sar_cfg_cli_transmitter_get(0, SRV_ADDR, &tx_cfg);
284 
285 	ASSERT_EQUAL(0, memcmp(&rx_cfg, &test_sar_rx, sizeof(test_sar_rx)));
286 	ASSERT_EQUAL(0, memcmp(&tx_cfg, &test_sar_tx, sizeof(test_sar_tx)));
287 
288 	PASS();
289 }
290 #endif
291 
292 #define TEST_CASE(role, name, description)              \
293 	{                                                   \
294 		.test_id = "sar_" #role "_" #name,              \
295 		.test_descr = description,                      \
296 		.test_tick_f = bt_mesh_test_timeout,            \
297 		.test_main_f = test_##role##_##name,            \
298 	}
299 
300 static const struct bst_test_instance test_sar[] = {
301 	TEST_CASE(cli, max_len_sdu_send,
302 		  "Send a 32-segment message with pre-defined test SAR configurations"),
303 	TEST_CASE(srv, max_len_sdu_receive,
304 		  "Receive a 32-segment message with pre-defined test SAR configurations."),
305 	TEST_CASE(cli, max_len_sdu_slow_send,
306 		  "Send a 32-segment message with SAR configured with slowest timings."),
307 	TEST_CASE(srv, max_len_sdu_slow_receive,
308 		  "Receive a 32-segment message with with SAR configured with slowest timings."),
309 
310 	BSTEST_END_MARKER};
311 
test_sar_install(struct bst_test_list * tests)312 struct bst_test_list *test_sar_install(struct bst_test_list *tests)
313 {
314 	tests = bst_add_tests(tests, test_sar);
315 	return tests;
316 }
317 
318 #if CONFIG_BT_SETTINGS
319 static const struct bst_test_instance test_sar_pst[] = {
320 	TEST_CASE(srv, cfg_store, "Set and save SAR RX/TX configuration"),
321 	TEST_CASE(srv, cfg_restore, "Restore SAR RX/TX configuration"),
322 
323 	BSTEST_END_MARKER};
324 
test_sar_pst_install(struct bst_test_list * tests)325 struct bst_test_list *test_sar_pst_install(struct bst_test_list *tests)
326 {
327 	tests = bst_add_tests(tests, test_sar_pst);
328 	return tests;
329 }
330 #endif
331