Skip to content

Fix timeout handling in DHCP lease renewal #169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@


import gc
import time
from random import randint
from micropython import const
from adafruit_ticks import ticks_ms, ticks_diff, ticks_add
from adafruit_ticks import ticks_ms, ticks_diff, ticks_add, ticks_less
from adafruit_wiznet5k.adafruit_wiznet5k_debug import ( # pylint: disable=ungrouped-imports
debug_msg,
)
Expand Down Expand Up @@ -152,7 +151,6 @@ def __init__(
# DHCP state machine
self._dhcp_state = _STATE_INIT
self._transaction_id = randint(1, 0x7FFFFFFF)
self._start_time = 0.0
self._start_ticks = 0
self._blocking = False
self._renew = None
Expand All @@ -165,9 +163,12 @@ def __init__(
self.dns_server_ip = _UNASSIGNED_IP_ADDR

# Lease expiry times
self._t1 = 0
self._t2 = 0
self._lease = 0
self._t1_timeout = 0
self._t2_timeout = 0
self._lease_timeout = 0
self._t1 = None
self._t2 = None
self._lease = None

# Host name
mac_string = "".join("{:02X}".format(o) for o in mac_address)
Expand Down Expand Up @@ -210,8 +211,10 @@ def _dsm_reset(self) -> None:
self.dns_server_ip = _UNASSIGNED_IP_ADDR
self._renew = None
self._increment_transaction_id()
self._start_time = time.monotonic()
self._start_ticks = ticks_ms()
self._lease = None
self._t1 = None
self._t2 = None

def _increment_transaction_id(self) -> None:
"""Increment the transaction ID and roll over from 0x7fffffff to 0."""
Expand Down Expand Up @@ -289,11 +292,14 @@ def _process_messaging_states(self, *, message_type: int):
self._dhcp_state = _STATE_INIT
elif message_type == _DHCP_ACK:
debug_msg("Message is ACK, setting FSM state to BOUND.", self._debug)
self._t1 = ticks_add(self._start_ticks, self._lease // 2)
self._t2 = ticks_diff(
ticks_add(self._start_ticks, self._lease), self._lease // 8
lease = self._lease or 60
self._lease_timeout = ticks_add(self._start_ticks, lease * 1000)
self._t1_timeout = ticks_add(
self._start_ticks, (self._t1 or (lease // 2)) * 1000
)
self._t2_timeout = ticks_add(
self._start_ticks, (self._t2 or (lease - lease // 8)) * 1000
)
self._lease = ticks_add(self._lease, self._start_ticks)
self._increment_transaction_id()
if not self._renew:
self._eth.ifconfig = (
Expand Down Expand Up @@ -391,16 +397,16 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
while True:
if self._dhcp_state == _STATE_BOUND:
now = ticks_ms()
if ticks_diff(now, self._t1) < 0:
if ticks_less(now, self._t1_timeout):
debug_msg("No timers have expired. Exiting FSM.", self._debug)
return
if ticks_diff(now, self._lease) > 0:
if ticks_less(self._lease_timeout, now):
debug_msg(
"Lease has expired, switching state to INIT.", self._debug
)
self._blocking = True
self._dhcp_state = _STATE_INIT
elif ticks_diff(now, self._t2) > 0:
elif ticks_less(self._t2_timeout, now):
debug_msg(
"T2 has expired, switching state to REBINDING.", self._debug
)
Expand All @@ -414,16 +420,20 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
if self._dhcp_state == _STATE_RENEWING:
debug_msg("FSM state is RENEWING.", self._debug)
self._renew = "renew"
self._start_time = time.monotonic()
self._start_ticks = ticks_ms()
self._lease = None
self._t1 = None
self._t2 = None
self._dhcp_state = _STATE_REQUESTING

if self._dhcp_state == _STATE_REBINDING:
debug_msg("FSM state is REBINDING.", self._debug)
self._renew = "rebind"
self.dhcp_server_ip = _BROADCAST_SERVER_ADDR
self._start_time = time.monotonic()
self._start_ticks = ticks_ms()
self._lease = None
self._t1 = None
self._t2 = None
self._dhcp_state = _STATE_REQUESTING

if self._dhcp_state == _STATE_INIT:
Expand Down
Loading