ble_mesh: Fixes Provisioner not support friend feature

This commit is contained in:
lly 2019-12-06 15:34:18 +08:00
parent 77e7d023b9
commit d83c37faed
8 changed files with 138 additions and 92 deletions

View file

@ -590,8 +590,7 @@ if BLE_MESH
endif # BLE_MESH_LOW_POWER
config BLE_MESH_FRIEND
bool "Support for acting as a Friend Node"
depends on BLE_MESH_NODE
bool "Support for Friend feature"
help
Enable this option to be able to act as a Friend Node.

View file

@ -783,7 +783,6 @@ static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature)
return;
}
#if CONFIG_BLE_MESH_NODE
#if CONFIG_BLE_MESH_LOW_POWER
static void btc_ble_mesh_lpn_cb(u16_t friend_addr, bool established)
{
@ -831,7 +830,6 @@ void btc_ble_mesh_friend_cb(bool establish, u16_t lpn_addr, u8_t reason)
return;
}
#endif /* CONFIG_BLE_MESH_FRIEND */
#endif /* CONFIG_BLE_MESH_NODE */
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
static void btc_ble_mesh_proxy_client_adv_recv_cb(const bt_mesh_addr_t *addr,
@ -1507,12 +1505,6 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
arg->mesh_init.prov->link_close_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_link_close_cb;
arg->mesh_init.prov->complete_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_complete_cb;
arg->mesh_init.prov->reset_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_reset_cb;
#if CONFIG_BLE_MESH_LOW_POWER
bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb);
#endif /* CONFIG_BLE_MESH_LOW_POWER */
#if CONFIG_BLE_MESH_FRIEND
bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb);
#endif /* CONFIG_BLE_MESH_FRIEND */
#endif /* CONFIG_BLE_MESH_NODE */
#if CONFIG_BLE_MESH_PROVISIONER
arg->mesh_init.prov->provisioner_prov_read_oob_pub_key = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_read_oob_pub_key_cb;
@ -1523,6 +1515,12 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
arg->mesh_init.prov->provisioner_prov_comp = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_complete_cb;
bt_mesh_prov_adv_pkt_cb_register(btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb);
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if CONFIG_BLE_MESH_LOW_POWER
bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb);
#endif /* CONFIG_BLE_MESH_LOW_POWER */
#if CONFIG_BLE_MESH_FRIEND
bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb);
#endif /* CONFIG_BLE_MESH_FRIEND */
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
bt_mesh_proxy_client_set_adv_recv_cb(btc_ble_mesh_proxy_client_adv_recv_cb);
bt_mesh_proxy_client_set_conn_cb(btc_ble_mesh_proxy_client_connect_cb);

View file

@ -26,6 +26,8 @@
#include "access.h"
#include "foundation.h"
#include "friend.h"
#include "client_common.h"
#include "provisioner_main.h"
#ifdef CONFIG_BLE_MESH_FRIEND
@ -72,7 +74,18 @@ enum {
static void (*friend_cb)(bool establish, u16_t lpn_addr, u8_t reason);
static struct bt_mesh_subnet *friend_subnet_get(u16_t net_idx)
{
struct bt_mesh_subnet *sub = NULL;
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
sub = bt_mesh_subnet_get(net_idx);
} else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
sub = provisioner_subnet_get(net_idx);
}
return sub;
}
static struct bt_mesh_adv *adv_alloc(int id)
{
@ -357,20 +370,31 @@ static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
struct unseg_app_sdu_meta *meta)
{
u16_t app_idx = FRIEND_ADV(buf)->app_idx;
u8_t role;
int err;
meta->subnet = bt_mesh_subnet_get(frnd->net_idx);
meta->subnet = friend_subnet_get(frnd->net_idx);
if (!meta->subnet) {
BT_ERR("Invalid subnet for unseg app sdu");
return -EINVAL;
}
role = (IS_ENABLED(CONFIG_BLE_MESH_NODE) &&
bt_mesh_is_provisioned()) ? NODE : PROVISIONER;
meta->is_dev_key = (app_idx == BLE_MESH_KEY_DEV);
bt_mesh_net_header_parse(&buf->b, &meta->net);
err = bt_mesh_app_key_get(meta->subnet, app_idx, &meta->key,
&meta->aid, 0x0, meta->net.ctx.addr);
&meta->aid, role, meta->net.ctx.addr);
if (err) {
BT_ERR("Failed to get AppKey");
return err;
}
if (BLE_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
if (!meta->ad) {
BT_ERR("Failed to get label uuid");
return -ENOENT;
}
} else {
@ -451,13 +475,18 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf,
bool master_cred)
{
struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx);
const u8_t *enc, *priv;
u32_t iv_index;
u16_t src;
u8_t nid;
int err;
if (!sub) {
BT_ERR("Invalid subnet to encrypt friend pdu");
return -EINVAL;
}
if (master_cred) {
enc = sub->keys[sub->kr_flag].enc;
priv = sub->keys[sub->kr_flag].privacy;
@ -534,7 +563,7 @@ static struct net_buf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
{
struct bt_mesh_ctl_friend_update *upd;
NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd));
struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx);
__ASSERT_NO_MSG(sub != NULL);
@ -774,7 +803,7 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
.send_ttl = BLE_MESH_TTL_MAX,
};
struct bt_mesh_net_tx tx = {
.sub = bt_mesh_subnet_get(frnd->net_idx),
.sub = friend_subnet_get(frnd->net_idx),
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
@ -786,6 +815,11 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
BT_DBG("%s", __func__);
if (!tx.sub) {
BT_ERR("Invalid subnet for Friend Clear");
return;
}
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
sizeof(req), NULL, &clear_sent_cb, frnd);
}
@ -1647,4 +1681,14 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
}
}
void bt_mesh_friend_remove_lpn(u16_t lpn_addr)
{
struct bt_mesh_friend *frnd;
frnd = bt_mesh_friend_find(BLE_MESH_KEY_ANY, lpn_addr, false, false);
if (frnd) {
friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE);
}
}
#endif /* CONFIG_BLE_MESH_FRIEND */

