Bluetooth: Mesh: Fix (re)transmit interval handling

The adv_send() function was incorrectly decoding the 5-bit value (it
was using it directly as milliseconds), which effectively lead to the
code always picking the controller's minimum supported interval.

Fix this issue, but do it by simplifying the (re)transmission state
tracking so that the state is always stored in the original "packed"
8-bit value, where 5 bits are reserved for the interval, and 3 for the
count.

Fixes #7972

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-06-04 14:06:48 +02:00 committed by Carles Cufí
commit ed5fb3ff37
8 changed files with 34 additions and 49 deletions

View file

@ -197,8 +197,8 @@ struct bt_mesh_model_op {
* @brief Encode transmission count & interval steps. * @brief Encode transmission count & interval steps.
* *
* @param count Number of retransmissions (first transmission is excluded). * @param count Number of retransmissions (first transmission is excluded).
* @param int_ms Interval steps in milliseconds. Must be greater than 0 * @param int_ms Interval steps in milliseconds. Must be greater than 0,
* and a multiple of 10. * less than or equal to 320, and a multiple of 10.
* *
* @return Mesh transmit value that can be used e.g. for the default * @return Mesh transmit value that can be used e.g. for the default
* values of the configuration model data. * values of the configuration model data.

View file

@ -102,14 +102,17 @@ static inline void adv_send(struct net_buf *buf)
struct bt_data ad; struct bt_data ad;
int err; int err;
adv_int = max(adv_int_min, BT_MESH_ADV(buf)->adv_int); adv_int = max(adv_int_min,
duration = MESH_SCAN_WINDOW_MS + BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit));
((BT_MESH_ADV(buf)->count + 1) * (adv_int + 10)); duration = (MESH_SCAN_WINDOW_MS +
((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) *
(adv_int + 10)));
BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type, BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type,
buf->len, bt_hex(buf->data, buf->len)); buf->len, bt_hex(buf->data, buf->len));
BT_DBG("count %u interval %ums duration %ums", BT_DBG("count %u interval %ums duration %ums",
BT_MESH_ADV(buf)->count + 1, adv_int, duration); BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int,
duration);
ad.type = adv_type[BT_MESH_ADV(buf)->type]; ad.type = adv_type[BT_MESH_ADV(buf)->type];
ad.data_len = buf->len; ad.data_len = buf->len;
@ -204,8 +207,7 @@ void bt_mesh_adv_update(void)
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
bt_mesh_adv_alloc_t get_id, bt_mesh_adv_alloc_t get_id,
enum bt_mesh_adv_type type, enum bt_mesh_adv_type type,
u8_t xmit_count, u8_t xmit_int, u8_t xmit, s32_t timeout)
s32_t timeout)
{ {
struct bt_mesh_adv *adv; struct bt_mesh_adv *adv;
struct net_buf *buf; struct net_buf *buf;
@ -221,17 +223,16 @@ struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
memset(adv, 0, sizeof(*adv)); memset(adv, 0, sizeof(*adv));
adv->type = type; adv->type = type;
adv->count = xmit_count; adv->xmit = xmit;
adv->adv_int = xmit_int;
return buf; return buf;
} }
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit_count, struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
u8_t xmit_int, s32_t timeout) s32_t timeout)
{ {
return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type, return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type,
xmit_count, xmit_int, timeout); xmit, timeout);
} }
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,

View file

