feat(ble_mesh): Proxy Client/Server Coexists Support

This commit is contained in:
luoxu 2024-10-12 10:10:38 +08:00
parent 38b737511c
commit 74c847210d
9 changed files with 180 additions and 53 deletions

View File

@ -427,6 +427,13 @@ if BLE_MESH
will store the solicitation src and solicitation sequence number of
the received Solicitation PDU message.
config BLE_MESH_PROXY_CLI_SRV_COEXIST
bool "Support Proxy Client and Proxy Server coexistence"
depends on BLE_MESH_EXPERIMENTAL
default n
help
Enable this option to support the coexistence of proxy client and proxy server.
config BLE_MESH_GATT_PROXY_CLIENT
bool "BLE Mesh GATT Proxy Client"
select BLE_MESH_PROXY
@ -1659,5 +1666,6 @@ if BLE_MESH
Experimental features list:
- CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG
- CONFIG_BLE_MESH_USE_BLE_50
- CONFIG_BLE_MESH_PROXY_CLI_SRV_COEXIST
endif # BLE_MESH

View File

@ -1164,6 +1164,19 @@ static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
/* When connection is created, advertising will be stopped automatically. */
bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
#endif
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
(CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT)
/* Check if this connection is created by Proxy client */
for (size_t i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) {
if (!memcmp(bt_mesh_gattc_info[i].addr.val, p_data->conn.remote_bda, BLE_MESH_ADDR_LEN)) {
BT_WARN("Already create connection with %s by proxy client",
bt_hex(p_data->conn.remote_bda, BLE_MESH_ADDR_LEN));
return;
}
}
#endif
if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) {
uint8_t index = BLE_MESH_GATT_GET_CONN_ID(p_data->conn.conn_id);
if (index < BLE_MESH_MAX_CONN) {

View File

@ -21,13 +21,61 @@ extern "C" {
#endif
/* BLE Mesh Max Connection Count */
/**
* The maximum number of connection count is limited by
* the resources allocated by both the host and the controller
* components, so the actual number of available connections
* is the minimum of the resources from both.
*
* On the C3/S3 platform, the controller uses the macro `CONFIG_BT_CTRL_BLE_MAX_ACT`,
* but adv and scan also occupy this resource, so the actual number of available
* connections is (CONFIG_BT_CTRL_BLE_MAX_ACT - adv instance count - scan).
* However, the macro allocation on the host is entirely for connections,
* so on the C3/S3 platform, the maximum number of connectable devices should
* be determined by the configuration at the host minus the number of
* advertising instances and scan from the controller's configuration.
*/
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#if CONFIG_IDF_TARGET_ESP32
#define BLE_MESH_MAX_CONN 1
#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */
#if CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2)
/* decrease the adv,scan */
#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2)
#else
#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS
#endif /* CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
#if CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS
#define BLE_MESH_MAX_CONN CONFIG_BT_LE_MAX_CONNECTIONS
#else
#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS
#endif /* CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS */
#else
/* default setting */
#define BLE_MESH_MAX_CONN 1
#endif
#endif /* CONFIG_BT_BLUEDROID_ENABLED */
#ifdef CONFIG_BT_NIMBLE_ENABLED
#if CONFIG_IDF_TARGET_ESP32
#define BLE_MESH_MAX_CONN 1
#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */
#if CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2)
/* decrease the adv,scan */
#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2)
#else
#define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#endif /* CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
#define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#else
/* default setting */
#define BLE_MESH_MAX_CONN 1
#endif
#endif /* CONFIG_BT_NIMBLE_ENABLED */
#define BLE_MESH_GAP_ADV_MAX_LEN 31

View File

@ -837,6 +837,9 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
uint16_t dst = 0U;
int err = 0;
/* The variable is not used when proxy server or proxy client is disabled. */
ARG_UNUSED(dst);
BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
buf->len);
@ -914,18 +917,22 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
return err;
}
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
bt_mesh_proxy_server_relay(&buf->b, dst) &&
BLE_MESH_ADDR_IS_UNICAST(dst)) {
/**
* TODO: Find a way to determine how the message was sent previously
* during a retransmission, to avoid ineffective advertising.
*/
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
if (bt_mesh_proxy_server_relay(&buf->b, dst) &&
BLE_MESH_ADDR_IS_UNICAST(dst) &&
bt_mesh_proxy_server_find_client_by_addr(dst)) {
send_cb_finalize(cb, cb_data);
return 0;
}
#endif
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) &&
bt_mesh_proxy_client_relay(&buf->b, dst)) {
send_cb_finalize(cb, cb_data);
return 0;
}
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
bt_mesh_proxy_client_relay(&buf->b, dst);
#endif
bt_mesh_adv_send(buf, BLE_MESH_ADV(buf)->xmit, cb, cb_data);
return 0;
@ -1052,6 +1059,7 @@ static void bt_mesh_net_adv_xmit_update(struct bt_mesh_net_tx *tx)
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
const struct bt_mesh_send_cb *send_cb = cb;
uint8_t bearer = BLE_MESH_ALL_BEARERS;
int err = 0;
@ -1116,40 +1124,48 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
* shall drop all messages secured using the friendship security
* credentials."
*/
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
(bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U ||
bt_mesh_tag_relay(tx->ctx->send_tag)) &&
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
if ((bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) &&
tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) {
if (bt_mesh_proxy_server_relay(&buf->b, tx->ctx->addr) &&
BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
/**
* When a message is sent to a proxy client, the message
* can be sent via GATT only, eliminating the need for
* an ADV bearer.
/* When the destination address is identified as a proxy client
* address, the message will be sent only to the proxy client.
* This action will enhance the efficiency of the proxy server
* in sending data packets.
*
* It should be noted that this approach does not significantly
* reduce the number of advertising packets in the air, as other
* proxy clients may receive the message and resend it through
* a advertising method.
*/
if (bt_mesh_proxy_server_find_client_by_addr(tx->ctx->addr)) {
bearer &= ~BLE_MESH_ADV_BEARER;
}
send_cb_finalize(send_cb, cb_data);
send_cb = NULL;
/* Notify completion if this only went
* through the Mesh Proxy.
*/
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
send_cb_finalize(cb, cb_data);
err = 0;
goto done;
}
/* Finalize transmission if this only went through GATT bearer */
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
send_cb_finalize(send_cb, cb_data);
send_cb = NULL;
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
/* This message will not be transmitted by proxy client */
if (!bt_mesh_proxy_client_get_conn_count()) {
goto done;
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
}
}
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) &&
(bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U ||
bt_mesh_tag_relay(tx->ctx->send_tag)) &&
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
if ((bearer & BLE_MESH_GATT_BEARER) &&
(tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) &&
tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) {
if (bt_mesh_proxy_client_relay(&buf->b, tx->ctx->addr)) {
/* If Proxy Client succeeds to send messages with GATT bearer,
@ -1157,45 +1173,43 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
* connection has been created with Proxy Client, here we will
* use advertising bearer for the messages.
*/
send_cb_finalize(cb, cb_data);
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
send_cb_finalize(send_cb, cb_data);
send_cb = NULL;
err = 0;
goto done;
goto done;
}
}
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
/* Deliver to local network interface if necessary */
if (((IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) ||
(IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en())) &&
(bt_mesh_fixed_group_match(tx->ctx->addr) || bt_mesh_elem_find(tx->ctx->addr))) {
/**
* If the target address isn't a unicast address, then the callback function
* will be called by `adv task` in place of here, to avoid the callback function
* being called twice.
/* If the target address isn't a unicast address, then the callback
* function will be called by mesh adv task instead of called here
* to avoid the callback function being called twice.
* See BLEMESH24-76 for more details.
*/
if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
if (cb && cb->start) {
cb->start(0, 0, cb_data);
if (send_cb && send_cb->start) {
send_cb->start(0, 0, cb_data);
}
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
if (cb && cb->end) {
cb->end(0, cb_data);
if (send_cb && send_cb->end) {
send_cb->end(0, cb_data);
}
bt_mesh_net_local();
err = 0;
goto done;
} else {
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
bt_mesh_net_local();
}
err = 0;
net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
bt_mesh_net_local();
}
if ((bearer & BLE_MESH_ADV_BEARER) &&
@ -1217,7 +1231,6 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
BLE_MESH_TRANSMIT_COUNT(tx->xmit), BLE_MESH_TRANSMIT_INT(tx->xmit));
bt_mesh_adv_send(buf, tx->xmit, cb, cb_data);
err = 0;
goto done;
}
@ -1737,8 +1750,8 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
* shall drop all messages secured using the friendship security
* credentials.
*/
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
(bearer & BLE_MESH_GATT_BEARER) &&
#if CONFIG_BLE_MESH_GATT_PROXY_SERVER
if ((bearer & BLE_MESH_GATT_BEARER) &&
((bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED &&
cred != BLE_MESH_FRIENDSHIP_CRED) ||
#if CONFIG_BLE_MESH_PRB_SRV
@ -1748,11 +1761,14 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED)) {
if (bt_mesh_proxy_server_relay(&buf->b, rx->ctx.recv_dst) &&
BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) {
if (((bearer & (~BLE_MESH_GATT_BEARER)) == 0) ||
bt_mesh_proxy_server_find_client_by_addr(rx->ctx.recv_dst)) {
goto done;
}
}
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
if (((bearer & BLE_MESH_ADV_BEARER) && relay_to_adv(rx->net_if)) ||
netkey_changed ||

View File

@ -410,7 +410,13 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error,
}
for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) {
if (bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) {
/**
* In scenarios with multiple connections, to prevent
* subsequent connections from affecting the first one,
* a check for the connection handle is needed here.
*/
if (bt_mesh_gattc_info[i].conn.handle == conn_handle &&
bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) {
bt_mesh_gattc_info[i].start_handle = service->start_handle;
bt_mesh_gattc_info[i].end_handle = service->end_handle;
break;
@ -834,6 +840,20 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
/* When connection is created, advertising will be stopped automatically. */
bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
#endif
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \
(CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT)
/* Check if this connection is created by Proxy client */
for (size_t i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) {
if (!memcmp(bt_mesh_gattc_info[i].addr.val, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)) {
BT_WARN("Already create connection with %s by proxy client",
bt_hex(desc.peer_id_addr.val, BLE_MESH_ADDR_LEN));
return 0;
}
}
#endif
if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) {
int index = 0;
#if CONFIG_BLE_MESH_USE_BLE_50

View File

@ -1471,6 +1471,9 @@ int bt_mesh_pb_gatt_close(struct bt_mesh_conn *conn, uint8_t reason)
if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) {
prov_link.pb_remote_cbd = true;
prov_link.pb_remote_reset = true;
/* @todo: the close reason is disconnect reason, not the
* link close reason, should change it to link close reason?
*/
prov_link.pb_remote_close(&prov_link, reason);
}
#endif

View File

@ -820,6 +820,23 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle)
return 0;
}
uint16_t bt_mesh_proxy_client_get_conn_count(void)
{
uint16_t count = 0;
for (size_t i = 0; i < ARRAY_SIZE(servers); i++) {
struct bt_mesh_proxy_server *server = &servers[i];
if (!server->conn || server->conn_type != CLI_PROXY) {
continue;
}
count++;
}
return count;
}
bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst)
{
bool send = false;

View File

@ -104,6 +104,8 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle);
bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub, bool private);
uint16_t bt_mesh_proxy_client_get_conn_count(void);
bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst);
int bt_mesh_proxy_client_cfg_send(uint8_t conn_handle, uint16_t net_idx,

View File

@ -29,7 +29,7 @@
#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_SERVER
#if !CONFIG_BLE_MESH_BQB_TEST
#if !CONFIG_BLE_MESH_BQB_TEST && !CONFIG_BLE_MESH_PROXY_CLI_SRV_COEXIST && !CONFIG_BLE_MESH_RPR_SRV
/* Not support enabling Proxy Client and Proxy Server simultaneously */
_Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)),
"Not support Proxy Server and Proxy Client simultaneously");