2020-08-20 05:42:23

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ] mesh: Use correct retransmit parameters for publications

This adds previously missing retransmit count and interval values
specific to model publications. The values are configured by Config CLient
and may be different to each model.
---
mesh/cfgmod-server.c | 26 +++++++++++-------
mesh/mesh-config-json.c | 36 ++++++++++++-------------
mesh/mesh-config.h | 4 +--
mesh/model.c | 59 +++++++++++++++++++++++------------------
mesh/model.h | 9 ++++---
mesh/net.c | 42 ++++++++++++++++++-----------
mesh/net.h | 6 ++---
7 files changed, 104 insertions(+), 78 deletions(-)

diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c
index 90ebdf046..239ea889d 100644
--- a/mesh/cfgmod-server.c
+++ b/mesh/cfgmod-server.c
@@ -48,7 +48,7 @@ static uint8_t msg[MAX_MSG_LEN];

static uint16_t set_pub_status(uint8_t status, uint16_t ele_addr, uint32_t id,
uint16_t pub_addr, uint16_t idx, bool cred_flag,
- uint8_t ttl, uint8_t period, uint8_t retransmit)
+ uint8_t ttl, uint8_t period, uint8_t rtx)
{
size_t n;

@@ -61,7 +61,7 @@ static uint16_t set_pub_status(uint8_t status, uint16_t ele_addr, uint32_t id,
n += 6;
msg[n++] = ttl;
msg[n++] = period;
- msg[n++] = retransmit;
+ msg[n++] = rtx;

if (!IS_VENDOR(id)) {
l_put_le16(MODEL_ID(id), msg + n);
@@ -80,6 +80,7 @@ static uint16_t config_pub_get(struct mesh_node *node, const uint8_t *pkt,
{
uint32_t id;
uint16_t ele_addr;
+ uint8_t rtx;
struct mesh_model_pub *pub;
int status;

@@ -88,10 +89,12 @@ static uint16_t config_pub_get(struct mesh_node *node, const uint8_t *pkt,

pub = mesh_model_pub_get(node, ele_addr, id, &status);

+ rtx = pub->rtx.cnt + (((pub->rtx.interval / 50) - 1) << 3);
+
if (pub && status == MESH_STATUS_SUCCESS)
return set_pub_status(status, ele_addr, id, pub->addr, pub->idx,
pub->credential, pub->ttl, pub->period,
- pub->retransmit);
+ rtx);
else
return set_pub_status(status, ele_addr, id, 0, 0, 0, 0, 0, 0);
}
@@ -102,7 +105,7 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
uint32_t id;
uint16_t ele_addr, idx, pub_dst;
const uint8_t *pub_addr;
- uint8_t ttl, period, retransmit;
+ uint8_t ttl, period, rtx, cnt, interval;
int status;
bool cred_flag;

@@ -124,12 +127,15 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
idx &= APP_IDX_MASK;
ttl = pkt[6];
period = pkt[7];
- retransmit = pkt[8];
+ rtx = pkt[8];
id = CFG_GET_ID(vendor, pkt + 9);

+ cnt = rtx & 0x7;
+ interval = ((rtx >> 3) + 1) * 50;
+
status = mesh_model_pub_set(node, ele_addr, id, pub_addr, idx,
- cred_flag, ttl, period, retransmit,
- virt, &pub_dst);
+ cred_flag, ttl, period, cnt,
+ interval, virt, &pub_dst);

l_debug("pub_set: status %d, ea %4.4x, ota: %4.4x, id: %x, idx: %3.3x",
status, ele_addr, pub_dst, id, idx);
@@ -153,8 +159,8 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
.ttl = ttl,
.credential = cred_flag,
.period = period,
- .count = retransmit & 0x7,
- .interval = ((retransmit >> 3) + 1) * 50
+ .cnt = cnt,
+ .interval = interval
};

if (virt)
@@ -168,7 +174,7 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
}

return set_pub_status(status, ele_addr, id, pub_dst, idx, cred_flag,
- ttl, period, retransmit);
+ ttl, period, rtx);
}

static uint16_t cfg_sub_get_msg(struct mesh_node *node, const uint8_t *pkt,
diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c
index a145388d6..63b6c3988 100644
--- a/mesh/mesh-config-json.c
+++ b/mesh/mesh-config-json.c
@@ -1021,7 +1021,7 @@ static struct mesh_config_pub *parse_model_publication(json_object *jpub)

if (!get_int(jvalue, "count", &value))
goto fail;
- pub->count = (uint8_t) value;
+ pub->cnt = (uint8_t) value;

if (!get_int(jvalue, "interval", &value))
goto fail;
@@ -1339,20 +1339,20 @@ static bool parse_composition(json_object *jcomp, struct mesh_config_node *node)

static bool read_net_transmit(json_object *jobj, struct mesh_config_node *node)
{
- json_object *jretransmit, *jvalue;
+ json_object *jrtx, *jvalue;
uint16_t interval;
uint8_t cnt;

- if (!json_object_object_get_ex(jobj, "retransmit", &jretransmit))
+ if (!json_object_object_get_ex(jobj, "retransmit", &jrtx))
return true;

- if (!json_object_object_get_ex(jretransmit, "count", &jvalue))
+ if (!json_object_object_get_ex(jrtx, "count", &jvalue))
return false;

/* TODO: add range checking */
cnt = (uint8_t) json_object_get_int(jvalue);

- if (!json_object_object_get_ex(jretransmit, "interval", &jvalue))
+ if (!json_object_object_get_ex(jrtx, "interval", &jvalue))
return false;

interval = (uint16_t) json_object_get_int(jvalue);
@@ -1566,30 +1566,30 @@ bool mesh_config_write_relay_mode(struct mesh_config *cfg, uint8_t mode,
bool mesh_config_write_net_transmit(struct mesh_config *cfg, uint8_t cnt,
uint16_t interval)
{
- json_object *jnode, *jretransmit;
+ json_object *jnode, *jrtx;

if (!cfg)
return false;

jnode = cfg->jnode;

- jretransmit = json_object_new_object();
- if (!jretransmit)
+ jrtx = json_object_new_object();
+ if (!jrtx)
return false;

- if (!write_int(jretransmit, "count", cnt))
+ if (!write_int(jrtx, "count", cnt))
goto fail;

- if (!write_int(jretransmit, "interval", interval))
+ if (!write_int(jrtx, "interval", interval))
goto fail;

json_object_object_del(jnode, "retransmit");
- json_object_object_add(jnode, "retransmit", jretransmit);
+ json_object_object_add(jnode, "retransmit", jrtx);

return save_config(cfg->jnode, cfg->node_dir_path);

fail:
- json_object_put(jretransmit);
+ json_object_put(jrtx);
return false;

}
@@ -1841,7 +1841,7 @@ bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t ele_addr,
uint32_t mod_id, bool vendor,
struct mesh_config_pub *pub)
{
- json_object *jnode, *jmodel, *jpub, *jretransmit;
+ json_object *jnode, *jmodel, *jpub, *jrtx;
bool res;
int ele_idx;

@@ -1885,17 +1885,17 @@ bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t ele_addr,
pub->credential ? 1 : 0))
goto fail;

- jretransmit = json_object_new_object();
- if (!jretransmit)
+ jrtx = json_object_new_object();
+ if (!jrtx)
goto fail;

- if (!write_int(jretransmit, "count", pub->count))
+ if (!write_int(jrtx, "count", pub->cnt))
goto fail;

- if (!write_int(jretransmit, "interval", pub->interval))
+ if (!write_int(jrtx, "interval", pub->interval))
goto fail;

- json_object_object_add(jpub, "retransmit", jretransmit);
+ json_object_object_add(jpub, "retransmit", jrtx);
json_object_object_add(jmodel, "publish", jpub);

return save_config(jnode, cfg->node_dir_path);
diff --git a/mesh/mesh-config.h b/mesh/mesh-config.h
index 50a55d51e..738cff9dd 100644
--- a/mesh/mesh-config.h
+++ b/mesh/mesh-config.h
@@ -34,10 +34,10 @@ struct mesh_config_pub {
uint32_t period;
uint16_t addr;
uint16_t idx;
+ uint16_t interval;
uint8_t ttl;
uint8_t credential;
- uint8_t count;
- uint8_t interval;
+ uint8_t cnt;
uint8_t virt_addr[16];
};

diff --git a/mesh/model.c b/mesh/model.c
index 961391f13..eb5142503 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -508,10 +508,11 @@ static int virt_packet_decrypt(struct mesh_net *net, const uint8_t *data,
return -1;
}

-static bool msg_send(struct mesh_node *node, bool credential, uint16_t src,
- uint32_t dst, uint16_t app_idx, uint16_t net_idx,
- uint8_t *label, uint8_t ttl, bool segmented,
- const void *msg, uint16_t msg_len)
+static bool msg_send(struct mesh_node *node, bool cred, uint16_t src,
+ uint16_t dst, uint16_t app_idx, uint16_t net_idx,
+ uint8_t *label, uint8_t ttl, uint8_t cnt,
+ uint16_t interval, bool segmented, const void *msg,
+ uint16_t msg_len)
{
uint8_t dev_key[16];
uint32_t iv_index, seq_num;
@@ -562,9 +563,9 @@ static bool msg_send(struct mesh_node *node, bool credential, uint16_t src,
goto done;
}

- ret = mesh_net_app_send(net, credential, src, dst, key_aid, net_idx,
- ttl, seq_num, iv_index, segmented,
- szmic, out, out_len);
+ ret = mesh_net_app_send(net, cred, src, dst, key_aid, net_idx, ttl,
+ cnt, interval, seq_num, iv_index,
+ segmented, szmic, out, out_len);
done:
l_free(out);
return ret;
@@ -705,7 +706,7 @@ static struct mesh_virtual *add_virtual(const uint8_t *v)

static int set_pub(struct mesh_model *mod, uint16_t pub_addr,
uint16_t idx, bool cred_flag, uint8_t ttl,
- uint8_t period, uint8_t retransmit)
+ uint8_t period, uint8_t cnt, uint16_t interval)
{
if (!mod->pub)
mod->pub = l_new(struct mesh_model_pub, 1);
@@ -715,14 +716,15 @@ static int set_pub(struct mesh_model *mod, uint16_t pub_addr,
mod->pub->idx = idx;
mod->pub->ttl = ttl;
mod->pub->period = period;
- mod->pub->retransmit = retransmit;
+ mod->pub->rtx.cnt = cnt;
+ mod->pub->rtx.interval = interval;

return MESH_STATUS_SUCCESS;
}

static int set_virt_pub(struct mesh_model *mod, const uint8_t *label,
uint16_t idx, bool cred_flag, uint8_t ttl,
- uint8_t period, uint8_t retransmit)
+ uint8_t period, uint8_t cnt, uint16_t interval)
{
struct mesh_virtual *virt = NULL;

@@ -734,8 +736,8 @@ static int set_virt_pub(struct mesh_model *mod, const uint8_t *label,
mod->pub = l_new(struct mesh_model_pub, 1);

mod->pub->virt = virt;
- return set_pub(mod, virt->addr, idx, cred_flag, ttl, period,
- retransmit);
+ return set_pub(mod, virt->addr, idx, cred_flag, ttl, period, cnt,
+ interval);
}

static int add_virt_sub(struct mesh_net *net, struct mesh_model *mod,
@@ -1058,9 +1060,10 @@ int mesh_model_publish(struct mesh_node *node, uint32_t id, uint16_t src,

net_idx = appkey_net_idx(net, mod->pub->idx);

- result = msg_send(node, mod->pub->credential != 0, src,
- mod->pub->addr, mod->pub->idx, net_idx,
- label, mod->pub->ttl, false, msg, msg_len);
+ result = msg_send(node, mod->pub->credential != 0, src, mod->pub->addr,
+ mod->pub->idx, net_idx, label, mod->pub->ttl,
+ mod->pub->rtx.cnt, mod->pub->rtx.interval,
+ false, msg, msg_len);

return result ? MESH_ERROR_NONE : MESH_ERROR_FAILED;
}
@@ -1070,6 +1073,10 @@ bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t dst,
uint8_t ttl, bool segmented,
const void *msg, uint16_t msg_len)
{
+ struct mesh_net *net = node_get_net(node);
+ uint8_t cnt;
+ uint16_t interval;
+
/* If SRC is 0, use the Primary Element */
if (src == 0)
src = node_get_primary(node);
@@ -1079,14 +1086,16 @@ bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t dst,
if (IS_UNASSIGNED(dst))
return false;

- return msg_send(node, false, src, dst, app_idx, net_idx,
- NULL, ttl, segmented, msg, msg_len);
+ mesh_net_transmit_params_get(net, &cnt, &interval);
+
+ return msg_send(node, false, src, dst, app_idx, net_idx, NULL, ttl, cnt,
+ interval, segmented, msg, msg_len);
}

int mesh_model_pub_set(struct mesh_node *node, uint16_t addr, uint32_t id,
const uint8_t *pub_addr, uint16_t idx, bool cred_flag,
- uint8_t ttl, uint8_t period, uint8_t retransmit,
- bool is_virt, uint16_t *pub_dst)
+ uint8_t ttl, uint8_t period, uint8_t cnt,
+ uint16_t interval, bool is_virt, uint16_t *pub_dst)
{
struct mesh_model *mod;
int status, ele_idx = node_get_element_idx(node, addr);
@@ -1124,10 +1133,10 @@ int mesh_model_pub_set(struct mesh_node *node, uint16_t addr, uint32_t id,

if (!is_virt) {
status = set_pub(mod, l_get_le16(pub_addr), idx, cred_flag,
- ttl, period, retransmit);
+ ttl, period, cnt, interval);
} else
status = set_virt_pub(mod, pub_addr, idx, cred_flag, ttl,
- period, retransmit);
+ period, cnt, interval);

*pub_dst = mod->pub->addr;

@@ -1703,15 +1712,13 @@ static struct mesh_model *model_setup(struct mesh_net *net, uint8_t ele_idx,

/* Add publication if enabled and present */
if (mod->pub_enabled && pub) {
- uint8_t retransmit = pub->count +
- ((pub->interval / 50 - 1) << 3);
if (pub->virt)
set_virt_pub(mod, pub->virt_addr, pub->idx,
- pub->credential, pub->ttl,
- pub->period, retransmit);
+ pub->credential, pub->ttl, pub->period,
+ pub->cnt, pub->interval);
else if (!IS_UNASSIGNED(pub->addr))
set_pub(mod, pub->addr, pub->idx, pub->credential,
- pub->ttl, pub->period, retransmit);
+ pub->ttl, pub->period, pub->cnt, pub->interval);
}

