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:
parent
812914ff5d
commit
538e19ee2e
6 changed files with 35 additions and 25 deletions
|
@ -58,6 +58,10 @@ API Changes
|
||||||
timeout usage must use the new-style k_timeout_t type and not the
|
timeout usage must use the new-style k_timeout_t type and not the
|
||||||
legacy/deprecated millisecond counts.
|
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
|
Deprecated in this release
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
|
|
@ -233,6 +233,8 @@ typedef int (*coap_reply_t)(const struct coap_packet *response,
|
||||||
struct coap_reply *reply,
|
struct coap_reply *reply,
|
||||||
const struct sockaddr *from);
|
const struct sockaddr *from);
|
||||||
|
|
||||||
|
#define COAP_DEFAULT_MAX_RETRANSMIT 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Represents a request awaiting for an acknowledgment (ACK).
|
* @brief Represents a request awaiting for an acknowledgment (ACK).
|
||||||
*/
|
*/
|
||||||
|
@ -243,6 +245,7 @@ struct coap_pending {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint16_t len;
|
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
|
* confirmation message, initialized with data from @a request
|
||||||
* @param request Message waiting for confirmation
|
* @param request Message waiting for confirmation
|
||||||
* @param addr Address to send the retransmission
|
* @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.
|
* @return 0 in case of success or negative in case of error.
|
||||||
*/
|
*/
|
||||||
int coap_pending_init(struct coap_pending *pending,
|
int coap_pending_init(struct coap_pending *pending,
|
||||||
const struct coap_packet *request,
|
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
|
* @brief Returns the next available pending struct, that can be used
|
||||||
|
|
|
@ -995,7 +995,8 @@ static int create_pending_request(struct coap_packet *response,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = coap_pending_init(pending, response, addr);
|
r = coap_pending_init(pending, response, addr,
|
||||||
|
COAP_DEFAULT_MAX_RETRANSMIT);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1072,7 +1072,8 @@ size_t coap_next_block(const struct coap_packet *cpkt,
|
||||||
|
|
||||||
int coap_pending_init(struct coap_pending *pending,
|
int coap_pending_init(struct coap_pending *pending,
|
||||||
const struct coap_packet *request,
|
const struct coap_packet *request,
|
||||||
const struct sockaddr *addr)
|
const struct sockaddr *addr,
|
||||||
|
uint8_t retries)
|
||||||
{
|
{
|
||||||
memset(pending, 0, sizeof(*pending));
|
memset(pending, 0, sizeof(*pending));
|
||||||
|
|
||||||
|
@ -1083,6 +1084,7 @@ int coap_pending_init(struct coap_pending *pending,
|
||||||
pending->data = request->data;
|
pending->data = request->data;
|
||||||
pending->len = request->offset;
|
pending->len = request->offset;
|
||||||
pending->t0 = k_uptime_get_32();
|
pending->t0 = k_uptime_get_32();
|
||||||
|
pending->retries = retries;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1201,30 +1203,24 @@ struct coap_pending *coap_pending_next_to_expire(
|
||||||
*/
|
*/
|
||||||
#define INIT_ACK_TIMEOUT CONFIG_COAP_INIT_ACK_TIMEOUT_MS
|
#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)
|
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->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)
|
void coap_pending_clear(struct coap_pending *pending)
|
||||||
|
|
|
@ -961,7 +961,8 @@ int lwm2m_init_message(struct lwm2m_message *msg)
|
||||||
goto cleanup;
|
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) {
|
if (r < 0) {
|
||||||
LOG_ERR("Unable to initialize a pending "
|
LOG_ERR("Unable to initialize a pending "
|
||||||
"retransmission (err:%d).", r);
|
"retransmission (err:%d).", r);
|
||||||
|
@ -3996,7 +3997,9 @@ static int lwm2m_response_promote_to_con(struct lwm2m_message *msg)
|
||||||
return -ENOMEM;
|
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) {
|
if (ret < 0) {
|
||||||
LOG_ERR("Unable to initialize a pending "
|
LOG_ERR("Unable to initialize a pending "
|
||||||
"retransmission (err:%d).", ret);
|
"retransmission (err:%d).", ret);
|
||||||
|
|
|
@ -1099,7 +1099,8 @@ static int test_retransmit_second_round(void)
|
||||||
goto done;
|
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) {
|
if (r < 0) {
|
||||||
TC_PRINT("Could not initialize packet\n");
|
TC_PRINT("Could not initialize packet\n");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue