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