Skip to content

Commit

Permalink
net: coap: Rework pending retransmission logic
Browse files Browse the repository at this point in the history
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 zephyrproject-rtos#28117

Signed-off-by: Robert Lubos <[email protected]>
  • Loading branch information
rlubos committed Jan 18, 2021
1 parent 78c77da commit 8a5268c
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 24 deletions.
4 changes: 4 additions & 0 deletions doc/releases/release-notes-2.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
==========================

Expand Down
7 changes: 6 additions & 1 deletion include/net/coap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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).
*/
Expand All @@ -243,6 +245,7 @@ struct coap_pending {
uint16_t id;
uint8_t *data;
uint16_t len;
uint8_t retries;
};

/**
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion samples/net/sockets/coap_server/src/coap-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
34 changes: 15 additions & 19 deletions subsys/net/lib/coap/coap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
bool coap_pending_cycle(struct coap_pending *pending)
{
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;
}
if (pending->timeout == 0) {
/* Initial transmission. */
pending->timeout = INIT_ACK_TIMEOUT;

/* initial or unrecognized */
return INIT_ACK_TIMEOUT;
}
return true;
}

bool coap_pending_cycle(struct coap_pending *pending)
{
int32_t old = pending->timeout;
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)
Expand Down
7 changes: 5 additions & 2 deletions subsys/net/lib/lwm2m/lwm2m_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion tests/net/lib/coap/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 8a5268c

Please sign in to comment.