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