1 /* Bluetooth Mesh */
2
3 /*
4 * SPDX-FileCopyrightText: 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <stdint.h>
10 #include <errno.h>
11
12 #include "crypto.h"
13 #include "adv.h"
14 #include "scan.h"
15 #include "mesh.h"
16 #include "transport.h"
17 #include "access.h"
18 #include "beacon.h"
19 #include "lpn.h"
20 #include "foundation.h"
21 #include "mesh_main.h"
22 #include "cfg_srv.h"
23
24 #ifdef CONFIG_BLE_MESH_LOW_POWER
25
26 #if defined(CONFIG_BLE_MESH_LPN_AUTO)
27 #define LPN_AUTO_TIMEOUT K_SECONDS(CONFIG_BLE_MESH_LPN_AUTO_TIMEOUT)
28 #else
29 #define LPN_AUTO_TIMEOUT 0
30 #endif
31
32 #define LPN_RECV_DELAY CONFIG_BLE_MESH_LPN_RECV_DELAY
33 #define SCAN_LATENCY MIN(CONFIG_BLE_MESH_LPN_SCAN_LATENCY, LPN_RECV_DELAY)
34
35 #define FRIEND_REQ_RETRY_TIMEOUT K_SECONDS(CONFIG_BLE_MESH_LPN_RETRY_TIMEOUT)
36
37 #define FRIEND_REQ_WAIT K_MSEC(100)
38 #define FRIEND_REQ_SCAN K_SECONDS(1)
39 #define FRIEND_REQ_TIMEOUT (FRIEND_REQ_WAIT + FRIEND_REQ_SCAN)
40
41 #define POLL_RETRY_TIMEOUT K_MSEC(100)
42
43 #define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
44 (lpn)->recv_win + POLL_RETRY_TIMEOUT))
45
46 #define POLL_TIMEOUT_INIT (CONFIG_BLE_MESH_LPN_INIT_POLL_TIMEOUT * 100)
47 #define POLL_TIMEOUT_MAX(lpn) ((CONFIG_BLE_MESH_LPN_POLL_TIMEOUT * 100) - \
48 REQ_RETRY_DURATION(lpn))
49
50 /**
51 * 1. Should use 20 attempts for BQB test case MESH/NODE/FRND/LPM/BI-02-C.
52 * 2. We should use more specific value for each PollTimeout range.
53 */
54 #define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 6)
55
56 #define CLEAR_ATTEMPTS 2
57
58 #define LPN_CRITERIA ((CONFIG_BLE_MESH_LPN_MIN_QUEUE_SIZE) | \
59 (CONFIG_BLE_MESH_LPN_RSSI_FACTOR << 3) | \
60 (CONFIG_BLE_MESH_LPN_RECV_WIN_FACTOR << 5))
61
62 #define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
63 #define LPN_POLL_TO POLL_TO(CONFIG_BLE_MESH_LPN_POLL_TIMEOUT)
64
65 /* 2 transmissions, 20ms interval */
66 #define POLL_XMIT BLE_MESH_TRANSMIT(1, 20)
67
68 #define FIRST_POLL_ATTEMPTS 6
69
70 static void (*lpn_cb)(uint16_t friend_addr, bool established);
71
72 #if !CONFIG_BLE_MESH_NO_LOG
state2str(int state)73 static const char *state2str(int state)
74 {
75 switch (state) {
76 case BLE_MESH_LPN_DISABLED:
77 return "disabled";
78 case BLE_MESH_LPN_CLEAR:
79 return "clear";
80 case BLE_MESH_LPN_TIMER:
81 return "timer";
82 case BLE_MESH_LPN_ENABLED:
83 return "enabled";
84 case BLE_MESH_LPN_REQ_WAIT:
85 return "req wait";
86 case BLE_MESH_LPN_WAIT_OFFER:
87 return "wait offer";
88 case BLE_MESH_LPN_ESTABLISHED:
89 return "established";
90 case BLE_MESH_LPN_RECV_DELAY:
91 return "recv delay";
92 case BLE_MESH_LPN_WAIT_UPDATE:
93 return "wait update";
94 case BLE_MESH_LPN_OFFER_RECV:
95 return "offer recv";
96 default:
97 return "(unknown)";
98 }
99 }
100 #endif
101
lpn_set_state(int state)102 static inline void lpn_set_state(int state)
103 {
104 BT_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state));
105 bt_mesh.lpn.state = state;
106 }
107
group_zero(bt_mesh_atomic_t * target)108 static inline void group_zero(bt_mesh_atomic_t *target)
109 {
110 #if CONFIG_BLE_MESH_LPN_GROUPS > 32
111 int i;
112
113 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
114 bt_mesh_atomic_set(&target[i], 0);
115 }
116 #else
117 bt_mesh_atomic_set(target, 0);
118 #endif
119 }
120
group_set(bt_mesh_atomic_t * target,bt_mesh_atomic_t * source)121 static inline void group_set(bt_mesh_atomic_t *target, bt_mesh_atomic_t *source)
122 {
123 #if CONFIG_BLE_MESH_LPN_GROUPS > 32
124 int i;
125
126 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
127 (void)bt_mesh_atomic_or(&target[i], bt_mesh_atomic_get(&source[i]));
128 }
129 #else
130 (void)bt_mesh_atomic_or(target, bt_mesh_atomic_get(source));
131 #endif
132 }
133
group_clear(bt_mesh_atomic_t * target,bt_mesh_atomic_t * source)134 static inline void group_clear(bt_mesh_atomic_t *target, bt_mesh_atomic_t *source)
135 {
136 #if CONFIG_BLE_MESH_LPN_GROUPS > 32
137 int i;
138
139 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
140 (void)bt_mesh_atomic_and(&target[i], ~bt_mesh_atomic_get(&source[i]));
141 }
142 #else
143 (void)bt_mesh_atomic_and(target, ~bt_mesh_atomic_get(source));
144 #endif
145 }
146
147 static void clear_friendship(bool force, bool disable);
148
149 static bool scan_after_clear;
150
friend_clear_sent(int err,void * user_data)151 static void friend_clear_sent(int err, void *user_data)
152 {
153 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
154
155 /* We're switching away from Low Power behavior, so permanently
156 * enable scanning.
157 */
158 if (scan_after_clear == false) {
159 bt_mesh_scan_enable();
160 scan_after_clear = true;
161 }
162
163 lpn->req_attempts++;
164
165 if (err) {
166 BT_ERR("Sending Friend Clear failed (err %d)", err);
167 lpn_set_state(BLE_MESH_LPN_ENABLED);
168 clear_friendship(false, lpn->disable);
169 return;
170 }
171
172 lpn_set_state(BLE_MESH_LPN_CLEAR);
173 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_TIMEOUT);
174 }
175
176 static const struct bt_mesh_send_cb clear_sent_cb = {
177 .end = friend_clear_sent,
178 };
179
send_friend_clear(void)180 static int send_friend_clear(void)
181 {
182 struct bt_mesh_msg_ctx ctx = {
183 .net_idx = bt_mesh.sub[0].net_idx,
184 .app_idx = BLE_MESH_KEY_UNUSED,
185 .addr = bt_mesh.lpn.frnd,
186 .send_ttl = 0,
187 };
188 struct bt_mesh_net_tx tx = {
189 .sub = &bt_mesh.sub[0],
190 .ctx = &ctx,
191 .src = bt_mesh_primary_addr(),
192 .xmit = bt_mesh_net_transmit_get(),
193 };
194 struct bt_mesh_ctl_friend_clear req = {
195 .lpn_addr = sys_cpu_to_be16(tx.src),
196 .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
197 };
198
199 BT_DBG("%s", __func__);
200
201 return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
202 sizeof(req), &clear_sent_cb, NULL);
203 }
204
clear_friendship(bool force,bool disable)205 static void clear_friendship(bool force, bool disable)
206 {
207 struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
208 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
209
210 BT_DBG("force %u disable %u", force, disable);
211
212 if (!force && lpn->established && !lpn->clear_success &&
213 lpn->req_attempts < CLEAR_ATTEMPTS) {
214 send_friend_clear();
215 lpn->disable = disable;
216 return;
217 }
218
219 bt_mesh_rx_reset(true);
220
221 k_delayed_work_cancel(&lpn->timer);
222
223 friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
224
225 if (lpn->clear_success) {
226 lpn->old_friend = BLE_MESH_ADDR_UNASSIGNED;
227 } else {
228 lpn->old_friend = lpn->frnd;
229 }
230
231 if (lpn_cb && lpn->frnd != BLE_MESH_ADDR_UNASSIGNED) {
232 lpn_cb(lpn->frnd, false);
233 }
234
235 lpn->frnd = BLE_MESH_ADDR_UNASSIGNED;
236 lpn->fsn = 0U;
237 lpn->req_attempts = 0U;
238 lpn->recv_win = 0U;
239 lpn->queue_size = 0U;
240 lpn->disable = 0U;
241 lpn->sent_req = 0U;
242 lpn->established = 0U;
243 lpn->clear_success = 0U;
244
245 group_zero(lpn->added);
246 group_zero(lpn->pending);
247 group_zero(lpn->to_remove);
248
249 /* Set this to 1 to force group subscription when the next
250 * Friendship is created, in case lpn->groups doesn't get
251 * modified meanwhile.
252 */
253 lpn->groups_changed = 1U;
254
255 if (cfg->hb_pub.feat & BLE_MESH_FEAT_LOW_POWER) {
256 bt_mesh_heartbeat_send();
257 }
258
259 if (disable) {
260 lpn_set_state(BLE_MESH_LPN_DISABLED);
261 return;
262 }
263
264 lpn_set_state(BLE_MESH_LPN_ENABLED);
265 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
266
267 scan_after_clear = false;
268 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
269 bt_mesh_scan_disable();
270 }
271 }
272
friend_req_sent(uint16_t duration,int err,void * user_data)273 static void friend_req_sent(uint16_t duration, int err, void *user_data)
274 {
275 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
276
277 if (err) {
278 BT_ERR("Sending Friend Request failed (err %d)", err);
279
280 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
281 bt_mesh_scan_enable();
282 }
283 return;
284 }
285
286 lpn->adv_duration = duration;
287
288 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
289 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_WAIT);
290 lpn_set_state(BLE_MESH_LPN_REQ_WAIT);
291 } else {
292 k_delayed_work_submit(&lpn->timer,
293 duration + FRIEND_REQ_TIMEOUT);
294 lpn_set_state(BLE_MESH_LPN_WAIT_OFFER);
295 }
296 }
297
298 static const struct bt_mesh_send_cb friend_req_sent_cb = {
299 .start = friend_req_sent,
300 };
301
send_friend_req(struct bt_mesh_lpn * lpn)302 static int send_friend_req(struct bt_mesh_lpn *lpn)
303 {
304 const struct bt_mesh_comp *comp = bt_mesh_comp_get();
305 struct bt_mesh_msg_ctx ctx = {
306 .net_idx = bt_mesh.sub[0].net_idx,
307 .app_idx = BLE_MESH_KEY_UNUSED,
308 .addr = BLE_MESH_ADDR_FRIENDS,
309 .send_ttl = 0,
310 };
311 struct bt_mesh_net_tx tx = {
312 .sub = &bt_mesh.sub[0],
313 .ctx = &ctx,
314 .src = bt_mesh_primary_addr(),
315 .xmit = POLL_XMIT,
316 };
317 struct bt_mesh_ctl_friend_req req = {
318 .criteria = LPN_CRITERIA,
319 .recv_delay = LPN_RECV_DELAY,
320 .poll_to = LPN_POLL_TO,
321 .prev_addr = sys_cpu_to_be16(lpn->old_friend),
322 .num_elem = comp->elem_count,
323 .lpn_counter = sys_cpu_to_be16(lpn->counter),
324 };
325
326 BT_DBG("%s", __func__);
327
328 return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
329 sizeof(req), &friend_req_sent_cb, NULL);
330 }
331
req_sent(uint16_t duration,int err,void * user_data)332 static void req_sent(uint16_t duration, int err, void *user_data)
333 {
334 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
335
336 BT_DBG("req 0x%02x duration %u err %d state %s",
337 lpn->sent_req, duration, err, state2str(lpn->state));
338
339 if (err) {
340 BT_ERR("Sending request failed (err %d)", err);
341 lpn->sent_req = 0U;
342 group_zero(lpn->pending);
343 return;
344 }
345
346 lpn->req_attempts++;
347 lpn->adv_duration = duration;
348
349 if (lpn->established || IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
350 lpn_set_state(BLE_MESH_LPN_RECV_DELAY);
351 /* We start scanning a bit early to elimitate risk of missing
352 * response data due to HCI and other latencies.
353 */
354 k_delayed_work_submit(&lpn->timer,
355 LPN_RECV_DELAY - SCAN_LATENCY);
356 } else {
357 lpn_set_state(BLE_MESH_LPN_OFFER_RECV);
358 /**
359 * Friend Update is replied by Friend Node with TTL set to 0 and Network
360 * Transmit set to 30ms which will cause the packet easy to be missed.
361 * Regarding this situation, here we can reduce the duration of receiving
362 * the first Friend Update.
363 */
364 k_delayed_work_submit(&lpn->timer,
365 LPN_RECV_DELAY + duration +
366 lpn->recv_win);
367 }
368 }
369
370 static const struct bt_mesh_send_cb req_sent_cb = {
371 .start = req_sent,
372 };
373
send_friend_poll(void)374 static int send_friend_poll(void)
375 {
376 struct bt_mesh_msg_ctx ctx = {
377 .net_idx = bt_mesh.sub[0].net_idx,
378 .app_idx = BLE_MESH_KEY_UNUSED,
379 .addr = bt_mesh.lpn.frnd,
380 .send_ttl = 0,
381 };
382 struct bt_mesh_net_tx tx = {
383 .sub = &bt_mesh.sub[0],
384 .ctx = &ctx,
385 .src = bt_mesh_primary_addr(),
386 .xmit = POLL_XMIT,
387 .friend_cred = true,
388 };
389 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
390 uint8_t fsn = lpn->fsn;
391 int err = 0;
392
393 BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
394
395 if (lpn->sent_req) {
396 if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
397 lpn->pending_poll = 1U;
398 }
399
400 return 0;
401 }
402
403 err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
404 &req_sent_cb, NULL);
405 if (err == 0) {
406 lpn->pending_poll = 0U;
407 lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
408 }
409
410 return err;
411 }
412
bt_mesh_lpn_disable(bool force)413 void bt_mesh_lpn_disable(bool force)
414 {
415 if (bt_mesh.lpn.state == BLE_MESH_LPN_DISABLED) {
416 return;
417 }
418
419 clear_friendship(force, true);
420 }
421
bt_mesh_lpn_set(bool enable,bool force)422 int bt_mesh_lpn_set(bool enable, bool force)
423 {
424 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
425
426 if (enable) {
427 if (lpn->state != BLE_MESH_LPN_DISABLED) {
428 return 0;
429 }
430 } else {
431 if (lpn->state == BLE_MESH_LPN_DISABLED) {
432 return 0;
433 }
434 }
435
436 if (!bt_mesh_is_provisioned()) {
437 if (enable) {
438 lpn_set_state(BLE_MESH_LPN_ENABLED);
439 } else {
440 lpn_set_state(BLE_MESH_LPN_DISABLED);
441 }
442
443 return 0;
444 }
445
446 if (enable) {
447 lpn_set_state(BLE_MESH_LPN_ENABLED);
448
449 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
450 bt_mesh_scan_disable();
451 }
452
453 send_friend_req(lpn);
454 } else {
455 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_AUTO) &&
456 lpn->state == BLE_MESH_LPN_TIMER) {
457 k_delayed_work_cancel(&lpn->timer);
458 lpn_set_state(BLE_MESH_LPN_DISABLED);
459 } else {
460 bt_mesh_lpn_disable(force);
461 }
462 }
463
464 return 0;
465 }
466
friend_response_received(struct bt_mesh_lpn * lpn)467 static void friend_response_received(struct bt_mesh_lpn *lpn)
468 {
469 BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
470
471 if (lpn->sent_req == TRANS_CTL_OP_FRIEND_POLL) {
472 lpn->fsn++;
473 }
474
475 k_delayed_work_cancel(&lpn->timer);
476 bt_mesh_scan_disable();
477 lpn_set_state(BLE_MESH_LPN_ESTABLISHED);
478 lpn->req_attempts = 0U;
479 lpn->sent_req = 0U;
480 }
481
bt_mesh_lpn_msg_received(struct bt_mesh_net_rx * rx)482 void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
483 {
484 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
485
486 if (lpn->state == BLE_MESH_LPN_TIMER) {
487 BT_DBG("Restarting establishment timer");
488 k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT);
489 return;
490 }
491
492 if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
493 BT_WARN("Unexpected message without a preceding Poll");
494 return;
495 }
496
497 friend_response_received(lpn);
498
499 BT_DBG("Requesting more messages from Friend");
500
501 send_friend_poll();
502 }
503
bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)504 int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
505 struct net_buf_simple *buf)
506 {
507 struct bt_mesh_ctl_friend_offer *msg = (void *)buf->data;
508 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
509 struct bt_mesh_subnet *sub = rx->sub;
510 struct friend_cred *cred = NULL;
511 uint16_t frnd_counter = 0U;
512 int err = 0;
513
514 if (buf->len < sizeof(*msg)) {
515 BT_WARN("Too short Friend Offer");
516 return -EINVAL;
517 }
518
519 if (lpn->state != BLE_MESH_LPN_WAIT_OFFER) {
520 BT_WARN("Ignoring unexpected Friend Offer");
521 return 0;
522 }
523
524 if (!msg->recv_win) {
525 BT_WARN("Prohibited ReceiveWindow value");
526 return -EINVAL;
527 }
528
529 frnd_counter = sys_be16_to_cpu(msg->frnd_counter);
530
531 BT_INFO("recv_win %u queue_size %u sub_list_size %u rssi %d counter %u",
532 msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
533 frnd_counter);
534
535 lpn->frnd = rx->ctx.addr;
536
537 cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
538 if (!cred) {
539 lpn->frnd = BLE_MESH_ADDR_UNASSIGNED;
540 return -ENOMEM;
541 }
542
543 /* TODO: Add offer acceptance criteria check */
544
545 k_delayed_work_cancel(&lpn->timer);
546
547 lpn->recv_win = msg->recv_win;
548 lpn->queue_size = msg->queue_size;
549
550 err = send_friend_poll();
551 if (err) {
552 friend_cred_clear(cred);
553 lpn->frnd = BLE_MESH_ADDR_UNASSIGNED;
554 lpn->recv_win = 0U;
555 lpn->queue_size = 0U;
556 return err;
557 }
558
559 lpn->counter++;
560
561 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
562 bt_mesh_scan_disable();
563 }
564
565 return 0;
566 }
567
bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)568 int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
569 struct net_buf_simple *buf)
570 {
571 struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data;
572 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
573 uint16_t addr = 0U, counter = 0U;
574
575 if (buf->len < sizeof(*msg)) {
576 BT_WARN("Too short Friend Clear Confirm");
577 return -EINVAL;
578 }
579
580 if (lpn->state != BLE_MESH_LPN_CLEAR) {
581 BT_WARN("Ignoring unexpected Friend Clear Confirm");
582 return 0;
583 }
584
585 addr = sys_be16_to_cpu(msg->lpn_addr);
586 counter = sys_be16_to_cpu(msg->lpn_counter);
587
588 BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
589
590 if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
591 BT_WARN("Invalid parameters in Friend Clear Confirm");
592 return 0;
593 }
594
595 lpn->clear_success = 1U;
596 clear_friendship(false, lpn->disable);
597
598 return 0;
599 }
600
lpn_group_add(uint16_t group)601 static void lpn_group_add(uint16_t group)
602 {
603 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
604 uint16_t *free_slot = NULL;
605 int i;
606
607 for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
608 if (lpn->groups[i] == group) {
609 bt_mesh_atomic_clear_bit(lpn->to_remove, i);
610 return;
611 }
612
613 if (!free_slot && lpn->groups[i] == BLE_MESH_ADDR_UNASSIGNED) {
614 free_slot = &lpn->groups[i];
615 }
616 }
617
618 if (!free_slot) {
619 BT_WARN("Friend Subscription List exceeded!");
620 return;
621 }
622
623 *free_slot = group;
624 lpn->groups_changed = 1U;
625 }
626
lpn_group_del(uint16_t group)627 static void lpn_group_del(uint16_t group)
628 {
629 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
630 int i;
631
632 for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
633 if (lpn->groups[i] == group) {
634 if (bt_mesh_atomic_test_bit(lpn->added, i) ||
635 bt_mesh_atomic_test_bit(lpn->pending, i)) {
636 bt_mesh_atomic_set_bit(lpn->to_remove, i);
637 lpn->groups_changed = 1U;
638 } else {
639 lpn->groups[i] = BLE_MESH_ADDR_UNASSIGNED;
640 }
641 }
642 }
643 }
644
group_popcount(bt_mesh_atomic_t * target)645 static inline int group_popcount(bt_mesh_atomic_t *target)
646 {
647 #if CONFIG_BLE_MESH_LPN_GROUPS > 32
648 int i, count = 0;
649
650 for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
651 count += popcount(bt_mesh_atomic_get(&target[i]));
652 }
653 #else
654 return popcount(bt_mesh_atomic_get(target));
655 #endif
656 }
657
sub_update(uint8_t op)658 static bool sub_update(uint8_t op)
659 {
660 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
661 int added_count = group_popcount(lpn->added);
662 struct bt_mesh_msg_ctx ctx = {
663 .net_idx = bt_mesh.sub[0].net_idx,
664 .app_idx = BLE_MESH_KEY_UNUSED,
665 .addr = lpn->frnd,
666 .send_ttl = 0,
667 };
668 struct bt_mesh_net_tx tx = {
669 .sub = &bt_mesh.sub[0],
670 .ctx = &ctx,
671 .src = bt_mesh_primary_addr(),
672 .xmit = POLL_XMIT,
673 .friend_cred = true,
674 };
675 struct bt_mesh_ctl_friend_sub req = {0};
676 size_t i = 0U, g = 0U;
677
678 BT_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req);
679
680 if (lpn->sent_req) {
681 return false;
682 }
683
684 for (i = 0U, g = 0U; i < ARRAY_SIZE(lpn->groups); i++) {
685 if (lpn->groups[i] == BLE_MESH_ADDR_UNASSIGNED) {
686 continue;
687 }
688
689 if (op == TRANS_CTL_OP_FRIEND_SUB_ADD) {
690 if (bt_mesh_atomic_test_bit(lpn->added, i)) {
691 continue;
692 }
693 } else {
694 if (!bt_mesh_atomic_test_bit(lpn->to_remove, i)) {
695 continue;
696 }
697 }
698
699 if (added_count + g >= lpn->queue_size) {
700 BT_WARN("Friend Queue Size exceeded");
701 break;
702 }
703
704 req.addr_list[g++] = sys_cpu_to_be16(lpn->groups[i]);
705 bt_mesh_atomic_set_bit(lpn->pending, i);
706
707 if (g == ARRAY_SIZE(req.addr_list)) {
708 break;
709 }
710 }
711
712 if (g == 0U) {
713 group_zero(lpn->pending);
714 return false;
715 }
716
717 req.xact = lpn->xact_next++;
718
719 if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
720 &req_sent_cb, NULL) < 0) {
721 group_zero(lpn->pending);
722 return false;
723 }
724
725 lpn->xact_pending = req.xact;
726 lpn->sent_req = op;
727 return true;
728 }
729
update_timeout(struct bt_mesh_lpn * lpn)730 static void update_timeout(struct bt_mesh_lpn *lpn)
731 {
732 if (lpn->established) {
733 BT_WARN("No response from Friend during ReceiveWindow");
734 bt_mesh_scan_disable();
735 lpn_set_state(BLE_MESH_LPN_ESTABLISHED);
736 k_delayed_work_submit(&lpn->timer, POLL_RETRY_TIMEOUT);
737 } else {
738 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
739 bt_mesh_scan_disable();
740 }
741
742 if (lpn->req_attempts < FIRST_POLL_ATTEMPTS) {
743 BT_WARN("Retrying first Friend Poll");
744 lpn->sent_req = 0U;
745 if (send_friend_poll() == 0) {
746 return;
747 }
748 }
749
750 BT_ERR("Timed out waiting for first Friend Update");
751 clear_friendship(false, false);
752 }
753 }
754
lpn_timeout(struct k_work * work)755 static void lpn_timeout(struct k_work *work)
756 {
757 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
758
759 BT_DBG("state: %s", state2str(lpn->state));
760
761 switch (lpn->state) {
762 case BLE_MESH_LPN_DISABLED:
763 break;
764 case BLE_MESH_LPN_CLEAR:
765 clear_friendship(false, bt_mesh.lpn.disable);
766 break;
767 case BLE_MESH_LPN_TIMER:
768 BT_DBG("Starting to look for Friend nodes");
769 lpn_set_state(BLE_MESH_LPN_ENABLED);
770 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
771 bt_mesh_scan_disable();
772 }
773 /* fall through */
774 case BLE_MESH_LPN_ENABLED:
775 send_friend_req(lpn);
776 break;
777 case BLE_MESH_LPN_REQ_WAIT:
778 bt_mesh_scan_enable();
779 k_delayed_work_submit(&lpn->timer,
780 lpn->adv_duration + FRIEND_REQ_SCAN);
781 lpn_set_state(BLE_MESH_LPN_WAIT_OFFER);
782 break;
783 case BLE_MESH_LPN_WAIT_OFFER:
784 BT_WARN("No acceptable Friend Offers received");
785 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
786 bt_mesh_scan_disable();
787 }
788 lpn->counter++;
789 lpn_set_state(BLE_MESH_LPN_ENABLED);
790 lpn->sent_req = 0U;
791 k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
792 break;
793 case BLE_MESH_LPN_OFFER_RECV:
794 if (lpn->req_attempts < FIRST_POLL_ATTEMPTS) {
795 BT_WARN("Retrying the first Friend Poll, %d attempts", lpn->req_attempts);
796 lpn->sent_req = 0U;
797 send_friend_poll();
798 break;
799 }
800
801 BT_ERR("Timeout waiting for the first Friend Update");
802 clear_friendship(true, false);
803 break;
804 case BLE_MESH_LPN_ESTABLISHED:
805 if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
806 uint8_t req = lpn->sent_req;
807
808 lpn->sent_req = 0U;
809
810 if (!req || req == TRANS_CTL_OP_FRIEND_POLL) {
811 send_friend_poll();
812 } else {
813 sub_update(req);
814 }
815
816 break;
817 }
818
819 BT_ERR("No response from Friend after %u retries",
820 lpn->req_attempts);
821 lpn->req_attempts = 0U;
822 clear_friendship(false, false);
823 break;
824 case BLE_MESH_LPN_RECV_DELAY:
825 k_delayed_work_submit(&lpn->timer,
826 lpn->adv_duration + SCAN_LATENCY +
827 lpn->recv_win);
828 bt_mesh_scan_enable();
829 lpn_set_state(BLE_MESH_LPN_WAIT_UPDATE);
830 break;
831 case BLE_MESH_LPN_WAIT_UPDATE:
832 update_timeout(lpn);
833 break;
834 default:
835 BT_ERR("Unhandled LPN state");
836 break;
837 }
838 }
839
bt_mesh_lpn_group_add(uint16_t group)840 void bt_mesh_lpn_group_add(uint16_t group)
841 {
842 BT_DBG("group 0x%04x", group);
843
844 lpn_group_add(group);
845
846 if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
847 return;
848 }
849
850 sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
851 }
852
bt_mesh_lpn_group_del(uint16_t * groups,size_t group_count)853 void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count)
854 {
855 int i;
856
857 for (i = 0; i < group_count; i++) {
858 if (groups[i] != BLE_MESH_ADDR_UNASSIGNED) {
859 BT_DBG("group 0x%04x", groups[i]);
860 lpn_group_del(groups[i]);
861 }
862 }
863
864 if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
865 return;
866 }
867
868 sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
869 }
870
poll_timeout(struct bt_mesh_lpn * lpn)871 static int32_t poll_timeout(struct bt_mesh_lpn *lpn)
872 {
873 /* If we're waiting for segment acks keep polling at high freq */
874 if (bt_mesh_tx_in_progress()) {
875 return MIN(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1));
876 }
877
878 if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) {
879 lpn->poll_timeout *= 2;
880 lpn->poll_timeout = MIN(lpn->poll_timeout,
881 POLL_TIMEOUT_MAX(lpn));
882 }
883
884 BT_DBG("Poll Timeout is %ums", lpn->poll_timeout);
885
886 return lpn->poll_timeout;
887 }
888
bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)889 int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
890 struct net_buf_simple *buf)
891 {
892 struct bt_mesh_ctl_friend_sub_confirm *msg = (void *)buf->data;
893 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
894
895 if (buf->len < sizeof(*msg)) {
896 BT_WARN("Too short Friend Subscription Confirm");
897 return -EINVAL;
898 }
899
900 BT_DBG("xact 0x%02x", msg->xact);
901
902 if (!lpn->sent_req) {
903 BT_WARN("No pending subscription list message");
904 return 0;
905 }
906
907 if (msg->xact != lpn->xact_pending) {
908 BT_WARN("Transaction mismatch (0x%02x != 0x%02x)",
909 msg->xact, lpn->xact_pending);
910 return 0;
911 }
912
913 if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_ADD) {
914 group_set(lpn->added, lpn->pending);
915 group_zero(lpn->pending);
916 } else if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_REM) {
917 int i;
918
919 group_clear(lpn->added, lpn->pending);
920
921 for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
922 if (bt_mesh_atomic_test_and_clear_bit(lpn->pending, i) &&
923 bt_mesh_atomic_test_and_clear_bit(lpn->to_remove, i)) {
924 lpn->groups[i] = BLE_MESH_ADDR_UNASSIGNED;
925 }
926 }
927 } else {
928 BT_WARN("Unexpected Friend Subscription Confirm");
929 return 0;
930 }
931
932 friend_response_received(lpn);
933
934 if (lpn->groups_changed) {
935 sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
936 sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
937
938 if (!lpn->sent_req) {
939 lpn->groups_changed = 0U;
940 }
941 }
942
943 if (lpn->pending_poll) {
944 send_friend_poll();
945 }
946
947 if (!lpn->sent_req) {
948 k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
949 }
950
951 return 0;
952 }
953
bt_mesh_lpn_friend_update(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)954 int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
955 struct net_buf_simple *buf)
956 {
957 struct bt_mesh_ctl_friend_update *msg = (void *)buf->data;
958 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
959 struct bt_mesh_subnet *sub = rx->sub;
960 uint32_t iv_index = 0U;
961
962 if (buf->len < sizeof(*msg)) {
963 BT_WARN("Too short Friend Update");
964 return -EINVAL;
965 }
966
967 if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
968 BT_WARN("Unexpected friend update");
969 return 0;
970 }
971
972 if (sub->kr_phase == BLE_MESH_KR_PHASE_2 && !rx->new_key) {
973 BT_WARN("Ignoring Phase 2 KR Update secured using old key");
974 return 0;
975 }
976
977 if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_INITIATOR) &&
978 (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS) ==
979 BLE_MESH_IV_UPDATE(msg->flags))) {
980 bt_mesh_beacon_ivu_initiator(false);
981 }
982
983 if (!lpn->established) {
984 struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
985
986 /* This is normally checked on the transport layer, however
987 * in this state we're also still accepting master
988 * credentials so we need to ensure the right ones (Friend
989 * Credentials) were used for this message.
990 */
991 if (!rx->friend_cred) {
992 BT_WARN("Friend Update with wrong credentials");
993 return -EINVAL;
994 }
995
996 lpn->established = 1U;
997
998 BT_INFO("Friendship established with 0x%04x", lpn->frnd);
999
1000 if (cfg->hb_pub.feat & BLE_MESH_FEAT_LOW_POWER) {
1001 bt_mesh_heartbeat_send();
1002 }
1003
1004 if (lpn_cb) {
1005 lpn_cb(lpn->frnd, true);
1006 }
1007
1008 /* Set initial poll timeout */
1009 lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn),
1010 POLL_TIMEOUT_INIT);
1011 }
1012
1013 friend_response_received(lpn);
1014
1015 iv_index = sys_be32_to_cpu(msg->iv_index);
1016
1017 BT_INFO("flags 0x%02x iv_index 0x%08x md %u", msg->flags, iv_index,
1018 msg->md);
1019
1020 if (bt_mesh_kr_update(sub, BLE_MESH_KEY_REFRESH(msg->flags),
1021 rx->new_key)) {
1022 bt_mesh_net_beacon_update(sub);
1023 }
1024
1025 bt_mesh_net_iv_update(iv_index, BLE_MESH_IV_UPDATE(msg->flags));
1026
1027 if (lpn->groups_changed) {
1028 sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
1029 sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
1030
1031 if (!lpn->sent_req) {
1032 lpn->groups_changed = 0U;
1033 }
1034 }
1035
1036 if (msg->md) {
1037 BT_DBG("Requesting for more messages");
1038 send_friend_poll();
1039 }
1040
1041 if (!lpn->sent_req) {
1042 k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
1043 }
1044
1045 return 0;
1046 }
1047
bt_mesh_lpn_poll(void)1048 int bt_mesh_lpn_poll(void)
1049 {
1050 if (!bt_mesh.lpn.established) {
1051 return -EAGAIN;
1052 }
1053
1054 BT_DBG("Requesting more messages");
1055
1056 return send_friend_poll();
1057 }
1058
bt_mesh_lpn_set_cb(void (* cb)(uint16_t friend_addr,bool established))1059 void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established))
1060 {
1061 lpn_cb = cb;
1062 }
1063
bt_mesh_lpn_init(void)1064 int bt_mesh_lpn_init(void)
1065 {
1066 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
1067
1068 BT_DBG("%s", __func__);
1069
1070 k_delayed_work_init(&lpn->timer, lpn_timeout);
1071
1072 if (lpn->state == BLE_MESH_LPN_ENABLED) {
1073 if (!IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) {
1074 bt_mesh_scan_enable();
1075 }
1076
1077 send_friend_req(lpn);
1078 } else {
1079 bt_mesh_scan_enable();
1080
1081 if (IS_ENABLED(CONFIG_BLE_MESH_LPN_AUTO)) {
1082 BT_DBG("Waiting %u ms for messages", LPN_AUTO_TIMEOUT);
1083 lpn_set_state(BLE_MESH_LPN_TIMER);
1084 k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT);
1085 }
1086 }
1087
1088 return 0;
1089 }
1090
1091 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_lpn_deinit(void)1092 int bt_mesh_lpn_deinit(void)
1093 {
1094 struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
1095
1096 bt_mesh_lpn_disable(true);
1097
1098 k_delayed_work_free(&lpn->timer);
1099
1100 return 0;
1101 }
1102 #endif /* CONFIG_BLE_MESH_DEINIT */
1103
1104 #endif /* CONFIG_BLE_MESH_LOW_POWER */
1105