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