From c819f0f8d63bee3b1a7cc446a16e2e9db46739ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Wed, 11 Jan 2023 10:35:46 +0100 Subject: [PATCH] Bluetooth: Mesh: Separate adv tag/set for friend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of this commit is to facilitate future improvements to the LPN and friendship feature. By being able to identify friendship related messages on the advertising layer, it will be possible to treat these in a specific manner so that message exchange between LPN and friend devices can be conducted in a more power efficient manner. This commit adds the following: - A separate tag for friendship related messages - A optional separate advertising set for friend related messages Signed-off-by: Anders Storrø --- subsys/bluetooth/mesh/Kconfig | 22 +++++++++--- subsys/bluetooth/mesh/adv.c | 64 ++++++++++++++++++++++----------- subsys/bluetooth/mesh/adv.h | 5 ++- subsys/bluetooth/mesh/adv_ext.c | 60 ++++++++++++++++++++++++++----- subsys/bluetooth/mesh/friend.c | 2 +- 5 files changed, 117 insertions(+), 36 deletions(-) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index e6ae3f6f3ed..12aeb8cc50a 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -421,7 +421,17 @@ config BT_MESH_ADV_EXT_GATT_SEPARATE depends on BT_MESH_GATT_SERVER help Use a separate extended advertising set for GATT Server Advertising, - otherwise will be used a shared advertising set. + otherwise a shared advertising set will be used. + +config BT_MESH_ADV_EXT_FRIEND_SEPARATE + bool "Use a separate extended advertising set for Friend advertising" + depends on BT_MESH_FRIEND + help + Use a separate extended advertising set for Friend advertising, + otherwise a shared advertising set will be used. Using the separate + extended advertising set makes the Friend node send friendship + messages as close to the start of the ReceiveWindow as possible, + thus reducing the scanning time on the Low Power node. endif # BT_MESH_ADV_EXT @@ -880,12 +890,14 @@ config BT_MESH_FRIEND_SEG_RX config BT_MESH_FRIEND_ADV_LATENCY int "Latency for enabling advertising" + range 0 4 default 0 help - Latency in milliseconds that it takes to start friend advertising - after requesting it. Used to tune the receive delay window to make - Friend poll events more efficient by compensating for the time the - non-ideal latency otherwise would add to the delay. + Latency in milliseconds between request for and start of Friend + advertising. Used to tune the ReceiveDelay, making Friend + start sending a message earlier thus compensating for the time between + pushing the message to the Bluetooth host and the actual advertising + start. endif # BT_MESH_FRIEND diff --git a/subsys/bluetooth/mesh/adv.c b/subsys/bluetooth/mesh/adv.c index b517c59617d..f57e3717595 100644 --- a/subsys/bluetooth/mesh/adv.c +++ b/subsys/bluetooth/mesh/adv.c @@ -43,6 +43,7 @@ const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = { static K_FIFO_DEFINE(bt_mesh_adv_queue); static K_FIFO_DEFINE(bt_mesh_relay_queue); +static K_FIFO_DEFINE(bt_mesh_friend_queue); static void adv_buf_destroy(struct net_buf *buf) { @@ -67,6 +68,14 @@ NET_BUF_POOL_DEFINE(relay_buf_pool, CONFIG_BT_MESH_RELAY_BUF_COUNT, static struct bt_mesh_adv adv_relay_pool[CONFIG_BT_MESH_RELAY_BUF_COUNT]; #endif +#if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) +NET_BUF_POOL_DEFINE(friend_buf_pool, CONFIG_BT_MESH_FRIEND_LPN_COUNT, + BT_MESH_ADV_DATA_SIZE, BT_MESH_ADV_USER_DATA_SIZE, + adv_buf_destroy); + +static struct bt_mesh_adv adv_friend_pool[CONFIG_BT_MESH_FRIEND_LPN_COUNT]; +#endif + static struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *buf_pool, struct bt_mesh_adv *adv_pool, enum bt_mesh_adv_type type, @@ -110,11 +119,19 @@ struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, } #endif +#if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) + if (tag & BT_MESH_FRIEND_ADV) { + return bt_mesh_adv_create_from_pool(&friend_buf_pool, + adv_friend_pool, type, + tag, xmit, timeout); + } +#endif + return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_local_pool, type, tag, xmit, timeout); } -#if CONFIG_BT_MESH_RELAY_ADV_SETS +#if CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE static struct net_buf *process_events(struct k_poll_event *ev, int count) { for (; count; ev++, count--) { @@ -159,22 +176,21 @@ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) return process_events(events, ARRAY_SIZE(events)); } -static struct net_buf *bt_mesh_adv_buf_relay_get(k_timeout_t timeout) -{ - return net_buf_get(&bt_mesh_relay_queue, timeout); -} - struct net_buf *bt_mesh_adv_buf_get_by_tag(uint8_t tag, k_timeout_t timeout) { - if (tag & BT_MESH_LOCAL_ADV) { - return bt_mesh_adv_buf_get(timeout); - } else if (tag & BT_MESH_RELAY_ADV) { - return bt_mesh_adv_buf_relay_get(timeout); - } else { - return NULL; + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && tag & BT_MESH_FRIEND_ADV) { + return net_buf_get(&bt_mesh_friend_queue, timeout); } + +#if CONFIG_BT_MESH_RELAY_ADV_SETS + if (tag & BT_MESH_RELAY_ADV) { + return net_buf_get(&bt_mesh_relay_queue, timeout); + } +#endif + + return bt_mesh_adv_buf_get(timeout); } -#else /* !CONFIG_BT_MESH_RELAY_ADV_SETS */ +#else /* !(CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) */ struct net_buf *bt_mesh_adv_buf_get(k_timeout_t timeout) { return net_buf_get(&bt_mesh_adv_queue, timeout); @@ -186,7 +202,7 @@ struct net_buf *bt_mesh_adv_buf_get_by_tag(uint8_t tag, k_timeout_t timeout) return bt_mesh_adv_buf_get(timeout); } -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ +#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS || CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ void bt_mesh_adv_buf_get_cancel(void) { @@ -198,6 +214,9 @@ void bt_mesh_adv_buf_get_cancel(void) k_fifo_cancel_wait(&bt_mesh_relay_queue); #endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE)) { + k_fifo_cancel_wait(&bt_mesh_friend_queue); + } } void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, @@ -210,18 +229,23 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, BT_MESH_ADV(buf)->cb_data = cb_data; BT_MESH_ADV(buf)->busy = 1U; + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && + BT_MESH_ADV(buf)->tag == BT_MESH_FRIEND_ADV) { + net_buf_put(&bt_mesh_friend_queue, net_buf_ref(buf)); + bt_mesh_adv_buf_friend_ready(); + return; + } + #if CONFIG_BT_MESH_RELAY_ADV_SETS - if (BT_MESH_ADV(buf)->tag == BT_MESH_LOCAL_ADV) { - net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf)); - bt_mesh_adv_buf_local_ready(); - } else { + if (BT_MESH_ADV(buf)->tag == BT_MESH_RELAY_ADV) { net_buf_put(&bt_mesh_relay_queue, net_buf_ref(buf)); bt_mesh_adv_buf_relay_ready(); + return; } -#else /* !CONFIG_BT_MESH_RELAY_ADV_SETS */ +#endif + net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf)); bt_mesh_adv_buf_local_ready(); -#endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ } int bt_mesh_adv_gatt_send(void) diff --git a/subsys/bluetooth/mesh/adv.h b/subsys/bluetooth/mesh/adv.h index 220a59ba93d..f67a172afb0 100644 --- a/subsys/bluetooth/mesh/adv.h +++ b/subsys/bluetooth/mesh/adv.h @@ -29,6 +29,7 @@ enum bt_mesh_adv_tag { BT_MESH_LOCAL_ADV = BIT(0), BT_MESH_RELAY_ADV = BIT(1), BT_MESH_PROXY_ADV = BIT(2), + BT_MESH_FRIEND_ADV = BIT(3), }; struct bt_mesh_adv { @@ -38,7 +39,7 @@ struct bt_mesh_adv { uint8_t type:2, started:1, busy:1, - tag:3; + tag:4; uint8_t xmit; }; @@ -74,6 +75,8 @@ void bt_mesh_adv_buf_local_ready(void); void bt_mesh_adv_buf_relay_ready(void); +void bt_mesh_adv_buf_friend_ready(void); + int bt_mesh_adv_gatt_send(void); int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param, int32_t duration, diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index c175bc03dde..f0ef1585a6e 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -68,6 +68,9 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv); static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = { .tag = ( +#if !defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) + BT_MESH_FRIEND_ADV | +#endif #if !defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) BT_MESH_PROXY_ADV | #endif /* !CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ @@ -88,16 +91,28 @@ static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_relay[CONFIG_BT_MESH_RELAY_A }; #endif /* CONFIG_BT_MESH_RELAY_ADV_SETS */ +#if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) +#define ADV_EXT_FRIEND 1 +static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_friend) = { + .tag = BT_MESH_FRIEND_ADV, + .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), +}; +#else /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ +#define ADV_EXT_FRIEND 0 +#endif /* CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE */ + #if defined(CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE) -#define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_RELAY_ADV_SETS + 1) +#define ADV_EXT_GATT 1 static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_gatt) = { .tag = BT_MESH_PROXY_ADV, .work = Z_WORK_DELAYABLE_INITIALIZER(send_pending_adv), }; #else /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ -#define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_RELAY_ADV_SETS) +#define ADV_EXT_GATT 0 #endif /* CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE */ +#define BT_MESH_ADV_COUNT (1 + CONFIG_BT_MESH_RELAY_ADV_SETS + ADV_EXT_FRIEND + ADV_EXT_GATT) + BUILD_ASSERT(CONFIG_BT_EXT_ADV_MAX_ADV_SET >= BT_MESH_ADV_COUNT, "Insufficient adv instances"); @@ -208,6 +223,21 @@ static int buf_send(struct bt_mesh_ext_adv *adv, struct net_buf *buf) return err; } +static const char *adv_tag_to_str(enum bt_mesh_adv_tag tag) +{ + if (tag & BT_MESH_LOCAL_ADV) { + return "local adv"; + } else if (tag & BT_MESH_PROXY_ADV) { + return "proxy adv"; + } else if (tag & BT_MESH_RELAY_ADV) { + return "relay adv"; + } else if (tag & BT_MESH_FRIEND_ADV) { + return "friend adv"; + } else { + return "(unknown tag)"; + } +} + static void send_pending_adv(struct k_work *work) { struct bt_mesh_ext_adv *adv; @@ -223,7 +253,8 @@ static void send_pending_adv(struct k_work *work) */ int64_t duration = k_uptime_delta(&adv->timestamp); - LOG_DBG("Advertising stopped after %u ms", (uint32_t)duration); + LOG_DBG("Advertising stopped after %u ms for (%u) %s", (uint32_t)duration, adv->tag, + adv_tag_to_str(adv->tag)); atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE); atomic_clear_bit(adv->flags, ADV_FLAG_PROXY); @@ -297,12 +328,16 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv) atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING); - /* The controller will send the next advertisement immediately. - * Introduce a delay here to avoid sending the next mesh packet closer - * to the previous packet than what's permitted by the specification. - */ - delta = k_uptime_delta(×tamp); - k_work_reschedule(&adv->work, K_MSEC(ADV_INT_FAST_MS - delta)); + if (IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && adv->tag & BT_MESH_FRIEND_ADV) { + k_work_reschedule(&adv->work, K_NO_WAIT); + } else { + /* The controller will send the next advertisement immediately. + * Introduce a delay here to avoid sending the next mesh packet closer + * to the previous packet than what's permitted by the specification. + */ + delta = k_uptime_delta(×tamp); + k_work_reschedule(&adv->work, K_MSEC(ADV_INT_FAST_MS - delta)); + } return true; } @@ -333,6 +368,13 @@ void bt_mesh_adv_buf_relay_ready(void) } } +void bt_mesh_adv_buf_friend_ready(void) +{ +#if defined(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) + (void)schedule_send(&adv_friend); +#endif +} + void bt_mesh_adv_init(void) { struct bt_le_adv_param adv_param = { diff --git a/subsys/bluetooth/mesh/friend.c b/subsys/bluetooth/mesh/friend.c index 2d532ccb759..18bfe6c110e 100644 --- a/subsys/bluetooth/mesh/friend.c +++ b/subsys/bluetooth/mesh/friend.c @@ -1269,7 +1269,7 @@ static void friend_timeout(struct k_work *work) frnd->queue_size--; send_last: - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_LOCAL_ADV, + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, BT_MESH_FRIEND_ADV, FRIEND_XMIT, K_NO_WAIT); if (!buf) { LOG_ERR("Unable to allocate friend adv buffer");