1 /*
2  * Copyright (c) 2022 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/bluetooth/hci.h>
9 #include "mesh_test.h"
10 #include "mesh/net.h"
11 #include "mesh/mesh.h"
12 #include "mesh/foundation.h"
13 #include "gatt_common.h"
14 
15 #define LOG_MODULE_NAME test_adv
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);
19 
20 #define WAIT_TIME 60 /*seconds*/
21 
22 extern const struct bt_mesh_comp comp;
23 
24 static uint8_t test_prov_uuid[16] = { 0x6c, 0x69, 0x6e, 0x67, 0x61, 0xaa };
25 
26 static const struct bt_mesh_test_cfg adv_cfg = {
27 	.addr = 0x0001,
28 	.dev_key = { 0x01 },
29 };
30 
31 static struct bt_mesh_send_cb send_cb;
32 static struct bt_mesh_test_adv xmit_param;
33 static const char txt_msg[] = "adv test";
34 static const char cb_msg[] = "cb test";
35 static int64_t tx_timestamp;
36 static int seq_checker;
37 static struct bt_mesh_test_gatt gatt_param;
38 static int num_adv_sent;
39 static uint8_t previous_checker = 0xff;
40 
41 static K_SEM_DEFINE(observer_sem, 0, 1);
42 
test_tx_init(void)43 static void test_tx_init(void)
44 {
45 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
46 }
47 
test_rx_init(void)48 static void test_rx_init(void)
49 {
50 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
51 }
52 
bt_init(void)53 static void bt_init(void)
54 {
55 	ASSERT_OK_MSG(bt_enable(NULL), "Bluetooth init failed");
56 	LOG_INF("Bluetooth initialized");
57 }
58 
adv_init(void)59 static void adv_init(void)
60 {
61 	bt_mesh_adv_init();
62 	ASSERT_OK_MSG(bt_mesh_adv_enable(), "Mesh adv init failed");
63 }
64 
allocate_all_array(struct bt_mesh_adv ** adv,size_t num_adv,uint8_t xmit)65 static void allocate_all_array(struct bt_mesh_adv **adv, size_t num_adv, uint8_t xmit)
66 {
67 	for (int i = 0; i < num_adv; i++) {
68 		*adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
69 					  xmit, K_NO_WAIT);
70 
71 		ASSERT_FALSE_MSG(!*adv, "Out of advs\n");
72 		adv++;
73 	}
74 }
75 
verify_adv_queue_overflow(void)76 static void verify_adv_queue_overflow(void)
77 {
78 	struct bt_mesh_adv *dummy_adv;
79 
80 	/* Verity Queue overflow */
81 	dummy_adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
82 				       BT_MESH_TRANSMIT(2, 20), K_NO_WAIT);
83 	ASSERT_TRUE_MSG(!dummy_adv, "Unexpected extra adv\n");
84 }
85 
check_delta_time(uint8_t transmit,uint64_t interval)86 static bool check_delta_time(uint8_t transmit, uint64_t interval)
87 {
88 	static int cnt;
89 	static int64_t timestamp;
90 
91 	if (cnt) {
92 		int64_t delta = k_uptime_delta(&timestamp);
93 
94 		LOG_INF("rx: cnt(%d) delta(%dms) interval(%ums)",
95 			cnt, (int32_t)delta, (uint32_t)interval);
96 
97 		ASSERT_TRUE(delta >= (interval - 5) &&
98 			    delta < (interval + 15));
99 	} else {
100 		timestamp = k_uptime_get();
101 
102 		LOG_INF("rx: cnt(%d) delta(0ms)", cnt);
103 	}
104 
105 	cnt++;
106 
107 	if (cnt >= transmit) {
108 		cnt = 0;
109 		timestamp = 0;
110 		return true;
111 	}
112 
113 	return false;
114 }
115 
single_start_cb(uint16_t duration,int err,void * cb_data)116 static void single_start_cb(uint16_t duration, int err, void *cb_data)
117 {
118 	int64_t delta;
119 
120 	delta = k_uptime_delta(&tx_timestamp);
121 	LOG_INF("tx start: +%d ms", delta);
122 	ASSERT_TRUE(duration >= 90 && duration <= 200);
123 	ASSERT_EQUAL(0, err);
124 	ASSERT_EQUAL(cb_msg, cb_data);
125 	ASSERT_EQUAL(0, seq_checker & 1);
126 	seq_checker++;
127 }
128 
single_end_cb(int err,void * cb_data)129 static void single_end_cb(int err, void *cb_data)
130 {
131 	int64_t delta;
132 
133 	delta = k_uptime_delta(&tx_timestamp);
134 	LOG_INF("tx end: +%d ms", delta);
135 	ASSERT_EQUAL(0, err);
136 	ASSERT_EQUAL(cb_msg, cb_data);
137 	ASSERT_EQUAL(1, seq_checker & 1);
138 	seq_checker++;
139 	k_sem_give(&observer_sem);
140 }
141 
realloc_end_cb(int err,void * cb_data)142 static void realloc_end_cb(int err, void *cb_data)
143 {
144 	struct bt_mesh_adv *adv = (struct bt_mesh_adv *)cb_data;
145 
146 	ASSERT_EQUAL(0, err);
147 	adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
148 			BT_MESH_TRANSMIT(2, 20), K_NO_WAIT);
149 	ASSERT_FALSE_MSG(!adv, "Out of advs\n");
150 
151 	k_sem_give(&observer_sem);
152 }
153 
seq_start_cb(uint16_t duration,int err,void * cb_data)154 static void seq_start_cb(uint16_t duration, int err, void *cb_data)
155 {
156 	ASSERT_EQUAL(0, err);
157 	ASSERT_EQUAL(seq_checker, (intptr_t)cb_data);
158 }
159 
seq_end_cb(int err,void * cb_data)160 static void seq_end_cb(int err, void *cb_data)
161 {
162 	ASSERT_EQUAL(0, err);
163 	ASSERT_EQUAL(seq_checker, (intptr_t)cb_data);
164 	seq_checker++;
165 
166 	if (seq_checker == CONFIG_BT_MESH_ADV_BUF_COUNT) {
167 		k_sem_give(&observer_sem);
168 	}
169 }
170 
gatt_scan_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)171 static void gatt_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
172 			  uint8_t adv_type, struct net_buf_simple *buf)
173 {
174 	if (adv_type != BT_GAP_ADV_TYPE_ADV_IND) {
175 		return;
176 	}
177 
178 	bt_mesh_test_parse_mesh_gatt_preamble(buf);
179 
180 	if (gatt_param.service == MESH_SERVICE_PROVISIONING) {
181 		bt_mesh_test_parse_mesh_pb_gatt_service(buf);
182 	} else {
183 		bt_mesh_test_parse_mesh_proxy_service(buf);
184 	}
185 
186 	LOG_INF("rx: %s", txt_msg);
187 
188 	if (check_delta_time(gatt_param.transmits, gatt_param.interval)) {
189 		LOG_INF("rx completed. stop observer.");
190 		k_sem_give(&observer_sem);
191 	}
192 }
193 
xmit_scan_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)194 static void xmit_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
195 			struct net_buf_simple *buf)
196 {
197 	uint8_t length;
198 
199 	if (adv_type != BT_GAP_ADV_TYPE_ADV_NONCONN_IND) {
200 		return;
201 	}
202 
203 	length = net_buf_simple_pull_u8(buf);
204 	ASSERT_EQUAL(buf->len, length);
205 	ASSERT_EQUAL(length, sizeof(uint8_t) + sizeof(txt_msg));
206 	ASSERT_EQUAL(BT_DATA_MESH_MESSAGE, net_buf_simple_pull_u8(buf));
207 
208 	char *data = net_buf_simple_pull_mem(buf, sizeof(txt_msg));
209 
210 	LOG_INF("rx: %s", txt_msg);
211 	ASSERT_EQUAL(0, memcmp(txt_msg, data, sizeof(txt_msg)));
212 
213 	/* Add 1 initial transmit to the retransmit. */
214 	if (check_delta_time(xmit_param.retr + 1, xmit_param.interval)) {
215 		LOG_INF("rx completed. stop observer.");
216 		k_sem_give(&observer_sem);
217 	}
218 }
219 
send_order_start_cb(uint16_t duration,int err,void * user_data)220 static void send_order_start_cb(uint16_t duration, int err, void *user_data)
221 {
222 	struct bt_mesh_adv *adv = (struct bt_mesh_adv *)user_data;
223 
224 	ASSERT_OK_MSG(err, "Failed adv start cb err (%d)", err);
225 	ASSERT_EQUAL(2, adv->b.len);
226 
227 	uint8_t current = adv->b.data[0];
228 	uint8_t previous = adv->b.data[1];
229 
230 	LOG_INF("tx start: current(%d) previous(%d)", current, previous);
231 
232 	ASSERT_EQUAL(previous_checker, previous);
233 	previous_checker = current;
234 }
235 
send_order_end_cb(int err,void * user_data)236 static void send_order_end_cb(int err, void *user_data)
237 {
238 	ASSERT_OK_MSG(err, "Failed adv start cb err (%d)", err);
239 	seq_checker++;
240 	LOG_INF("tx end: seq(%d)", seq_checker);
241 
242 	if (seq_checker == num_adv_sent) {
243 		seq_checker = 0;
244 		previous_checker = 0xff;
245 		k_sem_give(&observer_sem);
246 	}
247 }
248 
receive_order_scan_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)249 static void receive_order_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
250 			struct net_buf_simple *buf)
251 {
252 	uint8_t length;
253 	uint8_t current;
254 	uint8_t previous;
255 
256 	length = net_buf_simple_pull_u8(buf);
257 	ASSERT_EQUAL(buf->len, length);
258 	ASSERT_EQUAL(BT_DATA_MESH_MESSAGE, net_buf_simple_pull_u8(buf));
259 	current = net_buf_simple_pull_u8(buf);
260 	previous = net_buf_simple_pull_u8(buf);
261 	LOG_INF("rx: current(%d) previous(%d)", current, previous);
262 	ASSERT_EQUAL(previous_checker, previous);
263 
264 	/* Add 1 initial transmit to the retransmit. */
265 	if (check_delta_time(xmit_param.retr + 1, xmit_param.interval)) {
266 		previous_checker = current;
267 		k_sem_give(&observer_sem);
268 	}
269 }
270 
receive_order(int expect_adv)271 static void receive_order(int expect_adv)
272 {
273 	previous_checker = 0xff;
274 	for (int i = 0; i < expect_adv; i++) {
275 		ASSERT_OK(bt_mesh_test_wait_for_packet(receive_order_scan_cb, &observer_sem, 10));
276 	}
277 }
278 
send_adv_buf(struct bt_mesh_adv * adv,uint8_t curr,uint8_t prev)279 static void send_adv_buf(struct bt_mesh_adv *adv, uint8_t curr, uint8_t prev)
280 {
281 	send_cb.start = send_order_start_cb;
282 	send_cb.end = send_order_end_cb;
283 
284 	(void)net_buf_simple_add_u8(&adv->b, curr);
285 	(void)net_buf_simple_add_u8(&adv->b, prev);
286 
287 	bt_mesh_adv_send(adv, &send_cb, adv);
288 	bt_mesh_adv_unref(adv);
289 }
290 
send_adv_array(struct bt_mesh_adv ** adv,size_t num_buf,bool reverse)291 static void send_adv_array(struct bt_mesh_adv **adv, size_t num_buf, bool reverse)
292 {
293 	uint8_t previous;
294 	int i;
295 
296 	num_adv_sent = num_buf;
297 	previous = 0xff;
298 	if (!reverse) {
299 		i = 0;
300 	} else {
301 		i = num_buf - 1;
302 	}
303 	while ((!reverse && i < num_buf) || (reverse && i >= 0)) {
304 		send_adv_buf(*adv, (uint8_t)i, previous);
305 		previous = (uint8_t)i;
306 		if (!reverse) {
307 			adv++;
308 			i++;
309 		} else {
310 			adv--;
311 			i--;
312 		}
313 	}
314 }
315 
test_tx_cb_single(void)316 static void test_tx_cb_single(void)
317 {
318 	struct bt_mesh_adv *adv;
319 	int err;
320 
321 	bt_init();
322 	adv_init();
323 
324 	adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
325 			BT_MESH_TRANSMIT(2, 20), K_NO_WAIT);
326 	ASSERT_FALSE_MSG(!adv, "Out of advs\n");
327 
328 	send_cb.start = single_start_cb;
329 	send_cb.end = single_end_cb;
330 
331 	net_buf_simple_add_mem(&adv->b, txt_msg, sizeof(txt_msg));
332 	seq_checker = 0;
333 	tx_timestamp = k_uptime_get();
334 	bt_mesh_adv_send(adv, &send_cb, (void *)cb_msg);
335 	bt_mesh_adv_unref(adv);
336 
337 	err = k_sem_take(&observer_sem, K_SECONDS(1));
338 	ASSERT_OK_MSG(err, "Didn't call end tx cb.");
339 
340 	PASS();
341 }
342 
test_rx_xmit(void)343 static void test_rx_xmit(void)
344 {
345 	xmit_param.retr = 2;
346 	xmit_param.interval = 20;
347 
348 	bt_init();
349 	ASSERT_OK(bt_mesh_test_wait_for_packet(xmit_scan_cb, &observer_sem, 20));
350 
351 	PASS();
352 }
353 
test_tx_cb_multi(void)354 static void test_tx_cb_multi(void)
355 {
356 	struct bt_mesh_adv *adv[CONFIG_BT_MESH_ADV_BUF_COUNT];
357 	int err;
358 
359 	bt_init();
360 	adv_init();
361 
362 	/* Allocate all network advs. */
363 	allocate_all_array(adv, ARRAY_SIZE(adv), BT_MESH_TRANSMIT(2, 20));
364 
365 	/* Start single adv to reallocate one network adv in callback.
366 	 * Check that the adv is freed before cb is triggered.
367 	 */
368 	send_cb.start = NULL;
369 	send_cb.end = realloc_end_cb;
370 	net_buf_simple_add_mem(&(adv[0]->b), txt_msg, sizeof(txt_msg));
371 
372 	bt_mesh_adv_send(adv[0], &send_cb, adv[0]);
373 	bt_mesh_adv_unref(adv[0]);
374 
375 	err = k_sem_take(&observer_sem, K_SECONDS(1));
376 	ASSERT_OK_MSG(err, "Didn't call the end tx cb that reallocates adv one more time.");
377 
378 	/* Start multi advs to check that all advs are sent and cbs are triggered. */
379 	send_cb.start = seq_start_cb;
380 	send_cb.end = seq_end_cb;
381 	seq_checker = 0;
382 
383 	for (int i = 0; i < CONFIG_BT_MESH_ADV_BUF_COUNT; i++) {
384 		net_buf_simple_add_le32(&(adv[i]->b), i);
385 		bt_mesh_adv_send(adv[i], &send_cb, (void *)(intptr_t)i);
386 		bt_mesh_adv_unref(adv[i]);
387 	}
388 
389 	err = k_sem_take(&observer_sem, K_SECONDS(10));
390 	ASSERT_OK_MSG(err, "Didn't call the last end tx cb.");
391 
392 	PASS();
393 }
394 
test_tx_proxy_mixin(void)395 static void test_tx_proxy_mixin(void)
396 {
397 	static struct bt_mesh_prov prov = {
398 		.uuid = test_prov_uuid,
399 	};
400 	uint8_t status;
401 	int err;
402 
403 	/* Initialize mesh stack and enable pb gatt bearer to emit beacons. */
404 	bt_mesh_device_setup(&prov, &comp);
405 	err = bt_mesh_prov_enable(BT_MESH_PROV_GATT);
406 	ASSERT_OK_MSG(err, "Failed to enable GATT provisioner");
407 
408 	/* Let the tester to measure an interval between advertisements.
409 	 * The node should advertise pb gatt service with 100 msec interval.
410 	 */
411 	k_sleep(K_MSEC(1800));
412 
413 	LOG_INF("Provision device under test");
414 	/* Provision dut and start gatt proxy beacons. */
415 	bt_mesh_provision(test_net_key, 0, 0, 0, adv_cfg.addr, adv_cfg.dev_key);
416 	/* Disable secured network beacons to exclude influence of them on proxy beaconing. */
417 	ASSERT_OK(bt_mesh_cfg_cli_beacon_set(0, adv_cfg.addr, BT_MESH_BEACON_DISABLED, &status));
418 	ASSERT_EQUAL(BT_MESH_BEACON_DISABLED, status);
419 
420 	/* Let the tester to measure an interval between advertisements.
421 	 * The node should advertise proxy service with 1 second interval.
422 	 */
423 	k_sleep(K_MSEC(6000));
424 
425 	/* Send a mesh message while advertising proxy service.
426 	 * Advertising the proxy service should be resumed after
427 	 * finishing advertising the message.
428 	 */
429 	struct bt_mesh_adv *adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
430 			BT_MESH_TRANSMIT(5, 20), K_NO_WAIT);
431 	net_buf_simple_add_mem(&adv->b, txt_msg, sizeof(txt_msg));
432 	bt_mesh_adv_send(adv, NULL, NULL);
433 	k_sleep(K_MSEC(150));
434 
435 	/* Let the tester to measure an interval between advertisements again. */
436 	k_sleep(K_MSEC(6000));
437 
438 	PASS();
439 }
440 
test_rx_proxy_mixin(void)441 static void test_rx_proxy_mixin(void)
442 {
443 	/* (total transmit duration) / (transmit interval) */
444 	gatt_param.transmits = 1500 / 100;
445 	gatt_param.interval = 100;
446 	gatt_param.service = MESH_SERVICE_PROVISIONING;
447 
448 	bt_init();
449 
450 	/* Scan pb gatt beacons. */
451 	ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &observer_sem, 20));
452 
453 	/* Delay to provision dut */
454 	k_sleep(K_MSEC(1000));
455 
456 	/* Scan proxy beacons. */
457 	/* (total transmit duration) / (transmit interval) */
458 	gatt_param.transmits = 5000 / 1000;
459 	gatt_param.interval = 1000;
460 	gatt_param.service = MESH_SERVICE_PROXY;
461 	ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &observer_sem, 20));
462 
463 	/* Scan adv data. */
464 	xmit_param.retr = 5;
465 	xmit_param.interval = 20;
466 	ASSERT_OK(bt_mesh_test_wait_for_packet(xmit_scan_cb, &observer_sem, 20));
467 
468 	/* Scan proxy beacons again. */
469 	ASSERT_OK(bt_mesh_test_wait_for_packet(gatt_scan_cb, &observer_sem, 20));
470 
471 	PASS();
472 }
473 
test_tx_send_order(void)474 static void test_tx_send_order(void)
475 {
476 	struct bt_mesh_adv *adv[CONFIG_BT_MESH_ADV_BUF_COUNT];
477 	uint8_t xmit = BT_MESH_TRANSMIT(2, 20);
478 
479 	bt_init();
480 	adv_init();
481 
482 	/* Verify sending order */
483 	allocate_all_array(adv, ARRAY_SIZE(adv), xmit);
484 	verify_adv_queue_overflow();
485 	send_adv_array(&adv[0], ARRAY_SIZE(adv), false);
486 
487 	/* Wait for no message receive window to end. */
488 	ASSERT_OK_MSG(k_sem_take(&observer_sem, K_SECONDS(10)),
489 		      "Didn't call the last end tx cb.");
490 
491 	/* Verify adv allocation/deallocation after sending */
492 	allocate_all_array(adv, ARRAY_SIZE(adv), xmit);
493 	verify_adv_queue_overflow();
494 	for (int i = 0; i < CONFIG_BT_MESH_ADV_BUF_COUNT; i++) {
495 		bt_mesh_adv_unref(adv[i]);
496 		adv[i] = NULL;
497 	}
498 	/* Check that it possible to add just one net adv. */
499 	allocate_all_array(adv, 1, xmit);
500 
501 	PASS();
502 }
503 
test_tx_reverse_order(void)504 static void test_tx_reverse_order(void)
505 {
506 	struct bt_mesh_adv *adv[CONFIG_BT_MESH_ADV_BUF_COUNT];
507 	uint8_t xmit = BT_MESH_TRANSMIT(2, 20);
508 
509 	bt_init();
510 	adv_init();
511 
512 	/* Verify reversed sending order */
513 	allocate_all_array(adv, ARRAY_SIZE(adv), xmit);
514 
515 	send_adv_array(&adv[CONFIG_BT_MESH_ADV_BUF_COUNT - 1], ARRAY_SIZE(adv), true);
516 
517 	/* Wait for no message receive window to end. */
518 	ASSERT_OK_MSG(k_sem_take(&observer_sem, K_SECONDS(10)),
519 		      "Didn't call the last end tx cb.");
520 
521 	PASS();
522 }
523 
test_tx_random_order(void)524 static void test_tx_random_order(void)
525 {
526 	struct bt_mesh_adv *adv[3];
527 	uint8_t xmit = BT_MESH_TRANSMIT(0, 20);
528 
529 	bt_init();
530 	adv_init();
531 
532 	/* Verify random order calls */
533 	num_adv_sent = ARRAY_SIZE(adv);
534 	previous_checker = 0xff;
535 	adv[0] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
536 				    xmit, K_NO_WAIT);
537 	ASSERT_FALSE_MSG(!adv[0], "Out of advs\n");
538 	adv[1] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
539 				    xmit, K_NO_WAIT);
540 	ASSERT_FALSE_MSG(!adv[1], "Out of advs\n");
541 
542 	send_adv_buf(adv[0], 0, 0xff);
543 
544 	adv[2] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
545 				    xmit, K_NO_WAIT);
546 	ASSERT_FALSE_MSG(!adv[2], "Out of advs\n");
547 
548 	send_adv_buf(adv[2], 2, 0);
549 
550 	send_adv_buf(adv[1], 1, 2);
551 
552 	/* Wait for no message receive window to end. */
553 	ASSERT_OK_MSG(k_sem_take(&observer_sem, K_SECONDS(10)),
554 		      "Didn't call the last end tx cb.");
555 
556 	PASS();
557 }
558 
test_rx_receive_order(void)559 static void test_rx_receive_order(void)
560 {
561 	bt_init();
562 
563 	xmit_param.retr = 2;
564 	xmit_param.interval = 20;
565 
566 	receive_order(CONFIG_BT_MESH_ADV_BUF_COUNT);
567 
568 	PASS();
569 }
570 
test_rx_random_order(void)571 static void test_rx_random_order(void)
572 {
573 	bt_init();
574 
575 	xmit_param.retr = 0;
576 	xmit_param.interval = 20;
577 
578 	receive_order(3);
579 
580 	PASS();
581 }
582 
adv_suspend(void)583 static void adv_suspend(void)
584 {
585 	atomic_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
586 
587 	ASSERT_OK_MSG(bt_mesh_adv_disable(), "Failed to disable advertiser sync");
588 }
589 
adv_resume(void)590 static void adv_resume(void)
591 {
592 	atomic_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
593 
594 	if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) {
595 		bt_mesh_adv_init();
596 	}
597 
598 	ASSERT_OK_MSG(bt_mesh_adv_enable(), "Failed to enable advertiser");
599 }
600 
601 struct adv_suspend_ctx {
602 	bool suspend;
603 	int instance_idx;
604 };
605 
606 static K_SEM_DEFINE(adv_sent_sem, 0, 1);
607 static K_SEM_DEFINE(adv_suspended_sem, 0, 1);
608 
adv_send_end(int err,void * cb_data)609 static void adv_send_end(int err, void *cb_data)
610 {
611 	struct adv_suspend_ctx *adv_data = cb_data;
612 
613 	LOG_DBG("end(): err (%d), suspend (%d), i (%d)", err, adv_data->suspend,
614 		adv_data->instance_idx);
615 
616 	ASSERT_EQUAL(err, 0);
617 
618 	if (adv_data->suspend) {
619 		/* When suspending, the end callback will be called only for the first adv, because
620 		 * it was already scheduled.
621 		 */
622 		ASSERT_EQUAL(adv_data->instance_idx, 0);
623 	} else {
624 		if (adv_data->instance_idx == CONFIG_BT_MESH_ADV_BUF_COUNT - 1) {
625 			k_sem_give(&adv_sent_sem);
626 		}
627 	}
628 }
629 
adv_send_start(uint16_t duration,int err,void * cb_data)630 static void adv_send_start(uint16_t duration, int err, void *cb_data)
631 {
632 	struct adv_suspend_ctx *adv_data = cb_data;
633 
634 	LOG_DBG("start(): err (%d), suspend (%d), i (%d)", err, adv_data->suspend,
635 		adv_data->instance_idx);
636 
637 	if (adv_data->suspend) {
638 		if (adv_data->instance_idx == 0) {
639 			ASSERT_EQUAL(err, 0);
640 			adv_suspend();
641 		} else {
642 			/* For the advs that were pushed to the mesh advertiser by calling
643 			 * `bt_mesh_adv_send` function but not sent to the host, the start callback
644 			 * shall be called with -ENODEV.
645 			 */
646 			ASSERT_EQUAL(err, -ENODEV);
647 		}
648 
649 		if (adv_data->instance_idx == CONFIG_BT_MESH_ADV_BUF_COUNT - 1) {
650 			k_sem_give(&adv_suspended_sem);
651 		}
652 	} else {
653 		ASSERT_EQUAL(err, 0);
654 	}
655 }
656 
adv_create_and_send(bool suspend,uint8_t first_byte,struct adv_suspend_ctx * adv_data)657 static void adv_create_and_send(bool suspend, uint8_t first_byte, struct adv_suspend_ctx *adv_data)
658 {
659 	struct bt_mesh_adv *advs[CONFIG_BT_MESH_ADV_BUF_COUNT];
660 	static const struct bt_mesh_send_cb send_cb = {
661 		.start = adv_send_start,
662 		.end = adv_send_end,
663 	};
664 
665 	for (int i = 0; i < CONFIG_BT_MESH_ADV_BUF_COUNT; i++) {
666 		adv_data[i].suspend = suspend;
667 		adv_data[i].instance_idx = i;
668 
669 		advs[i] = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
670 					    BT_MESH_TRANSMIT(2, 20), K_NO_WAIT);
671 		ASSERT_FALSE_MSG(!advs[i], "Out of advs\n");
672 
673 		net_buf_simple_add_u8(&advs[i]->b, first_byte);
674 		net_buf_simple_add_u8(&advs[i]->b, i);
675 	}
676 
677 	for (int i = 0; i < CONFIG_BT_MESH_ADV_BUF_COUNT; i++) {
678 		bt_mesh_adv_send(advs[i], &send_cb, &adv_data[i]);
679 		bt_mesh_adv_unref(advs[i]);
680 	}
681 }
682 
test_tx_disable(void)683 static void test_tx_disable(void)
684 {
685 	struct adv_suspend_ctx adv_data[CONFIG_BT_MESH_ADV_BUF_COUNT];
686 	struct bt_mesh_adv *extra_adv;
687 	int err;
688 
689 	bt_init();
690 	adv_init();
691 
692 	/* Fill up the adv pool and suspend the advertiser in the first start callback call. */
693 	adv_create_and_send(true, 0xAA, adv_data);
694 
695 	err = k_sem_take(&adv_suspended_sem, K_SECONDS(10));
696 	ASSERT_OK_MSG(err, "Not all advs were sent");
697 
698 	extra_adv = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_ADV_TAG_LOCAL,
699 				       BT_MESH_TRANSMIT(2, 20), K_NO_WAIT);
700 	ASSERT_TRUE_MSG(!extra_adv, "Created adv while suspended");
701 
702 	adv_resume();
703 
704 	/* Fill up the adv pool and suspend the advertiser and let it send all advs. */
705 	adv_create_and_send(false, 0xBB, adv_data);
706 
707 	err = k_sem_take(&adv_sent_sem, K_SECONDS(10));
708 	ASSERT_OK_MSG(err, "Not all advs were sent");
709 
710 	PASS();
711 }
712 
suspended_adv_scan_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)713 static void suspended_adv_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
714 				  struct net_buf_simple *buf)
715 {
716 	uint8_t length;
717 	uint8_t type;
718 	uint8_t pdu;
719 
720 	length = net_buf_simple_pull_u8(buf);
721 	ASSERT_EQUAL(buf->len, length);
722 	ASSERT_EQUAL(length, sizeof(uint8_t) * 3);
723 	type = net_buf_simple_pull_u8(buf);
724 	ASSERT_EQUAL(BT_DATA_MESH_MESSAGE, type);
725 
726 	pdu = net_buf_simple_pull_u8(buf);
727 	if (pdu == 0xAA) {
728 		pdu = net_buf_simple_pull_u8(buf);
729 
730 		/* Because the advertiser is stopped after the advertisement has been passed to the
731 		 * host, the controller could already start sending the message. Therefore, if the
732 		 * tester receives an advertisement with the first byte as 0xAA, the second byte can
733 		 * only be 0x00. This applies to both advertisers.
734 		 */
735 		ASSERT_EQUAL(0, pdu);
736 	}
737 }
738 
test_rx_disable(void)739 static void test_rx_disable(void)
740 {
741 	int err;
742 
743 	bt_init();
744 
745 	/* It is sufficient to check that the advertiser didn't sent PDUs which the end callback was
746 	 * not called for.
747 	 */
748 	err = bt_mesh_test_wait_for_packet(suspended_adv_scan_cb, &observer_sem, 20);
749 	/* The error will always be -ETIMEDOUT as the semaphore is never given in the callback. */
750 	ASSERT_EQUAL(-ETIMEDOUT, err);
751 
752 	PASS();
753 }
754 
755 #define TEST_CASE(role, name, description)                     \
756 	{                                                      \
757 		.test_id = "adv_" #role "_" #name,             \
758 		.test_descr = description,                     \
759 		.test_pre_init_f = test_##role##_init,         \
760 		.test_tick_f = bt_mesh_test_timeout,           \
761 		.test_main_f = test_##role##_##name,           \
762 	}
763 
764 static const struct bst_test_instance test_adv[] = {
765 	TEST_CASE(tx, cb_single,     "ADV: tx cb parameter checker"),
766 	TEST_CASE(tx, cb_multi,      "ADV: tx cb sequence checker"),
767 	TEST_CASE(tx, proxy_mixin,   "ADV: proxy mix-in gatt adv"),
768 	TEST_CASE(tx, send_order,    "ADV: tx send order"),
769 	TEST_CASE(tx, reverse_order, "ADV: tx reversed order"),
770 	TEST_CASE(tx, random_order,  "ADV: tx random order"),
771 	TEST_CASE(tx, disable,       "ADV: test suspending/resuming advertiser"),
772 
773 	TEST_CASE(rx, xmit,          "ADV: xmit checker"),
774 	TEST_CASE(rx, proxy_mixin,   "ADV: proxy mix-in scanner"),
775 	TEST_CASE(rx, receive_order, "ADV: rx receive order"),
776 	TEST_CASE(rx, random_order,  "ADV: rx random order"),
777 	TEST_CASE(rx, disable,       "ADV: rx adv from resumed advertiser"),
778 
779 	BSTEST_END_MARKER
780 };
781 
test_adv_install(struct bst_test_list * tests)782 struct bst_test_list *test_adv_install(struct bst_test_list *tests)
783 {
784 	tests = bst_add_tests(tests, test_adv);
785 	return tests;
786 }
787