mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-12 11:40:39 +03:00
use fixpoint arithmetic for retransmission timeout calculation
It was noted on the mailing list that the changed retransmission timeout calculation in commit 1a28b3 may yield to inefficient code on embedded systems which have no fpu. This change now uses fixed point arithmetic instead. By default, it represents ACK_TIMEOUT and ACK_RANDOM_FACTOR as Q2.6 numbers and uses Q0.8 for the randomness parameter. The resulting timeout value is represented in system ticks (i.e. a multiple of COAP_TICKS_PER_SECOND) as an unsigned integer.
This commit is contained in:
1 parent
a81a37b29d
commit
b6c92bb927
2 files changed
+69
-2
No files matched your search
@@ -1,3 +1,8 @@
|
||||
2015-02-21 Olaf Bergmann <bergmann@tzi.org>
|
||||
|
||||
* net.c (coap_send_confirmed): Use fixed point arithmetic
|
||||
to calculate retransmission timeout.
|
||||
|
||||
2015-02-20 Olaf Bergmann <bergmann@tzi.org>
|
||||
|
||||
* coap_list.[hc]: Moved old list implementation into
|
||||
|
||||
@@ -87,6 +87,32 @@
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* The number of bits for the fractional part of ACK_TIMEOUT and
|
||||
* ACK_RANDOM_FACTOR. Must be less or equal 8.
|
||||
*/
|
||||
#define FRAC_BITS 6
|
||||
|
||||
/**
|
||||
* The maximum number of bits for fixed point integers that are used
|
||||
* for retransmission time calculation. Currently this must be @c 8.
|
||||
*/
|
||||
#define MAX_BITS 8
|
||||
|
||||
#if FRAC_BITS > 8
|
||||
#error FRAC_BITS must be less or equal 8
|
||||
#endif
|
||||
|
||||
/** creates a Qx.frac from fval */
|
||||
#define Q(frac,fval) ((unsigned short)(((1 << (frac)) * (fval))))
|
||||
|
||||
/** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_RANDOM_FACTOR */
|
||||
#define ACK_RANDOM_FACTOR \
|
||||
Q(FRAC_BITS, COAP_DEFAULT_ACK_RANDOM_FACTOR)
|
||||
|
||||
/** creates a Qx.FRAC_BITS from COAP_DEFAULT_ACK_TIMEOUT */
|
||||
#define ACK_TIMEOUT Q(FRAC_BITS, COAP_DEFAULT_ACK_TIMEOUT)
|
||||
|
||||
#if defined(WITH_POSIX)
|
||||
|
||||
time_t clock_offset;
|
||||
@@ -643,6 +669,43 @@ coap_send_message_type(coap_context_t *context,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the initial timeout based on the global CoAP transmission
|
||||
* parameters ACK_TIMEOUT, ACK_RANDOM_FACTOR, and COAP_TICKS_PER_SECOND.
|
||||
* The calculation requires ACK_TIMEOUT and ACK_RANDOM_FACTOR to be in
|
||||
* Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r
|
||||
* is interpreted as the fractional part of a Q0.MAX_BITS random value.
|
||||
*
|
||||
* @param r random value as fractional part of a Q0.MAX_BITS fixed point
|
||||
* value
|
||||
* @return COAP_TICKS_PER_SECOND * ACK_TIMEOUT * (1 + (ACK_RANDOM_FACTOR - 1) * r)
|
||||
*/
|
||||
static inline unsigned int
|
||||
calc_timeout(unsigned char r) {
|
||||
unsigned int result;
|
||||
|
||||
/* The integer 1.0 as a Qx.FRAC_BITS */
|
||||
#define FP1 Q(FRAC_BITS, 1)
|
||||
|
||||
/* rounds val up and right shifts by frac positions */
|
||||
#define SHR_FP(val,frac) (((val) + (1 << ((frac) - 1))) >> (frac))
|
||||
|
||||
/* Inner term: multiply ACK_RANDOM_FACTOR by Q0.MAX_BITS[r] and
|
||||
* make the result a rounded Qx.FRAC_BITS */
|
||||
result = SHR_FP((ACK_RANDOM_FACTOR - FP1) * r, MAX_BITS);
|
||||
|
||||
/* Add 1 to the inner term and multiply with ACK_TIMEOUT, then
|
||||
* make the result a rounded Qx.FRAC_BITS */
|
||||
result = SHR_FP(((result + FP1) * ACK_TIMEOUT), FRAC_BITS);
|
||||
|
||||
/* Multiply with COAP_TICKS_PER_SECOND to yield system ticks
|
||||
* (yields a Qx.FRAC_BITS) and shift to get an integer */
|
||||
return SHR_FP((COAP_TICKS_PER_SECOND * result), FRAC_BITS);
|
||||
|
||||
#undef FP1
|
||||
#undef SHR_FP
|
||||
}
|
||||
|
||||
coap_tid_t
|
||||
coap_send_confirmed(coap_context_t *context,
|
||||
const coap_endpoint_t *local_interface,
|
||||
@@ -668,8 +731,7 @@ coap_send_confirmed(coap_context_t *context,
|
||||
prng((unsigned char *)&r,sizeof(r));
|
||||
|
||||
/* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */
|
||||
node->timeout = COAP_TICKS_PER_SECOND * COAP_DEFAULT_ACK_TIMEOUT *
|
||||
(1 + (COAP_DEFAULT_ACK_RANDOM_FACTOR - 1) * ((r & 0xFF)/ 256.0));
|
||||
node->timeout = calc_timeout(r);
|
||||
|
||||
node->local_if = *local_interface;
|
||||
memcpy(&node->remote, dst, sizeof(coap_address_t));
|
||||
|
||||
Reference in new issue
Block a user