Skip to content

BLE: Mesh: When transport send seg_msg to LPN #18522

@LingaoM

Description

@LingaoM

static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
u8_t seg_hdr, seg_o;
u16_t seq_zero;
struct seg_tx *tx;
int i;
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u",
net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx,
net_tx->aszmic, sdu->len);
if (sdu->len < 1) {
BT_ERR("Zero-length SDU not allowed");
return -EINVAL;
}
if (sdu->len > BT_MESH_TX_SDU_MAX) {
BT_ERR("Not enough segment buffers for length %u", sdu->len);
return -EMSGSIZE;
}
for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) {
if (!seg_tx[i].nack_count) {
tx = &seg_tx[i];
break;
}
}
if (!tx) {
BT_ERR("No multi-segment message contexts available");
return -EBUSY;
}
if (net_tx->ctx->app_idx == BT_MESH_KEY_DEV) {
seg_hdr = SEG_HDR(0, 0);
} else {
seg_hdr = SEG_HDR(1, net_tx->aid);
}
seg_o = 0U;
tx->dst = net_tx->ctx->addr;
tx->seg_n = (sdu->len - 1) / 12U;
tx->nack_count = tx->seg_n + 1;
tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
tx->sub = net_tx->sub;
tx->new_key = net_tx->sub->kr_flag;
tx->cb = cb;
tx->cb_data = cb_data;
if (net_tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
tx->ttl = bt_mesh_default_ttl_get();
} else {
tx->ttl = net_tx->ctx->send_ttl;
}
seq_zero = tx->seq_auth & 0x1fff;
BT_DBG("SeqZero 0x%04x", seq_zero);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) &&
!bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src,
tx->dst, &tx->seq_auth,
tx->seg_n + 1) &&
BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
BT_ERR("Not enough space in Friend Queue for %u segments",
tx->seg_n + 1);
seg_tx_reset(tx);
return -ENOBUFS;
}
for (seg_o = 0U; sdu->len; seg_o++) {
struct net_buf *seg;
u16_t len;
int err;
seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, net_tx->xmit,
BUF_TIMEOUT);
if (!seg) {
BT_ERR("Out of segment buffers");
seg_tx_reset(tx);
return -ENOBUFS;
}
BT_MESH_ADV(seg)->seg.attempts = SEG_RETRANSMIT_ATTEMPTS;
net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
net_buf_add_u8(seg, seg_hdr);
net_buf_add_u8(seg, (net_tx->aszmic << 7) | seq_zero >> 6);
net_buf_add_u8(seg, (((seq_zero & 0x3f) << 2) |
(seg_o >> 3)));
net_buf_add_u8(seg, ((seg_o & 0x07) << 5) | tx->seg_n);
len = MIN(sdu->len, 12);
net_buf_add_mem(seg, sdu->data, len);
net_buf_simple_pull(sdu, len);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
if (seg_o == tx->seg_n) {
type = BT_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BT_MESH_FRIEND_PDU_PARTIAL;
}
if (bt_mesh_friend_enqueue_tx(net_tx, type,
&tx->seq_auth,
tx->seg_n + 1,
&seg->b) &&
BT_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
net_buf_unref(seg);
continue;
}
}
tx->seg[seg_o] = net_buf_ref(seg);
BT_DBG("Sending %u/%u", seg_o, tx->seg_n);
err = bt_mesh_net_send(net_tx, seg,
seg_o ? &seg_sent_cb : &first_sent_cb,
tx);
if (err) {
BT_ERR("Sending segment failed");
seg_tx_reset(tx);
return err;
}
}
/* This can happen if segments only went into the Friend Queue */
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !tx->seg[0]) {
seg_tx_reset(tx);
/* If there was a callback notify sending immediately since
* there's no other way to track this (at least currently)
* with the Friend Queue.
*/
send_cb_finalize(cb, cb_data);
}
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
bt_mesh_lpn_established()) {
bt_mesh_lpn_poll();
}
return 0;
}

        if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && 
 	    !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src, 
 					    tx->dst, &tx->seq_auth, 
 					    tx->seg_n + 1) && 
 	    BT_MESH_ADDR_IS_UNICAST(tx->dst)) { 
 		BT_ERR("Not enough space in Friend Queue for %u segments", 
 		       tx->seg_n + 1); 
 		seg_tx_reset(tx); 
 		return -ENOBUFS; 
 	} 

According to the code above, if I send a SEG message (greater than CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) to a UNICAST Address (not an LPN address),will be cause an abnormality.

I think should add some functions to determine if it is sent to LPN, such as bt_mesh_friend_match

Metadata

Metadata

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions