Skip to content

DHCP timeout and hostname fix, make both user settable #20

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 3 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from 2 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
16 changes: 10 additions & 6 deletions adafruit_wiznet5k/adafruit_wiznet5k.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ class WIZNET5K: # pylint: disable=too-many-public-methods
:param ~busio.SPI spi_bus: The SPI bus the Wiznet module is connected to.
:param ~digitalio.DigitalInOut cs: Chip select pin.
:param ~digitalio.DigitalInOut rst: Optional reset pin.
:param bool dhcp: Whether to start DHCP automatically or not.
:param str mac: The Wiznet's MAC Address.
:param bool is_dhcp: Whether to start DHCP automatically or not.
:param list mac: The Wiznet's MAC Address.
:param str hostname: The desired hostname, with optional {} to fill in MAC.
:param int dhcp_timeout: Timeout in seconds for DHCP response.
:param bool debug: Enable debugging output.

"""
Expand All @@ -154,7 +156,8 @@ class WIZNET5K: # pylint: disable=too-many-public-methods

# pylint: disable=too-many-arguments
def __init__(
self, spi_bus, cs, reset=None, is_dhcp=True, mac=DEFAULT_MAC, debug=False
self, spi_bus, cs, reset=None, is_dhcp=True, mac=DEFAULT_MAC,
hostname=None, dhcp_timeout=3, debug=False
):
self._debug = debug
self._chip_type = None
Expand Down Expand Up @@ -182,13 +185,14 @@ def __init__(
self._dns = 0
# Set DHCP
if is_dhcp:
ret = self.set_dhcp()
ret = self.set_dhcp(hostname, dhcp_timeout)
assert ret == 0, "Failed to configure DHCP Server!"

def set_dhcp(self, response_timeout=1):
def set_dhcp(self, hostname=None, response_timeout=3):
"""Initializes the DHCP client and attempts to retrieve
and set network configuration from the DHCP server.
Returns True if DHCP configured, False otherwise.
:param str hostname: The desired hostname, with optional {} to fill in MAC.
:param int response_timeout: Time to wait for server to return packet, in seconds.

"""
Expand All @@ -197,7 +201,7 @@ def set_dhcp(self, response_timeout=1):
self._src_port = 68
# Return IP assigned by DHCP
_dhcp_client = dhcp.DHCP(
self, self.mac_address, response_timeout, debug=self._debug
self, self.mac_address, hostname, response_timeout, debug=self._debug
)
ret = _dhcp_client.request_dhcp_lease()
if ret == 1:
Expand Down
62 changes: 33 additions & 29 deletions adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,22 @@ class DHCP:
"""W5k DHCP Client implementation.
:param eth: Wiznet 5k object
:param list mac_address: Hardware MAC.
:param int timeout: Packet parsing timeout.
:param int timeout_response: DHCP Response timeout.
:param str hostname: The desired hostname, with optional {} to fill in MAC.
:param int response_timeout: DHCP Response timeout.
:param bool debug: Enable debugging output.

"""

# pylint: disable=too-many-arguments, too-many-instance-attributes, invalid-name
def __init__(self, eth, mac_address, timeout=1, timeout_response=1, debug=False):
def __init__(self, eth, mac_address, hostname=None, response_timeout=3, debug=False):
self._debug = debug
self._timeout = timeout
self._response_timeout = timeout_response
self._response_timeout = response_timeout
self._mac_address = mac_address

# Initalize a new UDP socket for DHCP
socket.set_interface(eth)
self._sock = socket.socket(type=socket.SOCK_DGRAM)
self._sock.settimeout(timeout)
self._sock.settimeout(response_timeout)

# DHCP state machine
self._dhcp_state = STATE_DHCP_START
Expand All @@ -124,6 +123,7 @@ def __init__(self, eth, mac_address, timeout=1, timeout_response=1, debug=False)
self.gateway_ip = 0
self.subnet_mask = 0
self.dns_server_ip = 0

# Lease configuration
self._lease_time = 0
self._last_check_lease_ms = 0
Expand All @@ -132,6 +132,11 @@ def __init__(self, eth, mac_address, timeout=1, timeout_response=1, debug=False)
self._t1 = 0
self._t2 = 0

# Host name
mac_string = "".join("{:02X}".format(o) for o in mac_address)
self._hostname = bytes((hostname or "WIZnet{}")
.split('.')[0].format(mac_string)[:42], "utf-8")

def send_dhcp_message(self, state, time_elapsed):
"""Assemble and send a DHCP message packet to a socket.
:param int state: DHCP Message state.
Expand Down Expand Up @@ -193,38 +198,37 @@ def send_dhcp_message(self, state, time_elapsed):

