net: config: Wait network interface to come up

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>
This commit is contained in:
Jukka Rissanen 2019-11-05 15:36:29 +02:00 committed by Anas Nashif
parent 6378ac4e38
commit e3dc05f14d

View File

@ -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;
@ -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));
@ -298,22 +340,6 @@ int net_config_init(const char *app_info, u32_t flags, s32_t timeout)
return -ENODEV;
}
if (flags & NET_CONFIG_NEED_IPV6) {
count++;
}
if (flags & NET_CONFIG_NEED_IPV4) {
count++;
}
k_sem_init(&counter, count, UINT_MAX);
setup_ipv4(iface);
setup_dhcpv4(iface);
setup_ipv6(iface, flags);
if (timeout < 0) {
count = -1;
} else if (timeout == 0) {
@ -322,6 +348,48 @@ int net_config_init(const char *app_info, u32_t flags, s32_t timeout)
count = timeout / 1000 + 1;
}
/* First make sure that network interface is up */
if (check_interface(iface) == false) {
k_sem_init(&counter, 1, UINT_MAX);
while (count--) {
if (!k_sem_count_get(&counter)) {
break;
}
if (k_sem_take(&waiter, loop)) {
if (!k_sem_count_get(&counter)) {
break;
}
}
}
/* 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 (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.
*/