mod->sub_enabled = db_mod->sub_enabled;
diff --git a/mesh/model.h b/mesh/model.h
index 147a02279..a1afedd19 100644
--- a/mesh/model.h
+++ b/mesh/model.h
@@ -40,10 +40,13 @@ struct mesh_model_pub {
struct mesh_virtual *virt;
uint16_t addr;
uint16_t idx;
+ struct {
+ uint16_t interval;
+ uint8_t cnt;
+ } rtx;
uint8_t ttl;
uint8_t credential;
uint8_t period;
- uint8_t retransmit;
};

typedef void (*mesh_model_unregister)(void *user_data);
@@ -78,8 +81,8 @@ struct mesh_model_pub *mesh_model_pub_get(struct mesh_node *node,
uint32_t id, int *status);
int mesh_model_pub_set(struct mesh_node *node, uint16_t ele_addr, uint32_t id,
const uint8_t *addr, uint16_t idx, bool cred_flag,
- uint8_t ttl, uint8_t period, uint8_t retransmit,
- bool is_virt, uint16_t *dst);
+ uint8_t ttl, uint8_t period, uint8_t rtx_cnt,
+ uint16_t rtx_interval, bool is_virt, uint16_t *dst);

int mesh_model_binding_add(struct mesh_node *node, uint16_t ele_addr,
uint32_t id, uint16_t idx);
diff --git a/mesh/net.c b/mesh/net.c
index 26440b02d..93307e70c 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -212,6 +212,8 @@ struct net_queue_data {

struct oneshot_tx {
struct mesh_net *net;
+ uint16_t interval;
+ uint8_t cnt;
uint8_t size;
uint8_t packet[30];
};
@@ -1399,7 +1401,8 @@ static void friend_ack_rxed(struct mesh_net *net, uint32_t iv_index,
l_queue_foreach(net->friends, enqueue_friend_pkt, &frnd_ack);
}

-static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t seg);
+static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval,
+ struct mesh_sar *msg, uint8_t seg);

static void send_frnd_ack(struct mesh_net *net, uint16_t src, uint16_t dst,
uint32_t hdr, uint32_t flags)
@@ -1593,7 +1596,7 @@ static void ack_received(struct mesh_net *net, bool timeout,
l_debug("Resend Seg %d net:%p dst:%x app_idx:%3.3x",
i, net, outgoing->remote, outgoing->app_idx);

- send_seg(net, outgoing, i);
+ send_seg(net, net->tx_cnt, net->tx_interval, outgoing, i);
}

l_timeout_remove(outgoing->seg_timeout);
@@ -2143,8 +2146,8 @@ static void send_msg_pkt_oneshot(void *user_data)

