net: coap: Add initial tx time to coap_pending structure

So far, coap_pending structure kept track only of the timeout interval
between two consecutive retransmissions. Calculations inside
`coap_pending_next_to_expire` relied only on this value. This approach
gives incorrect results though, in case multiple messages are pending
for retransmission.

For instance, assuming initial retransmission timeout is set to 2
seconds. If some message had been retransmitted already, its timeout
would be increased to 4 seconds. Any new message added to the pending
list would have a retransmission timeout set to 2 seconds, and will be
returned as a first message to expire, no matter how long the initial
message was already on the list.

To resolve this, add a `t0` field to the coap_pending structure. This
field is initialized to the initial transmission time, and is increased
on each retransmission by the retransmission timeout.
`coap_pending_next_to_expire` uses this value to calculate absolute
time, when the next retransmission should take place, and based on this
information returns correctly first pending message to expire.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2020-04-23 17:07:26 +02:00 committed by Jukka Rissanen
commit df152ab59f
2 changed files with 13 additions and 2 deletions

View file

@ -233,7 +233,8 @@ typedef int (*coap_reply_t)(const struct coap_packet *response,
*/
struct coap_pending {
struct sockaddr addr;
s32_t timeout;
u32_t t0;
u32_t timeout;
u16_t id;
u8_t *data;
u16_t len;

View file

@ -1075,6 +1075,7 @@ int coap_pending_init(struct coap_pending *pending,
pending->data = request->data;
pending->len = request->offset;
pending->t0 = k_uptime_get_32();
return 0;
}
@ -1168,9 +1169,17 @@ struct coap_pending *coap_pending_next_to_expire(
{
struct coap_pending *p, *found = NULL;
size_t i;
u32_t expiry, min_expiry;
for (i = 0, p = pendings; i < len; i++, p++) {
if (p->timeout && (!found || found->timeout < p->timeout)) {
if (!p->timeout) {
continue;
}
expiry = p->t0 + p->timeout;
if (!found || (s32_t)(expiry - min_expiry) < 0) {
min_expiry = expiry;
found = p;
}
}
@ -1205,6 +1214,7 @@ bool coap_pending_cycle(struct coap_pending *pending)
{
s32_t old = pending->timeout;
pending->t0 += pending->timeout;
pending->timeout = next_timeout(pending->timeout);
return (old != pending->timeout);