in nimble/host/mesh/src/transport.c [371:451]
static void seg_tx_send_unacked(struct seg_tx *tx)
{
if (!tx->nack_count) {
return;
}
struct bt_mesh_msg_ctx ctx = {
.net_idx = tx->sub->net_idx,
/* App idx only used by network to detect control messages: */
.app_idx = (tx->ctl ? BT_MESH_KEY_UNUSED : 0),
.addr = tx->dst,
.send_rel = true,
.send_ttl = tx->ttl,
};
struct bt_mesh_net_tx net_tx = {
.sub = tx->sub,
.ctx = &ctx,
.src = tx->src,
.xmit = tx->xmit,
.friend_cred = tx->friend_cred,
.aid = tx->hdr & AID_MASK,
};
if (!tx->attempts) {
if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
BT_ERR("Ran out of retransmit attempts");
seg_tx_complete(tx, -ETIMEDOUT);
} else {
/* Segmented sending to groups doesn't have acks, so
* running out of attempts is the expected behavior.
*/
seg_tx_complete(tx, 0);
}
return;
}
BT_DBG("SeqZero: 0x%04x Attempts: %u",
(uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts);
tx->sending = 1U;
for (; tx->seg_o <= tx->seg_n; tx->seg_o++) {
struct os_mbuf *seg;
int err;
if (!tx->seg[tx->seg_o]) {
continue;
}
seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit,
BUF_TIMEOUT);
if (!seg) {
BT_DBG("Allocating segment failed");
goto end;
}
net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
seg_tx_buf_build(tx, tx->seg_o, seg);
tx->seg_pending++;
BT_DBG("Sending %u/%u", tx->seg_o, tx->seg_n);
err = bt_mesh_net_send(&net_tx, seg, &seg_sent_cb, tx);
if (err) {
BT_DBG("Sending segment failed");
tx->seg_pending--;
goto end;
}
}
tx->seg_o = 0U;
tx->attempts--;
end:
if (!tx->seg_pending) {
k_work_reschedule(&tx->retransmit,
K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
}
tx->sending = 0U;
}