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:
parent
c4f4cb17db
commit
3726bb98bd
3 changed files with 79 additions and 47 deletions
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue