Lines Matching +full:rx +full:- +full:addr +full:- +full:mode
4 * SPDX-License-Identifier: Apache-2.0
36 #warning Frienship feature may work unstable when non-deferred log mode is selected. Use the \
90 return frnd->subnet != NULL; in friend_is_allocated()
93 static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) in is_lpn_unicast() argument
95 if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) { in is_lpn_unicast()
99 return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem)); in is_lpn_unicast()
116 if (established && !frnd->established) { in bt_mesh_friend_find()
121 (!frnd->subnet || frnd->subnet->net_idx != net_idx)) { in bt_mesh_friend_find()
135 return bt_mesh_friend_cred_create(&frnd->cred[idx], frnd->lpn, in friend_cred_create()
137 frnd->lpn_counter, frnd->counter, in friend_cred_create()
138 &frnd->subnet->keys[idx].net); in friend_cred_create()
158 return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5); in recv_delay()
160 return frnd->recv_delay; in recv_delay()
168 LOG_DBG("LPN 0x%04x", frnd->lpn); in friend_clear()
171 (void)k_work_cancel_delayable(&frnd->timer); in friend_clear()
173 for (i = 0; i < ARRAY_SIZE(frnd->cred); i++) { in friend_clear()
174 if (frnd->subnet->keys[i].valid) { in friend_clear()
175 bt_mesh_friend_cred_destroy(&frnd->cred[i]); in friend_clear()
178 memset(frnd->cred, 0, sizeof(frnd->cred)); in friend_clear()
180 if (frnd->last) { in friend_clear()
181 net_buf_unref(frnd->last); in friend_clear()
182 frnd->last = NULL; in friend_clear()
185 purge_buffers(&frnd->queue); in friend_clear()
187 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { in friend_clear()
188 struct bt_mesh_friend_seg *seg = &frnd->seg[i]; in friend_clear()
190 purge_buffers(&seg->queue); in friend_clear()
191 seg->seg_count = 0U; in friend_clear()
195 if (frnd->established && cb->terminated) { in friend_clear()
196 cb->terminated(frnd->subnet->net_idx, frnd->lpn); in friend_clear()
200 frnd->counter++; in friend_clear()
201 frnd->subnet = NULL; in friend_clear()
202 frnd->established = 0U; in friend_clear()
203 frnd->pending_buf = 0U; in friend_clear()
204 frnd->fsn = 0U; in friend_clear()
205 frnd->queue_size = 0U; in friend_clear()
206 frnd->pending_req = 0U; in friend_clear()
207 (void)memset(frnd->sub_list, 0, sizeof(frnd->sub_list)); in friend_clear()
243 frnd->subnet->net_idx == net_idx) { in bt_mesh_friend_sec_update()
249 int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) in bt_mesh_friend_clear() argument
251 struct bt_mesh_ctl_friend_clear *msg = (void *)buf->data; in bt_mesh_friend_clear()
255 .sub = rx->sub, in bt_mesh_friend_clear()
256 .ctx = &rx->ctx, in bt_mesh_friend_clear()
262 if (buf->len < sizeof(*msg)) { in bt_mesh_friend_clear()
264 return -EBADMSG; in bt_mesh_friend_clear()
267 lpn_addr = sys_be16_to_cpu(msg->lpn_addr); in bt_mesh_friend_clear()
268 lpn_counter = sys_be16_to_cpu(msg->lpn_counter); in bt_mesh_friend_clear()
270 LOG_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter); in bt_mesh_friend_clear()
272 frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false); in bt_mesh_friend_clear()
274 LOG_WRN("No matching LPN addr 0x%04x", lpn_addr); in bt_mesh_friend_clear()
284 if (lpn_counter - frnd->lpn_counter > 255) { in bt_mesh_friend_clear()
285 LOG_WRN("LPN Counter out of range (old %u new %u)", frnd->lpn_counter, lpn_counter); in bt_mesh_friend_clear()
289 tx.ctx->send_ttl = BT_MESH_TTL_MAX; in bt_mesh_friend_clear()
291 cfm.lpn_addr = msg->lpn_addr; in bt_mesh_friend_clear()
292 cfm.lpn_counter = msg->lpn_counter; in bt_mesh_friend_clear()
302 static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr) in friend_sub_add() argument
306 for (int i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { in friend_sub_add()
307 if (frnd->sub_list[i] == addr) { in friend_sub_add()
311 if (frnd->sub_list[i] == BT_MESH_ADDR_UNASSIGNED) { in friend_sub_add()
317 frnd->sub_list[empty_idx] = addr; in friend_sub_add()
318 LOG_DBG("%04x added %04x to subscription list", frnd->lpn, addr); in friend_sub_add()
324 static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr) in friend_sub_rem() argument
328 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { in friend_sub_rem()
329 if (frnd->sub_list[i] == addr) { in friend_sub_rem()
330 LOG_DBG("%04x removed %04x from subscription list", frnd->lpn, addr); in friend_sub_rem()
331 frnd->sub_list[i] = BT_MESH_ADDR_UNASSIGNED; in friend_sub_rem()
351 net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */ in create_friend_pdu()
353 if (info->ctl) { in create_friend_pdu()
354 net_buf_add_u8(buf, info->ttl | 0x80); in create_friend_pdu()
356 net_buf_add_u8(buf, info->ttl); in create_friend_pdu()
359 net_buf_add_mem(buf, info->seq, sizeof(info->seq)); in create_friend_pdu()
361 net_buf_add_be16(buf, info->src); in create_friend_pdu()
362 net_buf_add_be16(buf, info->dst); in create_friend_pdu()
364 net_buf_add_mem(buf, sdu->data, sdu->len); in create_friend_pdu()
380 uint16_t app_idx = FRIEND_ADV(buf)->app_idx; in unseg_app_sdu_unpack()
381 uint16_t uuidx = FRIEND_ADV(buf)->uuidx; in unseg_app_sdu_unpack()
385 .net_idx = frnd->subnet->net_idx, in unseg_app_sdu_unpack()
390 meta->subnet = frnd->subnet; in unseg_app_sdu_unpack()
391 bt_mesh_net_header_parse(&buf->b, &net); in unseg_app_sdu_unpack()
392 err = bt_mesh_keys_resolve(&net.ctx, &net.sub, &meta->key, &meta->aid); in unseg_app_sdu_unpack()
397 meta->crypto.src = net.ctx.addr; in unseg_app_sdu_unpack()
398 meta->crypto.dst = net.ctx.recv_dst; in unseg_app_sdu_unpack()
399 meta->crypto.iv_index = BT_MESH_NET_IVI_TX; in unseg_app_sdu_unpack()
400 meta->crypto.dev_key = BT_MESH_IS_DEV_KEY(app_idx); in unseg_app_sdu_unpack()
401 meta->crypto.seq_num = net.seq; in unseg_app_sdu_unpack()
402 meta->crypto.aszmic = 0; in unseg_app_sdu_unpack()
404 if (BT_MESH_ADDR_IS_VIRTUAL(meta->crypto.dst)) { in unseg_app_sdu_unpack()
405 meta->crypto.ad = bt_mesh_va_get_uuid_by_idx(uuidx); in unseg_app_sdu_unpack()
407 meta->crypto.ad = NULL; in unseg_app_sdu_unpack()
423 net_buf_simple_clone(&buf->b, &in); in unseg_app_sdu_decrypt()
426 in.len -= BT_MESH_MIC_SHORT; in unseg_app_sdu_decrypt()
432 return bt_mesh_app_decrypt(meta->key, &meta->crypto, &in, &out); in unseg_app_sdu_decrypt()
441 net_buf_simple_clone(&buf->b, &sdu); in unseg_app_sdu_encrypt()
444 sdu.len -= BT_MESH_MIC_SHORT; in unseg_app_sdu_encrypt()
446 return bt_mesh_app_encrypt(meta->key, &meta->crypto, &sdu); in unseg_app_sdu_encrypt()
455 if (FRIEND_ADV(buf)->app_idx == BT_MESH_KEY_UNUSED) { in unseg_app_sdu_prepare()
471 LOG_DBG("Re-encrypting friend pdu (SeqNum %06x -> %06x)", meta.crypto.seq_num, bt_mesh.seq); in unseg_app_sdu_prepare()
483 LOG_WRN("Re-encryption failed! %d", err); in unseg_app_sdu_prepare()
498 cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)] in encrypt_friend_pdu()
501 cred = &frnd->cred[SUBNET_KEY_TX_IDX(frnd->subnet)]; in encrypt_friend_pdu()
504 src = sys_get_be16(&buf->data[5]); in encrypt_friend_pdu()
509 if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) { in encrypt_friend_pdu()
517 sys_put_be24(seq, &buf->data[2]); in encrypt_friend_pdu()
520 FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED; in encrypt_friend_pdu()
522 uint8_t ivi = (buf->data[0] >> 7); in encrypt_friend_pdu()
523 iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi)); in encrypt_friend_pdu()
526 buf->data[0] = (cred->nid | (iv_index & 1) << 7); in encrypt_friend_pdu()
528 if (bt_mesh_net_encrypt(&cred->enc, &buf->b, iv_index, BT_MESH_NONCE_NETWORK)) { in encrypt_friend_pdu()
530 return -EINVAL; in encrypt_friend_pdu()
533 if (bt_mesh_net_obfuscate(buf->data, iv_index, &cred->privacy)) { in encrypt_friend_pdu()
535 return -EINVAL; in encrypt_friend_pdu()
547 LOG_DBG("LPN 0x%04x", frnd->lpn); in encode_friend_ctl()
552 info.dst = frnd->lpn; in encode_friend_ctl()
571 LOG_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md); in encode_update()
576 upd->flags = bt_mesh_net_flags(frnd->subnet); in encode_update()
577 upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index); in encode_update()
578 upd->md = md; in encode_update()
589 LOG_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact); in enqueue_sub_cfm()
594 cfm->xact = xact; in enqueue_sub_cfm()
606 if (frnd->last) { in enqueue_sub_cfm()
608 net_buf_unref(frnd->last); in enqueue_sub_cfm()
611 frnd->last = buf; in enqueue_sub_cfm()
612 frnd->send_last = 1U; in enqueue_sub_cfm()
619 frnd->pending_req = 1U; in friend_recv_delay()
620 k_work_reschedule(&frnd->timer, K_MSEC(delay)); in friend_recv_delay()
624 int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, in bt_mesh_friend_sub_add() argument
630 if (buf->len < BT_MESH_FRIEND_SUB_MIN_LEN) { in bt_mesh_friend_sub_add()
632 return -EBADMSG; in bt_mesh_friend_sub_add()
635 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true); in bt_mesh_friend_sub_add()
637 LOG_WRN("No matching LPN addr 0x%04x", rx->ctx.addr); in bt_mesh_friend_sub_add()
641 if (frnd->pending_buf) { in bt_mesh_friend_sub_add()
650 while (buf->len >= 2U) { in bt_mesh_friend_sub_add()
659 int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, in bt_mesh_friend_sub_rem() argument
665 if (buf->len < BT_MESH_FRIEND_SUB_MIN_LEN) { in bt_mesh_friend_sub_rem()
667 return -EBADMSG; in bt_mesh_friend_sub_rem()
670 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true); in bt_mesh_friend_sub_rem()
672 LOG_WRN("No matching LPN addr 0x%04x", rx->ctx.addr); in bt_mesh_friend_sub_rem()
676 if (frnd->pending_buf) { in bt_mesh_friend_sub_rem()
685 while (buf->len >= 2U) { in bt_mesh_friend_sub_rem()
696 net_buf_slist_put(&frnd->queue, buf); in enqueue_buf()
697 frnd->queue_size++; in enqueue_buf()
713 int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) in bt_mesh_friend_poll() argument
715 struct bt_mesh_ctl_friend_poll *msg = (void *)buf->data; in bt_mesh_friend_poll()
718 if (buf->len < sizeof(*msg)) { in bt_mesh_friend_poll()
720 return -EBADMSG; in bt_mesh_friend_poll()
723 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); in bt_mesh_friend_poll()
725 LOG_WRN("No matching LPN addr 0x%04x", rx->ctx.addr); in bt_mesh_friend_poll()
729 if (msg->fsn & ~1) { in bt_mesh_friend_poll()
730 LOG_WRN("Prohibited (non-zero) padding bits"); in bt_mesh_friend_poll()
731 return -EBADMSG; in bt_mesh_friend_poll()
734 if (frnd->pending_buf) { in bt_mesh_friend_poll()
739 LOG_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn); in bt_mesh_friend_poll()
743 if (msg->fsn == frnd->fsn && frnd->last) { in bt_mesh_friend_poll()
744 LOG_DBG("Re-sending last PDU"); in bt_mesh_friend_poll()
745 frnd->send_last = 1U; in bt_mesh_friend_poll()
747 if (frnd->last) { in bt_mesh_friend_poll()
748 net_buf_unref(frnd->last); in bt_mesh_friend_poll()
749 frnd->last = NULL; in bt_mesh_friend_poll()
752 frnd->fsn = msg->fsn; in bt_mesh_friend_poll()
754 if (sys_slist_is_empty(&frnd->queue)) { in bt_mesh_friend_poll()
761 if (cb->polled) { in bt_mesh_friend_poll()
762 cb->polled(frnd->subnet->net_idx, frnd->lpn); in bt_mesh_friend_poll()
766 if (!frnd->established) { in bt_mesh_friend_poll()
767 LOG_DBG("Friendship established with 0x%04x", frnd->lpn); in bt_mesh_friend_poll()
768 frnd->established = 1U; in bt_mesh_friend_poll()
771 if (cb->established) { in bt_mesh_friend_poll()
772 cb->established(frnd->subnet->net_idx, frnd->lpn, frnd->recv_delay, in bt_mesh_friend_poll()
773 frnd->poll_to); in bt_mesh_friend_poll()
788 if (frnd->clear.frnd == prev_friend) { in find_clear()
800 k_work_reschedule(&frnd->clear.timer, in friend_clear_sent()
801 K_SECONDS(frnd->clear.repeat_sec)); in friend_clear_sent()
802 frnd->clear.repeat_sec *= 2U; in friend_clear_sent()
812 .net_idx = frnd->subnet->net_idx, in send_friend_clear()
814 .addr = frnd->clear.frnd, in send_friend_clear()
818 .sub = frnd->subnet, in send_friend_clear()
824 .lpn_addr = sys_cpu_to_be16(frnd->lpn), in send_friend_clear()
825 .lpn_counter = sys_cpu_to_be16(frnd->lpn_counter), in send_friend_clear()
841 if (frnd->clear.frnd == BT_MESH_ADDR_UNASSIGNED) { in clear_timeout()
846 LOG_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); in clear_timeout()
848 duration = k_uptime_get_32() - frnd->clear.start; in clear_timeout()
849 if (duration > 2 * frnd->poll_to) { in clear_timeout()
851 frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED; in clear_timeout()
860 LOG_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); in clear_procedure_start()
862 frnd->clear.start = k_uptime_get_32(); in clear_procedure_start()
863 frnd->clear.repeat_sec = 1U; in clear_procedure_start()
868 int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, in bt_mesh_friend_clear_cfm() argument
871 struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data; in bt_mesh_friend_clear_cfm()
877 if (buf->len < sizeof(*msg)) { in bt_mesh_friend_clear_cfm()
879 return -EBADMSG; in bt_mesh_friend_clear_cfm()
882 frnd = find_clear(rx->ctx.addr); in bt_mesh_friend_clear_cfm()
884 LOG_WRN("No pending clear procedure for 0x%02x", rx->ctx.addr); in bt_mesh_friend_clear_cfm()
888 lpn_addr = sys_be16_to_cpu(msg->lpn_addr); in bt_mesh_friend_clear_cfm()
889 if (lpn_addr != frnd->lpn) { in bt_mesh_friend_clear_cfm()
890 LOG_WRN("LPN address mismatch (0x%04x != 0x%04x)", lpn_addr, frnd->lpn); in bt_mesh_friend_clear_cfm()
894 lpn_counter = sys_be16_to_cpu(msg->lpn_counter); in bt_mesh_friend_clear_cfm()
895 if (lpn_counter != frnd->lpn_counter) { in bt_mesh_friend_clear_cfm()
896 LOG_WRN("LPN counter mismatch (0x%04x != 0x%04x)", lpn_counter, frnd->lpn_counter); in bt_mesh_friend_clear_cfm()
901 (void)k_work_cancel_delayable(&frnd->clear.timer); in bt_mesh_friend_clear_cfm()
902 frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED; in bt_mesh_friend_clear_cfm()
919 off->recv_win = CONFIG_BT_MESH_FRIEND_RECV_WIN, in enqueue_offer()
920 off->queue_size = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE, in enqueue_offer()
921 off->sub_list_size = ARRAY_SIZE(frnd->sub_list), in enqueue_offer()
922 off->rssi = rssi, in enqueue_offer()
927 off->frnd_counter = sys_cpu_to_be16(frnd->counter); in enqueue_offer()
939 if (frnd->last) { in enqueue_offer()
940 net_buf_unref(frnd->last); in enqueue_offer()
943 frnd->last = buf; in enqueue_offer()
944 frnd->send_last = 1U; in enqueue_offer()
956 * want to avoid floating-point arithmetic. in offer_delay()
964 /* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */ in offer_delay()
966 delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi; in offer_delay()
974 int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) in bt_mesh_friend_req() argument
976 struct bt_mesh_ctl_friend_req *msg = (void *)buf->data; in bt_mesh_friend_req()
982 if (rx->net_if == BT_MESH_NET_IF_LOCAL) { in bt_mesh_friend_req()
987 if (buf->len < sizeof(*msg)) { in bt_mesh_friend_req()
989 return -EBADMSG; in bt_mesh_friend_req()
992 if (msg->recv_delay <= 0x09) { in bt_mesh_friend_req()
993 LOG_WRN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay); in bt_mesh_friend_req()
994 return -EBADMSG; in bt_mesh_friend_req()
997 poll_to = sys_get_be24(msg->poll_to); in bt_mesh_friend_req()
1001 return -EBADMSG; in bt_mesh_friend_req()
1004 if (msg->num_elem == 0x00) { in bt_mesh_friend_req()
1006 return -EBADMSG; in bt_mesh_friend_req()
1009 if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr + msg->num_elem - 1)) { in bt_mesh_friend_req()
1011 return -EBADMSG; in bt_mesh_friend_req()
1014 if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) { in bt_mesh_friend_req()
1016 return -EBADMSG; in bt_mesh_friend_req()
1019 if (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) { in bt_mesh_friend_req()
1021 CONFIG_BT_MESH_FRIEND_QUEUE_SIZE, MIN_QUEUE_SIZE(msg->criteria)); in bt_mesh_friend_req()
1025 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); in bt_mesh_friend_req()
1027 LOG_WRN("Existing LPN re-requesting Friendship"); in bt_mesh_friend_req()
1041 return -ENOMEM; in bt_mesh_friend_req()
1045 frnd->lpn = rx->ctx.addr; in bt_mesh_friend_req()
1046 frnd->num_elem = msg->num_elem; in bt_mesh_friend_req()
1047 frnd->subnet = rx->sub; in bt_mesh_friend_req()
1048 frnd->recv_delay = msg->recv_delay - CONFIG_BT_MESH_FRIEND_ADV_LATENCY; in bt_mesh_friend_req()
1049 frnd->poll_to = poll_to * 100U; in bt_mesh_friend_req()
1050 frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter); in bt_mesh_friend_req()
1051 frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr); in bt_mesh_friend_req()
1053 err = friend_cred_create(frnd, SUBNET_KEY_TX_IDX(frnd->subnet)); in bt_mesh_friend_req()
1057 return -EIO; in bt_mesh_friend_req()
1060 LOG_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums", frnd->lpn, rx->ctx.recv_rssi, in bt_mesh_friend_req()
1061 frnd->recv_delay, frnd->poll_to); in bt_mesh_friend_req()
1063 if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && in bt_mesh_friend_req()
1064 !bt_mesh_has_addr(frnd->clear.frnd)) { in bt_mesh_friend_req()
1068 delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria); in bt_mesh_friend_req()
1069 k_work_reschedule(&frnd->timer, K_MSEC(delay)); in bt_mesh_friend_req()
1071 enqueue_offer(frnd, rx->ctx.recv_rssi); in bt_mesh_friend_req()
1078 struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue); in is_seg()
1087 net_buf_simple_save(&buf->b, &state); in is_seg()
1092 net_buf_simple_restore(&buf->b, &state); in is_seg()
1104 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { in get_seg()
1105 struct bt_mesh_friend_seg *seg = &frnd->seg[i]; in get_seg()
1111 if (!unassigned && !sys_slist_peek_head(&seg->queue)) { in get_seg()
1117 unassigned->seg_count = seg_count; in get_seg()
1137 uint16_t seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK); in enqueue_friend_pdu()
1141 LOG_ERR("No free friend segment RX contexts for 0x%04x", src); in enqueue_friend_pdu()
1146 net_buf_slist_put(&seg->queue, buf); in enqueue_friend_pdu()
1149 sys_slist_merge_slist(&frnd->queue, &seg->queue); in enqueue_friend_pdu()
1151 frnd->queue_size += seg->seg_count; in enqueue_friend_pdu()
1152 seg->seg_count = 0U; in enqueue_friend_pdu()
1154 FRIEND_ADV(buf)->seg = true; in enqueue_friend_pdu()
1164 if (!frnd->pending_buf) { in buf_send_start()
1169 frnd->pending_buf = 0U; in buf_send_start()
1171 /* Friend Offer doesn't follow the re-sending semantics */ in buf_send_start()
1172 if (!frnd->established && frnd->last) { in buf_send_start()
1173 net_buf_unref(frnd->last); in buf_send_start()
1174 frnd->last = NULL; in buf_send_start()
1184 if (frnd->pending_req || frnd->pending_buf) { in buf_send_end()
1189 if (frnd->established) { in buf_send_end()
1191 k_work_reschedule(&frnd->timer, K_MSEC(frnd->poll_to)); in buf_send_end()
1192 LOG_DBG("Waiting %u ms for next poll", frnd->poll_to); in buf_send_end()
1195 k_work_reschedule(&frnd->timer, K_SECONDS(1)); in buf_send_end()
1205 if (buf->len != 16) { in update_overwrite()
1209 net_buf_simple_save(&buf->b, &state); in update_overwrite()
1225 LOG_DBG("Update Previous Friend Update MD 0x%02x -> 0x%02x", upd->md, md); in update_overwrite()
1226 upd->md = md; in update_overwrite()
1229 net_buf_simple_restore(&buf->b, &state); in update_overwrite()
1248 __ASSERT_NO_MSG(frnd->pending_buf == 0U); in friend_timeout()
1250 LOG_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn, frnd->send_last, frnd->last); in friend_timeout()
1252 if (frnd->send_last && frnd->last) { in friend_timeout()
1253 LOG_DBG("Sending frnd->last %p", frnd->last); in friend_timeout()
1254 frnd->send_last = 0U; in friend_timeout()
1258 if (frnd->established && !frnd->pending_req) { in friend_timeout()
1259 LOG_WRN("Friendship lost with 0x%04x", frnd->lpn); in friend_timeout()
1264 frnd->last = (void *)net_buf_slist_get(&frnd->queue); in friend_timeout()
1265 if (!frnd->last) { in friend_timeout()
1266 LOG_WRN("Friendship not established with 0x%04x", frnd->lpn); in friend_timeout()
1271 md = (uint8_t)(sys_slist_peek_head(&frnd->queue) != NULL); in friend_timeout()
1273 update_overwrite(frnd->last, md); in friend_timeout()
1275 if (encrypt_friend_pdu(frnd, frnd->last, false)) { in friend_timeout()
1279 LOG_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", frnd->last, frnd->lpn); in friend_timeout()
1280 frnd->queue_size--; in friend_timeout()
1290 net_buf_simple_add_mem(&adv->b, frnd->last->data, frnd->last->len); in friend_timeout()
1292 frnd->pending_req = 0U; in friend_timeout()
1293 frnd->pending_buf = 1U; in friend_timeout()
1309 if (frnd->subnet != sub) { in subnet_evt()
1315 LOG_DBG("Cleared network for 0x%04x", frnd->lpn); in subnet_evt()
1319 LOG_DBG("Generating new keys for 0x%04x", frnd->lpn); in subnet_evt()
1322 LOG_ERR("Failed updating friend cred for 0x%04x", frnd->lpn); in subnet_evt()
1330 LOG_DBG("Revoking old keys for 0x%04x", frnd->lpn); in subnet_evt()
1331 bt_mesh_friend_cred_destroy(&frnd->cred[0]); in subnet_evt()
1332 memcpy(&frnd->cred[0], &frnd->cred[1], in subnet_evt()
1333 sizeof(frnd->cred[0])); in subnet_evt()
1334 memset(&frnd->cred[1], 0, sizeof(frnd->cred[1])); in subnet_evt()
1355 sys_slist_init(&frnd->queue); in bt_mesh_friend_init()
1357 k_work_init_delayable(&frnd->timer, friend_timeout); in bt_mesh_friend_init()
1358 k_work_init_delayable(&frnd->clear.timer, clear_timeout); in bt_mesh_friend_init()
1360 for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { in bt_mesh_friend_init()
1361 sys_slist_init(&frnd->seg[j].queue); in bt_mesh_friend_init()
1373 if (buf->len != 16) { in is_segack()
1377 net_buf_simple_save(&buf->b, &state); in is_segack()
1400 net_buf_simple_restore(&buf->b, &state); in is_segack()
1411 for (cur = sys_slist_peek_head(&frnd->queue); in friend_purge_old_ack()
1418 sys_slist_remove(&frnd->queue, prev, cur); in friend_purge_old_ack()
1419 frnd->queue_size--; in friend_purge_old_ack()
1428 struct bt_mesh_net_rx *rx, in friend_lpn_enqueue_rx() argument
1437 * this rx function. These packets have already been added to the in friend_lpn_enqueue_rx()
1440 if (bt_mesh_has_addr(rx->ctx.addr)) { in friend_lpn_enqueue_rx()
1444 LOG_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size); in friend_lpn_enqueue_rx()
1447 friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr); in friend_lpn_enqueue_rx()
1450 info.src = rx->ctx.addr; in friend_lpn_enqueue_rx()
1451 info.dst = rx->ctx.recv_dst; in friend_lpn_enqueue_rx()
1453 if (rx->net_if == BT_MESH_NET_IF_LOCAL) { in friend_lpn_enqueue_rx()
1454 info.ttl = rx->ctx.recv_ttl; in friend_lpn_enqueue_rx()
1456 info.ttl = rx->ctx.recv_ttl - 1U; in friend_lpn_enqueue_rx()
1459 info.ctl = rx->ctl; in friend_lpn_enqueue_rx()
1461 sys_put_be24(rx->seq, info.seq); in friend_lpn_enqueue_rx()
1463 info.iv_index = BT_MESH_NET_IVI_RX(rx); in friend_lpn_enqueue_rx()
1473 LOG_DBG("Queued message for LPN 0x%04x, queue_size %u", frnd->lpn, frnd->queue_size); in friend_lpn_enqueue_rx()
1485 LOG_DBG("LPN 0x%04x", frnd->lpn); in friend_lpn_enqueue_tx()
1488 friend_purge_old_ack(frnd, seq_auth, tx->src); in friend_lpn_enqueue_tx()
1491 info.src = tx->src; in friend_lpn_enqueue_tx()
1492 info.dst = tx->ctx->addr; in friend_lpn_enqueue_tx()
1494 info.ttl = tx->ctx->send_ttl; in friend_lpn_enqueue_tx()
1495 info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED); in friend_lpn_enqueue_tx()
1512 FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx; in friend_lpn_enqueue_tx()
1515 if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) { in friend_lpn_enqueue_tx()
1519 err = bt_mesh_va_get_idx_by_uuid(tx->ctx->uuid, &uuidx); in friend_lpn_enqueue_tx()
1525 FRIEND_ADV(buf)->uuidx = uuidx; in friend_lpn_enqueue_tx()
1531 LOG_DBG("Queued message for LPN 0x%04x, dst: %04x, uuid: %p", frnd->lpn, tx->ctx->addr, in friend_lpn_enqueue_tx()
1532 tx->ctx->uuid); in friend_lpn_enqueue_tx()
1536 uint16_t addr) in friend_lpn_matches() argument
1540 if (!frnd->established) { in friend_lpn_matches()
1544 if (net_idx != frnd->subnet->net_idx) { in friend_lpn_matches()
1548 if (BT_MESH_ADDR_IS_UNICAST(addr)) { in friend_lpn_matches()
1549 return is_lpn_unicast(frnd, addr); in friend_lpn_matches()
1552 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { in friend_lpn_matches()
1553 if (frnd->sub_list[i] == addr) { in friend_lpn_matches()
1561 bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr) in bt_mesh_friend_match() argument
1568 if (friend_lpn_matches(frnd, net_idx, addr)) { in bt_mesh_friend_match()
1569 LOG_DBG("LPN 0x%04x matched address 0x%04x", frnd->lpn, addr); in bt_mesh_friend_match()
1574 LOG_DBG("No matching LPN for address 0x%04x", addr); in bt_mesh_friend_match()
1579 static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr, in friend_queue_has_space() argument
1589 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { in friend_queue_has_space()
1590 struct bt_mesh_friend_seg *seg = &frnd->seg[i]; in friend_queue_has_space()
1592 if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) { in friend_queue_has_space()
1599 total += seg->seg_count; in friend_queue_has_space()
1607 return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count; in friend_queue_has_space()
1648 struct bt_mesh_net_rx rx; in friend_queue_check_dup() local
1651 for (cur = sys_slist_peek_head(&frnd->queue); cur != NULL; in friend_queue_check_dup()
1655 bt_mesh_net_header_parse(&buf->b, &rx); in friend_queue_check_dup()
1657 if ((src == rx.ctx.addr) && (seq == rx.seq)) { in friend_queue_check_dup()
1665 static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr, in friend_queue_prepare_space() argument
1671 if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) { in friend_queue_prepare_space()
1675 avail_space = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - frnd->queue_size; in friend_queue_prepare_space()
1679 struct net_buf *buf = (void *)net_buf_slist_get(&frnd->queue); in friend_queue_prepare_space()
1686 frnd->queue_size--; in friend_queue_prepare_space()
1689 pending_segments = FRIEND_ADV(buf)->seg; in friend_queue_prepare_space()
1697 void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, in bt_mesh_friend_enqueue_rx() argument
1704 if (!rx->friend_match || in bt_mesh_friend_enqueue_rx()
1705 (rx->ctx.recv_ttl <= 1U && rx->net_if != BT_MESH_NET_IF_LOCAL) || in bt_mesh_friend_enqueue_rx()
1710 LOG_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.recv_ttl, in bt_mesh_friend_enqueue_rx()
1711 rx->sub->net_idx, rx->ctx.addr, rx->ctx.recv_dst); in bt_mesh_friend_enqueue_rx()
1716 if (!friend_lpn_matches(frnd, rx->sub->net_idx, in bt_mesh_friend_enqueue_rx()
1717 rx->ctx.recv_dst)) { in bt_mesh_friend_enqueue_rx()
1721 if (friend_lpn_matches(frnd, rx->sub->net_idx, in bt_mesh_friend_enqueue_rx()
1722 rx->ctx.addr)) { in bt_mesh_friend_enqueue_rx()
1726 if (friend_queue_check_dup(frnd, rx->seq, rx->ctx.addr)) { in bt_mesh_friend_enqueue_rx()
1730 if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth, in bt_mesh_friend_enqueue_rx()
1735 friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count, in bt_mesh_friend_enqueue_rx()
1748 if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) || in bt_mesh_friend_enqueue_tx()
1753 LOG_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx, tx->ctx->addr, tx->src); in bt_mesh_friend_enqueue_tx()
1758 if (!friend_lpn_matches(frnd, tx->sub->net_idx, in bt_mesh_friend_enqueue_tx()
1759 tx->ctx->addr)) { in bt_mesh_friend_enqueue_tx()
1763 if (!friend_queue_prepare_space(frnd, tx->src, seq_auth, in bt_mesh_friend_enqueue_tx()
1782 return -ENOENT; in bt_mesh_friend_terminate()
1801 if (!friend_lpn_matches(frnd, sub->net_idx, dst)) { in bt_mesh_friend_clear_incomplete()
1805 for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { in bt_mesh_friend_clear_incomplete()
1806 struct bt_mesh_friend_seg *seg = &frnd->seg[j]; in bt_mesh_friend_clear_incomplete()
1814 purge_buffers(&seg->queue); in bt_mesh_friend_clear_incomplete()
1815 seg->seg_count = 0U; in bt_mesh_friend_clear_incomplete()