tx->packet[0] = MESH_AD_TYPE_NETWORK;
info.type = MESH_IO_TIMING_TYPE_GENERAL;
- info.u.gen.interval = net->tx_interval;
- info.u.gen.cnt = net->tx_cnt;
+ info.u.gen.interval = tx->interval;
+ info.u.gen.cnt = tx->cnt;
info.u.gen.min_delay = DEFAULT_MIN_DELAY;
/* No extra randomization when sending regular mesh messages */
info.u.gen.max_delay = DEFAULT_MIN_DELAY;
@@ -2153,11 +2156,14 @@ static void send_msg_pkt_oneshot(void *user_data)
l_free(tx);
}

-static void send_msg_pkt(struct mesh_net *net, uint8_t *packet, uint8_t size)
+static void send_msg_pkt(struct mesh_net *net, uint8_t cnt, uint16_t interval,
+ uint8_t *packet, uint8_t size)
{
struct oneshot_tx *tx = l_new(struct oneshot_tx, 1);

tx->net = net;
+ tx->interval = interval;
+ tx->cnt = cnt;
tx->size = size;
memcpy(tx->packet, packet, size);

@@ -2872,7 +2878,8 @@ bool mesh_net_dst_unreg(struct mesh_net *net, uint16_t dst)
return true;
}

-static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
+static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval,
+ struct mesh_sar *msg, uint8_t segO)
{
struct mesh_subnet *subnet;
uint8_t seg_len;
@@ -2927,7 +2934,7 @@ static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
return false;
}

- send_msg_pkt(net, packet, packet_len + 1);
+ send_msg_pkt(net, cnt, interval, packet, packet_len + 1);

msg->last_seg = segO;

@@ -2967,7 +2974,8 @@ void mesh_net_send_seg(struct mesh_net *net, uint32_t net_key_id,
return;
}

- send_msg_pkt(net, packet, packet_len + 1);
+ send_msg_pkt(net, net->tx_cnt, net->tx_interval, packet,
+ packet_len + 1);

l_debug("TX: Friend Seg-%d %04x -> %04x : len %u) : TTL %d : SEQ %06x",
segO, src, dst, packet_len, ttl, seq);
@@ -2977,9 +2985,9 @@ void mesh_net_send_seg(struct mesh_net *net, uint32_t net_key_id,

bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
uint16_t dst, uint8_t key_aid, uint16_t net_idx,
- uint8_t ttl, uint32_t seq, uint32_t iv_index,
- bool segmented, bool szmic,
- const void *msg, uint16_t msg_len)
+ uint8_t ttl, uint8_t cnt, uint16_t interval,
+ uint32_t seq, uint32_t iv_index, bool segmented,
+ bool szmic, const void *msg, uint16_t msg_len)
{
struct mesh_sar *payload = NULL;
uint8_t seg, seg_max;
@@ -3054,11 +3062,12 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,

for (i = 0; i < 4; i++) {
for (seg = 0; seg <= seg_max && result; seg++)
- result = send_seg(net, payload, seg);
+ result = send_seg(net, cnt, interval, payload,
+ seg);
}
} else {
for (seg = 0; seg <= seg_max && result; seg++)
- result = send_seg(net, payload, seg);
+ result = send_seg(net, cnt, interval, payload, seg);
}

/* Reliable: Cache; Unreliable: Flush*/
@@ -3108,7 +3117,7 @@ void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id, uint32_t iv_index,
return;
}

- send_msg_pkt(net, pkt, pkt_len + 1);
+ send_msg_pkt(net, net->tx_cnt, net->tx_interval, pkt, pkt_len + 1);

l_debug("TX: Friend ACK %04x -> %04x : len %u : TTL %d : SEQ %06x",
src, dst, pkt_len, ttl, seq);
@@ -3182,8 +3191,9 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
return;
}

- if (dst != 0)
- send_msg_pkt(net, pkt, pkt_len + 1);
+ if (!(IS_UNASSIGNED(dst)))
+ send_msg_pkt(net, net->tx_cnt, net->tx_interval, pkt,
+ pkt_len + 1);
}

int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx,
diff --git a/mesh/net.h b/mesh/net.h
index 91e07ef78..253185e42 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -300,9 +300,9 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,

bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
uint16_t dst, uint8_t key_id, uint16_t net_idx,
- uint8_t ttl, uint32_t seq, uint32_t iv_index,
- bool segmented, bool szmic, const void *msg,
- uint16_t msg_len);
+ uint8_t ttl, uint8_t cnt, uint16_t interval,
+ uint32_t seq, uint32_t iv_index, bool segmented,
+ bool szmic, const void *msg, uint16_t msg_len);
void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id,
uint32_t iv_index, uint8_t ttl, uint32_t seq,
uint16_t src, uint16_t dst, bool rly,
--
2.26.2


2020-08-22 14:31:07

by Gix, Brian

[permalink] [raw]
Subject: Re: [PATCH BlueZ] mesh: Use correct retransmit parameters for publications

