zephyr/subsys/net/lib/app/init.c
Andrew Boie 65a9d2a94a kernel: make K_.*_INITIALIZER private to kernel
Upcoming memory protection features will be placing some additional
constraints on kernel objects:

- They need to reside in memory owned by the kernel and not the
application
- Certain kernel object validation schemes will require some run-time
initialization of all kernel objects before they can be used.

Per Ben these initializer macros were never intended to be public. It is
not forbidden to use them, but doing so requires care: the memory being
initialized must reside in kernel space, and extra runtime
initialization steps may need to be peformed before they are fully
usable as kernel objects. In particular, kernel subsystems or drivers
whose objects are already in kernel memory may still need to use these
macros if they define kernel objects as members of a larger data
structure.

It is intended that application developers instead use the
K_<object>_DEFINE macros, which will automatically put the object in the
right memory and add them to a section which can be iterated over at
boot to complete initiailization.

There was no K_WORK_DEFINE() macro for creating struct k_work objects,
this is now added.

k_poll_event and k_poll_signal are intended to be instatiated from
application memory and have not been changed.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2017-07-10 11:44:56 -07:00

273 lines
6.0 KiB
C

/* init.c */
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#if defined(CONFIG_NET_DEBUG_APP)
#define SYS_LOG_DOMAIN "net/app"
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#define NET_LOG_ENABLED 1
#endif
#include <zephyr.h>
#include <init.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_if.h>
#include <net/dhcpv4.h>
#include <net/net_mgmt.h>
#include <net/dns_resolve.h>
#include <net/net_app.h>
static K_SEM_DEFINE(waiter, 0, 1);
static struct k_sem counter;
#if defined(CONFIG_NET_DHCPV4)
static struct net_mgmt_event_callback mgmt4_cb;
static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
u32_t mgmt_event,
struct net_if *iface)
{
#if defined(CONFIG_NET_DEBUG_APP) && CONFIG_SYS_LOG_NET_LEVEL > 1
char hr_addr[NET_IPV4_ADDR_LEN];
#endif
int i;
if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
return;
}
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
struct net_if_addr *if_addr = &iface->ipv4.unicast[i];
if (if_addr->addr_type != NET_ADDR_DHCP || !if_addr->is_used) {
continue;
}
NET_INFO("IPv4 address: %s",
net_addr_ntop(AF_INET, &if_addr->address.in_addr,
hr_addr, NET_IPV4_ADDR_LEN));
NET_INFO("Lease time: %u seconds", iface->dhcpv4.lease_time);
NET_INFO("Subnet: %s",
net_addr_ntop(AF_INET, &iface->ipv4.netmask,
hr_addr, NET_IPV4_ADDR_LEN));
NET_INFO("Router: %s",
net_addr_ntop(AF_INET, &iface->ipv4.gw,
hr_addr, NET_IPV4_ADDR_LEN));
break;
}
k_sem_take(&counter, K_NO_WAIT);
k_sem_give(&waiter);
}
static void setup_dhcpv4(struct net_if *iface)
{
NET_INFO("Running dhcpv4 client...");
net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler,
NET_EVENT_IPV4_ADDR_ADD);
net_mgmt_add_event_callback(&mgmt4_cb);
net_dhcpv4_start(iface);
}
#else
#define setup_dhcpv4(...)
#endif /* CONFIG_NET_DHCPV4 */
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_DHCPV4)
#if !defined(CONFIG_NET_APP_MY_IPV4_ADDR)
#error "You need to define an IPv4 address or enable DHCPv4!"
#endif
static void setup_ipv4(struct net_if *iface)
{
#if defined(CONFIG_NET_DEBUG_APP) && CONFIG_SYS_LOG_NET_LEVEL > 1
char hr_addr[NET_IPV4_ADDR_LEN];
#endif
struct in_addr addr;
if (net_addr_pton(AF_INET, CONFIG_NET_APP_MY_IPV4_ADDR, &addr)) {
NET_ERR("Invalid address: %s", CONFIG_NET_APP_MY_IPV4_ADDR);
return;
}
net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
NET_INFO("IPv4 address: %s",
net_addr_ntop(AF_INET, &addr, hr_addr, NET_IPV4_ADDR_LEN));
k_sem_take(&counter, K_NO_WAIT);
k_sem_give(&waiter);
}
#else
#define setup_ipv4(...)
#endif /* CONFIG_NET_IPV4 && !CONFIG_NET_DHCPV4 */
#if defined(CONFIG_NET_IPV6)
#if !defined(CONFIG_NET_APP_MY_IPV6_ADDR)
#error "You need to define an IPv6 address!"
#endif
static struct net_mgmt_event_callback mgmt6_cb;
static struct in6_addr laddr;
static void ipv6_event_handler(struct net_mgmt_event_callback *cb,
u32_t mgmt_event, struct net_if *iface)
{
if (mgmt_event == NET_EVENT_IPV6_DAD_SUCCEED) {
#if defined(CONFIG_NET_DEBUG_APP) && CONFIG_SYS_LOG_NET_LEVEL > 1
char hr_addr[NET_IPV6_ADDR_LEN];
#endif
struct net_if_addr *ifaddr;
ifaddr = net_if_ipv6_addr_lookup(&laddr, &iface);
if (!ifaddr ||
!(net_ipv6_addr_cmp(&ifaddr->address.in6_addr, &laddr) &&
ifaddr->addr_state == NET_ADDR_PREFERRED)) {
/* Address is not yet properly setup */
return;
}
NET_INFO("IPv6 address: %s",
net_addr_ntop(AF_INET6, &laddr, hr_addr,
NET_IPV6_ADDR_LEN));
k_sem_take(&counter, K_NO_WAIT);
k_sem_give(&waiter);
}
if (mgmt_event == NET_EVENT_IPV6_ROUTER_ADD) {
k_sem_take(&counter, K_NO_WAIT);
k_sem_give(&waiter);
}
}
static void setup_ipv6(struct net_if *iface, u32_t flags)
{
struct net_if_addr *ifaddr;
u32_t mask = NET_EVENT_IPV6_DAD_SUCCEED;
if (net_addr_pton(AF_INET6, CONFIG_NET_APP_MY_IPV6_ADDR, &laddr)) {
NET_ERR("Invalid address: %s", CONFIG_NET_APP_MY_IPV6_ADDR);
return;
}
if (flags & NET_APP_NEED_ROUTER) {
mask |= NET_EVENT_IPV6_ROUTER_ADD;
}
net_mgmt_init_event_callback(&mgmt6_cb, ipv6_event_handler, mask);
net_mgmt_add_event_callback(&mgmt6_cb);
ifaddr = net_if_ipv6_addr_add(iface, &laddr, NET_ADDR_MANUAL, 0);
if (!ifaddr) {
NET_ERR("Cannot add %s to interface",
CONFIG_NET_APP_MY_IPV6_ADDR);
return;
}
}
#else
#define setup_ipv6(...)
#endif /* CONFIG_NET_IPV6 */
int net_app_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;
if (app_info) {
NET_INFO("%s", app_info);
}
if (flags & NET_APP_NEED_IPV6) {
count++;
}
if (flags & NET_APP_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) {
count = 0;
} else {
count = timeout / 1000 + 1;
}
/* Loop here until until we are ready to continue. As we might need
* to wait multiple events, sleep smaller amounts of data.
*/
while (count--) {
if (k_sem_take(&waiter, loop)) {
if (!k_sem_count_get(&counter)) {
break;
}
}
}
if (!count && timeout) {
NET_ERR("Timeout while waiting setup");
return -ETIMEDOUT;
}
return 0;
}
#if defined(CONFIG_NET_APP_AUTO_INIT)
static int init_net_app(struct device *device)
{
u32_t flags = 0;
int ret;
ARG_UNUSED(device);
if (IS_ENABLED(CONFIG_NET_APP_NEED_IPV6)) {
flags |= NET_APP_NEED_IPV6;
}
if (IS_ENABLED(CONFIG_NET_APP_NEED_IPV6_ROUTER)) {
flags |= NET_APP_NEED_ROUTER;
}
if (IS_ENABLED(CONFIG_NET_APP_NEED_IPV4)) {
flags |= NET_APP_NEED_IPV4;
}
/* Initialize the application automatically if needed */
ret = net_app_init("Initializing network", flags,
K_SECONDS(CONFIG_NET_APP_INIT_TIMEOUT));
if (ret < 0) {
NET_ERR("Network initialization failed (%d)", ret);
}
return ret;
}
SYS_INIT(init_net_app, APPLICATION, CONFIG_NET_APP_INIT_PRIO);
#endif /* CONFIG_NET_APP_AUTO_INIT */