net/dhcpv4: Introduce start/stop API and disabled state.

Change-Id: Iae3b96dd91325ecf51b33b8c58f65aa5ec2b40c9
Signed-off-by: Marcus Shawcroft <marcus.shawcroft@arm.com>
This commit is contained in:
Marcus Shawcroft 2017-02-11 17:45:17 +00:00 committed by Jukka Rissanen
commit 3726bb98bd
3 changed files with 79 additions and 47 deletions

View file

@ -26,6 +26,7 @@
* reflected within corresponding changes to net_dhcpv4_state_name. * reflected within corresponding changes to net_dhcpv4_state_name.
*/ */
enum net_dhcpv4_state { enum net_dhcpv4_state {
NET_DHCPV4_DISABLED,
NET_DHCPV4_INIT, NET_DHCPV4_INIT,
NET_DHCPV4_SELECTING, NET_DHCPV4_SELECTING,
NET_DHCPV4_REQUESTING, NET_DHCPV4_REQUESTING,
@ -34,7 +35,7 @@ enum net_dhcpv4_state {
}; };
/** /**
* @brief Start DHCPv4 client * @brief Start DHCPv4 client on an iface
* *
* @details Start DHCPv4 client on a given interface. DHCPv4 client * @details Start DHCPv4 client on a given interface. DHCPv4 client
* will start negotiation for IPv4 address. Once the negotiation is * will start negotiation for IPv4 address. Once the negotiation is
@ -44,6 +45,17 @@ enum net_dhcpv4_state {
*/ */
void net_dhcpv4_start(struct net_if *iface); void net_dhcpv4_start(struct net_if *iface);
/**
* @brief Stop DHCPv4 client on an iface
*
* @details Stop DHCPv4 client on a given interface. DHCPv4 client
* will remove all configuration obtained from a DHCP server from the
* interface and stop any further negotiation with the server.
*
* @param iface A valid pointer on an interface
*/
void net_dhcpv4_stop(struct net_if *iface);
/** /**
* @brief DHCPv4 state name * @brief DHCPv4 state name
* *

View file

@ -1135,7 +1135,7 @@ struct net_if_api {
}; };
#if defined(CONFIG_NET_DHCPV4) #if defined(CONFIG_NET_DHCPV4)
#define NET_IF_DHCPV4_INIT .dhcpv4.state = NET_DHCPV4_INIT, #define NET_IF_DHCPV4_INIT .dhcpv4.state = NET_DHCPV4_DISABLED,
#else #else
#define NET_IF_DHCPV4_INIT #define NET_IF_DHCPV4_INIT
#endif #endif

View file

@ -122,6 +122,7 @@ net_dhcpv4_msg_type_name(enum dhcpv4_msg_type msg_type) __attribute__((unused));
const char *net_dhcpv4_state_name(enum net_dhcpv4_state state) const char *net_dhcpv4_state_name(enum net_dhcpv4_state state)
{ {
static const char * const name[] = { static const char * const name[] = {
"disabled",
"init", "init",
"selecting", "selecting",
"requesting", "requesting",
@ -157,26 +158,6 @@ static inline uint32_t get_dhcpv4_renewal_time(struct net_if *iface)
iface->dhcpv4.lease_time / 2); iface->dhcpv4.lease_time / 2);
} }
static inline void unset_dhcpv4_on_iface(struct net_if *iface)
{
if (!iface) {
return;
}
iface->dhcpv4.state = NET_DHCPV4_INIT;
NET_DBG("state=%s", net_dhcpv4_state_name(iface->dhcpv4.state));
iface->dhcpv4.attempts = 0;
iface->dhcpv4.lease_time = 0;
iface->dhcpv4.renewal_time = 0;
memset(iface->dhcpv4.server_id.s4_addr, 0, 4);
memset(iface->dhcpv4.server_id.s4_addr, 0, 4);
memset(iface->dhcpv4.requested_ip.s4_addr, 0, 4);
k_delayed_work_cancel(&iface->dhcpv4.timer);
k_delayed_work_cancel(&iface->dhcpv4.t1_timer);
}
/* Add magic cookie to DCHPv4 messages */ /* Add magic cookie to DCHPv4 messages */
static inline bool add_cookie(struct net_buf *buf) static inline bool add_cookie(struct net_buf *buf)
{ {
@ -488,6 +469,8 @@ static void dhcpv4_timeout(struct k_work *work)
} }
switch (iface->dhcpv4.state) { switch (iface->dhcpv4.state) {
case NET_DHCPV4_DISABLED:
break;
case NET_DHCPV4_INIT: case NET_DHCPV4_INIT:
enter_selecting(iface); enter_selecting(iface);
break; break;
@ -700,6 +683,7 @@ static enum net_verdict parse_options(struct net_if *iface, struct net_buf *buf,
static inline void handle_offer(struct net_if *iface) static inline void handle_offer(struct net_if *iface)
{ {
switch (iface->dhcpv4.state) { switch (iface->dhcpv4.state) {
case NET_DHCPV4_DISABLED:
case NET_DHCPV4_INIT: case NET_DHCPV4_INIT:
case NET_DHCPV4_REQUESTING: case NET_DHCPV4_REQUESTING:
case NET_DHCPV4_RENEWING: case NET_DHCPV4_RENEWING:
@ -717,6 +701,7 @@ static void handle_ack(struct net_if *iface)
uint32_t timeout; uint32_t timeout;
switch (iface->dhcpv4.state) { switch (iface->dhcpv4.state) {
case NET_DHCPV4_DISABLED:
case NET_DHCPV4_INIT: case NET_DHCPV4_INIT:
case NET_DHCPV4_SELECTING: case NET_DHCPV4_SELECTING:
case NET_DHCPV4_BOUND: case NET_DHCPV4_BOUND:
@ -762,6 +747,7 @@ static void handle_ack(struct net_if *iface)
static void handle_nak(struct net_if *iface) static void handle_nak(struct net_if *iface)
{ {
switch (iface->dhcpv4.state) { switch (iface->dhcpv4.state) {
case NET_DHCPV4_DISABLED:
case NET_DHCPV4_INIT: case NET_DHCPV4_INIT:
case NET_DHCPV4_SELECTING: case NET_DHCPV4_SELECTING:
case NET_DHCPV4_RENEWING: case NET_DHCPV4_RENEWING:
@ -896,38 +882,72 @@ void net_dhcpv4_start(struct net_if *iface)
uint32_t timeout; uint32_t timeout;
uint32_t entropy; uint32_t entropy;
iface->dhcpv4.state = NET_DHCPV4_INIT; switch (iface->dhcpv4.state) {
NET_DBG("state=%s", net_dhcpv4_state_name(iface->dhcpv4.state)); case NET_DHCPV4_DISABLED:
iface->dhcpv4.state = NET_DHCPV4_INIT;
NET_DBG("state=%s", net_dhcpv4_state_name(iface->dhcpv4.state));
iface->dhcpv4.attempts = 0; iface->dhcpv4.attempts = 0;
iface->dhcpv4.lease_time = 0; iface->dhcpv4.lease_time = 0;
iface->dhcpv4.renewal_time = 0; iface->dhcpv4.renewal_time = 0;
/* We need entropy for both an XID and a random delay before iface->dhcpv4.server_id.s_addr[0] = 0;
* sending the initial discover message. iface->dhcpv4.requested_ip.s_addr[0] = 0;
*/
entropy = sys_rand32_get();
/* A DHCP client MUST choose xid's in such a way as to /* We need entropy for both an XID and a random delay
* minimize the change of using and xid identical to one used * before sending the initial discover message.
* by another client. Choose a random xid st startup and */
* increment it on each new request. entropy = sys_rand32_get();
*/
iface->dhcpv4.xid = entropy; /* A DHCP client MUST choose xid's in such a way as to
* minimize the change of using and xid identical to
* one used by another client. Choose a random xid st
* startup and increment it on each new request.
*/
iface->dhcpv4.xid = entropy;
/* RFC2131 4.1.1 requires we wait a random period between 1 /* RFC2131 4.1.1 requires we wait a random period
* and 10 seconds before sending the initial discover. * between 1 and 10 seconds before sending the initial
*/ * discover.
timeout = entropy % */
(DHCPV4_INITIAL_DELAY_MAX - DHCPV4_INITIAL_DELAY_MIN) + timeout = entropy %
DHCPV4_INITIAL_DELAY_MIN; (DHCPV4_INITIAL_DELAY_MAX - DHCPV4_INITIAL_DELAY_MIN) +
DHCPV4_INITIAL_DELAY_MIN;
NET_DBG("enter state=%s timeout=%"PRIu32"s", NET_DBG("wait timeout=%"PRIu32"s", timeout);
net_dhcpv4_state_name(iface->dhcpv4.state), timeout);
k_delayed_work_init(&iface->dhcpv4.timer, dhcpv4_timeout); k_delayed_work_init(&iface->dhcpv4.timer, dhcpv4_timeout);
k_delayed_work_submit(&iface->dhcpv4.timer, timeout * MSEC_PER_SEC); k_delayed_work_submit(&iface->dhcpv4.timer,
timeout * MSEC_PER_SEC);
break;
case NET_DHCPV4_INIT:
case NET_DHCPV4_SELECTING:
case NET_DHCPV4_REQUESTING:
case NET_DHCPV4_RENEWING:
case NET_DHCPV4_BOUND:
break;
}
}
void net_dhcpv4_stop(struct net_if *iface)
{
switch (iface->dhcpv4.state) {
case NET_DHCPV4_DISABLED:
break;
case NET_DHCPV4_INIT:
case NET_DHCPV4_SELECTING:
case NET_DHCPV4_REQUESTING:
case NET_DHCPV4_RENEWING:
case NET_DHCPV4_BOUND:
iface->dhcpv4.state = NET_DHCPV4_DISABLED;
NET_DBG("state=%s", net_dhcpv4_state_name(iface->dhcpv4.state));
k_delayed_work_cancel(&iface->dhcpv4.timer);
k_delayed_work_cancel(&iface->dhcpv4.t1_timer);
break;
}
} }
int dhcpv4_init(void) int dhcpv4_init(void)