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
|
||||
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
|
||||
==========================
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue