Bluetooth: Mesh: Fix transport layer heartbeat subscription matching

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2017-11-02 13:30:46 +02:00 committed by Johan Hedberg
commit cad1f4ce7b
4 changed files with 40 additions and 18 deletions

View file

@ -2902,6 +2902,9 @@ static void heartbeat_sub_set(struct bt_mesh_model *model,
period_ms = hb_pwr2(sub_period, 1) * 1000;
}
/* Let the transport layer know it needs to handle this address */
bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst);
BT_DBG("period_ms %u", period_ms);
if (period_ms) {

View file

@ -105,6 +105,8 @@ void bt_mesh_reset(void)
bt_mesh.last_update = 0;
bt_mesh.ivu_initiator = 0;
bt_mesh_set_hb_sub_dst(BT_MESH_ADDR_UNASSIGNED);
k_delayed_work_cancel(&bt_mesh.ivu_complete);
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {

View file

@ -90,6 +90,13 @@ static struct seg_rx {
},
};
static u16_t hb_sub_dst = BT_MESH_ADDR_UNASSIGNED;
void bt_mesh_set_hb_sub_dst(u16_t addr)
{
hb_sub_dst = addr;
}
static int send_unseg(struct bt_mesh_net_tx *tx, u8_t aid,
struct net_buf_simple *sdu)
{
@ -687,6 +694,11 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
return -EINVAL;
}
if (rx->dst != hb_sub_dst) {
BT_WARN("Ignoring heartbeat to non-subscribed destination");
return 0;
}
init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
feat = net_buf_simple_pull_be16(buf);
@ -711,18 +723,15 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
switch (ctl_op) {
case TRANS_CTL_OP_ACK:
return trans_ack(rx, hdr, buf, seq_auth);
}
/* Only acks need processing for Friend behavior */
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
return 0;
}
switch (ctl_op) {
case TRANS_CTL_OP_HEARTBEAT:
return trans_heartbeat(rx, buf);
}
/* Only acks and heartbeats may need processing without local_match */
if (!rx->local_match) {
return 0;
}
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_POLL:
@ -784,6 +793,11 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
if (rx->ctl) {
return ctl_recv(rx, hdr, buf, seq_auth);
} else {
/* SDUs must match a local element or an LPN of this Friend. */
if (!rx->local_match && !rx->friend_match) {
return 0;
}
return sdu_recv(rx, hdr, 4, 0, buf);
}
}
@ -1197,12 +1211,8 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
rx->friend_match = false;
}
if (!rx->local_match && !rx->friend_match) {
return 0;
}
BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x", rx->ctx.addr, rx->dst,
rx->seq);
BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u",
rx->ctx.addr, rx->dst, rx->seq, rx->friend_match);
/* Remove network headers */
net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
@ -1217,8 +1227,7 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
bt_mesh_lpn_established() &&
(!bt_mesh_lpn_waiting_update() || !rx->ctx.friend_cred)) {
BT_WARN("Ignoring unexpected message in Low Power mode");
err = -EAGAIN;
goto done;
return -EAGAIN;
}
/* Save the parsing state so the buffer can later be relayed or
@ -1227,6 +1236,13 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
net_buf_simple_save(buf, &state);
if (SEG(buf->data)) {
/* Segmented messages must match a local element or an
* LPN of this Friend.
*/
if (!rx->local_match && !rx->friend_match) {
return 0;
}
err = trans_seg(buf, rx, &pdu_type, &seq_auth);
} else {
err = trans_unseg(buf, rx, &seq_auth);
@ -1244,10 +1260,9 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
bt_mesh_lpn_msg_received(rx);
}
done:
net_buf_simple_restore(buf, &state);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !err) {
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match && !err) {
if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, buf);
} else {

View file

@ -74,6 +74,8 @@ struct bt_mesh_ctl_friend_sub_confirm {
u8_t xact;
} __packed;
void bt_mesh_set_hb_sub_dst(u16_t addr);
struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx);
bool bt_mesh_tx_in_progress(void);