1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9
10 #include "syscfg/syscfg.h"
11 #if MYNEWT_VAL(BLE_MESH_FRIEND) == 1
12
13 #include <stdint.h>
14 #include <errno.h>
15 #include <assert.h>
16
17 #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_FRIEND))
18 #include "host/ble_hs_log.h"
19
20 #include "mesh/mesh.h"
21 #include "mesh/slist.h"
22 #include "mesh_priv.h"
23 #include "crypto.h"
24 #include "adv.h"
25 #include "net.h"
26 #include "transport.h"
27 #include "access.h"
28 #include "foundation.h"
29 #include "friend.h"
30
31 /* We reserve one extra buffer for each friendship, since we need to be able
32 * to resend the last sent PDU, which sits separately outside of the queue.
33 */
34 #define FRIEND_BUF_COUNT ((MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE) + 1) * MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT))
35
36 static os_membuf_t friend_buf_mem[OS_MEMPOOL_SIZE(
37 FRIEND_BUF_COUNT,
38 BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)];
39
40 struct os_mbuf_pool friend_os_mbuf_pool;
41 static struct os_mempool friend_buf_mempool;
42
43
44 #define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), \
45 struct friend_adv, adv)
46
47 /* PDUs from Friend to the LPN should only be transmitted once with the
48 * smallest possible interval (20ms).
49 */
50 #define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20)
51
52 struct friend_pdu_info {
53 u16_t src;
54 u16_t dst;
55
56 u8_t seq[3];
57
58 u8_t ttl:7,
59 ctl:1;
60
61 u32_t iv_index;
62 };
63
64 static struct friend_adv {
65 struct bt_mesh_adv adv;
66 u64_t seq_auth;
67 } adv_pool[FRIEND_BUF_COUNT];
68
adv_alloc(int id)69 static struct bt_mesh_adv *adv_alloc(int id)
70 {
71 return &adv_pool[id].adv;
72 }
73
discard_buffer(void)74 static void discard_buffer(void)
75 {
76 struct bt_mesh_friend *frnd = &bt_mesh.frnd[0];
77 struct os_mbuf *buf;
78 int i;
79
80 /* Find the Friend context with the most queued buffers */
81 for (i = 1; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
82 if (bt_mesh.frnd[i].queue_size > frnd->queue_size) {
83 frnd = &bt_mesh.frnd[i];
84 }
85 }
86
87 buf = net_buf_slist_get(&frnd->queue);
88 __ASSERT_NO_MSG(buf != NULL);
89 BT_WARN("Discarding buffer %p for LPN 0x%04x", buf, frnd->lpn);
90 net_buf_unref(buf);
91 }
92
friend_buf_alloc(u16_t src)93 static struct os_mbuf *friend_buf_alloc(u16_t src)
94 {
95 struct os_mbuf *buf;
96
97 do {
98 buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc,
99 BT_MESH_ADV_DATA,
100 FRIEND_XMIT, K_NO_WAIT);
101 if (!buf) {
102 discard_buffer();
103 }
104 } while (!buf);
105
106 BT_MESH_ADV(buf)->addr = src;
107 FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL;
108
109 BT_DBG("allocated buf %p", buf);
110
111 return buf;
112 }
113
bt_mesh_friend_find(u16_t net_idx,u16_t lpn_addr,bool valid,bool established)114 struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
115 bool valid, bool established)
116 {
117 int i;
118
119 BT_DBG("net_idx 0x%04x lpn_addr 0x%04x", net_idx, lpn_addr);
120
121 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
122 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
123
124 if (valid && !frnd->valid) {
125 continue;
126 }
127
128 if (established && !frnd->established) {
129 continue;
130 }
131
132 if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) {
133 continue;
134 }
135
136 if (frnd->lpn == lpn_addr) {
137 return frnd;
138 }
139 }
140
141 return NULL;
142 }
143
144 /* Intentionally start a little bit late into the ReceiveWindow when
145 * it's large enough. This may improve reliability with some platforms,
146 * like the PTS, where the receiver might not have sufficiently compensated
147 * for internal latencies required to start scanning.
148 */
recv_delay(struct bt_mesh_friend * frnd)149 static s32_t recv_delay(struct bt_mesh_friend *frnd)
150 {
151 #if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50
152 return (s32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
153 #else
154 return frnd->recv_delay;
155 #endif
156 }
157
friend_clear(struct bt_mesh_friend * frnd)158 static void friend_clear(struct bt_mesh_friend *frnd)
159 {
160 int i;
161
162 BT_DBG("LPN 0x%04x", frnd->lpn);
163
164 k_delayed_work_cancel(&frnd->timer);
165
166 friend_cred_del(frnd->net_idx, frnd->lpn);
167
168 if (frnd->last) {
169 /* Cancel the sending if necessary */
170 if (frnd->pending_buf) {
171 BT_MESH_ADV(frnd->last)->busy = 0;
172 }
173
174 net_buf_unref(frnd->last);
175 frnd->last = NULL;
176 }
177
178 while (!net_buf_slist_is_empty(&frnd->queue)) {
179 net_buf_unref(net_buf_slist_get(&frnd->queue));
180 }
181
182 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
183 struct bt_mesh_friend_seg *seg = &frnd->seg[i];
184
185 while (!net_buf_slist_is_empty(&seg->queue)) {
186 net_buf_unref(net_buf_slist_get(&seg->queue));
187 }
188 }
189
190 frnd->valid = 0;
191 frnd->established = 0;
192 frnd->pending_buf = 0;
193 frnd->fsn = 0;
194 frnd->queue_size = 0;
195 frnd->pending_req = 0;
196 memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
197 }
198
bt_mesh_friend_clear_net_idx(u16_t net_idx)199 void bt_mesh_friend_clear_net_idx(u16_t net_idx)
200 {
201 int i;
202
203 BT_DBG("net_idx 0x%04x", net_idx);
204
205 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
206 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
207
208 if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
209 continue;
210 }
211
212 if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
213 friend_clear(frnd);
214 }
215 }
216 }
217
bt_mesh_friend_sec_update(u16_t net_idx)218 void bt_mesh_friend_sec_update(u16_t net_idx)
219 {
220 int i;
221
222 BT_DBG("net_idx 0x%04x", net_idx);
223
224 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
225 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
226
227 if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
228 continue;
229 }
230
231 if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
232 frnd->sec_update = 1;
233 }
234 }
235 }
236
bt_mesh_friend_clear(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)237 int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
238 {
239 struct bt_mesh_ctl_friend_clear *msg = (void *)buf->om_data;
240 struct bt_mesh_friend *frnd;
241 u16_t lpn_addr, lpn_counter;
242 struct bt_mesh_net_tx tx = {
243 .sub = rx->sub,
244 .ctx = &rx->ctx,
245 .src = bt_mesh_primary_addr(),
246 .xmit = bt_mesh_net_transmit_get(),
247 };
248 struct bt_mesh_ctl_friend_clear_confirm cfm;
249
250 if (buf->om_len < sizeof(*msg)) {
251 BT_WARN("Too short Friend Clear");
252 return -EINVAL;
253 }
254
255 lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
256 lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
257
258 BT_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter);
259
260 frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false);
261 if (!frnd) {
262 BT_WARN("No matching LPN addr 0x%04x", lpn_addr);
263 return 0;
264 }
265
266 /* A Friend Clear message is considered valid if the result of the
267 * subtraction of the value of the LPNCounter field of the Friend
268 * Request message (the one that initiated the friendship) from the
269 * value of the LPNCounter field of the Friend Clear message, modulo
270 * 65536, is in the range 0 to 255 inclusive.
271 */
272 if (lpn_counter - frnd->lpn_counter > 255) {
273 BT_WARN("LPN Counter out of range (old %u new %u)",
274 frnd->lpn_counter, lpn_counter);
275 return 0;
276 }
277
278 tx.ctx->send_ttl = BT_MESH_TTL_MAX;
279
280 cfm.lpn_addr = msg->lpn_addr;
281 cfm.lpn_counter = msg->lpn_counter;
282
283 bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
284 sizeof(cfm), NULL, NULL, NULL);
285
286 friend_clear(frnd);
287
288 return 0;
289 }
290
friend_sub_add(struct bt_mesh_friend * frnd,u16_t addr)291 static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
292 {
293 int i;
294
295 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
296 if (frnd->sub_list[i] == BT_MESH_ADDR_UNASSIGNED) {
297 frnd->sub_list[i] = addr;
298 return;
299 }
300 }
301
302 BT_WARN("No space in friend subscription list");
303 }
304
friend_sub_rem(struct bt_mesh_friend * frnd,u16_t addr)305 static void friend_sub_rem(struct bt_mesh_friend *frnd, u16_t addr)
306 {
307 int i;
308
309 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
310 if (frnd->sub_list[i] == addr) {
311 frnd->sub_list[i] = BT_MESH_ADDR_UNASSIGNED;
312 return;
313 }
314 }
315 }
316
create_friend_pdu(struct bt_mesh_friend * frnd,struct friend_pdu_info * info,struct os_mbuf * sdu)317 static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
318 struct friend_pdu_info *info,
319 struct os_mbuf *sdu)
320 {
321 struct bt_mesh_subnet *sub;
322 const u8_t *enc, *priv;
323 struct os_mbuf *buf;
324 u8_t nid;
325
326 sub = bt_mesh_subnet_get(frnd->net_idx);
327 __ASSERT_NO_MSG(sub != NULL);
328
329 buf = friend_buf_alloc(info->src);
330
331 /* Friend Offer needs master security credentials */
332 if (info->ctl && TRANS_CTL_OP(sdu->om_data) == TRANS_CTL_OP_FRIEND_OFFER) {
333 enc = sub->keys[sub->kr_flag].enc;
334 priv = sub->keys[sub->kr_flag].privacy;
335 nid = sub->keys[sub->kr_flag].nid;
336 } else {
337 if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
338 BT_ERR("friend_cred_get failed");
339 goto failed;
340 }
341 }
342
343 net_buf_add_u8(buf, (nid | (info->iv_index & 1) << 7));
344
345 if (info->ctl) {
346 net_buf_add_u8(buf, info->ttl | 0x80);
347 } else {
348 net_buf_add_u8(buf, info->ttl);
349 }
350
351 net_buf_add_mem(buf, info->seq, sizeof(info->seq));
352
353 net_buf_add_be16(buf, info->src);
354 net_buf_add_be16(buf, info->dst);
355
356 net_buf_add_mem(buf, sdu->om_data, sdu->om_len);
357
358 /* We re-encrypt and obfuscate using the received IVI rather than
359 * the normal TX IVI (which may be different) since the transport
360 * layer nonce includes the IVI.
361 */
362 if (bt_mesh_net_encrypt(enc, buf, info->iv_index, false)) {
363 BT_ERR("Re-encrypting failed");
364 goto failed;
365 }
366
367 if (bt_mesh_net_obfuscate(buf->om_data, info->iv_index, priv)) {
368 BT_ERR("Re-obfuscating failed");
369 goto failed;
370 }
371
372 return buf;
373
374 failed:
375 net_buf_unref(buf);
376 return NULL;
377 }
378
encode_friend_ctl(struct bt_mesh_friend * frnd,u8_t ctl_op,struct os_mbuf * sdu)379 static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
380 u8_t ctl_op,
381 struct os_mbuf *sdu)
382 {
383 struct friend_pdu_info info;
384 u32_t seq;
385
386 BT_DBG("LPN 0x%04x", frnd->lpn);
387
388 net_buf_simple_push_u8(sdu, TRANS_CTL_HDR(ctl_op, 0));
389
390 info.src = bt_mesh_primary_addr();
391 info.dst = frnd->lpn;
392
393 info.ctl = 1;
394 info.ttl = 0;
395
396 seq = bt_mesh_next_seq();
397 info.seq[0] = seq >> 16;
398 info.seq[1] = seq >> 8;
399 info.seq[2] = seq;
400
401 info.iv_index = BT_MESH_NET_IVI_TX;
402
403 return create_friend_pdu(frnd, &info, sdu);
404 }
405
encode_update(struct bt_mesh_friend * frnd,u8_t md)406 static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
407 {
408 struct bt_mesh_ctl_friend_update *upd;
409 struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd));
410 struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
411 struct os_mbuf *buf;
412
413 __ASSERT_NO_MSG(sub != NULL);
414
415 BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
416
417 net_buf_simple_init(sdu, 1);
418
419 upd = net_buf_simple_add(sdu, sizeof(*upd));
420 upd->flags = bt_mesh_net_flags(sub);
421 upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
422 upd->md = md;
423
424 buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_UPDATE, sdu);
425
426 os_mbuf_free_chain(sdu);
427 return buf;
428 }
429
enqueue_sub_cfm(struct bt_mesh_friend * frnd,u8_t xact)430 static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
431 {
432 struct bt_mesh_ctl_friend_sub_confirm *cfm;
433 struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*cfm));
434 struct os_mbuf *buf;
435
436 BT_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact);
437
438 net_buf_simple_init(sdu, 1);
439
440 cfm = net_buf_simple_add(sdu, sizeof(*cfm));
441 cfm->xact = xact;
442
443 buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_SUB_CFM, sdu);
444 if (!buf) {
445 BT_ERR("Unable to encode Subscription List Confirmation");
446 goto done;
447 }
448
449 if (frnd->last) {
450 BT_DBG("Discarding last PDU");
451 net_buf_unref(frnd->last);
452 }
453
454 frnd->last = buf;
455 frnd->send_last = 1;
456
457 done:
458 os_mbuf_free_chain(sdu);
459 }
460
friend_recv_delay(struct bt_mesh_friend * frnd)461 static void friend_recv_delay(struct bt_mesh_friend *frnd)
462 {
463 frnd->pending_req = 1;
464 k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
465 BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
466 }
467
bt_mesh_friend_sub_add(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)468 int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
469 struct os_mbuf *buf)
470 {
471 struct bt_mesh_friend *frnd;
472 u8_t xact;
473
474 if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
475 BT_WARN("Too short Friend Subscription Add");
476 return -EINVAL;
477 }
478
479 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
480 if (!frnd) {
481 BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
482 return 0;
483 }
484
485 if (frnd->pending_buf) {
486 BT_WARN("Previous buffer not yet sent!");
487 return 0;
488 }
489
490 friend_recv_delay(frnd);
491
492 xact = net_buf_simple_pull_u8(buf);
493
494 while (buf->om_len >= 2) {
495 friend_sub_add(frnd, net_buf_simple_pull_be16(buf));
496 }
497
498 enqueue_sub_cfm(frnd, xact);
499
500 return 0;
501 }
502
bt_mesh_friend_sub_rem(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)503 int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
504 struct os_mbuf *buf)
505 {
506 struct bt_mesh_friend *frnd;
507 u8_t xact;
508
509 if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
510 BT_WARN("Too short Friend Subscription Remove");
511 return -EINVAL;
512 }
513
514 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
515 if (!frnd) {
516 BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
517 return 0;
518 }
519
520 if (frnd->pending_buf) {
521 BT_WARN("Previous buffer not yet sent!");
522 return 0;
523 }
524
525 friend_recv_delay(frnd);
526
527 xact = net_buf_simple_pull_u8(buf);
528
529 while (buf->om_len >= 2) {
530 friend_sub_rem(frnd, net_buf_simple_pull_be16(buf));
531 }
532
533 enqueue_sub_cfm(frnd, xact);
534
535 return 0;
536 }
537
enqueue_buf(struct bt_mesh_friend * frnd,struct os_mbuf * buf)538 static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf)
539 {
540 net_buf_slist_put(&frnd->queue, buf);
541 frnd->queue_size++;
542 }
543
enqueue_update(struct bt_mesh_friend * frnd,u8_t md)544 static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
545 {
546 struct os_mbuf *buf;
547
548 buf = encode_update(frnd, md);
549 if (!buf) {
550 BT_ERR("Unable to encode Friend Update");
551 return;
552 }
553
554 frnd->sec_update = 0;
555 enqueue_buf(frnd, buf);
556 }
557
bt_mesh_friend_poll(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)558 int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
559 {
560 struct bt_mesh_ctl_friend_poll *msg = (void *)buf->om_data;
561 struct bt_mesh_friend *frnd;
562
563 if (buf->om_len < sizeof(*msg)) {
564 BT_WARN("Too short Friend Poll");
565 return -EINVAL;
566 }
567
568 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
569 if (!frnd) {
570 BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
571 return 0;
572 }
573
574 if (msg->fsn & ~1) {
575 BT_WARN("Prohibited (non-zero) padding bits");
576 return -EINVAL;
577 }
578
579 if (frnd->pending_buf) {
580 BT_WARN("Previous buffer not yet sent");
581 return 0;
582 }
583
584 BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn);
585
586 friend_recv_delay(frnd);
587
588 if (!frnd->established) {
589 BT_DBG("Friendship established with 0x%04x", frnd->lpn);
590 frnd->established = 1;
591 }
592
593 if (msg->fsn == frnd->fsn && frnd->last) {
594 BT_DBG("Re-sending last PDU");
595 frnd->send_last = 1;
596 } else {
597 if (frnd->last) {
598 net_buf_unref(frnd->last);
599 frnd->last = NULL;
600 }
601
602 frnd->fsn = msg->fsn;
603
604 if (net_buf_slist_is_empty(&frnd->queue)) {
605 enqueue_update(frnd, 0);
606 BT_DBG("Enqueued Friend Update to empty queue");
607 }
608 }
609
610 return 0;
611 }
612
find_clear(u16_t prev_friend)613 static struct bt_mesh_friend *find_clear(u16_t prev_friend)
614 {
615 int i;
616
617 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
618 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
619
620 if (frnd->clear.frnd == prev_friend) {
621 return frnd;
622 }
623 }
624
625 return NULL;
626 }
627
friend_clear_sent(int err,void * user_data)628 static void friend_clear_sent(int err, void *user_data)
629 {
630 struct bt_mesh_friend *frnd = user_data;
631
632 k_delayed_work_submit(&frnd->clear.timer,
633 K_SECONDS(frnd->clear.repeat_sec));
634 frnd->clear.repeat_sec *= 2;
635 }
636
637 static const struct bt_mesh_send_cb clear_sent_cb = {
638 .end = friend_clear_sent,
639 };
640
send_friend_clear(struct bt_mesh_friend * frnd)641 static void send_friend_clear(struct bt_mesh_friend *frnd)
642 {
643 struct bt_mesh_msg_ctx ctx = {
644 .net_idx = frnd->net_idx,
645 .app_idx = BT_MESH_KEY_UNUSED,
646 .addr = frnd->clear.frnd,
647 .send_ttl = BT_MESH_TTL_MAX,
648 };
649 struct bt_mesh_net_tx tx = {
650 .sub = &bt_mesh.sub[0],
651 .ctx = &ctx,
652 .src = bt_mesh_primary_addr(),
653 .xmit = bt_mesh_net_transmit_get(),
654 };
655 struct bt_mesh_ctl_friend_clear req = {
656 .lpn_addr = sys_cpu_to_be16(frnd->lpn),
657 .lpn_counter = sys_cpu_to_be16(frnd->lpn_counter),
658 };
659
660 BT_DBG("");
661
662 bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
663 sizeof(req), NULL, &clear_sent_cb, frnd);
664 }
665
clear_timeout(struct ble_npl_event * work)666 static void clear_timeout(struct ble_npl_event *work)
667 {
668 struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
669 u32_t duration;
670
671 BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
672
673 duration = k_uptime_get_32() - frnd->clear.start;
674 if (duration > 2 * frnd->poll_to) {
675 BT_DBG("Clear Procedure timer expired");
676 frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED;
677 return;
678 }
679
680 send_friend_clear(frnd);
681 }
682
clear_procedure_start(struct bt_mesh_friend * frnd)683 static void clear_procedure_start(struct bt_mesh_friend *frnd)
684 {
685 BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
686
687 frnd->clear.start = k_uptime_get_32() + (2 * frnd->poll_to);
688 frnd->clear.repeat_sec = 1;
689
690 send_friend_clear(frnd);
691 }
692
bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)693 int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
694 struct os_mbuf *buf)
695 {
696 struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
697 struct bt_mesh_friend *frnd;
698 u16_t lpn_addr, lpn_counter;
699
700 BT_DBG("");
701
702 if (buf->om_len < sizeof(*msg)) {
703 BT_WARN("Too short Friend Clear Confirm");
704 return -EINVAL;
705 }
706
707 frnd = find_clear(rx->ctx.addr);
708 if (!frnd) {
709 BT_WARN("No pending clear procedure for 0x%02x", rx->ctx.addr);
710 return 0;
711 }
712
713 lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
714 if (lpn_addr != frnd->lpn) {
715 BT_WARN("LPN address mismatch (0x%04x != 0x%04x)",
716 lpn_addr, frnd->lpn);
717 return 0;
718 }
719
720 lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
721 if (lpn_counter != frnd->lpn_counter) {
722 BT_WARN("LPN counter mismatch (0x%04x != 0x%04x)",
723 lpn_counter, frnd->lpn_counter);
724 return 0;
725 }
726
727 k_delayed_work_cancel(&frnd->clear.timer);
728 frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED;
729
730 return 0;
731 }
732
enqueue_offer(struct bt_mesh_friend * frnd,s8_t rssi)733 static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
734 {
735 struct bt_mesh_ctl_friend_offer *off;
736 struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*off));
737 struct os_mbuf *buf;
738
739 BT_DBG("");
740
741 net_buf_simple_init(sdu, 1);
742
743 off = net_buf_simple_add(sdu, sizeof(*off));
744
745 off->recv_win = CONFIG_BT_MESH_FRIEND_RECV_WIN,
746 off->queue_size = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE,
747 off->sub_list_size = ARRAY_SIZE(frnd->sub_list),
748 off->rssi = rssi,
749 off->frnd_counter = sys_cpu_to_be16(frnd->counter);
750
751 buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_OFFER, sdu);
752 if (!buf) {
753 BT_ERR("Unable to encode Friend Offer");
754 goto done;
755 }
756
757 frnd->counter++;
758
759 if (frnd->last) {
760 net_buf_unref(frnd->last);
761 }
762
763 frnd->last = buf;
764 frnd->send_last = 1;
765
766 done:
767 os_mbuf_free_chain(sdu);
768 }
769
770 #define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN
771 #define RSSI_FACT(crit) (((crit) >> 5) & (u8_t)BIT_MASK(2))
772 #define RECV_WIN_FACT(crit) (((crit) >> 3) & (u8_t)BIT_MASK(2))
773 #define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (u8_t)BIT_MASK(3))
774 #define MIN_QUEUE_SIZE(crit) ((u32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
775
offer_delay(struct bt_mesh_friend * frnd,s8_t rssi,u8_t crit)776 static s32_t offer_delay(struct bt_mesh_friend *frnd, s8_t rssi, u8_t crit)
777 {
778 /* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
779 * want to avoid floating-point arithmetic.
780 */
781 static const u8_t fact[] = { 10, 15, 20, 25 };
782 s32_t delay;
783
784 BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
785 fact[RECV_WIN_FACT(crit)], RECV_WIN,
786 fact[RSSI_FACT(crit)], rssi);
787
788 /* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
789 delay = (s32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
790 delay -= (s32_t)fact[RSSI_FACT(crit)] * rssi;
791 delay /= 10;
792
793 BT_DBG("Local Delay calculated as %d ms", delay);
794
795 if (delay < 100) {
796 return K_MSEC(100);
797 }
798
799 return K_MSEC(delay);
800 }
801
bt_mesh_friend_req(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)802 int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
803 {
804 struct bt_mesh_ctl_friend_req *msg = (void *)buf->om_data;
805 struct bt_mesh_friend *frnd = NULL;
806 u16_t old_friend;
807 u32_t poll_to;
808 int i;
809
810 if (buf->om_len < sizeof(*msg)) {
811 BT_WARN("Too short Friend Request");
812 return -EINVAL;
813 }
814
815 if (msg->recv_delay <= 0x09) {
816 BT_WARN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay);
817 return -EINVAL;
818 }
819
820 poll_to = (((u32_t)msg->poll_to[0] << 16) |
821 ((u32_t)msg->poll_to[1] << 8) |
822 ((u32_t)msg->poll_to[2]));
823
824 if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
825 BT_WARN("Prohibited PollTimeout (0x%06x)", poll_to);
826 return -EINVAL;
827 }
828
829 if (msg->num_elem == 0x00) {
830 BT_WARN("Prohibited NumElements value (0x00)");
831 return -EINVAL;
832 }
833
834 if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) {
835 BT_WARN("Prohibited Minimum Queue Size in Friend Request");
836 return -EINVAL;
837 }
838
839 if (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) {
840 BT_WARN("We have a too small Friend Queue size (%u < %u)",
841 CONFIG_BT_MESH_FRIEND_QUEUE_SIZE,
842 MIN_QUEUE_SIZE(msg->criteria));
843 return 0;
844 }
845
846 old_friend = sys_be16_to_cpu(msg->prev_addr);
847 if (BT_MESH_ADDR_IS_UNICAST(old_friend)) {
848 frnd = bt_mesh_friend_find(rx->sub->net_idx, old_friend,
849 true, false);
850 } else {
851 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr,
852 true, false);
853 }
854
855 if (frnd) {
856 BT_WARN("Existing LPN re-requesting Friendship");
857 friend_clear(frnd);
858 goto init_friend;
859 }
860
861 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
862 if (!bt_mesh.frnd[i].valid) {
863 frnd = &bt_mesh.frnd[i];
864 frnd->valid = 1;
865 break;
866 }
867 }
868
869 if (!frnd) {
870 BT_WARN("No free Friend contexts for new LPN");
871 return -ENOMEM;
872 }
873
874 init_friend:
875 frnd->lpn = rx->ctx.addr;
876 frnd->net_idx = rx->sub->net_idx;
877 frnd->recv_delay = msg->recv_delay;
878 frnd->poll_to = poll_to * 100;
879 frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
880 frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
881
882 BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
883 frnd->lpn, rx->rssi, frnd->recv_delay, frnd->poll_to);
884
885 if (BT_MESH_ADDR_IS_UNICAST(old_friend) &&
886 !bt_mesh_elem_find(old_friend)) {
887 clear_procedure_start(frnd);
888 }
889
890 k_delayed_work_submit(&frnd->timer,
891 offer_delay(frnd, rx->rssi, msg->criteria));
892
893 friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
894 frnd->counter);
895
896 enqueue_offer(frnd, rx->rssi);
897
898 return 0;
899 }
900
get_seg(struct bt_mesh_friend * frnd,u16_t src,u64_t * seq_auth)901 static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
902 u16_t src, u64_t *seq_auth)
903 {
904 struct bt_mesh_friend_seg *unassigned = NULL;
905 int i;
906
907 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
908 struct bt_mesh_friend_seg *seg = &frnd->seg[i];
909 struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
910
911 if (buf && BT_MESH_ADV(buf)->addr == src &&
912 FRIEND_ADV(buf)->seq_auth == *seq_auth) {
913 return seg;
914 }
915
916 if (!unassigned && !buf) {
917 unassigned = seg;
918 }
919 }
920
921 return unassigned;
922 }
923
enqueue_friend_pdu(struct bt_mesh_friend * frnd,enum bt_mesh_friend_pdu_type type,struct os_mbuf * buf)924 static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
925 enum bt_mesh_friend_pdu_type type,
926 struct os_mbuf *buf)
927 {
928 struct bt_mesh_friend_seg *seg;
929 struct friend_adv *adv;
930
931 BT_DBG("type %u", type);
932
933 if (type == BT_MESH_FRIEND_PDU_SINGLE) {
934 if (frnd->sec_update) {
935 enqueue_update(frnd, 1);
936 }
937
938 enqueue_buf(frnd, buf);
939 return;
940 }
941
942 adv = FRIEND_ADV(buf);
943 seg = get_seg(frnd, BT_MESH_ADV(buf)->addr, &adv->seq_auth);
944 if (!seg) {
945 BT_ERR("No free friend segment RX contexts for 0x%04x",
946 BT_MESH_ADV(buf)->addr);
947 net_buf_unref(buf);
948 return;
949 }
950
951 net_buf_slist_put(&seg->queue, buf);
952
953 if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
954 if (frnd->sec_update) {
955 enqueue_update(frnd, 1);
956 }
957
958 /* Only acks should have a valid SeqAuth in the Friend queue
959 * (otherwise we can't easily detect them there), so clear
960 * the SeqAuth information from the segments before merging.
961 */
962 struct os_mbuf *m;
963 struct os_mbuf_pkthdr *pkthdr;
964 NET_BUF_SLIST_FOR_EACH_NODE(&seg->queue, pkthdr) {
965 m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
966 FRIEND_ADV(m)->seq_auth = TRANS_SEQ_AUTH_NVAL;
967 frnd->queue_size++;
968 }
969
970 net_buf_slist_merge_slist(&frnd->queue, &seg->queue);
971 }
972 }
973
buf_send_start(u16_t duration,int err,void * user_data)974 static void buf_send_start(u16_t duration, int err, void *user_data)
975 {
976 struct bt_mesh_friend *frnd = user_data;
977
978 BT_DBG("err %d", err);
979
980 frnd->pending_buf = 0;
981
982 /* Friend Offer doesn't follow the re-sending semantics */
983 if (!frnd->established) {
984 net_buf_unref(frnd->last);
985 frnd->last = NULL;
986 }
987 }
988
buf_send_end(int err,void * user_data)989 static void buf_send_end(int err, void *user_data)
990 {
991 struct bt_mesh_friend *frnd = user_data;
992
993 BT_DBG("err %d", err);
994
995 if (frnd->pending_req) {
996 BT_WARN("Another request before previous completed sending");
997 return;
998 }
999
1000 if (frnd->established) {
1001 k_delayed_work_submit(&frnd->timer, frnd->poll_to);
1002 BT_DBG("Waiting %u ms for next poll", frnd->poll_to);
1003 } else {
1004 /* Friend offer timeout is 1 second */
1005 k_delayed_work_submit(&frnd->timer, K_SECONDS(1));
1006 BT_DBG("Waiting for first poll");
1007 }
1008 }
1009
friend_timeout(struct ble_npl_event * work)1010 static void friend_timeout(struct ble_npl_event *work)
1011 {
1012 struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
1013 static const struct bt_mesh_send_cb buf_sent_cb = {
1014 .start = buf_send_start,
1015 .end = buf_send_end,
1016 };
1017
1018 __ASSERT_NO_MSG(frnd->pending_buf == 0);
1019
1020 BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
1021 frnd->send_last, frnd->last);
1022
1023 if (frnd->send_last && frnd->last) {
1024 BT_DBG("Sending frnd->last %p", frnd->last);
1025 frnd->send_last = 0;
1026 goto send_last;
1027 }
1028
1029 if (frnd->established && !frnd->pending_req) {
1030 BT_WARN("Friendship lost with 0x%04x", frnd->lpn);
1031 friend_clear(frnd);
1032 return;
1033 }
1034
1035 frnd->last = net_buf_slist_get(&frnd->queue);
1036 if (!frnd->last) {
1037 BT_WARN("Friendship not established with 0x%04x", frnd->lpn);
1038 friend_clear(frnd);
1039 return;
1040 }
1041
1042 BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
1043 frnd->last, frnd->lpn);
1044 frnd->queue_size--;
1045
1046 send_last:
1047 frnd->pending_req = 0;
1048 frnd->pending_buf = 1;
1049 bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
1050 }
1051
bt_mesh_friend_init(void)1052 int bt_mesh_friend_init(void)
1053 {
1054 int rc;
1055 int i;
1056
1057 rc = os_mempool_init(&friend_buf_mempool, FRIEND_BUF_COUNT,
1058 BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE,
1059 friend_buf_mem, "friend_buf_pool");
1060 assert(rc == 0);
1061
1062 rc = os_mbuf_pool_init(&friend_os_mbuf_pool, &friend_buf_mempool,
1063 BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE,
1064 FRIEND_BUF_COUNT);
1065 assert(rc == 0);
1066
1067 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1068 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1069 int j;
1070
1071 frnd->net_idx = BT_MESH_KEY_UNUSED;
1072
1073 net_buf_slist_init(&frnd->queue);
1074
1075 k_delayed_work_init(&frnd->timer, friend_timeout);
1076 k_delayed_work_add_arg(&frnd->timer, frnd);
1077 k_delayed_work_init(&frnd->clear.timer, clear_timeout);
1078 k_delayed_work_add_arg(&frnd->clear.timer, frnd);
1079
1080 for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
1081 net_buf_slist_init(&frnd->seg[j].queue);
1082 }
1083 }
1084
1085 return 0;
1086 }
1087
friend_purge_old_ack(struct bt_mesh_friend * frnd,u64_t * seq_auth,u16_t src)1088 static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
1089 u16_t src)
1090 {
1091 struct os_mbuf *cur, *prev = NULL;
1092
1093 BT_DBG("SeqAuth %llx src 0x%04x", *seq_auth, src);
1094
1095 for (cur = net_buf_slist_peek_head(&frnd->queue);
1096 cur != NULL; prev = cur, cur = net_buf_slist_peek_next(cur)) {
1097 struct os_mbuf *buf = (void *)cur;
1098
1099 if (BT_MESH_ADV(buf)->addr == src &&
1100 FRIEND_ADV(buf)->seq_auth == *seq_auth) {
1101 BT_DBG("Removing old ack from Friend Queue");
1102
1103 net_buf_slist_remove(&frnd->queue, prev, cur);
1104 frnd->queue_size--;
1105
1106 net_buf_unref(buf);
1107 break;
1108 }
1109 }
1110 }
1111
friend_lpn_enqueue_rx(struct bt_mesh_friend * frnd,struct bt_mesh_net_rx * rx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1112 static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
1113 struct bt_mesh_net_rx *rx,
1114 enum bt_mesh_friend_pdu_type type,
1115 u64_t *seq_auth, struct os_mbuf *sbuf)
1116 {
1117 struct friend_pdu_info info;
1118 struct os_mbuf *buf;
1119
1120 BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size);
1121
1122 if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
1123 friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr);
1124 }
1125
1126 info.src = rx->ctx.addr;
1127 info.dst = rx->ctx.recv_dst;
1128
1129 if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
1130 info.ttl = rx->ctx.recv_ttl;
1131 } else {
1132 info.ttl = rx->ctx.recv_ttl - 1;
1133 }
1134
1135 info.ctl = rx->ctl;
1136
1137 info.seq[0] = (rx->seq >> 16);
1138 info.seq[1] = (rx->seq >> 8);
1139 info.seq[2] = rx->seq;
1140
1141 info.iv_index = BT_MESH_NET_IVI_RX(rx);
1142
1143 buf = create_friend_pdu(frnd, &info, sbuf);
1144 if (!buf) {
1145 BT_ERR("Failed to encode Friend buffer");
1146 return;
1147 }
1148
1149 if (seq_auth) {
1150 FRIEND_ADV(buf)->seq_auth = *seq_auth;
1151 }
1152
1153 enqueue_friend_pdu(frnd, type, buf);
1154
1155 BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
1156 frnd->lpn, frnd->queue_size);
1157 }
1158
friend_lpn_enqueue_tx(struct bt_mesh_friend * frnd,struct bt_mesh_net_tx * tx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1159 static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
1160 struct bt_mesh_net_tx *tx,
1161 enum bt_mesh_friend_pdu_type type,
1162 u64_t *seq_auth, struct os_mbuf *sbuf)
1163 {
1164 struct friend_pdu_info info;
1165 struct os_mbuf *buf;
1166 u32_t seq;
1167
1168 BT_DBG("LPN 0x%04x", frnd->lpn);
1169
1170 if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
1171 friend_purge_old_ack(frnd, seq_auth, tx->src);
1172 }
1173
1174 info.src = tx->src;
1175 info.dst = tx->ctx->addr;
1176
1177 info.ttl = tx->ctx->send_ttl;
1178 info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
1179
1180 seq = bt_mesh_next_seq();
1181 info.seq[0] = seq >> 16;
1182 info.seq[1] = seq >> 8;
1183 info.seq[2] = seq;
1184
1185 info.iv_index = BT_MESH_NET_IVI_TX;
1186
1187 buf = create_friend_pdu(frnd, &info, sbuf);
1188 if (!buf) {
1189 BT_ERR("Failed to encode Friend buffer");
1190 return;
1191 }
1192
1193 if (seq_auth) {
1194 FRIEND_ADV(buf)->seq_auth = *seq_auth;
1195 }
1196
1197 enqueue_friend_pdu(frnd, type, buf);
1198
1199 BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
1200 }
1201
friend_lpn_matches(struct bt_mesh_friend * frnd,u16_t net_idx,u16_t addr)1202 static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
1203 u16_t addr)
1204 {
1205 int i;
1206
1207 if (!frnd->established) {
1208 return false;
1209 }
1210
1211 if (net_idx != frnd->net_idx) {
1212 return false;
1213 }
1214
1215 if (BT_MESH_ADDR_IS_UNICAST(addr)) {
1216 if (addr == frnd->lpn) {
1217 return true;
1218 }
1219
1220 return false;
1221 }
1222
1223 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
1224 if (frnd->sub_list[i] == addr) {
1225 return true;
1226 }
1227 }
1228
1229 return false;
1230 }
1231
bt_mesh_friend_match(u16_t net_idx,u16_t addr)1232 bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
1233 {
1234 int i;
1235
1236 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1237 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1238
1239 if (friend_lpn_matches(frnd, net_idx, addr)) {
1240 BT_DBG("LPN 0x%04x matched address 0x%04x",
1241 frnd->lpn, addr);
1242 return true;
1243 }
1244 }
1245
1246 BT_DBG("No matching LPN for address 0x%04x", addr);
1247
1248 return false;
1249 }
1250
bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx * rx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1251 void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
1252 enum bt_mesh_friend_pdu_type type,
1253 u64_t *seq_auth, struct os_mbuf *sbuf)
1254 {
1255 int i;
1256
1257 if (!rx->friend_match ||
1258 (rx->ctx.recv_ttl <= 1 && rx->net_if != BT_MESH_NET_IF_LOCAL) ||
1259 bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) {
1260 return;
1261 }
1262
1263 BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x",
1264 rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr,
1265 rx->ctx.recv_dst);
1266
1267 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1268 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1269
1270 if (friend_lpn_matches(frnd, rx->sub->net_idx,
1271 rx->ctx.recv_dst)) {
1272 friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, sbuf);
1273 }
1274 }
1275 }
1276
bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx * tx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1277 bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
1278 enum bt_mesh_friend_pdu_type type,
1279 u64_t *seq_auth, struct os_mbuf *sbuf)
1280 {
1281 bool matched = false;
1282 int i;
1283
1284 if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) ||
1285 bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) {
1286 return matched;
1287 }
1288
1289 BT_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx,
1290 tx->ctx->addr, tx->src);
1291
1292 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1293 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1294
1295 if (friend_lpn_matches(frnd, tx->sub->net_idx, tx->ctx->addr)) {
1296 friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, sbuf);
1297 matched = true;
1298 }
1299 }
1300
1301 return matched;
1302 }
1303
bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet * sub,u16_t src,u16_t dst,u64_t * seq_auth)1304 void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
1305 u16_t dst, u64_t *seq_auth)
1306 {
1307 int i;
1308
1309 BT_DBG("");
1310
1311 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1312 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1313 int j;
1314
1315 if (!friend_lpn_matches(frnd, sub->net_idx, dst)) {
1316 continue;
1317 }
1318
1319 for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
1320 struct bt_mesh_friend_seg *seg = &frnd->seg[j];
1321 struct os_mbuf *buf;
1322
1323 buf = (void *)net_buf_slist_peek_head(&seg->queue);
1324 if (!buf) {
1325 continue;
1326 }
1327
1328 if (BT_MESH_ADV(buf)->addr != src) {
1329 continue;
1330 }
1331
1332 if (FRIEND_ADV(buf)->seq_auth != *seq_auth) {
1333 continue;
1334 }
1335
1336 BT_WARN("Clearing incomplete segments for 0x%04x", src);
1337
1338 while (!net_buf_slist_is_empty(&seg->queue)) {
1339 net_buf_unref(net_buf_slist_get(&seg->queue));
1340 }
1341 }
1342 }
1343 }
1344
1345 #endif //MYNEWT_VAL(BLE_MESH_FRIEND)
1346