The conversion from uint64_t to float caused the RT value
to become 0. This caused the transmission timeout to expire
immediately and the machine load to go to 100%.
This is fixed by using directly uints instead of floats.
---
src/dhcpv6.c | 49 +++++++++++++++++++++++++++++--------------------
1 file changed, 29 insertions(+), 20 deletions(-)
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index c311045..9249e55 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -105,28 +105,37 @@ static void clear_timer(struct connman_dhcpv6 *dhcp)
}
}
-static inline float get_random(void)
+static inline guint get_random(void)
{
uint64_t val;
__connman_util_get_random(&val);
- return (val % 200 - 100) / 1000.0;
+
+ /* Make sure the value is always positive so strip MSB */
+ return ((uint32_t)val) >> 1;
+}
+
+static guint compute_random(guint val)
+{
+ return val - val / 10 +
+ (get_random() % (2 * 1000)) * val / 10 / 1000;
}
/* Calculate a random delay, RFC 3315 chapter 14 */
/* RT and MRT are milliseconds */
static guint calc_delay(guint RT, guint MRT)
{
- float delay = get_random();
- float rt = RT * (2 + delay);
+ if (MRT && (RT > MRT / 2))
+ RT = compute_random(MRT);
+ else
+ RT += compute_random(RT);
- if (rt > MRT)
- rt = MRT * (1 + delay);
-
- if (rt < 0)
- rt = MRT;
+ return RT;
+}
- return (guint)rt;
+static guint initial_rt(guint timeout)
+{
+ return compute_random(timeout);
}
static void free_prefix(gpointer data)
@@ -1223,7 +1232,7 @@ static gboolean start_rebind(gpointer user_data)
if (check_restart(dhcp) < 0)
return FALSE;
- dhcp->RT = REB_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REB_TIMEOUT);
DBG("rebind initial RT timeout %d msec", dhcp->RT);
@@ -1390,7 +1399,7 @@ static gboolean start_renew(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = REN_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REN_TIMEOUT);
DBG("renew initial RT timeout %d msec", dhcp->RT);
@@ -1588,7 +1597,7 @@ static gboolean start_info_req(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = INF_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(INF_TIMEOUT);
DBG("info initial RT timeout %d msec", dhcp->RT);
@@ -1655,7 +1664,7 @@ static void advertise_cb(GDHCPClient *dhcp_client,
gpointer user_data)
return;
}
- dhcp->RT = REQ_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REQ_TIMEOUT);
DBG("request initial RT timeout %d msec", dhcp->RT);
dhcp->timeout = g_timeout_add(dhcp->RT, timeout_request, dhcp);
@@ -1766,7 +1775,7 @@ static gboolean start_solicitation(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = SOL_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(SOL_TIMEOUT);
DBG("solicit initial RT timeout %d msec", dhcp->RT);
@@ -2178,7 +2187,7 @@ static gboolean start_pd_rebind(gpointer user_data)
if (check_pd_restart(dhcp) < 0)
return FALSE;
- dhcp->RT = REB_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REB_TIMEOUT);
DBG("rebind initial RT timeout %d msec", dhcp->RT);
@@ -2230,7 +2239,7 @@ static gboolean start_pd_rebind_with_confirm(gpointer
user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = CNF_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(CNF_TIMEOUT);
DBG("rebind with confirm initial RT timeout %d msec", dhcp->RT);
@@ -2267,7 +2276,7 @@ static gboolean start_pd_renew(gpointer user_data)
{
struct connman_dhcpv6 *dhcp = user_data;
- dhcp->RT = REN_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REN_TIMEOUT);
DBG("renew initial RT timeout %d msec", dhcp->RT);
@@ -2483,7 +2492,7 @@ static void advertise_pd_cb(GDHCPClient *dhcp_client,
gpointer user_data)
return;
}
- dhcp->RT = REQ_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(REQ_TIMEOUT);
DBG("request initial RT timeout %d msec", dhcp->RT);
dhcp->timeout = g_timeout_add(dhcp->RT, timeout_pd_request, dhcp);
@@ -2538,7 +2547,7 @@ static gboolean start_pd_solicitation(gpointer user_data)
struct connman_dhcpv6 *dhcp = user_data;
/* Set the retransmission timeout, RFC 3315 chapter 14 */
- dhcp->RT = SOL_TIMEOUT * (1 + get_random());
+ dhcp->RT = initial_rt(SOL_TIMEOUT);
DBG("solicit initial RT timeout %d msec", dhcp->RT);
--
1.8.3.1
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman