Skip to content

Commit d489765

Browse files
pabigotjukkar
authored andcommitted
net: dhcp: correct timeout scheduling with multiple interfaces
If there are multiple interfaces a change to the timeout for one cannot determine the correct delay until the next timeout event. That can be determined only by checking for the next event over all interfaces, which is exactly what's done by the timeout worker. Refactor interface timeout configuration to just set the start time and request time, and trigger the worker to calculate the next scheduled event. Signed-off-by: Peter Bigot <[email protected]>
1 parent b4ed597 commit d489765

File tree

1 file changed

+30
-22
lines changed

1 file changed

+30
-22
lines changed

subsys/net/ip/dhcpv4.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,28 @@ static struct net_pkt *dhcpv4_create_message(struct net_if *iface, uint8_t type,
276276
return NULL;
277277
}
278278

279+
static void dhcpv4_immediate_timeout(struct net_if_dhcpv4 *dhcpv4)
280+
{
281+
NET_DBG("force timeout dhcpv4=%p", dhcpv4);
282+
dhcpv4->timer_start = k_uptime_get() - 1;
283+
dhcpv4->request_time = 0U;
284+
k_delayed_work_submit(&timeout_work, K_NO_WAIT);
285+
}
286+
287+
static void dhcpv4_set_timeout(struct net_if_dhcpv4 *dhcpv4,
288+
uint32_t timeout)
289+
{
290+
NET_DBG("sched timeout dhcvp4=%p timeout=%us", dhcpv4, timeout);
291+
dhcpv4->timer_start = k_uptime_get();
292+
dhcpv4->request_time = timeout;
293+
294+
/* NB: This interface may not be providing the next timeout
295+
* event; also this timeout may replace the current timeout
296+
* event. Delegate scheduling to the timeout manager.
297+
*/
298+
k_delayed_work_submit(&timeout_work, K_NO_WAIT);
299+
}
300+
279301
static uint32_t dhcpv4_update_message_timeout(struct net_if_dhcpv4 *dhcpv4)
280302
{
281303
uint32_t timeout;
@@ -291,8 +313,7 @@ static uint32_t dhcpv4_update_message_timeout(struct net_if_dhcpv4 *dhcpv4)
291313
timeout += (sys_rand32_get() % 3U) - 1;
292314

293315
dhcpv4->attempts++;
294-
dhcpv4->timer_start = k_uptime_get();
295-
dhcpv4->request_time = timeout;
316+
dhcpv4_set_timeout(dhcpv4, timeout);
296317

297318
return timeout;
298319
}
@@ -419,11 +440,6 @@ static uint32_t dhcpv4_send_discover(struct net_if *iface)
419440
DHCPV4_INITIAL_DELAY_MIN;
420441
}
421442

422-
static void dhcpv4_update_timeout_work(uint32_t timeout)
423-
{
424-
k_delayed_work_submit(&timeout_work, K_SECONDS(timeout));
425-
}
426-
427443
static void dhcpv4_enter_selecting(struct net_if *iface)
428444
{
429445
struct in_addr any = INADDR_ANY_INIT;
@@ -505,7 +521,7 @@ static void dhcpv4_enter_requesting(struct net_if *iface)
505521
NET_DBG("enter state=%s",
506522
net_dhcpv4_state_name(iface->config.dhcpv4.state));
507523

508-
dhcpv4_update_timeout_work(dhcpv4_send_request(iface));
524+
dhcpv4_send_request(iface);
509525
}
510526

511527
static void dhcpv4_enter_bound(struct net_if *iface)
@@ -532,10 +548,8 @@ static void dhcpv4_enter_bound(struct net_if *iface)
532548
net_dhcpv4_state_name(iface->config.dhcpv4.state),
533549
renewal_time, rebinding_time);
534550

535-
iface->config.dhcpv4.timer_start = k_uptime_get();
536-
iface->config.dhcpv4.request_time = MIN(renewal_time, rebinding_time);
537-
538-
dhcpv4_update_timeout_work(iface->config.dhcpv4.request_time);
551+
dhcpv4_set_timeout(&iface->config.dhcpv4,
552+
MIN(renewal_time, rebinding_time));
539553

540554
net_mgmt_event_notify_with_info(NET_EVENT_IPV4_DHCP_BOUND, iface,
541555
&iface->config.dhcpv4,
@@ -546,7 +560,8 @@ static uint32_t dhcpv4_manage_timers(struct net_if *iface, int64_t now)
546560
{
547561
uint32_t timeleft = dhcpv4_request_timeleft(iface, now);
548562

549-
NET_DBG("iface %p state=%s timeleft=%u", iface,
563+
NET_DBG("iface %p dhcpv4=%p state=%s timeleft=%u", iface,
564+
&iface->config.dhcpv4,
550565
net_dhcpv4_state_name(iface->config.dhcpv4.state), timeleft);
551566

552567
if (timeleft != 0U) {
@@ -1083,11 +1098,7 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb,
10831098
* enough. Instead we can force a request timeout
10841099
* which will then call dhcpv4_send_request() automatically.
10851100
*/
1086-
iface->config.dhcpv4.timer_start = k_uptime_get() - 1;
1087-
iface->config.dhcpv4.request_time = 0U;
1088-
1089-
k_delayed_work_cancel(&timeout_work);
1090-
k_delayed_work_submit(&timeout_work, K_NO_WAIT);
1101+
dhcpv4_immediate_timeout(&iface->config.dhcpv4);
10911102
}
10921103
}
10931104

@@ -1151,10 +1162,7 @@ void net_dhcpv4_start(struct net_if *iface)
11511162
sys_slist_append(&dhcpv4_ifaces,
11521163
&iface->config.dhcpv4.node);
11531164

1154-
iface->config.dhcpv4.timer_start = k_uptime_get();
1155-
iface->config.dhcpv4.request_time = timeout;
1156-
1157-
dhcpv4_update_timeout_work(timeout);
1165+
dhcpv4_set_timeout(&iface->config.dhcpv4, timeout);
11581166

11591167
break;
11601168
case NET_DHCPV4_INIT:

0 commit comments

Comments
 (0)