net: coap: Rework pending retransmission logic

Introduce retransmission counter to the coap_pending structure. This
allows to simplify the retransmission logic and allows to keep track of
the number of remaining retranmissions.

Additionally, extend the `coap_pending_init()` function with `retries`
parameter, which allows to set the retransmission count individually for
each confirmable transaction.

Fixes #28117

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2021-01-18 13:13:26 +01:00 committed by Anas Nashif
commit 538e19ee2e
6 changed files with 35 additions and 25 deletions

View file

@ -58,6 +58,10 @@ API Changes
timeout usage must use the new-style k_timeout_t type and not the
legacy/deprecated millisecond counts.
* The :c:func:`coap_pending_init` function now accepts an additional ``retries``
parameter, allowing to specify the maximum retransmission count of the
confirmable message.
Deprecated in this release
==========================

View file

@ -233,6 +233,8 @@ typedef int (*coap_reply_t)(const struct coap_packet *response,
struct coap_reply *reply,
const struct sockaddr *from);
#define COAP_DEFAULT_MAX_RETRANSMIT 4
/**
* @brief Represents a request awaiting for an acknowledgment (ACK).
*/
@ -243,6 +245,7 @@ struct coap_pending {
uint16_t id;
uint8_t *data;
uint16_t len;
uint8_t retries;
};
/**
@ -687,12 +690,14 @@ void coap_reply_init(struct coap_reply *reply,
* confirmation message, initialized with data from @a request
* @param request Message waiting for confirmation
* @param addr Address to send the retransmission
* @param retries Maximum number of retransmissions of the message.
*
* @return 0 in case of success or negative in case of error.
*/
int coap_pending_init(struct coap_pending *pending,
const struct coap_packet *request,
const struct sockaddr *addr);
const struct sockaddr *addr,
uint8_t retries);
/**
* @brief Returns the next available pending struct, that can be used

View file

@ -995,7 +995,8 @@ static int create_pending_request(struct coap_packet *response,
return -ENOMEM;
}
r = coap_pending_init(pending, response, addr);
r = coap_pending_init(pending, response, addr,
COAP_DEFAULT_MAX_RETRANSMIT);
if (r < 0) {
return -EINVAL;
}

View file

@ -1072,7 +1072,8 @@ size_t coap_next_block(const struct coap_packet *cpkt,
int coap_pending_init(struct coap_pending *pending,
const struct coap_packet *request,
const struct sockaddr *addr)
const struct sockaddr *addr,
uint8_t retries)
{
memset(pending, 0, sizeof(*pending));
@ -1083,6 +1084,7 @@ int coap_pending_init(struct coap_pending *pending,
pending->data = request->data;
pending->len = request->offset;
pending->t0 = k_uptime_get_32();
pending->retries = retries;
return 0;
}
@ -1201,30 +1203,24 @@ struct coap_pending *coap_pending_next_to_expire(
*/
#define INIT_ACK_TIMEOUT CONFIG_COAP_INIT_ACK_TIMEOUT_MS
static int32_t next_timeout(int32_t previous)
{
switch (previous) {
case INIT_ACK_TIMEOUT:
case (INIT_ACK_TIMEOUT * 2):
case (INIT_ACK_TIMEOUT * 4):
return previous << 1;
case (INIT_ACK_TIMEOUT * 8):
/* equal value is returned to end retransmit */
return previous;
}
/* initial or unrecognized */
return INIT_ACK_TIMEOUT;
}
bool coap_pending_cycle(struct coap_pending *pending)
{
int32_t old = pending->timeout;
if (pending->timeout == 0) {
/* Initial transmission. */
pending->timeout = INIT_ACK_TIMEOUT;
return true;
}
if (pending->retries == 0) {
return false;
}
pending->t0 += pending->timeout;
pending->timeout = next_timeout(pending->timeout);
pending->timeout = pending->timeout << 1;
pending->retries--;
return (old != pending->timeout);
return true;
}
void coap_pending_clear(struct coap_pending *pending)

View file

@ -961,7 +961,8 @@ int lwm2m_init_message(struct lwm2m_message *msg)
goto cleanup;
}
r = coap_pending_init(msg->pending, &msg->cpkt, &msg->ctx->remote_addr);
r = coap_pending_init(msg->pending, &msg->cpkt, &msg->ctx->remote_addr,
COAP_DEFAULT_MAX_RETRANSMIT);
if (r < 0) {
LOG_ERR("Unable to initialize a pending "
"retransmission (err:%d).", r);
@ -3996,7 +3997,9 @@ static int lwm2m_response_promote_to_con(struct lwm2m_message *msg)
return -ENOMEM;
}
ret = coap_pending_init(msg->pending, &msg->cpkt, &msg->ctx->remote_addr);
ret = coap_pending_init(msg->pending, &msg->cpkt,
&msg->ctx->remote_addr,
COAP_DEFAULT_MAX_RETRANSMIT);
if (ret < 0) {
LOG_ERR("Unable to initialize a pending "
"retransmission (err:%d).", ret);

View file

@ -1099,7 +1099,8 @@ static int test_retransmit_second_round(void)
goto done;
}
r = coap_pending_init(pending, &cpkt, (struct sockaddr *) &dummy_addr);
r = coap_pending_init(pending, &cpkt, (struct sockaddr *) &dummy_addr,
COAP_DEFAULT_MAX_RETRANSMIT);
if (r < 0) {
TC_PRINT("Could not initialize packet\n");
goto done;