blob: 9afe0f9f75f7b4e8af1547de5e86682265484a75 [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <tc_util.h>
#include <errno.h>
#include <toolchain.h>
#include <linker/sections.h>
#include <net/net_mgmt.h>
#include <net/net_pkt.h>
#include <ztest.h>
#define TEST_MGMT_REQUEST 0x17AB1234
#define TEST_MGMT_EVENT 0x97AB1234
#define TEST_MGMT_EVENT_UNHANDLED 0x97AB4321
/* Notifier infra */
static u32_t event2throw;
static u32_t throw_times;
static int throw_sleep;
static bool with_info;
static K_THREAD_STACK_DEFINE(thrower_stack, 512);
static struct k_thread thrower_thread_data;
static struct k_sem thrower_lock;
/* Receiver infra */
static u32_t rx_event;
static u32_t rx_calls;
static struct net_mgmt_event_callback rx_cb;
static struct in6_addr addr6 = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
static char info_data[CONFIG_NET_MGMT_EVENT_INFO_SIZE] = "mgmt event info";
static int test_mgmt_request(u32_t mgmt_request,
struct net_if *iface, void *data, u32_t len)
{
u32_t *test_data = data;
ARG_UNUSED(iface);
if (len == sizeof(u32_t)) {
*test_data = 1;
return 0;
}
return -EIO;
}
NET_MGMT_REGISTER_REQUEST_HANDLER(TEST_MGMT_REQUEST, test_mgmt_request);
int fake_dev_init(struct device *dev)
{
ARG_UNUSED(dev);
return 0;
}
static void fake_iface_init(struct net_if *iface)
{
u8_t mac[8] = { 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d};
net_if_set_link_addr(iface, mac, 8, NET_LINK_DUMMY);
}
static int fake_iface_send(struct net_if *iface, struct net_pkt *pkt)
{
net_pkt_unref(pkt);
return NET_OK;
}
static struct net_if_api fake_iface_api = {
.init = fake_iface_init,
.send = fake_iface_send,
};
NET_DEVICE_INIT(net_event_test, "net_event_test",
fake_dev_init, NULL, NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&fake_iface_api, DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), 127);
void test_requesting_nm(void)
{
u32_t data = 0;
TC_PRINT("- Request Net MGMT\n");
zassert_false(net_mgmt(TEST_MGMT_REQUEST, NULL, &data, sizeof(data)),
"Requesting Net MGMT failed");
}
static void thrower_thread(void)
{
while (1) {
k_sem_take(&thrower_lock, K_FOREVER);
TC_PRINT("\tThrowing event 0x%08X %u times\n",
event2throw, throw_times);
for (; throw_times; throw_times--) {
k_sleep(throw_sleep);
if (with_info) {
net_mgmt_event_notify_with_info(
event2throw, net_if_get_default(),
info_data,
CONFIG_NET_MGMT_EVENT_INFO_SIZE);
} else {
net_mgmt_event_notify(event2throw,
net_if_get_default());
}
}
}
}
static void receiver_cb(struct net_mgmt_event_callback *cb,
u32_t nm_event, struct net_if *iface)
{
TC_PRINT("\t\tReceived event 0x%08X\n", nm_event);
if (with_info && cb->info) {
if (memcmp(info_data, cb->info,
CONFIG_NET_MGMT_EVENT_INFO_SIZE)) {
rx_calls = (u32_t) -1;
return;
}
}
rx_event = nm_event;
rx_calls++;
}
static int sending_event(u32_t times, bool receiver, bool info)
{
int ret = TC_PASS;
TC_PRINT("- Sending event %u times, %s a receiver, %s info\n",
times, receiver ? "with" : "without",
info ? "with" : "without");
event2throw = TEST_MGMT_EVENT;
throw_times = times;
with_info = info;
if (receiver) {
net_mgmt_add_event_callback(&rx_cb);
}
k_sem_give(&thrower_lock);
k_yield();
if (receiver) {
TC_PRINT("\tReceived 0x%08X %u times\n",
rx_event, rx_calls);
zassert_equal(rx_event, event2throw, "rx_event check failed");
zassert_equal(rx_calls, times, "rx_calls check failed");
net_mgmt_del_event_callback(&rx_cb);
rx_event = rx_calls = 0;
}
return ret;
}
static int test_sending_event(u32_t times, bool receiver)
{
return sending_event(times, receiver, false);
}
static int test_sending_event_info(u32_t times, bool receiver)
{
return sending_event(times, receiver, true);
}
static int test_synchronous_event_listener(u32_t times, bool on_iface)
{
u32_t event_mask;
int ret;
TC_PRINT("- Synchronous event listener %s\n",
on_iface ? "on interface" : "");
event2throw = TEST_MGMT_EVENT | (on_iface ? NET_MGMT_IFACE_BIT : 0);
throw_times = times;
throw_sleep = K_MSEC(200);
event_mask = event2throw;
k_sem_give(&thrower_lock);
if (on_iface) {
ret = net_mgmt_event_wait_on_iface(net_if_get_default(),
event_mask, NULL, NULL,
K_SECONDS(1));
} else {
ret = net_mgmt_event_wait(event_mask, NULL, NULL, NULL,
K_SECONDS(1));
}
if (ret < 0) {
if (ret == -ETIMEDOUT) {
TC_ERROR("Call timed out\n");
}
return TC_FAIL;
}
return TC_PASS;
}
static void initialize_event_tests(void)
{
event2throw = 0;
throw_times = 0;
throw_sleep = K_NO_WAIT;
with_info = false;
rx_event = 0;
rx_calls = 0;
k_sem_init(&thrower_lock, 0, UINT_MAX);
net_mgmt_init_event_callback(&rx_cb, receiver_cb, TEST_MGMT_EVENT);
k_thread_create(&thrower_thread_data, thrower_stack,
K_THREAD_STACK_SIZEOF(thrower_stack),
(k_thread_entry_t)thrower_thread,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
}
static int test_core_event(u32_t event, bool (*func)(void))
{
int ret = TC_PASS;
TC_PRINT("- Triggering core event: 0x%08X\n", event);
net_mgmt_init_event_callback(&rx_cb, receiver_cb, event);
net_mgmt_add_event_callback(&rx_cb);
zassert_true(func(), "func() check failed");
k_yield();
zassert_true(rx_calls, "rx_calls empty");
zassert_equal(rx_event, event, "rx_event check failed");
net_mgmt_del_event_callback(&rx_cb);
rx_event = rx_calls = 0;
return ret;
}
static bool _iface_ip6_add(void)
{
if (net_if_ipv6_addr_add(net_if_get_default(),
&addr6, NET_ADDR_MANUAL, 0)) {
return true;
}
return false;
}
static bool _iface_ip6_del(void)
{
if (net_if_ipv6_addr_rm(net_if_get_default(), &addr6)) {
return true;
}
return false;
}
void test_mgmt(void)
{
TC_PRINT("Starting Network Management API test\n");
test_requesting_nm();
initialize_event_tests();
zassert_false(test_sending_event(1, false),
"test_sending_event failed");
zassert_false(test_sending_event(2, false),
"test_sending_event failed");
zassert_false(test_sending_event(1, true),
"test_sending_event failed");
zassert_false(test_sending_event(2, true),
"test_sending_event failed");
zassert_false(test_sending_event_info(1, false),
"test_sending_event failed");
zassert_false(test_sending_event_info(2, false),
"test_sending_event failed");
zassert_false(test_sending_event_info(1, true),
"test_sending_event failed");
zassert_false(test_sending_event_info(2, true),
"test_sending_event failed");
zassert_false(test_core_event(NET_EVENT_IPV6_ADDR_ADD, _iface_ip6_add),
"test_core_event failed");
zassert_false(test_core_event(NET_EVENT_IPV6_ADDR_DEL, _iface_ip6_del),
"test_core_event failed");
zassert_false(test_synchronous_event_listener(2, false),
"test_synchronous_event_listener failed");
zassert_false(test_synchronous_event_listener(2, true),
"test_synchronous_event_listener failed");
}
void test_main(void)
{
ztest_test_suite(test_mgmt_fn, ztest_unit_test(test_mgmt));
ztest_run_test_suite(test_mgmt_fn);
}