Applied
On Wed, 2020-08-19 at 22:41 -0700, Inga Stotland wrote:
> This adds previously missing retransmit count and interval values
> specific to model publications. The values are configured by Config CLient
> and may be different to each model.
> ---
> mesh/cfgmod-server.c | 26 +++++++++++-------
> mesh/mesh-config-json.c | 36 ++++++++++++-------------
> mesh/mesh-config.h | 4 +--
> mesh/model.c | 59 +++++++++++++++++++++++------------------
> mesh/model.h | 9 ++++---
> mesh/net.c | 42 ++++++++++++++++++-----------
> mesh/net.h | 6 ++---
> 7 files changed, 104 insertions(+), 78 deletions(-)
>
> diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c
> index 90ebdf046..239ea889d 100644
> --- a/mesh/cfgmod-server.c
> +++ b/mesh/cfgmod-server.c
> @@ -48,7 +48,7 @@ static uint8_t msg[MAX_MSG_LEN];
>
> static uint16_t set_pub_status(uint8_t status, uint16_t ele_addr, uint32_t id,
> uint16_t pub_addr, uint16_t idx, bool cred_flag,
> - uint8_t ttl, uint8_t period, uint8_t retransmit)
> + uint8_t ttl, uint8_t period, uint8_t rtx)
> {
> size_t n;
>
> @@ -61,7 +61,7 @@ static uint16_t set_pub_status(uint8_t status, uint16_t ele_addr, uint32_t id,
> n += 6;
> msg[n++] = ttl;
> msg[n++] = period;
> - msg[n++] = retransmit;
> + msg[n++] = rtx;
>
> if (!IS_VENDOR(id)) {
> l_put_le16(MODEL_ID(id), msg + n);
> @@ -80,6 +80,7 @@ static uint16_t config_pub_get(struct mesh_node *node, const uint8_t *pkt,
> {
> uint32_t id;
> uint16_t ele_addr;
> + uint8_t rtx;
> struct mesh_model_pub *pub;
> int status;
>
> @@ -88,10 +89,12 @@ static uint16_t config_pub_get(struct mesh_node *node, const uint8_t *pkt,
>
> pub = mesh_model_pub_get(node, ele_addr, id, &status);
>
> + rtx = pub->rtx.cnt + (((pub->rtx.interval / 50) - 1) << 3);
> +
> if (pub && status == MESH_STATUS_SUCCESS)
> return set_pub_status(status, ele_addr, id, pub->addr, pub->idx,
> pub->credential, pub->ttl, pub->period,
> - pub->retransmit);
> + rtx);
> else
> return set_pub_status(status, ele_addr, id, 0, 0, 0, 0, 0, 0);
> }
> @@ -102,7 +105,7 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
> uint32_t id;
> uint16_t ele_addr, idx, pub_dst;
> const uint8_t *pub_addr;
> - uint8_t ttl, period, retransmit;
> + uint8_t ttl, period, rtx, cnt, interval;
> int status;
> bool cred_flag;
>
> @@ -124,12 +127,15 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
> idx &= APP_IDX_MASK;
> ttl = pkt[6];
> period = pkt[7];
> - retransmit = pkt[8];
> + rtx = pkt[8];
> id = CFG_GET_ID(vendor, pkt + 9);
>
> + cnt = rtx & 0x7;
> + interval = ((rtx >> 3) + 1) * 50;
> +
> status = mesh_model_pub_set(node, ele_addr, id, pub_addr, idx,
> - cred_flag, ttl, period, retransmit,
> - virt, &pub_dst);
> + cred_flag, ttl, period, cnt,
> + interval, virt, &pub_dst);
>
> l_debug("pub_set: status %d, ea %4.4x, ota: %4.4x, id: %x, idx: %3.3x",
> status, ele_addr, pub_dst, id, idx);
> @@ -153,8 +159,8 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
> .ttl = ttl,
> .credential = cred_flag,
> .period = period,
> - .count = retransmit & 0x7,
> - .interval = ((retransmit >> 3) + 1) * 50
> + .cnt = cnt,
> + .interval = interval
> };
>
> if (virt)
> @@ -168,7 +174,7 @@ static uint16_t config_pub_set(struct mesh_node *node, const uint8_t *pkt,
> }
>
> return set_pub_status(status, ele_addr, id, pub_dst, idx, cred_flag,
> - ttl, period, retransmit);
> + ttl, period, rtx);
> }
>
> static uint16_t cfg_sub_get_msg(struct mesh_node *node, const uint8_t *pkt,
> diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c
> index a145388d6..63b6c3988 100644
> --- a/mesh/mesh-config-json.c
> +++ b/mesh/mesh-config-json.c
> @@ -1021,7 +1021,7 @@ static struct mesh_config_pub *parse_model_publication(json_object *jpub)
>
> if (!get_int(jvalue, "count", &value))
> goto fail;
> - pub->count = (uint8_t) value;
> + pub->cnt = (uint8_t) value;
>
> if (!get_int(jvalue, "interval", &value))
> goto fail;
> @@ -1339,20 +1339,20 @@ static bool parse_composition(json_object *jcomp, struct mesh_config_node *node)
>
> static bool read_net_transmit(json_object *jobj, struct mesh_config_node *node)
> {
> - json_object *jretransmit, *jvalue;
> + json_object *jrtx, *jvalue;
> uint16_t interval;
> uint8_t cnt;
>
> - if (!json_object_object_get_ex(jobj, "retransmit", &jretransmit))
> + if (!json_object_object_get_ex(jobj, "retransmit", &jrtx))
> return true;
>
> - if (!json_object_object_get_ex(jretransmit, "count", &jvalue))
> + if (!json_object_object_get_ex(jrtx, "count", &jvalue))
> return false;
>
> /* TODO: add range checking */
> cnt = (uint8_t) json_object_get_int(jvalue);
>
> - if (!json_object_object_get_ex(jretransmit, "interval", &jvalue))
> + if (!json_object_object_get_ex(jrtx, "interval", &jvalue))
> return false;
>
> interval = (uint16_t) json_object_get_int(jvalue);
> @@ -1566,30 +1566,30 @@ bool mesh_config_write_relay_mode(struct mesh_config *cfg, uint8_t mode,
> bool mesh_config_write_net_transmit(struct mesh_config *cfg, uint8_t cnt,
> uint16_t interval)
> {
> - json_object *jnode, *jretransmit;
> + json_object *jnode, *jrtx;
>
> if (!cfg)
> return false;
>
> jnode = cfg->jnode;
>
> - jretransmit = json_object_new_object();
> - if (!jretransmit)
> + jrtx = json_object_new_object();
> + if (!jrtx)
> return false;
>
> - if (!write_int(jretransmit, "count", cnt))
> + if (!write_int(jrtx, "count", cnt))
> goto fail;
>
> - if (!write_int(jretransmit, "interval", interval))
> + if (!write_int(jrtx, "interval", interval))
> goto fail;
>
> json_object_object_del(jnode, "retransmit");
> - json_object_object_add(jnode, "retransmit", jretransmit);
> + json_object_object_add(jnode, "retransmit", jrtx);
>
> return save_config(cfg->jnode, cfg->node_dir_path);
>
> fail:
> - json_object_put(jretransmit);
> + json_object_put(jrtx);
> return false;
>
> }
> @@ -1841,7 +1841,7 @@ bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t ele_addr,
> uint32_t mod_id, bool vendor,
> struct mesh_config_pub *pub)
> {
> - json_object *jnode, *jmodel, *jpub, *jretransmit;
> + json_object *jnode, *jmodel, *jpub, *jrtx;
> bool res;
> int ele_idx;
>
> @@ -1885,17 +1885,17 @@ bool mesh_config_model_pub_add(struct mesh_config *cfg, uint16_t ele_addr,
> pub->credential ? 1 : 0))
> goto fail;
>
> - jretransmit = json_object_new_object();
> - if (!jretransmit)
> + jrtx = json_object_new_object();
> + if (!jrtx)
> goto fail;
>
> - if (!write_int(jretransmit, "count", pub->count))
> + if (!write_int(jrtx, "count", pub->cnt))
> goto fail;
>
> - if (!write_int(jretransmit, "interval", pub->interval))
> + if (!write_int(jrtx, "interval", pub->interval))
> goto fail;
>
> - json_object_object_add(jpub, "retransmit", jretransmit);
> + json_object_object_add(jpub, "retransmit", jrtx);
> json_object_object_add(jmodel, "publish", jpub);
>
> return save_config(jnode, cfg->node_dir_path);
> diff --git a/mesh/mesh-config.h b/mesh/mesh-config.h
> index 50a55d51e..738cff9dd 100644
> --- a/mesh/mesh-config.h
> +++ b/mesh/mesh-config.h
> @@ -34,10 +34,10 @@ struct mesh_config_pub {
> uint32_t period;
> uint16_t addr;
> uint16_t idx;
> + uint16_t interval;
> uint8_t ttl;
> uint8_t credential;
> - uint8_t count;
> - uint8_t interval;
> + uint8_t cnt;
> uint8_t virt_addr[16];
> };
>
> diff --git a/mesh/model.c b/mesh/model.c
> index 961391f13..eb5142503 100644
> --- a/mesh/model.c
> +++ b/mesh/model.c
> @@ -508,10 +508,11 @@ static int virt_packet_decrypt(struct mesh_net *net, const uint8_t *data,
> return -1;
> }
>
> -static bool msg_send(struct mesh_node *node, bool credential, uint16_t src,
> - uint32_t dst, uint16_t app_idx, uint16_t net_idx,
> - uint8_t *label, uint8_t ttl, bool segmented,
> - const void *msg, uint16_t msg_len)
> +static bool msg_send(struct mesh_node *node, bool cred, uint16_t src,
> + uint16_t dst, uint16_t app_idx, uint16_t net_idx,
> + uint8_t *label, uint8_t ttl, uint8_t cnt,
> + uint16_t interval, bool segmented, const void *msg,
> + uint16_t msg_len)
> {
> uint8_t dev_key[16];
> uint32_t iv_index, seq_num;
> @@ -562,9 +563,9 @@ static bool msg_send(struct mesh_node *node, bool credential, uint16_t src,
> goto done;
> }
>
> - ret = mesh_net_app_send(net, credential, src, dst, key_aid, net_idx,
> - ttl, seq_num, iv_index, segmented,
> - szmic, out, out_len);
> + ret = mesh_net_app_send(net, cred, src, dst, key_aid, net_idx, ttl,
> + cnt, interval, seq_num, iv_index,
> + segmented, szmic, out, out_len);
> done:
> l_free(out);
> return ret;
> @@ -705,7 +706,7 @@ static struct mesh_virtual *add_virtual(const uint8_t *v)
>
> static int set_pub(struct mesh_model *mod, uint16_t pub_addr,
> uint16_t idx, bool cred_flag, uint8_t ttl,
> - uint8_t period, uint8_t retransmit)
> + uint8_t period, uint8_t cnt, uint16_t interval)
> {
> if (!mod->pub)
> mod->pub = l_new(struct mesh_model_pub, 1);
> @@ -715,14 +716,15 @@ static int set_pub(struct mesh_model *mod, uint16_t pub_addr,
> mod->pub->idx = idx;
> mod->pub->ttl = ttl;
> mod->pub->period = period;
> - mod->pub->retransmit = retransmit;
> + mod->pub->rtx.cnt = cnt;
> + mod->pub->rtx.interval = interval;
>
> return MESH_STATUS_SUCCESS;
> }
>
> static int set_virt_pub(struct mesh_model *mod, const uint8_t *label,
> uint16_t idx, bool cred_flag, uint8_t ttl,
> - uint8_t period, uint8_t retransmit)
> + uint8_t period, uint8_t cnt, uint16_t interval)
> {
> struct mesh_virtual *virt = NULL;
>
> @@ -734,8 +736,8 @@ static int set_virt_pub(struct mesh_model *mod, const uint8_t *label,
> mod->pub = l_new(struct mesh_model_pub, 1);
>
> mod->pub->virt = virt;
> - return set_pub(mod, virt->addr, idx, cred_flag, ttl, period,
> - retransmit);
> + return set_pub(mod, virt->addr, idx, cred_flag, ttl, period, cnt,
> + interval);
> }
>
> static int add_virt_sub(struct mesh_net *net, struct mesh_model *mod,
> @@ -1058,9 +1060,10 @@ int mesh_model_publish(struct mesh_node *node, uint32_t id, uint16_t src,
>
> net_idx = appkey_net_idx(net, mod->pub->idx);
>
> - result = msg_send(node, mod->pub->credential != 0, src,
> - mod->pub->addr, mod->pub->idx, net_idx,
> - label, mod->pub->ttl, false, msg, msg_len);
> + result = msg_send(node, mod->pub->credential != 0, src, mod->pub->addr,
> + mod->pub->idx, net_idx, label, mod->pub->ttl,
> + mod->pub->rtx.cnt, mod->pub->rtx.interval,
> + false, msg, msg_len);
>
> return result ? MESH_ERROR_NONE : MESH_ERROR_FAILED;
> }
> @@ -1070,6 +1073,10 @@ bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t dst,
> uint8_t ttl, bool segmented,
> const void *msg, uint16_t msg_len)
> {
> + struct mesh_net *net = node_get_net(node);
> + uint8_t cnt;
> + uint16_t interval;
> +
> /* If SRC is 0, use the Primary Element */
> if (src == 0)
> src = node_get_primary(node);
> @@ -1079,14 +1086,16 @@ bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t dst,
> if (IS_UNASSIGNED(dst))
> return false;
>
> - return msg_send(node, false, src, dst, app_idx, net_idx,
> - NULL, ttl, segmented, msg, msg_len);
> + mesh_net_transmit_params_get(net, &cnt, &interval);
> +
> + return msg_send(node, false, src, dst, app_idx, net_idx, NULL, ttl, cnt,
> + interval, segmented, msg, msg_len);
> }
>
> int mesh_model_pub_set(struct mesh_node *node, uint16_t addr, uint32_t id,
> const uint8_t *pub_addr, uint16_t idx, bool cred_flag,
> - uint8_t ttl, uint8_t period, uint8_t retransmit,
> - bool is_virt, uint16_t *pub_dst)
> + uint8_t ttl, uint8_t period, uint8_t cnt,
> + uint16_t interval, bool is_virt, uint16_t *pub_dst)
> {
> struct mesh_model *mod;
> int status, ele_idx = node_get_element_idx(node, addr);
> @@ -1124,10 +1133,10 @@ int mesh_model_pub_set(struct mesh_node *node, uint16_t addr, uint32_t id,
>
> if (!is_virt) {
> status = set_pub(mod, l_get_le16(pub_addr), idx, cred_flag,
> - ttl, period, retransmit);
> + ttl, period, cnt, interval);
> } else
> status = set_virt_pub(mod, pub_addr, idx, cred_flag, ttl,
> - period, retransmit);
> + period, cnt, interval);
>
> *pub_dst = mod->pub->addr;
>
> @@ -1703,15 +1712,13 @@ static struct mesh_model *model_setup(struct mesh_net *net, uint8_t ele_idx,
>
> /* Add publication if enabled and present */
> if (mod->pub_enabled && pub) {
> - uint8_t retransmit = pub->count +
> - ((pub->interval / 50 - 1) << 3);
> if (pub->virt)
> set_virt_pub(mod, pub->virt_addr, pub->idx,
> - pub->credential, pub->ttl,
> - pub->period, retransmit);
> + pub->credential, pub->ttl, pub->period,
> + pub->cnt, pub->interval);
> else if (!IS_UNASSIGNED(pub->addr))
> set_pub(mod, pub->addr, pub->idx, pub->credential,
> - pub->ttl, pub->period, retransmit);
> + pub->ttl, pub->period, pub->cnt, pub->interval);
> }
>
> mod->sub_enabled = db_mod->sub_enabled;
> diff --git a/mesh/model.h b/mesh/model.h
> index 147a02279..a1afedd19 100644
> --- a/mesh/model.h
> +++ b/mesh/model.h
> @@ -40,10 +40,13 @@ struct mesh_model_pub {
> struct mesh_virtual *virt;
> uint16_t addr;
> uint16_t idx;
> + struct {
> + uint16_t interval;
> + uint8_t cnt;
> + } rtx;
> uint8_t ttl;
> uint8_t credential;
> uint8_t period;
> - uint8_t retransmit;
> };
>
> typedef void (*mesh_model_unregister)(void *user_data);
> @@ -78,8 +81,8 @@ struct mesh_model_pub *mesh_model_pub_get(struct mesh_node *node,
> uint32_t id, int *status);
> int mesh_model_pub_set(struct mesh_node *node, uint16_t ele_addr, uint32_t id,
> const uint8_t *addr, uint16_t idx, bool cred_flag,
> - uint8_t ttl, uint8_t period, uint8_t retransmit,
> - bool is_virt, uint16_t *dst);
> + uint8_t ttl, uint8_t period, uint8_t rtx_cnt,
> + uint16_t rtx_interval, bool is_virt, uint16_t *dst);
>
> int mesh_model_binding_add(struct mesh_node *node, uint16_t ele_addr,
> uint32_t id, uint16_t idx);
> diff --git a/mesh/net.c b/mesh/net.c
> index 26440b02d..93307e70c 100644
> --- a/mesh/net.c
> +++ b/mesh/net.c
> @@ -212,6 +212,8 @@ struct net_queue_data {
>
> struct oneshot_tx {
> struct mesh_net *net;
> + uint16_t interval;
> + uint8_t cnt;
> uint8_t size;
> uint8_t packet[30];
> };
> @@ -1399,7 +1401,8 @@ static void friend_ack_rxed(struct mesh_net *net, uint32_t iv_index,
> l_queue_foreach(net->friends, enqueue_friend_pkt, &frnd_ack);
> }
>
> -static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t seg);
> +static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval,
> + struct mesh_sar *msg, uint8_t seg);
>
> static void send_frnd_ack(struct mesh_net *net, uint16_t src, uint16_t dst,
> uint32_t hdr, uint32_t flags)
> @@ -1593,7 +1596,7 @@ static void ack_received(struct mesh_net *net, bool timeout,
> l_debug("Resend Seg %d net:%p dst:%x app_idx:%3.3x",
> i, net, outgoing->remote, outgoing->app_idx);
>
> - send_seg(net, outgoing, i);
> + send_seg(net, net->tx_cnt, net->tx_interval, outgoing, i);
> }
>
> l_timeout_remove(outgoing->seg_timeout);
> @@ -2143,8 +2146,8 @@ static void send_msg_pkt_oneshot(void *user_data)
>
> tx->packet[0] = MESH_AD_TYPE_NETWORK;
> info.type = MESH_IO_TIMING_TYPE_GENERAL;
> - info.u.gen.interval = net->tx_interval;
> - info.u.gen.cnt = net->tx_cnt;
> + info.u.gen.interval = tx->interval;
> + info.u.gen.cnt = tx->cnt;
> info.u.gen.min_delay = DEFAULT_MIN_DELAY;
> /* No extra randomization when sending regular mesh messages */
> info.u.gen.max_delay = DEFAULT_MIN_DELAY;
> @@ -2153,11 +2156,14 @@ static void send_msg_pkt_oneshot(void *user_data)
> l_free(tx);
> }
>
> -static void send_msg_pkt(struct mesh_net *net, uint8_t *packet, uint8_t size)
> +static void send_msg_pkt(struct mesh_net *net, uint8_t cnt, uint16_t interval,
> + uint8_t *packet, uint8_t size)
> {
> struct oneshot_tx *tx = l_new(struct oneshot_tx, 1);
>
> tx->net = net;
> + tx->interval = interval;
> + tx->cnt = cnt;
> tx->size = size;
> memcpy(tx->packet, packet, size);
>
> @@ -2872,7 +2878,8 @@ bool mesh_net_dst_unreg(struct mesh_net *net, uint16_t dst)
> return true;
> }
>
> -static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
> +static bool send_seg(struct mesh_net *net, uint8_t cnt, uint16_t interval,
> + struct mesh_sar *msg, uint8_t segO)
> {
> struct mesh_subnet *subnet;
> uint8_t seg_len;
> @@ -2927,7 +2934,7 @@ static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
> return false;
> }
>
> - send_msg_pkt(net, packet, packet_len + 1);
> + send_msg_pkt(net, cnt, interval, packet, packet_len + 1);
>
> msg->last_seg = segO;
>
> @@ -2967,7 +2974,8 @@ void mesh_net_send_seg(struct mesh_net *net, uint32_t net_key_id,
> return;
> }
>
> - send_msg_pkt(net, packet, packet_len + 1);
> + send_msg_pkt(net, net->tx_cnt, net->tx_interval, packet,
> + packet_len + 1);
>
> l_debug("TX: Friend Seg-%d %04x -> %04x : len %u) : TTL %d : SEQ %06x",
> segO, src, dst, packet_len, ttl, seq);
> @@ -2977,9 +2985,9 @@ void mesh_net_send_seg(struct mesh_net *net, uint32_t net_key_id,
>
> bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
> uint16_t dst, uint8_t key_aid, uint16_t net_idx,
> - uint8_t ttl, uint32_t seq, uint32_t iv_index,
> - bool segmented, bool szmic,
> - const void *msg, uint16_t msg_len)
> + uint8_t ttl, uint8_t cnt, uint16_t interval,
> + uint32_t seq, uint32_t iv_index, bool segmented,
> + bool szmic, const void *msg, uint16_t msg_len)
> {
> struct mesh_sar *payload = NULL;
> uint8_t seg, seg_max;
> @@ -3054,11 +3062,12 @@ bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
>
> for (i = 0; i < 4; i++) {
> for (seg = 0; seg <= seg_max && result; seg++)
> - result = send_seg(net, payload, seg);
> + result = send_seg(net, cnt, interval, payload,
> + seg);
> }
> } else {
> for (seg = 0; seg <= seg_max && result; seg++)
> - result = send_seg(net, payload, seg);
> + result = send_seg(net, cnt, interval, payload, seg);
> }
>
> /* Reliable: Cache; Unreliable: Flush*/
> @@ -3108,7 +3117,7 @@ void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id, uint32_t iv_index,
> return;
> }
>
> - send_msg_pkt(net, pkt, pkt_len + 1);
> + send_msg_pkt(net, net->tx_cnt, net->tx_interval, pkt, pkt_len + 1);
>
> l_debug("TX: Friend ACK %04x -> %04x : len %u : TTL %d : SEQ %06x",
> src, dst, pkt_len, ttl, seq);
> @@ -3182,8 +3191,9 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
> return;
> }
>
> - if (dst != 0)
> - send_msg_pkt(net, pkt, pkt_len + 1);
> + if (!(IS_UNASSIGNED(dst)))
> + send_msg_pkt(net, net->tx_cnt, net->tx_interval, pkt,
> + pkt_len + 1);
> }
>
> int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx,
> diff --git a/mesh/net.h b/mesh/net.h
> index 91e07ef78..253185e42 100644
> --- a/mesh/net.h
> +++ b/mesh/net.h
> @@ -300,9 +300,9 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
>
> bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
> uint16_t dst, uint8_t key_id, uint16_t net_idx,
> - uint8_t ttl, uint32_t seq, uint32_t iv_index,
> - bool segmented, bool szmic, const void *msg,
> - uint16_t msg_len);
> + uint8_t ttl, uint8_t cnt, uint16_t interval,
> + uint32_t seq, uint32_t iv_index, bool segmented,
> + bool szmic, const void *msg, uint16_t msg_len);
> void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id,
> uint32_t iv_index, uint8_t ttl, uint32_t seq,
> uint16_t src, uint16_t dst, bool rly,