net: lwm2m: Fix retransmission logic
The retaransmission logic was not correct in the lwm2m_engine, and could lead to faulty behavior in case multiple messages were pending for retransmission in the queue. 1. Since there is a singe delayed work item for entire retransmission queue, `coap_pending_next_to_expire` should be called before scheduling next timeout, to identify which message is going to expire next (and when). Currently, the engine always set next timeout, based on timeout from the message being currently re-transmitted. 2. In case the message was re-transmitted several times, and is removed from the retansmission queue due to a timeout, next retransmission should be scheduled, in case there are other messages on the queue. 3. Verify the timeout of the earliest message to expire in the retransmission handler. In case messages from the beginning of the queue were removed, we might need to schedule the retransmission again, instead of sending message rightaway. 4. `lwm2m_send_message` is not handling retransmissions anyway, so there's no need to check send attempts. Instead, verify retransmission work item is already pending, and update its timeout if needed. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
df152ab59f
commit
afb73d1d09
1 changed files with 34 additions and 10 deletions
|
@ -1037,13 +1037,16 @@ int lwm2m_send_message(struct lwm2m_message *msg)
|
|||
}
|
||||
|
||||
if (msg->type == COAP_TYPE_CON) {
|
||||
/* don't re-queue the retransmit work on retransmits */
|
||||
if (msg->send_attempts > 1) {
|
||||
return 0;
|
||||
}
|
||||
s32_t remaining = k_delayed_work_remaining_get(
|
||||
&msg->ctx->retransmit_work);
|
||||
|
||||
k_delayed_work_submit(&msg->ctx->retransmit_work,
|
||||
K_MSEC(msg->pending->timeout));
|
||||
/* If the item is already pending and its timeout is smaller
|
||||
* than the new one, skip the submission.
|
||||
*/
|
||||
if (remaining == 0 || remaining > msg->pending->timeout) {
|
||||
k_delayed_work_submit(&msg->ctx->retransmit_work,
|
||||
K_MSEC(msg->pending->timeout));
|
||||
}
|
||||
} else {
|
||||
lwm2m_reset_message(msg, true);
|
||||
}
|
||||
|
@ -3717,6 +3720,7 @@ static void retransmit_request(struct k_work *work)
|
|||
struct lwm2m_ctx *client_ctx;
|
||||
struct lwm2m_message *msg;
|
||||
struct coap_pending *pending;
|
||||
s32_t remaining;
|
||||
|
||||
client_ctx = CONTAINER_OF(work, struct lwm2m_ctx, retransmit_work);
|
||||
pending = coap_pending_next_to_expire(client_ctx->pendings,
|
||||
|
@ -3725,10 +3729,19 @@ static void retransmit_request(struct k_work *work)
|
|||
return;
|
||||
}
|
||||
|
||||
remaining = pending->t0 + pending->timeout - k_uptime_get_32();
|
||||
if (remaining > 0) {
|
||||
/* First message to expire was removed from the list,
|
||||
* schedule next.
|
||||
*/
|
||||
goto next;
|
||||
}
|
||||
|
||||
msg = find_msg(pending, NULL);
|
||||
if (!msg) {
|
||||
LOG_ERR("pending has no valid LwM2M message!");
|
||||
return;
|
||||
coap_pending_clear(pending);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (!coap_pending_cycle(pending)) {
|
||||
|
@ -3742,7 +3755,7 @@ static void retransmit_request(struct k_work *work)
|
|||
* which balances the ref we made in coap_pending_cycle()
|
||||
*/
|
||||
lwm2m_reset_message(msg, true);
|
||||
return;
|
||||
goto next;
|
||||
}
|
||||
|
||||
LOG_INF("Resending message: %p", msg);
|
||||
|
@ -3752,8 +3765,19 @@ static void retransmit_request(struct k_work *work)
|
|||
/* don't error here, retry until timeout */
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&client_ctx->retransmit_work,
|
||||
K_MSEC(pending->timeout));
|
||||
next:
|
||||
pending = coap_pending_next_to_expire(client_ctx->pendings,
|
||||
CONFIG_LWM2M_ENGINE_MAX_PENDING);
|
||||
if (!pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
remaining = pending->t0 + pending->timeout - k_uptime_get_32();
|
||||
if (remaining < 0) {
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&client_ctx->retransmit_work, K_MSEC(remaining));
|
||||
}
|
||||
|
||||
static int notify_message_reply_cb(const struct coap_packet *response,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue