Lines Matching +full:rx +full:- +full:addr +full:- +full:mode
4 * SPDX-License-Identifier: Apache-2.0
54 #define BLOCK_COMPLETE(seg_n) (uint32_t)(((uint64_t)1 << (seg_n + 1)) - 1)
126 tx->xmit, BUF_TIMEOUT); in send_unseg()
129 return -ENOBUFS; in send_unseg()
132 net_buf_simple_reserve(&adv->b, BT_MESH_NET_HDR_LEN); in send_unseg()
135 net_buf_simple_add_u8(&adv->b, TRANS_CTL_HDR(*ctl_op, 0)); in send_unseg()
136 } else if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) { in send_unseg()
137 net_buf_simple_add_u8(&adv->b, UNSEG_HDR(0, 0)); in send_unseg()
139 net_buf_simple_add_u8(&adv->b, UNSEG_HDR(1, tx->aid)); in send_unseg()
142 net_buf_simple_add_mem(&adv->b, sdu->data, sdu->len); in send_unseg()
145 if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, in send_unseg()
146 tx->src, tx->ctx->addr, in send_unseg()
148 if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { in send_unseg()
151 return -ENOBUFS; in send_unseg()
159 NULL, 1, &adv->b) && in send_unseg()
160 BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { in send_unseg()
198 k_mem_slab_free(&segs, (void *)tx->seg[seg_idx]); in seg_tx_done()
199 tx->seg[seg_idx] = NULL; in seg_tx_done()
200 tx->nack_count--; in seg_tx_done()
205 return (tx->src == src) && (tx->dst == dst); in seg_tx_blocks()
218 (!blocked || seg_tx[i].seq_auth < blocked->seq_auth)) { in seg_tx_unblock_check()
224 LOG_DBG("Unblocked 0x%04x", (uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK)); in seg_tx_unblock_check()
225 blocked->blocked = false; in seg_tx_unblock_check()
226 k_work_reschedule(&blocked->retransmit, K_NO_WAIT); in seg_tx_unblock_check()
235 (void)k_work_cancel_delayable(&tx->retransmit); in seg_tx_reset()
237 tx->cb = NULL; in seg_tx_reset()
238 tx->cb_data = NULL; in seg_tx_reset()
239 tx->seq_auth = 0U; in seg_tx_reset()
240 tx->sub = NULL; in seg_tx_reset()
241 tx->src = BT_MESH_ADDR_UNASSIGNED; in seg_tx_reset()
242 tx->dst = BT_MESH_ADDR_UNASSIGNED; in seg_tx_reset()
243 tx->ack_src = BT_MESH_ADDR_UNASSIGNED; in seg_tx_reset()
244 tx->blocked = false; in seg_tx_reset()
246 for (i = 0; i <= tx->seg_n && tx->nack_count; i++) { in seg_tx_reset()
247 if (!tx->seg[i]) { in seg_tx_reset()
254 tx->nack_count = 0; in seg_tx_reset()
255 tx->seg_send_started = 0; in seg_tx_reset()
256 tx->ack_received = 0; in seg_tx_reset()
260 /* bt_mesh_net_iv_update() will re-enable the flag if this in seg_tx_reset()
269 const struct bt_mesh_send_cb *cb = tx->cb; in seg_tx_complete()
270 void *cb_data = tx->cb_data; in seg_tx_complete()
276 if (cb && cb->end) { in seg_tx_complete()
277 cb->end(err, cb_data); in seg_tx_complete()
285 if (!tx->nack_count) { in schedule_transmit_continue()
292 timeout = BT_MESH_SAR_TX_SEG_INT_MS - delta; in schedule_transmit_continue()
299 k_work_reschedule(&tx->retransmit, in schedule_transmit_continue()
300 (tx->seg_o <= tx->seg_n) ? in schedule_transmit_continue()
309 if (!tx->started && tx->cb && tx->cb->start) { in seg_send_start()
310 tx->cb->start(duration, err, tx->cb_data); in seg_send_start()
311 tx->started = 1U; in seg_send_start()
314 tx->seg_send_started = 1U; in seg_send_start()
315 tx->adv_start_timestamp = k_uptime_get(); in seg_send_start()
329 uint32_t delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp); in seg_sent()
331 if (!tx->seg_send_started) { in seg_sent()
346 uint16_t seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK; in seg_tx_buf_build()
347 uint8_t len = MIN(seg_len(tx->ctl), tx->len - (seg_len(tx->ctl) * seg_o)); in seg_tx_buf_build()
349 net_buf_simple_add_u8(buf, tx->hdr); in seg_tx_buf_build()
350 net_buf_simple_add_u8(buf, (tx->aszmic << 7) | seq_zero >> 6); in seg_tx_buf_build()
352 net_buf_simple_add_u8(buf, ((seg_o & 0x07) << 5) | tx->seg_n); in seg_tx_buf_build()
353 net_buf_simple_add_mem(buf, tx->seg[seg_o], len); in seg_tx_buf_build()
358 if (!tx->nack_count) { in seg_tx_send_unacked()
365 .net_idx = tx->sub->net_idx, in seg_tx_send_unacked()
367 .app_idx = (tx->ctl ? BT_MESH_KEY_UNUSED : 0), in seg_tx_send_unacked()
368 .addr = tx->dst, in seg_tx_send_unacked()
370 .send_ttl = tx->ttl, in seg_tx_send_unacked()
373 .sub = tx->sub, in seg_tx_send_unacked()
375 .src = tx->src, in seg_tx_send_unacked()
376 .xmit = tx->xmit, in seg_tx_send_unacked()
377 .friend_cred = tx->friend_cred, in seg_tx_send_unacked()
378 .aid = tx->hdr & AID_MASK, in seg_tx_send_unacked()
381 if (BT_MESH_ADDR_IS_UNICAST(tx->dst) && in seg_tx_send_unacked()
382 !tx->attempts_left_without_progress) { in seg_tx_send_unacked()
384 seg_tx_complete(tx, -ETIMEDOUT); in seg_tx_send_unacked()
388 if (!tx->attempts_left) { in seg_tx_send_unacked()
389 if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) { in seg_tx_send_unacked()
391 seg_tx_complete(tx, -ETIMEDOUT); in seg_tx_send_unacked()
403 (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts_left); in seg_tx_send_unacked()
405 while (tx->seg_o <= tx->seg_n) { in seg_tx_send_unacked()
409 if (!tx->seg[tx->seg_o]) { in seg_tx_send_unacked()
411 tx->seg_o++; in seg_tx_send_unacked()
416 tx->xmit, BUF_TIMEOUT); in seg_tx_send_unacked()
422 net_buf_simple_reserve(&seg->b, BT_MESH_NET_HDR_LEN); in seg_tx_send_unacked()
423 seg_tx_buf_build(tx, tx->seg_o, &seg->b); in seg_tx_send_unacked()
425 LOG_DBG("Sending %u/%u", tx->seg_o, tx->seg_n); in seg_tx_send_unacked()
434 tx->seg_o++; in seg_tx_send_unacked()
436 tx->ack_received = 0U; in seg_tx_send_unacked()
446 tx->seg_o = 0U; in seg_tx_send_unacked()
447 tx->attempts_left--; in seg_tx_send_unacked()
448 if (BT_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->ack_received) { in seg_tx_send_unacked()
449 tx->attempts_left_without_progress--; in seg_tx_send_unacked()
454 bt_mesh_lpn_established() && !bt_mesh_has_addr(ctx.addr)) { in seg_tx_send_unacked()
458 delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp); in seg_tx_send_unacked()
459 if (tx->ack_received) { in seg_tx_send_unacked()
464 tx->ack_received = 0U; in seg_tx_send_unacked()
466 timeout = BT_MESH_SAR_TX_RETRANS_TIMEOUT_MS(tx->dst, tx->ttl); in seg_tx_send_unacked()
470 timeout -= delta_ms; in seg_tx_send_unacked()
474 k_work_reschedule(&tx->retransmit, K_MSEC(timeout)); in seg_tx_send_unacked()
494 LOG_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u", net_tx->src, in send_seg()
495 net_tx->ctx->addr, net_tx->ctx->app_idx, net_tx->aszmic, sdu->len); in send_seg()
499 blocked |= seg_tx_blocks(&seg_tx[i], net_tx->src, in send_seg()
500 net_tx->ctx->addr); in send_seg()
507 LOG_ERR("No multi-segment message contexts available"); in send_seg()
508 return -EBUSY; in send_seg()
512 tx->hdr = TRANS_CTL_HDR(*ctl_op, 1); in send_seg()
513 } else if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) { in send_seg()
514 tx->hdr = SEG_HDR(0, 0); in send_seg()
516 tx->hdr = SEG_HDR(1, net_tx->aid); in send_seg()
519 tx->src = net_tx->src; in send_seg()
520 tx->dst = net_tx->ctx->addr; in send_seg()
521 tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op); in send_seg()
522 tx->seg_o = 0; in send_seg()
523 tx->len = sdu->len; in send_seg()
524 tx->nack_count = tx->seg_n + 1; in send_seg()
525 tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq); in send_seg()
526 tx->sub = net_tx->sub; in send_seg()
527 tx->cb = cb; in send_seg()
528 tx->cb_data = cb_data; in send_seg()
529 tx->attempts_left = BT_MESH_SAR_TX_RETRANS_COUNT(tx->dst); in send_seg()
530 tx->attempts_left_without_progress = BT_MESH_SAR_TX_RETRANS_NO_PROGRESS; in send_seg()
531 tx->xmit = net_tx->xmit; in send_seg()
532 tx->aszmic = net_tx->aszmic; in send_seg()
533 tx->friend_cred = net_tx->friend_cred; in send_seg()
534 tx->blocked = blocked; in send_seg()
535 tx->started = 0; in send_seg()
536 tx->seg_send_started = 0; in send_seg()
537 tx->ctl = !!ctl_op; in send_seg()
538 tx->ttl = net_tx->ctx->send_ttl; in send_seg()
540 LOG_DBG("SeqZero 0x%04x (segs: %u)", (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), in send_seg()
541 tx->nack_count); in send_seg()
544 !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src, in send_seg()
545 tx->dst, &tx->seq_auth, in send_seg()
546 tx->seg_n + 1) && in send_seg()
547 BT_MESH_ADDR_IS_UNICAST(tx->dst)) { in send_seg()
548 LOG_ERR("Not enough space in Friend Queue for %u segments", tx->seg_n + 1); in send_seg()
550 return -ENOBUFS; in send_seg()
553 for (seg_o = 0U; sdu->len; seg_o++) { in send_seg()
562 return -ENOBUFS; in send_seg()
565 len = MIN(sdu->len, seg_len(!!ctl_op)); in send_seg()
570 tx->seg[seg_o] = buf; in send_seg()
578 if (seg_o == tx->seg_n) { in send_seg()
585 net_tx, type, ctl_op ? NULL : &tx->seq_auth, in send_seg()
586 tx->seg_n + 1, &seg) && in send_seg()
587 BT_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { in send_seg()
592 tx->seg[seg_o] = NULL; in send_seg()
600 if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !tx->seg[0]) { in send_seg()
630 .dev_key = BT_MESH_IS_DEV_KEY(tx->ctx->app_idx), in trans_encrypt()
631 .aszmic = tx->aszmic, in trans_encrypt()
632 .src = tx->src, in trans_encrypt()
633 .dst = tx->ctx->addr, in trans_encrypt()
638 if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) { in trans_encrypt()
639 crypto.ad = tx->ctx->uuid; in trans_encrypt()
652 if (msg->len < 1) { in bt_mesh_trans_send()
653 LOG_ERR("Zero-length SDU not allowed"); in bt_mesh_trans_send()
654 return -EINVAL; in bt_mesh_trans_send()
657 if (msg->len > BT_MESH_TX_SDU_MAX - BT_MESH_MIC_SHORT) { in bt_mesh_trans_send()
658 LOG_ERR("Message too big: %u", msg->len); in bt_mesh_trans_send()
659 return -EMSGSIZE; in bt_mesh_trans_send()
664 return -EINVAL; in bt_mesh_trans_send()
667 if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) { in bt_mesh_trans_send()
668 tx->ctx->send_ttl = bt_mesh_default_ttl_get(); in bt_mesh_trans_send()
669 } else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) { in bt_mesh_trans_send()
671 return -EINVAL; in bt_mesh_trans_send()
674 if (msg->len > BT_MESH_SDU_UNSEG_MAX) { in bt_mesh_trans_send()
675 tx->ctx->send_rel = true; in bt_mesh_trans_send()
678 if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED || in bt_mesh_trans_send()
679 (!BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) && in bt_mesh_trans_send()
680 BT_MESH_IS_DEV_KEY(tx->ctx->app_idx))) { in bt_mesh_trans_send()
682 return -EINVAL; in bt_mesh_trans_send()
685 err = bt_mesh_keys_resolve(tx->ctx, &tx->sub, &key, &aid); in bt_mesh_trans_send()
690 LOG_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx, tx->ctx->app_idx, in bt_mesh_trans_send()
691 tx->ctx->addr); in bt_mesh_trans_send()
692 LOG_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len)); in bt_mesh_trans_send()
694 tx->xmit = bt_mesh_net_transmit_get(); in bt_mesh_trans_send()
695 tx->aid = aid; in bt_mesh_trans_send()
697 if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) { in bt_mesh_trans_send()
698 tx->aszmic = 0U; in bt_mesh_trans_send()
700 tx->aszmic = 1U; in bt_mesh_trans_send()
708 if (tx->ctx->send_rel) { in bt_mesh_trans_send()
717 static void seg_rx_assemble(struct seg_rx *rx, struct net_buf_simple *buf, in seg_rx_assemble() argument
724 for (i = 0; i <= rx->seg_n; i++) { in seg_rx_assemble()
725 net_buf_simple_add_mem(buf, rx->seg[i], in seg_rx_assemble()
726 MIN(seg_len(rx->ctl), in seg_rx_assemble()
727 rx->len - (i * seg_len(rx->ctl)))); in seg_rx_assemble()
731 if (!rx->ctl) { in seg_rx_assemble()
732 buf->len -= APP_MIC_LEN(aszmic); in seg_rx_assemble()
743 static int sdu_try_decrypt(struct bt_mesh_net_rx *rx, const struct bt_mesh_key *key, in sdu_try_decrypt() argument
749 ctx->crypto.ad = NULL; in sdu_try_decrypt()
752 if (ctx->seg) { in sdu_try_decrypt()
753 seg_rx_assemble(ctx->seg, ctx->buf, ctx->crypto.aszmic); in sdu_try_decrypt()
756 if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) { in sdu_try_decrypt()
757 ctx->crypto.ad = bt_mesh_va_uuid_get(rx->ctx.recv_dst, ctx->crypto.ad, in sdu_try_decrypt()
760 if (!ctx->crypto.ad) { in sdu_try_decrypt()
761 return -ENOENT; in sdu_try_decrypt()
765 net_buf_simple_reset(ctx->sdu); in sdu_try_decrypt()
767 err = bt_mesh_app_decrypt(key, &ctx->crypto, ctx->buf, ctx->sdu); in sdu_try_decrypt()
768 } while (err && ctx->crypto.ad != NULL); in sdu_try_decrypt()
770 if (!err && BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) { in sdu_try_decrypt()
771 rx->ctx.uuid = ctx->crypto.ad; in sdu_try_decrypt()
777 static int sdu_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, uint8_t aszmic, in sdu_recv() argument
785 .src = rx->ctx.addr, in sdu_recv()
786 .dst = rx->ctx.recv_dst, in sdu_recv()
787 .seq_num = seg ? (seg->seq_auth & 0xffffff) : rx->seq, in sdu_recv()
788 .iv_index = BT_MESH_NET_IVI_RX(rx), in sdu_recv()
797 if (!rx->local_match) { in sdu_recv()
799 return rx->friend_match ? 0 : -ENXIO; in sdu_recv()
802 rx->ctx.app_idx = bt_mesh_app_key_find(ctx.crypto.dev_key, AID(&hdr), in sdu_recv()
803 rx, sdu_try_decrypt, &ctx); in sdu_recv()
804 if (rx->ctx.app_idx == BT_MESH_KEY_UNUSED) { in sdu_recv()
806 return -EACCES; in sdu_recv()
809 rx->ctx.uuid = ctx.crypto.ad; in sdu_recv()
811 LOG_DBG("Decrypted (AppIdx: 0x%03x)", rx->ctx.app_idx); in sdu_recv()
813 return bt_mesh_access_recv(&rx->ctx, sdu); in sdu_recv()
816 static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t addr) in seg_tx_lookup() argument
824 if ((tx->seq_auth & TRANS_SEQ_ZERO_MASK) != seq_zero) { in seg_tx_lookup()
828 if (tx->dst == addr) { in seg_tx_lookup()
837 if (obo && (tx->nack_count == tx->seg_n + 1 || tx->ack_src == addr)) { in seg_tx_lookup()
838 tx->ack_src = addr; in seg_tx_lookup()
846 static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, in trans_ack() argument
856 if (buf->len < 6) { in trans_ack()
858 return -EBADMSG; in trans_ack()
865 if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match) { in trans_ack()
866 LOG_DBG("Ack for LPN 0x%04x of this Friend", rx->ctx.recv_dst); in trans_ack()
867 /* Best effort - we don't have enough info for true SeqAuth */ in trans_ack()
868 *seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_RX(rx), seq_zero); in trans_ack()
870 } else if (!rx->local_match) { in trans_ack()
878 tx = seg_tx_lookup(seq_zero, obo, rx->ctx.addr); in trans_ack()
881 return -ENOENT; in trans_ack()
884 if (!BT_MESH_ADDR_IS_UNICAST(tx->dst)) { in trans_ack()
886 return -EINVAL; in trans_ack()
889 *seq_auth = tx->seq_auth; in trans_ack()
893 seg_tx_complete(tx, -ECANCELED); in trans_ack()
897 if (find_msb_set(ack) - 1 > tx->seg_n) { in trans_ack()
899 return -EINVAL; in trans_ack()
903 if (tx->seg[bit - 1]) { in trans_ack()
904 LOG_DBG("seg %u/%u acked", bit - 1, tx->seg_n); in trans_ack()
905 seg_tx_done(tx, bit - 1); in trans_ack()
909 ack &= ~BIT(bit - 1); in trans_ack()
913 tx->attempts_left_without_progress = in trans_ack()
917 if (tx->nack_count) { in trans_ack()
921 if (tx->seg_o == 0) { in trans_ack()
928 if ((BT_MESH_ADDR_IS_UNICAST(tx->dst) && in trans_ack()
929 !tx->attempts_left_without_progress) || in trans_ack()
930 !tx->attempts_left) { in trans_ack()
934 uint32_t delta_ms = (uint32_t)(k_uptime_get() - tx->adv_start_timestamp); in trans_ack()
942 timeout = K_MSEC(BT_MESH_SAR_TX_SEG_INT_MS - delta_ms); in trans_ack()
946 k_work_reschedule(&tx->retransmit, timeout); in trans_ack()
948 tx->ack_received = 1U; in trans_ack()
958 static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, in ctl_recv() argument
963 LOG_DBG("OpCode 0x%02x len %u", ctl_op, buf->len); in ctl_recv()
967 return trans_ack(rx, hdr, buf, seq_auth); in ctl_recv()
969 return bt_mesh_hb_recv(rx, buf); in ctl_recv()
973 if (!rx->local_match) { in ctl_recv()
980 return bt_mesh_friend_poll(rx, buf); in ctl_recv()
982 return bt_mesh_friend_req(rx, buf); in ctl_recv()
984 return bt_mesh_friend_clear(rx, buf); in ctl_recv()
986 return bt_mesh_friend_clear_cfm(rx, buf); in ctl_recv()
988 return bt_mesh_friend_sub_add(rx, buf); in ctl_recv()
990 return bt_mesh_friend_sub_rem(rx, buf); in ctl_recv()
996 return bt_mesh_lpn_friend_offer(rx, buf); in ctl_recv()
999 if (rx->ctx.addr == bt_mesh.lpn.frnd) { in ctl_recv()
1001 return bt_mesh_lpn_friend_clear_cfm(rx, buf); in ctl_recv()
1004 if (!rx->friend_cred) { in ctl_recv()
1006 return -EINVAL; in ctl_recv()
1011 return bt_mesh_lpn_friend_update(rx, buf); in ctl_recv()
1013 return bt_mesh_lpn_friend_sub_cfm(rx, buf); in ctl_recv()
1020 return -EBADMSG; in ctl_recv()
1023 static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, in trans_unseg() argument
1031 LOG_DBG("AFK %u AID 0x%02x", AKF(buf->data), AID(buf->data)); in trans_unseg()
1033 if (buf->len < 1) { in trans_unseg()
1035 return -EBADMSG; in trans_unseg()
1038 if (bt_mesh_rpl_check(rx, &rpl, false)) { in trans_unseg()
1039 LOG_WRN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", rx->ctx.addr, rx->ctx.recv_dst, in trans_unseg()
1040 rx->seq); in trans_unseg()
1041 return -EINVAL; in trans_unseg()
1046 if (rx->ctl) { in trans_unseg()
1047 err = ctl_recv(rx, hdr, buf, seq_auth); in trans_unseg()
1048 } else if (buf->len < 1 + APP_MIC_LEN(0)) { in trans_unseg()
1050 err = -EINVAL; in trans_unseg()
1053 buf->len -= APP_MIC_LEN(0); in trans_unseg()
1054 err = sdu_recv(rx, hdr, 0, buf, &sdu, NULL); in trans_unseg()
1059 bt_mesh_rpl_update(rpl, rx); in trans_unseg()
1071 if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) { in bt_mesh_ctl_send()
1072 tx->ctx->send_ttl = bt_mesh_default_ttl_get(); in bt_mesh_ctl_send()
1073 } else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) { in bt_mesh_ctl_send()
1075 return -EINVAL; in bt_mesh_ctl_send()
1081 tx->ctx->send_rel = true; in bt_mesh_ctl_send()
1084 tx->ctx->app_idx = BT_MESH_KEY_UNUSED; in bt_mesh_ctl_send()
1086 if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED || in bt_mesh_ctl_send()
1087 BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) { in bt_mesh_ctl_send()
1089 return -EINVAL; in bt_mesh_ctl_send()
1092 LOG_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src, tx->ctx->addr, in bt_mesh_ctl_send()
1093 tx->ctx->send_ttl, ctl_op); in bt_mesh_ctl_send()
1096 if (tx->ctx->send_rel) { in bt_mesh_ctl_send()
1107 .net_idx = sub->net_idx, in send_ack()
1109 .addr = dst, in send_ack()
1123 if (bt_mesh_lpn_established() && !bt_mesh_has_addr(ctx.addr)) { in send_ack()
1132 LOG_DBG("Not sending ack for non-unicast address"); in send_ack()
1143 static void seg_rx_reset(struct seg_rx *rx, bool full_reset) in seg_rx_reset() argument
1147 LOG_DBG("rx %p", rx); in seg_rx_reset()
1150 * it checks rx->in_use. in seg_rx_reset()
1152 (void)k_work_cancel_delayable(&rx->ack); in seg_rx_reset()
1153 (void)k_work_cancel_delayable(&rx->discard); in seg_rx_reset()
1155 if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo && in seg_rx_reset()
1156 rx->block != BLOCK_COMPLETE(rx->seg_n)) { in seg_rx_reset()
1158 bt_mesh_friend_clear_incomplete(rx->sub, rx->src, rx->dst, in seg_rx_reset()
1159 &rx->seq_auth); in seg_rx_reset()
1162 for (i = 0; i <= rx->seg_n; i++) { in seg_rx_reset()
1163 if (!rx->seg[i]) { in seg_rx_reset()
1167 k_mem_slab_free(&segs, rx->seg[i]); in seg_rx_reset()
1168 rx->seg[i] = NULL; in seg_rx_reset()
1171 rx->in_use = 0U; in seg_rx_reset()
1178 rx->seq_auth = 0U; in seg_rx_reset()
1179 rx->sub = NULL; in seg_rx_reset()
1180 rx->src = BT_MESH_ADDR_UNASSIGNED; in seg_rx_reset()
1181 rx->dst = BT_MESH_ADDR_UNASSIGNED; in seg_rx_reset()
1188 struct seg_rx *rx = CONTAINER_OF(dwork, struct seg_rx, discard); in seg_discard() local
1191 seg_rx_reset(rx, false); in seg_discard()
1192 rx->block = 0U; in seg_discard()
1202 struct seg_rx *rx = CONTAINER_OF(dwork, struct seg_rx, ack); in seg_ack() local
1204 if (!rx->in_use || rx->block == BLOCK_COMPLETE(rx->seg_n)) { in seg_ack()
1214 LOG_DBG("rx %p", rx); in seg_ack()
1216 send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth, in seg_ack()
1217 rx->block, rx->obo); in seg_ack()
1219 rx->last_ack = k_uptime_get_32(); in seg_ack()
1221 if (rx->attempts_left == 0) { in seg_ack()
1226 if (rx->seg_n > BT_MESH_SAR_RX_SEG_THRESHOLD) { in seg_ack()
1227 --rx->attempts_left; in seg_ack()
1228 k_work_schedule(&rx->ack, K_MSEC(BT_MESH_SAR_RX_SEG_INT_MS)); in seg_ack()
1243 struct seg_rx *rx = &seg_rx[i]; in seg_rx_find() local
1245 if (rx->src != net_rx->ctx.addr || in seg_rx_find()
1246 rx->dst != net_rx->ctx.recv_dst) { in seg_rx_find()
1250 /* Return newer RX context in addition to an exact match, so in seg_rx_find()
1253 if (rx->seq_auth >= *seq_auth) { in seg_rx_find()
1254 return rx; in seg_rx_find()
1257 if (rx->in_use) { in seg_rx_find()
1258 LOG_WRN("Duplicate SDU from src 0x%04x", net_rx->ctx.addr); in seg_rx_find()
1263 seg_rx_reset(rx, true); in seg_rx_find()
1265 /* Return non-match so caller can re-allocate */ in seg_rx_find()
1273 static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx, in seg_rx_is_valid() argument
1276 if (rx->hdr != *hdr || rx->seg_n != seg_n) { in seg_rx_is_valid()
1281 if (rx->src != net_rx->ctx.addr || rx->dst != net_rx->ctx.recv_dst) { in seg_rx_is_valid()
1286 if (rx->ctl != net_rx->ctl) { in seg_rx_is_valid()
1301 * the collaborative Bluetooth rx thread: in seg_rx_alloc()
1309 struct seg_rx *rx = &seg_rx[i]; in seg_rx_alloc() local
1311 if (rx->in_use) { in seg_rx_alloc()
1315 rx->in_use = 1U; in seg_rx_alloc()
1316 rx->sub = net_rx->sub; in seg_rx_alloc()
1317 rx->ctl = net_rx->ctl; in seg_rx_alloc()
1318 rx->seq_auth = *seq_auth; in seg_rx_alloc()
1319 rx->seg_n = seg_n; in seg_rx_alloc()
1320 rx->hdr = *hdr; in seg_rx_alloc()
1321 rx->ttl = net_rx->ctx.send_ttl; in seg_rx_alloc()
1322 rx->src = net_rx->ctx.addr; in seg_rx_alloc()
1323 rx->dst = net_rx->ctx.recv_dst; in seg_rx_alloc()
1324 rx->block = 0U; in seg_rx_alloc()
1326 LOG_DBG("New RX context. Block Complete 0x%08x", BLOCK_COMPLETE(seg_n)); in seg_rx_alloc()
1328 return rx; in seg_rx_alloc()
1339 struct seg_rx *rx; in trans_seg() local
1340 uint8_t *hdr = buf->data; in trans_seg()
1347 if (buf->len < 5) { in trans_seg()
1348 LOG_ERR("Too short segmented message (len %u)", buf->len); in trans_seg()
1349 return -EBADMSG; in trans_seg()
1353 LOG_WRN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", net_rx->ctx.addr, in trans_seg()
1354 net_rx->ctx.recv_dst, net_rx->seq); in trans_seg()
1355 return -EINVAL; in trans_seg()
1373 return -EBADMSG; in trans_seg()
1383 * SEQ(0) = SEQ(n) - (delta between seqZero and SEQ(n) by looking into in trans_seg()
1390 (net_rx->seq - in trans_seg()
1391 ((((net_rx->seq & BIT_MASK(14)) - seq_zero)) & in trans_seg()
1396 /* Look for old RX sessions */ in trans_seg()
1397 rx = seg_rx_find(net_rx, seq_auth); in trans_seg()
1398 if (rx) { in trans_seg()
1400 if (rx->seq_auth > *seq_auth) { in trans_seg()
1402 return -EINVAL; in trans_seg()
1405 if (!seg_rx_is_valid(rx, net_rx, hdr, seg_n)) { in trans_seg()
1406 return -EINVAL; in trans_seg()
1409 if (rx->in_use) { in trans_seg()
1410 LOG_DBG("Existing RX context. Block 0x%08x", rx->block); in trans_seg()
1414 if (rx->block == BLOCK_COMPLETE(rx->seg_n)) { in trans_seg()
1422 if (k_uptime_get_32() - rx->last_ack > in trans_seg()
1424 send_ack(net_rx->sub, net_rx->ctx.recv_dst, in trans_seg()
1425 net_rx->ctx.addr, net_rx->ctx.send_ttl, in trans_seg()
1426 seq_auth, rx->block, rx->obo); in trans_seg()
1427 rx->last_ack = k_uptime_get_32(); in trans_seg()
1434 return -EALREADY; in trans_seg()
1442 return -EINVAL; in trans_seg()
1446 if (!sdu_len_is_ok(net_rx->ctl, seg_n)) { in trans_seg()
1448 send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, in trans_seg()
1449 net_rx->ctx.send_ttl, seq_auth, 0, in trans_seg()
1450 net_rx->friend_match); in trans_seg()
1451 return -EMSGSIZE; in trans_seg()
1458 net_rx->friend_match && !net_rx->local_match && in trans_seg()
1459 !bt_mesh_friend_queue_has_space(net_rx->sub->net_idx, in trans_seg()
1460 net_rx->ctx.addr, in trans_seg()
1461 net_rx->ctx.recv_dst, seq_auth, in trans_seg()
1464 send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, in trans_seg()
1465 net_rx->ctx.send_ttl, seq_auth, 0, in trans_seg()
1466 net_rx->friend_match); in trans_seg()
1467 return -ENOBUFS; in trans_seg()
1475 * initial value of rpl->seg is 0, which would normally fail the in trans_seg()
1477 * - If this is the first time we receive from this source, rpl->src in trans_seg()
1479 * - If this is the first time we receive from this source on the new IV in trans_seg()
1480 * index, rpl->old_iv will be set, and the check is also skipped. in trans_seg()
1481 * - If this is the first segmented message on the new IV index, but we in trans_seg()
1483 * message will have reset rpl->seg to 0, and this message's SeqAuth in trans_seg()
1486 if (rpl && rpl->src && auth_seqnum <= rpl->seg && in trans_seg()
1487 (!rpl->old_iv || net_rx->old_iv)) { in trans_seg()
1489 return -EALREADY; in trans_seg()
1492 /* Look for free slot for a new RX session */ in trans_seg()
1493 rx = seg_rx_alloc(net_rx, hdr, seq_auth, seg_n); in trans_seg()
1494 if (!rx) { in trans_seg()
1500 return -ENOMEM; in trans_seg()
1503 rx->obo = net_rx->friend_match; in trans_seg()
1506 if (BIT(seg_o) & rx->block) { in trans_seg()
1508 return -EALREADY; in trans_seg()
1517 rx->len = seg_n * seg_len(rx->ctl) + buf->len; in trans_seg()
1518 LOG_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl), buf->len, rx->len); in trans_seg()
1520 if (rx->len > BT_MESH_RX_SDU_MAX) { in trans_seg()
1522 send_ack(net_rx->sub, net_rx->ctx.recv_dst, in trans_seg()
1523 net_rx->ctx.addr, net_rx->ctx.send_ttl, in trans_seg()
1524 seq_auth, 0, rx->obo); in trans_seg()
1525 seg_rx_reset(rx, true); in trans_seg()
1526 return -EMSGSIZE; in trans_seg()
1529 if (buf->len != seg_len(rx->ctl)) { in trans_seg()
1531 return -EINVAL; in trans_seg()
1536 k_work_schedule(&rx->discard, in trans_seg()
1538 rx->attempts_left = BT_MESH_SAR_RX_ACK_RETRANS_COUNT; in trans_seg()
1540 if (!bt_mesh_lpn_established() && BT_MESH_ADDR_IS_UNICAST(rx->dst)) { in trans_seg()
1541 LOG_DBG("ack delay %u", ACK_DELAY(rx->seg_n)); in trans_seg()
1542 k_work_reschedule(&rx->ack, K_MSEC(ACK_DELAY(rx->seg_n))); in trans_seg()
1546 err = k_mem_slab_alloc(&segs, &rx->seg[seg_o], K_NO_WAIT); in trans_seg()
1549 return -ENOBUFS; in trans_seg()
1552 memcpy(rx->seg[seg_o], buf->data, buf->len); in trans_seg()
1557 rx->block |= BIT(seg_o); in trans_seg()
1559 if (rx->block != BLOCK_COMPLETE(seg_n)) { in trans_seg()
1568 * block is fully received, or rx->in_use is false. in trans_seg()
1570 (void)k_work_cancel_delayable(&rx->ack); in trans_seg()
1572 send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, in trans_seg()
1573 net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo); in trans_seg()
1574 rx->last_ack = k_uptime_get_32(); in trans_seg()
1576 if (net_rx->ctl) { in trans_seg()
1578 seg_rx_assemble(rx, &sdu, 0U); in trans_seg()
1580 } else if (rx->len < 1 + APP_MIC_LEN(ASZMIC(hdr))) { in trans_seg()
1582 err = -EINVAL; in trans_seg()
1593 &sdu, seg_buf.data, rx->len - APP_MIC_LEN(ASZMIC(hdr))); in trans_seg()
1595 err = sdu_recv(net_rx, *hdr, ASZMIC(hdr), &seg_buf, &sdu, rx); in trans_seg()
1606 rpl->seg = MAX(rpl->seg, auth_seqnum); in trans_seg()
1609 seg_rx_reset(rx, false); in trans_seg()
1614 int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) in bt_mesh_trans_recv() argument
1623 rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx, in bt_mesh_trans_recv()
1624 rx->ctx.recv_dst); in bt_mesh_trans_recv()
1626 rx->friend_match = false; in bt_mesh_trans_recv()
1629 LOG_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u", rx->ctx.addr, rx->ctx.recv_dst, in bt_mesh_trans_recv()
1630 rx->seq, rx->friend_match); in bt_mesh_trans_recv()
1635 LOG_DBG("Payload %s", bt_hex(buf->data, buf->len)); in bt_mesh_trans_recv()
1638 bt_mesh_test_net_recv(rx->ctx.recv_ttl, rx->ctl, rx->ctx.addr, rx->ctx.recv_dst, in bt_mesh_trans_recv()
1639 buf->data, buf->len); in bt_mesh_trans_recv()
1642 /* If LPN mode is enabled messages are only accepted when we've in bt_mesh_trans_recv()
1647 bt_mesh_lpn_established() && rx->net_if == BT_MESH_NET_IF_ADV && in bt_mesh_trans_recv()
1648 (!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) { in bt_mesh_trans_recv()
1649 LOG_WRN("Ignoring unexpected message in Low Power mode"); in bt_mesh_trans_recv()
1650 return -EAGAIN; in bt_mesh_trans_recv()
1653 /* Save the app-level state so the buffer can later be placed in in bt_mesh_trans_recv()
1658 if (SEG(buf->data)) { in bt_mesh_trans_recv()
1662 if (!rx->local_match && !rx->friend_match) { in bt_mesh_trans_recv()
1666 err = trans_seg(buf, rx, &pdu_type, &seq_auth, &seg_count); in bt_mesh_trans_recv()
1673 if (!rx->ctl && !rx->local_match && !rx->friend_match) { in bt_mesh_trans_recv()
1677 err = trans_unseg(buf, rx, &seq_auth); in bt_mesh_trans_recv()
1682 bt_mesh_lpn_msg_received(rx); in bt_mesh_trans_recv()
1687 if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match && !err) { in bt_mesh_trans_recv()
1689 bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, in bt_mesh_trans_recv()
1692 bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth, in bt_mesh_trans_recv()