net: coap: Randomize initial ACK timeout

Add Kconfig option to randomize the initial ACK timeout, as specified in
RFC 7252. The option is enabled by default.

Additionally, finetune the default value of COAP_INIT_ACK_TIMEOUT_MS
option, to match the default ACK_TIMEOUT value specified by the RFC
7252. The RFC does not specify the minimum/maximum value of the
ACK_TIMEOUT parameter, but only suggests it should be no lower than 1
second, so adjust the option range to reflect this.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2021-01-18 14:21:16 +01:00 committed by Anas Nashif
parent 538e19ee2e
commit c563736bd3
3 changed files with 30 additions and 9 deletions

View file

@ -234,6 +234,7 @@ typedef int (*coap_reply_t)(const struct coap_packet *response,
const struct sockaddr *from);
#define COAP_DEFAULT_MAX_RETRANSMIT 4
#define COAP_DEFAULT_ACK_RANDOM_FACTOR 1.5
/**
* @brief Represents a request awaiting for an acknowledgment (ACK).

View file

@ -54,11 +54,21 @@ config COAP_EXTENDED_OPTIONS_LEN_VALUE
config COAP_INIT_ACK_TIMEOUT_MS
int "base length of the random generated initial ACK timeout in ms"
default 2345
range 2345 100000
default 2000
range 1000 100000
help
This value is used as a base value to retry pending CoAP packets.
config COAP_RANDOMIZE_ACK_TIMEOUT
bool "Randomize initial ACK timeout, as specified in RFC 7252"
default y
help
If enabled, the initial ACK timeout will be randomized, as specified
in RFC 7252, i.e. will be a random number between ACK_TIMEOUT and
ACK_TIMEOUT * ACK_RANDOM_FACTOR (where ACK_TIMEOUT is specified by
COAP_INIT_ACK_TIMEOUT_MS option). Otherwise, the initial ACK timeout
will be fixed to the value of COAP_INIT_ACK_TIMEOUT_MS option.
config COAP_URI_WILDCARD
bool "Enable wildcards in CoAP resource path"
default y

View file

@ -1196,18 +1196,28 @@ struct coap_pending *coap_pending_next_to_expire(
return found;
}
/* TODO: random generated initial ACK timeout
* ACK_TIMEOUT < INIT_ACK_TIMEOUT < ACK_TIMEOUT * ACK_RANDOM_FACTOR
* where ACK_TIMEOUT = 2 and ACK_RANDOM_FACTOR = 1.5 by default
* Ref: https://tools.ietf.org/html/rfc7252#section-4.8
*/
#define INIT_ACK_TIMEOUT CONFIG_COAP_INIT_ACK_TIMEOUT_MS
static uint32_t init_ack_timeout(void)
{
#if defined(CONFIG_COAP_RANDOMIZE_ACK_TIMEOUT)
const uint32_t max_ack = CONFIG_COAP_INIT_ACK_TIMEOUT_MS *
COAP_DEFAULT_ACK_RANDOM_FACTOR;
const uint32_t min_ack = CONFIG_COAP_INIT_ACK_TIMEOUT_MS;
/* Randomly generated initial ACK timeout
* ACK_TIMEOUT < INIT_ACK_TIMEOUT < ACK_TIMEOUT * ACK_RANDOM_FACTOR
* Ref: https://tools.ietf.org/html/rfc7252#section-4.8
*/
return min_ack + (sys_rand32_get() % (max_ack - min_ack));
#else
return CONFIG_COAP_INIT_ACK_TIMEOUT_MS;
#endif /* defined(CONFIG_COAP_RANDOMIZE_ACK_TIMEOUT) */
}
bool coap_pending_cycle(struct coap_pending *pending)
{
if (pending->timeout == 0) {
/* Initial transmission. */
pending->timeout = INIT_ACK_TIMEOUT;
pending->timeout = init_ack_timeout();
return true;
}