Skip to content

Commit

Permalink
net: config: Wait network interface to come up
Browse files Browse the repository at this point in the history
Before we try to set IP addresses to the network interface,
make sure that the interface is up.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
  • Loading branch information
jukkar authored and nashif committed Dec 9, 2019
1 parent 6378ac4 commit e3dc05f
Showing 1 changed file with 83 additions and 15 deletions.
98 changes: 83 additions & 15 deletions subsys/net/lib/config/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ extern int net_init_clock_via_sntp(void);
static K_SEM_DEFINE(waiter, 0, 1);
static struct k_sem counter;

#if defined(CONFIG_NET_NATIVE)
static struct net_mgmt_event_callback mgmt_iface_cb;
#endif

#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4)
static struct net_mgmt_event_callback mgmt4_cb;

Expand Down Expand Up @@ -282,12 +286,50 @@ static void setup_ipv6(struct net_if *iface, u32_t flags)
#define setup_ipv6(...)
#endif /* CONFIG_NET_IPV6 */

#if defined(CONFIG_NET_NATIVE)
static void iface_up_handler(struct net_mgmt_event_callback *cb,
u32_t mgmt_event, struct net_if *iface)
{
if (mgmt_event == NET_EVENT_IF_UP) {
NET_INFO("Interface %p coming up", iface);

k_sem_reset(&counter);
k_sem_give(&waiter);
}
}

static bool check_interface(struct net_if *iface)
{
if (net_if_is_up(iface)) {
k_sem_reset(&counter);
k_sem_give(&waiter);
return true;
}

NET_INFO("Waiting interface %p to be up...", iface);

net_mgmt_init_event_callback(&mgmt_iface_cb, iface_up_handler,
NET_EVENT_IF_UP);
net_mgmt_add_event_callback(&mgmt_iface_cb);

return false;
}
#else
static void check_interface(struct net_if *iface)
{
k_sem_reset(&counter);
k_sem_give(&waiter);

return true;
}
#endif

int net_config_init(const char *app_info, u32_t flags, s32_t timeout)
{
#define LOOP_DIVIDER 10
struct net_if *iface = net_if_get_default();
int loop = timeout / LOOP_DIVIDER;
int count = 0;
int count, need = 0;

if (app_info) {
NET_INFO("%s", log_strdup(app_info));
Expand All @@ -298,30 +340,56 @@ int net_config_init(const char *app_info, u32_t flags, s32_t timeout)
return -ENODEV;
}

if (flags & NET_CONFIG_NEED_IPV6) {
count++;
if (timeout < 0) {
count = -1;
} else if (timeout == 0) {
count = 0;
} else {
count = timeout / 1000 + 1;
}

if (flags & NET_CONFIG_NEED_IPV4) {
count++;
}
/* First make sure that network interface is up */
if (check_interface(iface) == false) {
k_sem_init(&counter, 1, UINT_MAX);

k_sem_init(&counter, count, UINT_MAX);
while (count--) {
if (!k_sem_count_get(&counter)) {
break;
}

setup_ipv4(iface);
if (k_sem_take(&waiter, loop)) {
if (!k_sem_count_get(&counter)) {
break;
}
}
}

setup_dhcpv4(iface);
/* If the above while() loop timeouted, reset the count so that
* the while() loop below will not wait more.
*/
if (timeout > 0 && count < 0) {
count = 0;
}

#if defined(CONFIG_NET_NATIVE)
net_mgmt_del_event_callback(&mgmt_iface_cb);
#endif
}

setup_ipv4(iface);
setup_dhcpv4(iface);
setup_ipv6(iface, flags);

if (timeout < 0) {
count = -1;
} else if (timeout == 0) {
count = 0;
} else {
count = timeout / 1000 + 1;
if (flags & NET_CONFIG_NEED_IPV6) {
need++;
}

if (flags & NET_CONFIG_NEED_IPV4) {
need++;
}

k_sem_init(&counter, need, UINT_MAX);

/* Loop here until we are ready to continue. As we might need
* to wait multiple events, sleep smaller amounts of data.
*/
Expand Down

0 comments on commit e3dc05f

Please sign in to comment.