@ -30,8 +30,8 @@ struct bt_mesh_adv {
u8_t type:2, u8_t type:2,
busy:1; busy:1;
u8_t count:3, u8_t xmit;
adv_int:5;
union { union {
/* Address, used e.g. for Friend Queue messages */ /* Address, used e.g. for Friend Queue messages */
u16_t addr; u16_t addr;
@ -46,14 +46,13 @@ struct bt_mesh_adv {
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id); typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */ /* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit_count, struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
u8_t xmit_int, s32_t timeout); s32_t timeout);
struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
bt_mesh_adv_alloc_t get_id, bt_mesh_adv_alloc_t get_id,
enum bt_mesh_adv_type type, enum bt_mesh_adv_type type,
u8_t xmit_count, u8_t xmit_int, u8_t xmit, s32_t timeout);
s32_t timeout);
void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
void *cb_data); void *cb_data);

View file

@ -33,12 +33,10 @@
#define BEACON_TYPE_SECURE 0x01 #define BEACON_TYPE_SECURE 0x01
/* 3 transmissions, 20ms interval */ /* 3 transmissions, 20ms interval */
#define UNPROV_XMIT_COUNT 2 #define UNPROV_XMIT BT_MESH_TRANSMIT(2, 20)
#define UNPROV_XMIT_INT 20
/* 1 transmission, 20ms interval */ /* 1 transmission, 20ms interval */
#define PROV_XMIT_COUNT 0 #define PROV_XMIT BT_MESH_TRANSMIT(0, 20)
#define PROV_XMIT_INT 20
static struct k_delayed_work beacon_timer; static struct k_delayed_work beacon_timer;
@ -134,8 +132,8 @@ static int secure_beacon_send(void)
continue; continue;
} }
buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT_COUNT, buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
PROV_XMIT_INT, K_NO_WAIT); K_NO_WAIT);
if (!buf) { if (!buf) {
BT_ERR("Unable to allocate beacon buffer"); BT_ERR("Unable to allocate beacon buffer");
return -ENOBUFS; return -ENOBUFS;
@ -160,8 +158,7 @@ static int unprovisioned_beacon_send(void)
BT_DBG(""); BT_DBG("");
buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT_COUNT, buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT, K_NO_WAIT);
UNPROV_XMIT_INT, K_NO_WAIT);
if (!buf) { if (!buf) {
BT_ERR("Unable to allocate beacon buffer"); BT_ERR("Unable to allocate beacon buffer");
return -ENOBUFS; return -ENOBUFS;
@ -187,8 +184,8 @@ static int unprovisioned_beacon_send(void)
if (prov->uri) { if (prov->uri) {
size_t len; size_t len;
buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT_COUNT, buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT,
UNPROV_XMIT_INT, K_NO_WAIT); K_NO_WAIT);
if (!buf) { if (!buf) {
BT_ERR("Unable to allocate URI buffer"); BT_ERR("Unable to allocate URI buffer");
return -ENOBUFS; return -ENOBUFS;

View file

@ -40,8 +40,7 @@
/* PDUs from Friend to the LPN should only be transmitted once with the /* PDUs from Friend to the LPN should only be transmitted once with the
* smallest possible interval (20ms). * smallest possible interval (20ms).
*/ */
#define FRIEND_XMIT_COUNT 0 #define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20)
#define FRIEND_XMIT_INT 20
struct friend_pdu_info { struct friend_pdu_info {
u16_t src; u16_t src;
@ -96,8 +95,7 @@ static struct net_buf *friend_buf_alloc(u16_t src)
do { do {
buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc, buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc,
BT_MESH_ADV_DATA, BT_MESH_ADV_DATA,
FRIEND_XMIT_COUNT, FRIEND_XMIT, K_NO_WAIT);
FRIEND_XMIT_INT, K_NO_WAIT);
if (!buf) { if (!buf) {
discard_buffer(); discard_buffer();
} }

View file

@ -1170,9 +1170,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
transmit = bt_mesh_net_transmit_get(); transmit = bt_mesh_net_transmit_get();
} }
buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, transmit, K_NO_WAIT);
BT_MESH_TRANSMIT_COUNT(transmit),
BT_MESH_TRANSMIT_INT(transmit), K_NO_WAIT);
if (!buf) { if (!buf) {
BT_ERR("Out of relay buffers"); BT_ERR("Out of relay buffers");
return; return;

View file

@ -34,8 +34,7 @@
#include "prov.h" #include "prov.h"
/* 3 transmissions, 20ms interval */ /* 3 transmissions, 20ms interval */
#define PROV_XMIT_COUNT 2 #define PROV_XMIT BT_MESH_TRANSMIT(2, 20)
#define PROV_XMIT_INT 20
#define AUTH_METHOD_NO_OOB 0x00 #define AUTH_METHOD_NO_OOB 0x00
#define AUTH_METHOD_STATIC 0x01 #define AUTH_METHOD_STATIC 0x01
@ -264,8 +263,7 @@ static struct net_buf *adv_buf_create(void)
{ {
struct net_buf *buf; struct net_buf *buf;
buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT_COUNT, buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT, BUF_TIMEOUT);
PROV_XMIT_INT, BUF_TIMEOUT);
if (!buf) { if (!buf) {
BT_ERR("Out of provisioning buffers"); BT_ERR("Out of provisioning buffers");
return NULL; return NULL;

View file

@ -115,9 +115,7 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u", BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u",
tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->len); tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->len);
buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
BT_MESH_TRANSMIT_COUNT(tx->xmit),
BT_MESH_TRANSMIT_INT(tx->xmit), BUF_TIMEOUT);
if (!buf) { if (!buf) {
BT_ERR("Out of network buffers"); BT_ERR("Out of network buffers");
return -ENOBUFS; return -ENOBUFS;
@ -356,9 +354,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
u16_t len; u16_t len;
int err; int err;
seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, net_tx->xmit,
BT_MESH_TRANSMIT_COUNT(net_tx->xmit),
BT_MESH_TRANSMIT_INT(net_tx->xmit),
BUF_TIMEOUT); BUF_TIMEOUT);
if (!seg) { if (!seg) {
BT_ERR("Out of segment buffers"); BT_ERR("Out of segment buffers");
@ -930,9 +926,7 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
tx->ctx->addr, tx->ctx->send_ttl, ctl_op); tx->ctx->addr, tx->ctx->send_ttl, ctl_op);
BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len)); BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len));
buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
BT_MESH_TRANSMIT_COUNT(tx->xmit),
BT_MESH_TRANSMIT_INT(tx->xmit), BUF_TIMEOUT);
if (!buf) { if (!buf) {
BT_ERR("Out of transport buffers"); BT_ERR("Out of transport buffers");
return -ENOBUFS; return -ENOBUFS;