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