# Option - Host Name
_BUFF[252] = 12
_BUFF[253] = len(b"Wiznet") + 6
_BUFF[254:260] = b"WIZnet"

for mac in range(0, 5):
_BUFF[260 + mac] = self._mac_address[mac]
hostname_len = len(self._hostname)
after_hostname = 254 + hostname_len
_BUFF[253] = hostname_len
_BUFF[254:after_hostname] = self._hostname

if state == DHCP_REQUEST:
# Set the parsed local IP addr
_BUFF[266] = 50
_BUFF[267] = 0x04
_BUFF[after_hostname] = 50
_BUFF[after_hostname+1] = 0x04

_BUFF[268:272] = self.local_ip
_BUFF[after_hostname+2:after_hostname+6] = self.local_ip
# Set the parsed dhcp server ip addr
_BUFF[272] = 54
_BUFF[273] = 0x04
_BUFF[274:278] = self.dhcp_server_ip
_BUFF[after_hostname+6] = 54
_BUFF[after_hostname+7] = 0x04
_BUFF[after_hostname+8:after_hostname+12] = self.dhcp_server_ip

_BUFF[278] = 55
_BUFF[279] = 0x06
_BUFF[after_hostname+12] = 55
_BUFF[after_hostname+13] = 0x06
# subnet mask
_BUFF[280] = 1
_BUFF[after_hostname+14] = 1
# routers on subnet
_BUFF[281] = 3
_BUFF[after_hostname+15] = 3
# DNS
_BUFF[282] = 6
_BUFF[after_hostname+16] = 6
# domain name
_BUFF[283] = 15
_BUFF[after_hostname+17] = 15
# renewal (T1) value
_BUFF[284] = 58
_BUFF[after_hostname+18] = 58
# rebinding (T2) value
_BUFF[285] = 59
_BUFF[286] = 255
_BUFF[after_hostname+19] = 59
_BUFF[after_hostname+20] = 255

# Send DHCP packet
self._sock.send(_BUFF)
Expand Down Expand Up @@ -373,7 +377,7 @@ def request_dhcp_lease(
elif self._dhcp_state == STATE_DHCP_DISCOVER:
if self._debug:
print("* DHCP: Parsing OFFER")
msg_type, xid = self.parse_dhcp_response(self._timeout)
msg_type, xid = self.parse_dhcp_response(self._response_timeout)
if msg_type == DHCP_OFFER:
# use the _transaction_id the offer returned,
# rather than the current one
Expand All @@ -389,7 +393,7 @@ def request_dhcp_lease(
elif STATE_DHCP_REQUEST:
if self._debug:
print("* DHCP: Parsing ACK")
msg_type, xid = self.parse_dhcp_response(self._timeout)
msg_type, xid = self.parse_dhcp_response(self._response_timeout)
if msg_type == DHCP_ACK:
self._dhcp_state = STATE_DHCP_LEASED
result = 1
Expand All @@ -412,7 +416,7 @@ def request_dhcp_lease(
msg_type = 0
self._dhcp_state = STATE_DHCP_START

if result != 1 and ((time.monotonic() - start_time > self._timeout)):
if result != 1 and ((time.monotonic() - start_time > self._response_timeout)):
break

self._transaction_id += 1
Expand Down