View file

@ -51,4 +51,6 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
int bt_mesh_friend_init(void);
void bt_mesh_friend_remove_lpn(u16_t lpn_addr);
#endif /* _FRIEND_H_ */

View file

@ -413,6 +413,10 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers)
provisioner_pb_gatt_enable();
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_init();
}
provisioner_en = true;
return 0;
@ -437,6 +441,10 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers)
bt_mesh_scan_disable();
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY);
}
provisioner_en = false;
return 0;

View file

@ -1123,18 +1123,14 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
continue;
}
#if CONFIG_BLE_MESH_NODE
if (bt_mesh_is_provisioned()) {
#if (defined(CONFIG_BLE_MESH_LOW_POWER) || defined(CONFIG_BLE_MESH_FRIEND))
if (!friend_decrypt(sub, data, data_len, rx, buf)) {
rx->friend_cred = 1;
rx->ctx.net_idx = sub->net_idx;
rx->sub = sub;
return true;
}
#endif
if (!friend_decrypt(sub, data, data_len, rx, buf)) {
rx->friend_cred = 1;
rx->ctx.net_idx = sub->net_idx;
rx->sub = sub;
return true;
}
#endif /* CONFIG_BLE_MESH_NODE */
#endif
if (NID(data) == sub->keys[0].nid &&
!net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,

View file

@ -28,6 +28,7 @@
#include "adv.h"
#include "net.h"
#include "access.h"
#include "friend.h"
#include "provisioner_prov.h"
#include "proxy_client.h"
@ -142,6 +143,10 @@ int provisioner_node_reset(int node_index)
}
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_remove_lpn(node->unicast_addr);
}
osi_free(mesh_nodes[node_index]);
mesh_nodes[node_index] = NULL;

View file

@ -139,32 +139,30 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
net_buf_add_mem(buf, sdu->data, sdu->len);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx,
tx->src, tx->ctx->addr,
NULL, 1)) {
if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
BT_ERR("Not enough space in Friend Queue");
net_buf_unref(buf);
return -ENOBUFS;
} else {
BT_WARN("No space in Friend Queue");
goto send;
}
}
if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE,
NULL, 1, &buf->b) &&
BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx,
tx->src, tx->ctx->addr,
NULL, 1)) {
if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
BT_ERR("Not enough space in Friend Queue");
net_buf_unref(buf);
send_cb_finalize(cb, cb_data);
return 0;
return -ENOBUFS;
} else {
BT_WARN("No space in Friend Queue");
goto send;
}
}
if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE,
NULL, 1, &buf->b) &&
BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
net_buf_unref(buf);
send_cb_finalize(cb, cb_data);
return 0;
}
}
send:
@ -413,27 +411,25 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
net_buf_add_mem(seg, sdu->data, len);
net_buf_simple_pull(sdu, len);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
if (seg_o == tx->seg_n) {
type = BLE_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BLE_MESH_FRIEND_PDU_PARTIAL;
}
if (seg_o == tx->seg_n) {
type = BLE_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BLE_MESH_FRIEND_PDU_PARTIAL;
}
if (bt_mesh_friend_enqueue_tx(net_tx, type,
&tx->seq_auth,
tx->seg_n + 1,
&seg->b) &&
BLE_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;
}
if (bt_mesh_friend_enqueue_tx(net_tx, type,
&tx->seq_auth,
tx->seg_n + 1,
&seg->b) &&
BLE_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;
}
}
@ -904,24 +900,24 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
return 0;
}
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) {
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_POLL:
return bt_mesh_friend_poll(rx, buf);
case TRANS_CTL_OP_FRIEND_REQ:
return bt_mesh_friend_req(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR:
return bt_mesh_friend_clear(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR_CFM:
return bt_mesh_friend_clear_cfm(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_ADD:
return bt_mesh_friend_sub_add(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_REM:
return bt_mesh_friend_sub_rem(rx, buf);
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) {
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_POLL:
return bt_mesh_friend_poll(rx, buf);
case TRANS_CTL_OP_FRIEND_REQ:
return bt_mesh_friend_req(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR:
return bt_mesh_friend_clear(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR_CFM:
return bt_mesh_friend_clear_cfm(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_ADD:
return bt_mesh_friend_sub_add(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_REM:
return bt_mesh_friend_sub_rem(rx, buf);
}
}
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
#if defined(CONFIG_BLE_MESH_LOW_POWER)
if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) {
return bt_mesh_lpn_friend_offer(rx, buf);
@ -1530,15 +1526,13 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
net_buf_simple_restore(buf, &state);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) {
if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL,
seg_count, buf);
} else {
bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth,
seg_count, buf);
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) {
if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL,
seg_count, buf);
} else {
bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth,
seg_count, buf);
}
}