1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/sys/iterable_sections.h>
11 #include <zephyr/net/buf.h>
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/mesh.h>
14 
15 #include "crypto.h"
16 #include "adv.h"
17 #include "mesh.h"
18 #include "net.h"
19 #include "transport.h"
20 #include "heartbeat.h"
21 #include "access.h"
22 #include "beacon.h"
23 #include "foundation.h"
24 #include "lpn.h"
25 
26 #define LOG_LEVEL CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL
27 #include <zephyr/logging/log.h>
28 LOG_MODULE_REGISTER(bt_mesh_lpn);
29 
30 /**
31  * Log modes other than the deferred may cause unintended delays during processing of log messages.
32  * This in turns will affect scheduling of the receive delay and receive window.
33  */
34 #if !defined(CONFIG_TEST) && !defined(CONFIG_ARCH_POSIX) && \
35 	defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_DEFERRED) && \
36 	(LOG_LEVEL >= LOG_LEVEL_INF)
37 #warning Frienship feature may work unstable when non-deferred log mode is selected. Use the \
38 	 CONFIG_LOG_MODE_DEFERRED Kconfig option when Low Power node feature is enabled.
39 #endif
40 
41 #if defined(CONFIG_BT_MESH_ADV_LEGACY)
42 #define RX_DELAY_CORRECTION(lpn) ((lpn)->adv_duration)
43 #else
44 #define RX_DELAY_CORRECTION(lpn) 0
45 #endif
46 
47 #if defined(CONFIG_BT_MESH_LPN_AUTO)
48 #define LPN_AUTO_TIMEOUT (CONFIG_BT_MESH_LPN_AUTO_TIMEOUT * MSEC_PER_SEC)
49 #else
50 #define LPN_AUTO_TIMEOUT 0
51 #endif
52 
53 #define LPN_RECV_DELAY            CONFIG_BT_MESH_LPN_RECV_DELAY
54 #define SCAN_LATENCY              MIN(CONFIG_BT_MESH_LPN_SCAN_LATENCY, \
55 				      LPN_RECV_DELAY)
56 
57 #define FRIEND_REQ_RETRY_TIMEOUT  K_SECONDS(CONFIG_BT_MESH_LPN_RETRY_TIMEOUT)
58 
59 #define FRIEND_REQ_WAIT           100
60 #define FRIEND_REQ_SCAN           (1 * MSEC_PER_SEC)
61 #define FRIEND_REQ_TIMEOUT        (FRIEND_REQ_WAIT + FRIEND_REQ_SCAN)
62 
63 #define POLL_RETRY_TIMEOUT        100
64 
65 #define REQ_RETRY_DURATION(lpn)   (LPN_RECV_DELAY + (lpn)->adv_duration + \
66 				      (lpn)->recv_win + POLL_RETRY_TIMEOUT)
67 
68 #define POLL_TIMEOUT_INIT         (CONFIG_BT_MESH_LPN_INIT_POLL_TIMEOUT * 100)
69 
70 #define POLL_TIMEOUT              (CONFIG_BT_MESH_LPN_POLL_TIMEOUT * 100)
71 
72 #define REQ_ATTEMPTS_MAX          6
73 #define REQ_ATTEMPTS(lpn)         MIN(REQ_ATTEMPTS_MAX, \
74 			  POLL_TIMEOUT / REQ_RETRY_DURATION(lpn))
75 
76 #define POLL_TIMEOUT_MAX(lpn)     (POLL_TIMEOUT - \
77 			  (REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn)))
78 
79 #define CLEAR_ATTEMPTS            3
80 
81 #define LPN_CRITERIA ((CONFIG_BT_MESH_LPN_MIN_QUEUE_SIZE) | \
82 		      (CONFIG_BT_MESH_LPN_RSSI_FACTOR << 3) | \
83 		      (CONFIG_BT_MESH_LPN_RECV_WIN_FACTOR << 5))
84 
85 #define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
86 #define LPN_POLL_TO POLL_TO(CONFIG_BT_MESH_LPN_POLL_TIMEOUT)
87 
88 /* 1 transmission, 20ms interval */
89 #define POLL_XMIT BT_MESH_TRANSMIT(0, 20)
90 
91 #if defined(CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL_DBG)
state2str(int state)92 static const char *state2str(int state)
93 {
94 	switch (state) {
95 	case BT_MESH_LPN_DISABLED:
96 		return "disabled";
97 	case BT_MESH_LPN_CLEAR:
98 		return "clear";
99 	case BT_MESH_LPN_TIMER:
100 		return "timer";
101 	case BT_MESH_LPN_ENABLED:
102 		return "enabled";
103 	case BT_MESH_LPN_REQ_WAIT:
104 		return "req wait";
105 	case BT_MESH_LPN_WAIT_OFFER:
106 		return "wait offer";
107 	case BT_MESH_LPN_ESTABLISHED:
108 		return "established";
109 	case BT_MESH_LPN_RECV_DELAY:
110 		return "recv delay";
111 	case BT_MESH_LPN_WAIT_UPDATE:
112 		return "wait update";
113 	default:
114 		return "(unknown)";
115 	}
116 }
117 #endif /* CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL_DBG */
118 
poll_timeout(struct bt_mesh_lpn * lpn)119 static int32_t poll_timeout(struct bt_mesh_lpn *lpn)
120 {
121 	/* If we're waiting for segment acks keep polling at high freq */
122 	if (bt_mesh_tx_in_progress()) {
123 		LOG_DBG("Tx is in progress. Keep polling");
124 		return MIN(POLL_TIMEOUT_MAX(lpn), 1 * MSEC_PER_SEC);
125 	}
126 
127 	if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) {
128 		lpn->poll_timeout *= 2;
129 		lpn->poll_timeout =
130 			MIN(lpn->poll_timeout, POLL_TIMEOUT_MAX(lpn));
131 	}
132 
133 	LOG_DBG("Poll Timeout is %ums", lpn->poll_timeout);
134 
135 	return lpn->poll_timeout;
136 }
137 
lpn_set_state(int state)138 static inline void lpn_set_state(int state)
139 {
140 #if defined(CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL_DBG)
141 	LOG_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state));
142 #endif
143 	bt_mesh.lpn.state = state;
144 }
145 
group_zero(atomic_t * target)146 static inline void group_zero(atomic_t *target)
147 {
148 #if CONFIG_BT_MESH_LPN_GROUPS > 32
149 	int i;
150 
151 	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
152 		atomic_set(&target[i], 0);
153 	}
154 #else
155 	atomic_set(target, 0);
156 #endif
157 }
158 
group_set(atomic_t * target,atomic_t * source)159 static inline void group_set(atomic_t *target, atomic_t *source)
160 {
161 #if CONFIG_BT_MESH_LPN_GROUPS > 32
162 	int i;
163 
164 	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
165 		(void)atomic_or(&target[i], atomic_get(&source[i]));
166 	}
167 #else
168 	(void)atomic_or(target, atomic_get(source));
169 #endif
170 }
171 
group_clear(atomic_t * target,atomic_t * source)172 static inline void group_clear(atomic_t *target, atomic_t *source)
173 {
174 #if CONFIG_BT_MESH_LPN_GROUPS > 32
175 	int i;
176 
177 	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
178 		(void)atomic_and(&target[i], ~atomic_get(&source[i]));
179 	}
180 #else
181 	(void)atomic_and(target, ~atomic_get(source));
182 #endif
183 }
184 
185 static void clear_friendship(bool force, bool disable);
186 
friend_clear_sent(int err,void * user_data)187 static void friend_clear_sent(int err, void *user_data)
188 {
189 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
190 
191 	bt_mesh_scan_enable();
192 
193 	lpn->req_attempts++;
194 
195 	if (err) {
196 		LOG_ERR("Sending Friend Request failed (err %d)", err);
197 		lpn_set_state(BT_MESH_LPN_ENABLED);
198 		clear_friendship(false, lpn->disable);
199 		return;
200 	}
201 
202 	lpn_set_state(BT_MESH_LPN_CLEAR);
203 	k_work_reschedule(&lpn->timer, K_MSEC(FRIEND_REQ_TIMEOUT));
204 }
205 
206 static const struct bt_mesh_send_cb clear_sent_cb = {
207 	.end = friend_clear_sent,
208 };
209 
send_friend_clear(void)210 static int send_friend_clear(void)
211 {
212 	struct bt_mesh_msg_ctx ctx = {
213 		.net_idx     = bt_mesh.lpn.sub->net_idx,
214 		.app_idx     = BT_MESH_KEY_UNUSED,
215 		.addr        = bt_mesh.lpn.frnd,
216 		.send_ttl    = 0,
217 	};
218 	struct bt_mesh_net_tx tx = {
219 		.sub = bt_mesh.lpn.sub,
220 		.ctx = &ctx,
221 		.src = bt_mesh_primary_addr(),
222 		.xmit = bt_mesh_net_transmit_get(),
223 	};
224 	struct bt_mesh_ctl_friend_clear req = {
225 		.lpn_addr    = sys_cpu_to_be16(tx.src),
226 		.lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.lpn_counter),
227 	};
228 
229 	LOG_DBG("");
230 
231 	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
232 				sizeof(req), &clear_sent_cb, NULL);
233 }
234 
clear_friendship(bool force,bool disable)235 static void clear_friendship(bool force, bool disable)
236 {
237 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
238 	bool was_established = lpn->established;
239 	uint16_t frnd = lpn->frnd;
240 	uint16_t net_idx = lpn->sub->net_idx;
241 
242 	LOG_DBG("force %u disable %u", force, disable);
243 
244 	if (!force && lpn->established && !lpn->clear_success &&
245 	    lpn->req_attempts < CLEAR_ATTEMPTS) {
246 		send_friend_clear();
247 		lpn->disable = disable;
248 		return;
249 	}
250 
251 	bt_mesh_rx_reset();
252 
253 	/* Disable LPN while clearing, in case the work handler gets a chance to fire. */
254 	lpn_set_state(BT_MESH_LPN_DISABLED);
255 	/* The timer handler returns without any actions if this fails. */
256 	(void)k_work_cancel_delayable(&lpn->timer);
257 
258 	if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT) || disable) {
259 		bt_mesh_scan_disable();
260 	}
261 
262 	if (lpn->clear_success) {
263 		lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
264 	} else {
265 		lpn->old_friend = lpn->frnd;
266 	}
267 
268 	for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
269 		if (lpn->sub->keys[i].valid) {
270 			bt_mesh_friend_cred_destroy(&lpn->cred[i]);
271 		}
272 	}
273 
274 	lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
275 	lpn->fsn = 0U;
276 	lpn->req_attempts = 0U;
277 	lpn->recv_win = 0U;
278 	lpn->queue_size = 0U;
279 	lpn->disable = 0U;
280 	lpn->sent_req = 0U;
281 	lpn->established = 0U;
282 	lpn->clear_success = 0U;
283 	lpn->sub = NULL;
284 
285 	group_zero(lpn->added);
286 	group_zero(lpn->pending);
287 	group_zero(lpn->to_remove);
288 
289 	/* Set this to 1 to force group subscription when the next
290 	 * Friendship is created, in case lpn->groups doesn't get
291 	 * modified meanwhile.
292 	 */
293 	lpn->groups_changed = 1U;
294 
295 	bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
296 
297 	if (!disable) {
298 		lpn_set_state(BT_MESH_LPN_ENABLED);
299 
300 		if (!IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
301 			bt_mesh_scan_enable();
302 		}
303 
304 		k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
305 	}
306 
307 	if (was_established) {
308 		STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
309 			if (cb->terminated) {
310 				cb->terminated(net_idx, frnd);
311 			}
312 		}
313 	}
314 }
315 
friend_req_send_end(int err,void * user_data)316 static void friend_req_send_end(int err, void *user_data)
317 {
318 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
319 
320 	if (lpn->state != BT_MESH_LPN_ENABLED) {
321 		return;
322 	}
323 
324 	if (err) {
325 		LOG_ERR("Sending Friend Request failed (err %d)", err);
326 		return;
327 	}
328 
329 	lpn->adv_duration = k_uptime_get_32() - lpn->adv_start_time;
330 
331 	if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
332 		k_work_reschedule(&lpn->timer,
333 				  K_MSEC(FRIEND_REQ_WAIT - (int32_t)lpn->adv_duration));
334 		lpn_set_state(BT_MESH_LPN_REQ_WAIT);
335 	} else {
336 		k_work_reschedule(&lpn->timer, K_MSEC(FRIEND_REQ_TIMEOUT));
337 		lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
338 	}
339 }
340 
friend_req_send_start(uint16_t duration,int err,void * user_data)341 static void friend_req_send_start(uint16_t duration, int err, void *user_data)
342 {
343 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
344 
345 	lpn->adv_start_time = k_uptime_get_32();
346 
347 	if (err) {
348 		friend_req_send_end(err, user_data);
349 	}
350 }
351 
352 static const struct bt_mesh_send_cb friend_req_send_cb = {
353 	.start = friend_req_send_start,
354 	.end = friend_req_send_end,
355 };
356 
send_friend_req(struct bt_mesh_lpn * lpn)357 static int send_friend_req(struct bt_mesh_lpn *lpn)
358 {
359 	const struct bt_mesh_comp *comp = bt_mesh_comp_get();
360 	struct bt_mesh_msg_ctx ctx = {
361 		.app_idx  = BT_MESH_KEY_UNUSED,
362 		.addr     = BT_MESH_ADDR_FRIENDS,
363 		.send_ttl = 0,
364 	};
365 	struct bt_mesh_net_tx tx = {
366 		.ctx = &ctx,
367 		.src = bt_mesh_primary_addr(),
368 		.xmit = POLL_XMIT,
369 	};
370 
371 	lpn->lpn_counter++;
372 
373 	struct bt_mesh_ctl_friend_req req = {
374 		.criteria    = LPN_CRITERIA,
375 		.recv_delay  = LPN_RECV_DELAY,
376 		.poll_to     = LPN_POLL_TO,
377 		.prev_addr   = sys_cpu_to_be16(lpn->old_friend),
378 		.num_elem    = comp->elem_count,
379 		.lpn_counter = sys_cpu_to_be16(lpn->lpn_counter),
380 	};
381 
382 	LOG_DBG("");
383 
384 	lpn->sub = bt_mesh_subnet_next(NULL);
385 	if (!lpn->sub) {
386 		LOG_ERR("No subnets, can't start LPN mode");
387 		return -ENOENT;
388 	}
389 
390 	ctx.net_idx = lpn->sub->net_idx;
391 	tx.sub = lpn->sub;
392 
393 	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
394 				sizeof(req), &friend_req_send_cb, NULL);
395 }
396 
req_send_end(int err,void * user_data)397 static void req_send_end(int err, void *user_data)
398 {
399 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
400 	bool retry;
401 
402 	if (lpn->state == BT_MESH_LPN_DISABLED) {
403 		return;
404 	}
405 
406 	lpn->adv_duration = k_uptime_get_32() - lpn->adv_start_time;
407 
408 #if defined(CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL_DBG)
409 	LOG_DBG("req 0x%02x duration %u err %d state %s", lpn->sent_req, lpn->adv_duration, err,
410 		state2str(lpn->state));
411 #endif
412 
413 	if (err) {
414 		LOG_ERR("Sending request failed (err %d)", err);
415 		lpn->sent_req = 0U;
416 		group_zero(lpn->pending);
417 		return;
418 	}
419 
420 	retry = (lpn->req_attempts > 0);
421 
422 	lpn->req_attempts++;
423 
424 	if (lpn->established || IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
425 		lpn_set_state(BT_MESH_LPN_RECV_DELAY);
426 		/* We start scanning a bit early to eliminate risk of missing
427 		 * response data due to HCI and other latencies.
428 		 */
429 		k_work_reschedule(&lpn->timer,
430 				  K_MSEC(LPN_RECV_DELAY - SCAN_LATENCY - RX_DELAY_CORRECTION(lpn)));
431 	} else {
432 		lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
433 		k_work_reschedule(&lpn->timer, K_MSEC(LPN_RECV_DELAY + lpn->recv_win));
434 	}
435 
436 	STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
437 		if (cb->polled) {
438 			cb->polled(lpn->sub->net_idx, lpn->frnd, retry);
439 		}
440 	}
441 }
442 
req_send_start(uint16_t duration,int err,void * user_data)443 static void req_send_start(uint16_t duration, int err, void *user_data)
444 {
445 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
446 
447 	lpn->adv_start_time = k_uptime_get_32();
448 
449 	if (err) {
450 		req_send_end(err, user_data);
451 	}
452 }
453 
454 static const struct bt_mesh_send_cb req_send_cb = {
455 	.start = req_send_start,
456 	.end = req_send_end,
457 };
458 
send_friend_poll(void)459 static int send_friend_poll(void)
460 {
461 	struct bt_mesh_msg_ctx ctx = {
462 		.net_idx     = bt_mesh.lpn.sub->net_idx,
463 		.app_idx     = BT_MESH_KEY_UNUSED,
464 		.addr        = bt_mesh.lpn.frnd,
465 		.send_ttl    = 0,
466 	};
467 	struct bt_mesh_net_tx tx = {
468 		.sub = bt_mesh.lpn.sub,
469 		.ctx = &ctx,
470 		.src = bt_mesh_primary_addr(),
471 		.xmit = POLL_XMIT,
472 		.friend_cred = true,
473 	};
474 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
475 	uint8_t fsn = lpn->fsn;
476 	int err;
477 
478 	LOG_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
479 
480 	if (lpn->sent_req) {
481 		if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
482 			lpn->pending_poll = 1U;
483 		}
484 
485 		return 0;
486 	}
487 
488 	err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
489 			       &req_send_cb, NULL);
490 	if (err == 0) {
491 		lpn->pending_poll = 0U;
492 		lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
493 	}
494 
495 	return err;
496 }
497 
bt_mesh_lpn_disable(bool force)498 void bt_mesh_lpn_disable(bool force)
499 {
500 	if (bt_mesh.lpn.state == BT_MESH_LPN_DISABLED) {
501 		return;
502 	}
503 
504 	clear_friendship(force, true);
505 }
506 
bt_mesh_lpn_set(bool enable)507 int bt_mesh_lpn_set(bool enable)
508 {
509 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
510 
511 	if (enable) {
512 		if (lpn->state != BT_MESH_LPN_DISABLED) {
513 			return 0;
514 		}
515 	} else {
516 		if (lpn->state == BT_MESH_LPN_DISABLED) {
517 			return 0;
518 		}
519 	}
520 
521 	if (!bt_mesh_is_provisioned()) {
522 		if (enable) {
523 			lpn_set_state(BT_MESH_LPN_ENABLED);
524 		} else {
525 			lpn_set_state(BT_MESH_LPN_DISABLED);
526 		}
527 
528 		return 0;
529 	}
530 
531 	if (enable) {
532 		lpn_set_state(BT_MESH_LPN_ENABLED);
533 
534 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
535 			bt_mesh_scan_disable();
536 		}
537 
538 		send_friend_req(lpn);
539 	} else {
540 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO) &&
541 		    lpn->state == BT_MESH_LPN_TIMER) {
542 			/* If this fails, the work handler will just exit on the
543 			 * next timeout.
544 			 */
545 			(void)k_work_cancel_delayable(&lpn->timer);
546 			lpn_set_state(BT_MESH_LPN_DISABLED);
547 		} else {
548 			bt_mesh_lpn_disable(false);
549 		}
550 	}
551 
552 	return 0;
553 }
554 
bt_mesh_lpn_friendship_end(void)555 void bt_mesh_lpn_friendship_end(void)
556 {
557 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
558 
559 	if (!lpn->established) {
560 		return;
561 	}
562 
563 	clear_friendship(true, false);
564 }
565 
friend_response_received(struct bt_mesh_lpn * lpn)566 static void friend_response_received(struct bt_mesh_lpn *lpn)
567 {
568 	LOG_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
569 
570 	if (lpn->sent_req == TRANS_CTL_OP_FRIEND_POLL) {
571 		lpn->fsn++;
572 	}
573 
574 	bt_mesh_scan_disable();
575 	lpn_set_state(BT_MESH_LPN_ESTABLISHED);
576 	lpn->req_attempts = 0U;
577 	lpn->sent_req = 0U;
578 
579 	/* Schedule the next poll. This may be overridden by additional
580 	 * processing of the received response.
581 	 */
582 	int32_t timeout = poll_timeout(lpn);
583 
584 	k_work_reschedule(&lpn->timer, K_MSEC(timeout));
585 }
586 
bt_mesh_lpn_msg_received(struct bt_mesh_net_rx * rx)587 void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
588 {
589 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
590 
591 	if (lpn->state == BT_MESH_LPN_TIMER) {
592 		LOG_DBG("Restarting establishment timer");
593 		k_work_reschedule(&lpn->timer, K_MSEC(LPN_AUTO_TIMEOUT));
594 		return;
595 	}
596 
597 	/* If the message was a Friend control message, it's possible that a
598 	 * Poll was already queued for sending. In this case, we're already in
599 	 * a different state.
600 	 */
601 	if (lpn->state != BT_MESH_LPN_WAIT_UPDATE) {
602 		return;
603 	}
604 
605 	if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
606 		LOG_WRN("Unexpected message without a preceding Poll");
607 		return;
608 	}
609 
610 	friend_response_received(lpn);
611 
612 	LOG_DBG("Requesting more messages from Friend");
613 
614 	send_friend_poll();
615 }
616 
friend_cred_create(struct bt_mesh_net_cred * cred,const struct bt_mesh_key * key)617 static int friend_cred_create(struct bt_mesh_net_cred *cred, const struct bt_mesh_key *key)
618 {
619 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
620 
621 	return bt_mesh_friend_cred_create(cred, bt_mesh_primary_addr(),
622 					  lpn->frnd, lpn->lpn_counter,
623 					  lpn->frnd_counter, key);
624 }
625 
bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)626 int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
627 			     struct net_buf_simple *buf)
628 {
629 	struct bt_mesh_ctl_friend_offer *msg = (void *)buf->data;
630 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
631 	uint16_t frnd_counter;
632 	int err;
633 
634 	if (buf->len < sizeof(*msg)) {
635 		LOG_WRN("Too short Friend Offer");
636 		return -EBADMSG;
637 	}
638 
639 	if (lpn->state != BT_MESH_LPN_WAIT_OFFER) {
640 		LOG_WRN("Ignoring unexpected Friend Offer");
641 		return 0;
642 	}
643 
644 	if (!msg->recv_win) {
645 		LOG_WRN("Prohibited ReceiveWindow value");
646 		return -EBADMSG;
647 	}
648 
649 	frnd_counter = sys_be16_to_cpu(msg->frnd_counter);
650 
651 	LOG_DBG("recv_win %u queue_size %u sub_list_size %u rssi %d counter %u", msg->recv_win,
652 		msg->queue_size, msg->sub_list_size, msg->rssi, frnd_counter);
653 
654 	lpn->frnd_counter = frnd_counter;
655 	lpn->frnd = rx->ctx.addr;
656 
657 	/* Create friend credentials for each of the valid keys in the
658 	 * friendship subnet:
659 	 */
660 	for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
661 		if (!lpn->sub->keys[i].valid) {
662 			continue;
663 		}
664 
665 		err = friend_cred_create(&lpn->cred[i], &lpn->sub->keys[i].net);
666 		if (err) {
667 			lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
668 			return err;
669 		}
670 	}
671 
672 	/* TODO: Add offer acceptance criteria check */
673 
674 	lpn->recv_win = msg->recv_win;
675 	lpn->queue_size = msg->queue_size;
676 
677 	err = send_friend_poll();
678 	if (err) {
679 		/* Will retry sending later */
680 		for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
681 			if (lpn->sub->keys[i].valid) {
682 				bt_mesh_friend_cred_destroy(&lpn->cred[i]);
683 			}
684 		}
685 
686 		lpn->sub = NULL;
687 		lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
688 		lpn->recv_win = 0U;
689 		lpn->queue_size = 0U;
690 		return err;
691 	}
692 
693 	return 0;
694 }
695 
bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)696 int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
697 				 struct net_buf_simple *buf)
698 {
699 	struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data;
700 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
701 	uint16_t addr, counter;
702 
703 	if (buf->len < sizeof(*msg)) {
704 		LOG_WRN("Too short Friend Clear Confirm");
705 		return -EBADMSG;
706 	}
707 
708 	if (lpn->state != BT_MESH_LPN_CLEAR) {
709 		LOG_WRN("Ignoring unexpected Friend Clear Confirm");
710 		return 0;
711 	}
712 
713 	addr = sys_be16_to_cpu(msg->lpn_addr);
714 	counter = sys_be16_to_cpu(msg->lpn_counter);
715 
716 	LOG_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
717 
718 	if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) {
719 		LOG_WRN("Invalid parameters in Friend Clear Confirm");
720 		return 0;
721 	}
722 
723 	lpn->clear_success = 1U;
724 	clear_friendship(false, lpn->disable);
725 
726 	return 0;
727 }
728 
lpn_group_add(uint16_t group)729 static void lpn_group_add(uint16_t group)
730 {
731 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
732 	uint16_t *free_slot = NULL;
733 	int i;
734 
735 	for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
736 		if (lpn->groups[i] == group) {
737 			atomic_clear_bit(lpn->to_remove, i);
738 			return;
739 		}
740 
741 		if (!free_slot && lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
742 			free_slot = &lpn->groups[i];
743 		}
744 	}
745 
746 	if (!free_slot) {
747 		LOG_WRN("Friend Subscription List exceeded!");
748 		return;
749 	}
750 
751 	*free_slot = group;
752 	lpn->groups_changed = 1U;
753 }
754 
lpn_group_del(uint16_t group)755 static void lpn_group_del(uint16_t group)
756 {
757 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
758 	int i;
759 
760 	for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
761 		if (lpn->groups[i] == group) {
762 			if (atomic_test_bit(lpn->added, i) ||
763 			    atomic_test_bit(lpn->pending, i)) {
764 				atomic_set_bit(lpn->to_remove, i);
765 				lpn->groups_changed = 1U;
766 			} else {
767 				lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED;
768 			}
769 		}
770 	}
771 }
772 
group_popcount(atomic_t * target)773 static inline int group_popcount(atomic_t *target)
774 {
775 #if CONFIG_BT_MESH_LPN_GROUPS > 32
776 	int i, count = 0;
777 
778 	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
779 		count += POPCOUNT(atomic_get(&target[i]));
780 	}
781 #else
782 	return POPCOUNT(atomic_get(target));
783 #endif
784 }
785 
sub_update(uint8_t op)786 static bool sub_update(uint8_t op)
787 {
788 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
789 	int added_count = group_popcount(lpn->added);
790 	struct bt_mesh_msg_ctx ctx = {
791 		.net_idx     = lpn->sub->net_idx,
792 		.app_idx     = BT_MESH_KEY_UNUSED,
793 		.addr        = lpn->frnd,
794 		.send_ttl    = 0,
795 	};
796 	struct bt_mesh_net_tx tx = {
797 		.sub = lpn->sub,
798 		.ctx = &ctx,
799 		.src = bt_mesh_primary_addr(),
800 		.xmit = POLL_XMIT,
801 		.friend_cred = true,
802 	};
803 	struct bt_mesh_ctl_friend_sub req;
804 	size_t i, g;
805 
806 	LOG_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req);
807 
808 	if (lpn->sent_req) {
809 		return false;
810 	}
811 
812 	for (i = 0, g = 0; i < ARRAY_SIZE(lpn->groups); i++) {
813 		if (lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
814 			continue;
815 		}
816 
817 		if (op == TRANS_CTL_OP_FRIEND_SUB_ADD) {
818 			if (atomic_test_bit(lpn->added, i)) {
819 				continue;
820 			}
821 		} else {
822 			if (!atomic_test_bit(lpn->to_remove, i)) {
823 				continue;
824 			}
825 		}
826 
827 		if (added_count + g >= lpn->queue_size) {
828 			LOG_WRN("Friend Queue Size exceeded");
829 			break;
830 		}
831 
832 		req.addr_list[g++] = sys_cpu_to_be16(lpn->groups[i]);
833 		atomic_set_bit(lpn->pending, i);
834 
835 		if (g == ARRAY_SIZE(req.addr_list)) {
836 			break;
837 		}
838 	}
839 
840 	if (g == 0) {
841 		group_zero(lpn->pending);
842 		return false;
843 	}
844 
845 	req.xact = lpn->xact_next++;
846 
847 	if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
848 			     &req_send_cb, NULL) < 0) {
849 		group_zero(lpn->pending);
850 		return false;
851 	}
852 
853 	lpn->xact_pending = req.xact;
854 	lpn->sent_req = op;
855 	return true;
856 }
857 
update_timeout(struct bt_mesh_lpn * lpn)858 static void update_timeout(struct bt_mesh_lpn *lpn)
859 {
860 	if (lpn->established) {
861 		LOG_WRN("No response from Friend during ReceiveWindow");
862 		bt_mesh_scan_disable();
863 		lpn_set_state(BT_MESH_LPN_ESTABLISHED);
864 		k_work_reschedule(&lpn->timer, K_MSEC(POLL_RETRY_TIMEOUT));
865 	} else {
866 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
867 			bt_mesh_scan_disable();
868 		}
869 
870 		if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
871 			LOG_WRN("Retrying first Friend Poll");
872 			lpn->sent_req = 0U;
873 			if (send_friend_poll() == 0) {
874 				return;
875 			}
876 		}
877 
878 		LOG_ERR("Timed out waiting for first Friend Update");
879 		clear_friendship(false, false);
880 	}
881 }
882 
lpn_timeout(struct k_work * work)883 static void lpn_timeout(struct k_work *work)
884 {
885 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
886 
887 #if defined(CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL_DBG)
888 	LOG_DBG("state: %s", state2str(lpn->state));
889 #endif
890 
891 	switch (lpn->state) {
892 	case BT_MESH_LPN_DISABLED:
893 		break;
894 	case BT_MESH_LPN_CLEAR:
895 		clear_friendship(false, bt_mesh.lpn.disable);
896 		break;
897 	case BT_MESH_LPN_TIMER:
898 		LOG_DBG("Starting to look for Friend nodes");
899 		lpn_set_state(BT_MESH_LPN_ENABLED);
900 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
901 			bt_mesh_scan_disable();
902 		}
903 		__fallthrough;
904 	case BT_MESH_LPN_ENABLED:
905 		send_friend_req(lpn);
906 		break;
907 	case BT_MESH_LPN_REQ_WAIT:
908 		bt_mesh_scan_enable();
909 		k_work_reschedule(&lpn->timer, K_MSEC(lpn->adv_duration + FRIEND_REQ_SCAN));
910 		lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
911 		break;
912 	case BT_MESH_LPN_WAIT_OFFER:
913 		LOG_WRN("No acceptable Friend Offers received");
914 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
915 			bt_mesh_scan_disable();
916 		}
917 
918 		lpn_set_state(BT_MESH_LPN_ENABLED);
919 		lpn->sent_req = 0U;
920 		k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
921 		break;
922 	case BT_MESH_LPN_ESTABLISHED:
923 		if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
924 			uint8_t req = lpn->sent_req;
925 
926 			lpn->sent_req = 0U;
927 
928 			if (!req || req == TRANS_CTL_OP_FRIEND_POLL) {
929 				send_friend_poll();
930 			} else {
931 				sub_update(req);
932 			}
933 
934 			break;
935 		}
936 
937 		LOG_ERR("No response from Friend after %u retries", lpn->req_attempts);
938 		lpn->req_attempts = 0U;
939 		clear_friendship(true, false);
940 		break;
941 	case BT_MESH_LPN_RECV_DELAY:
942 		k_work_reschedule(&lpn->timer,
943 				  K_MSEC(SCAN_LATENCY + lpn->recv_win + RX_DELAY_CORRECTION(lpn)));
944 		bt_mesh_scan_enable();
945 		lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
946 		break;
947 	case BT_MESH_LPN_WAIT_UPDATE:
948 		update_timeout(lpn);
949 		break;
950 	default:
951 		__ASSERT(0, "Unhandled LPN state");
952 		break;
953 	}
954 }
955 
bt_mesh_lpn_group_add(uint16_t group)956 void bt_mesh_lpn_group_add(uint16_t group)
957 {
958 	LOG_DBG("group 0x%04x", group);
959 
960 	lpn_group_add(group);
961 
962 	if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
963 		return;
964 	}
965 
966 	sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
967 }
968 
bt_mesh_lpn_group_del(const uint16_t * groups,size_t group_count)969 void bt_mesh_lpn_group_del(const uint16_t *groups, size_t group_count)
970 {
971 	int i;
972 
973 	for (i = 0; i < group_count; i++) {
974 		if (groups[i] != BT_MESH_ADDR_UNASSIGNED) {
975 			LOG_DBG("group 0x%04x", groups[i]);
976 			lpn_group_del(groups[i]);
977 		}
978 	}
979 
980 	if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
981 		return;
982 	}
983 
984 	sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
985 }
986 
bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)987 int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
988 			       struct net_buf_simple *buf)
989 {
990 	struct bt_mesh_ctl_friend_sub_confirm *msg = (void *)buf->data;
991 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
992 
993 	if (buf->len < sizeof(*msg)) {
994 		LOG_WRN("Too short Friend Subscription Confirm");
995 		return -EBADMSG;
996 	}
997 
998 	LOG_DBG("xact 0x%02x", msg->xact);
999 
1000 	if (!lpn->sent_req) {
1001 		LOG_WRN("No pending subscription list message");
1002 		return 0;
1003 	}
1004 
1005 	if (msg->xact != lpn->xact_pending) {
1006 		LOG_WRN("Transaction mismatch (0x%02x != 0x%02x)", msg->xact, lpn->xact_pending);
1007 		return 0;
1008 	}
1009 
1010 	if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_ADD) {
1011 		group_set(lpn->added, lpn->pending);
1012 		group_zero(lpn->pending);
1013 	} else if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_REM) {
1014 		int i;
1015 
1016 		group_clear(lpn->added, lpn->pending);
1017 
1018 		for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
1019 			if (atomic_test_and_clear_bit(lpn->pending, i) &&
1020 			    atomic_test_and_clear_bit(lpn->to_remove, i)) {
1021 				lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED;
1022 			}
1023 		}
1024 	} else {
1025 		LOG_WRN("Unexpected Friend Subscription Confirm");
1026 		return 0;
1027 	}
1028 
1029 	friend_response_received(lpn);
1030 
1031 	if (lpn->groups_changed) {
1032 		sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
1033 		sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
1034 
1035 		if (!lpn->sent_req) {
1036 			lpn->groups_changed = 0U;
1037 		}
1038 	}
1039 
1040 	if (lpn->pending_poll) {
1041 		send_friend_poll();
1042 	}
1043 
1044 	return 0;
1045 }
1046 
bt_mesh_lpn_friend_update(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)1047 int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
1048 			      struct net_buf_simple *buf)
1049 {
1050 	struct bt_mesh_ctl_friend_update *msg = (void *)buf->data;
1051 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
1052 	struct bt_mesh_subnet *sub = rx->sub;
1053 	uint32_t iv_index;
1054 	bool established = false;
1055 
1056 	if (buf->len < sizeof(*msg)) {
1057 		LOG_WRN("Too short Friend Update");
1058 		return -EBADMSG;
1059 	}
1060 
1061 	if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
1062 		LOG_WRN("Unexpected friend update");
1063 		return 0;
1064 	}
1065 
1066 	if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !rx->new_key) {
1067 		LOG_WRN("Ignoring Phase 2 KR Update secured using old key");
1068 		return 0;
1069 	}
1070 
1071 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
1072 	    (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
1073 	     BT_MESH_IV_UPDATE(msg->flags))) {
1074 		bt_mesh_beacon_ivu_initiator(false);
1075 	}
1076 
1077 	if (!lpn->established) {
1078 		/* This is normally checked on the transport layer, however
1079 		 * in this state we're also still accepting flooding
1080 		 * credentials so we need to ensure the right ones (Friend
1081 		 * Credentials) were used for this message.
1082 		 */
1083 		if (!rx->friend_cred) {
1084 			LOG_WRN("Friend Update with wrong credentials");
1085 			return -EINVAL;
1086 		}
1087 
1088 		lpn->established = 1U;
1089 
1090 		LOG_INF("Friendship established with 0x%04x", lpn->frnd);
1091 
1092 		bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
1093 
1094 		/* Set initial poll timeout */
1095 		lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn),
1096 					POLL_TIMEOUT_INIT);
1097 
1098 		established = true;
1099 	}
1100 
1101 	friend_response_received(lpn);
1102 
1103 	iv_index = sys_be32_to_cpu(msg->iv_index);
1104 
1105 	LOG_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags, iv_index, msg->md);
1106 
1107 	bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), rx->new_key);
1108 	bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
1109 
1110 	if (lpn->groups_changed) {
1111 		sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
1112 		sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
1113 
1114 		if (!lpn->sent_req) {
1115 			lpn->groups_changed = 0U;
1116 		}
1117 	}
1118 
1119 	if (msg->md) {
1120 		LOG_DBG("Requesting for more messages");
1121 		send_friend_poll();
1122 	}
1123 
1124 	if (established) {
1125 		STRUCT_SECTION_FOREACH(bt_mesh_lpn_cb, cb) {
1126 			if (cb->established) {
1127 				cb->established(lpn->sub->net_idx, lpn->frnd, lpn->queue_size,
1128 						lpn->recv_win);
1129 			}
1130 		}
1131 	}
1132 
1133 	return 0;
1134 }
1135 
bt_mesh_lpn_poll(void)1136 int bt_mesh_lpn_poll(void)
1137 {
1138 	if (!bt_mesh.lpn.established) {
1139 		return -EAGAIN;
1140 	}
1141 
1142 	LOG_DBG("Requesting more messages");
1143 
1144 	return send_friend_poll();
1145 }
1146 
subnet_evt(struct bt_mesh_subnet * sub,enum bt_mesh_key_evt evt)1147 static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
1148 {
1149 	switch (evt) {
1150 	case BT_MESH_KEY_DELETED:
1151 		if (sub == bt_mesh.lpn.sub) {
1152 			LOG_DBG("NetKey deleted");
1153 			clear_friendship(true, false);
1154 		}
1155 		break;
1156 	case BT_MESH_KEY_UPDATED:
1157 		LOG_DBG("NetKey updated");
1158 		friend_cred_create(&bt_mesh.lpn.cred[1], &sub->keys[1].net);
1159 		break;
1160 	default:
1161 		break;
1162 	}
1163 }
1164 
1165 BT_MESH_SUBNET_CB_DEFINE(lpn) = {
1166 	.evt_handler = subnet_evt,
1167 };
1168 
bt_mesh_lpn_init(void)1169 int bt_mesh_lpn_init(void)
1170 {
1171 	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
1172 
1173 	LOG_DBG("");
1174 
1175 	k_work_init_delayable(&lpn->timer, lpn_timeout);
1176 
1177 	if (lpn->state == BT_MESH_LPN_ENABLED) {
1178 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
1179 			bt_mesh_scan_disable();
1180 		} else {
1181 			bt_mesh_scan_enable();
1182 		}
1183 
1184 		send_friend_req(lpn);
1185 	} else {
1186 		bt_mesh_scan_enable();
1187 
1188 		if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO)) {
1189 			LOG_DBG("Waiting %u ms for messages", LPN_AUTO_TIMEOUT);
1190 			lpn_set_state(BT_MESH_LPN_TIMER);
1191 			k_work_reschedule(&lpn->timer,
1192 					  K_MSEC(LPN_AUTO_TIMEOUT));
1193 		}
1194 	}
1195 
1196 	return 0;
1197 }
1198