tests/net: Test network power management awareness
A quick test on a dummy device that: - opens a socket (success) - sends data (success) - suspends (success) - suspends (failure) - sends data (failure) - resumes (success) - resumes (failure) - sends data (success) This permits to show that PM states are properly handled in network stack. Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
d2a139ee9b
commit
9dd822dc93
9
tests/net/pm/CMakeLists.txt
Normal file
9
tests/net/pm/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
|
||||
project(pm)
|
||||
|
||||
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip)
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
12
tests/net/pm/Kconfig
Normal file
12
tests/net/pm/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Private config options for net pm test
|
||||
|
||||
# Copyright (c) 2020 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
mainmenu "Network Power-Management test"
|
||||
|
||||
config FAKE_DEV
|
||||
def_bool y
|
||||
select NET_POWER_MANAGEMENT if DEVICE_POWER_MANAGEMENT
|
||||
|
||||
source "Kconfig.zephyr"
|
17
tests/net/pm/prj.conf
Normal file
17
tests/net/pm/prj.conf
Normal file
|
@ -0,0 +1,17 @@
|
|||
CONFIG_SYS_POWER_MANAGEMENT=y
|
||||
CONFIG_DEVICE_POWER_MANAGEMENT=y
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_TEST=y
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_SOCKETS=y
|
||||
CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
CONFIG_POSIX_MAX_FDS=2
|
||||
CONFIG_ZTEST_STACKSIZE=2048
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2
|
||||
CONFIG_ZTEST=y
|
188
tests/net/pm/src/main.c
Normal file
188
tests/net/pm/src/main.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <linker/sections.h>
|
||||
#include <ztest.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/dummy.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/socket.h>
|
||||
|
||||
struct fake_dev_context {
|
||||
u8_t mac_addr[sizeof(struct net_eth_addr)];
|
||||
struct net_if *iface;
|
||||
};
|
||||
|
||||
static int fake_dev_pm_control(struct device *dev, u32_t command,
|
||||
void *context, device_pm_cb cb, void *arg)
|
||||
{
|
||||
struct fake_dev_context *ctx = dev->driver_data;
|
||||
int ret = 0;
|
||||
|
||||
if (command == DEVICE_PM_SET_POWER_STATE) {
|
||||
if (*(u32_t *)context == DEVICE_PM_SUSPEND_STATE) {
|
||||
ret = net_if_suspend(ctx->iface);
|
||||
if (ret == -EBUSY) {
|
||||
goto out;
|
||||
}
|
||||
} else if (*(u32_t *)context == DEVICE_PM_ACTIVE_STATE) {
|
||||
ret = net_if_resume(ctx->iface);
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
if (cb) {
|
||||
cb(dev, ret, context, arg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int fake_dev_send(struct device *dev, struct net_pkt *pkt)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8_t *fake_dev_get_mac(struct fake_dev_context *ctx)
|
||||
{
|
||||
if (ctx->mac_addr[2] == 0x00) {
|
||||
/* 00-00-5E-00-53-xx Documentation RFC 7042 */
|
||||
ctx->mac_addr[0] = 0x00;
|
||||
ctx->mac_addr[1] = 0x00;
|
||||
ctx->mac_addr[2] = 0x5E;
|
||||
ctx->mac_addr[3] = 0x00;
|
||||
ctx->mac_addr[4] = 0x53;
|
||||
ctx->mac_addr[5] = sys_rand32_get();
|
||||
}
|
||||
|
||||
return ctx->mac_addr;
|
||||
}
|
||||
|
||||
static void fake_dev_iface_init(struct net_if *iface)
|
||||
{
|
||||
struct device *dev = net_if_get_device(iface);
|
||||
struct fake_dev_context *ctx = dev->driver_data;
|
||||
u8_t *mac = fake_dev_get_mac(ctx);
|
||||
|
||||
net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);
|
||||
|
||||
ctx->iface = iface;
|
||||
}
|
||||
|
||||
int fake_dev_init(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fake_dev_context fake_dev_context_data;
|
||||
|
||||
static struct dummy_api fake_dev_if_api = {
|
||||
.iface_api.init = fake_dev_iface_init,
|
||||
.send = fake_dev_send,
|
||||
};
|
||||
|
||||
#define _ETH_L2_LAYER DUMMY_L2
|
||||
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
|
||||
|
||||
NET_DEVICE_INIT(fake_dev, "fake_dev",
|
||||
fake_dev_init, fake_dev_pm_control,
|
||||
&fake_dev_context_data, NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&fake_dev_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE, 127);
|
||||
|
||||
void test_setup(void)
|
||||
{
|
||||
struct net_if *iface = net_if_get_default();
|
||||
struct in_addr in4addr_my = { { { 192, 168, 0, 2 } } };
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
net_if_up(iface);
|
||||
|
||||
ifaddr = net_if_ipv4_addr_add(iface, &in4addr_my, NET_ADDR_MANUAL, 0);
|
||||
zassert_not_null(ifaddr, "Could not add iface address");
|
||||
}
|
||||
|
||||
void test_pm(void)
|
||||
{
|
||||
struct net_if *iface = net_if_get_default();
|
||||
struct device *dev = net_if_get_device(iface);
|
||||
char data[] = "some data";
|
||||
struct sockaddr_in addr4;
|
||||
int sock;
|
||||
int ret;
|
||||
|
||||
addr4.sin_family = AF_INET;
|
||||
addr4.sin_port = htons(12345);
|
||||
inet_pton(AF_INET, "192.168.0.1", &addr4.sin_addr);
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
zassert_true(sock >= 0, "Could not open socket");
|
||||
|
||||
zassert_false(net_if_is_suspended(iface), "net iface is not suspended");
|
||||
|
||||
/* Let's send some data, it should go through */
|
||||
ret = sendto(sock, data, ARRAY_SIZE(data), 0,
|
||||
(struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
|
||||
zassert_true(ret > 0, "Could not send data");
|
||||
|
||||
/* Let's make sure net stack's thread gets ran, or setting PM state
|
||||
* might return -EBUSY instead
|
||||
*/
|
||||
k_yield();
|
||||
|
||||
ret = device_set_power_state(dev, DEVICE_PM_SUSPEND_STATE,
|
||||
NULL, NULL);
|
||||
zassert_true(ret == 0, "Could not set state");
|
||||
|
||||
zassert_true(net_if_is_suspended(iface), "net iface is not suspended");
|
||||
|
||||
/* Let's try to suspend it again, it should fail relevantly */
|
||||
ret = device_set_power_state(dev, DEVICE_PM_SUSPEND_STATE,
|
||||
NULL, NULL);
|
||||
zassert_true(ret == -EALREADY, "Could change state");
|
||||
|
||||
zassert_true(net_if_is_suspended(iface), "net iface is not suspended");
|
||||
|
||||
/* Let's send some data, it should fail relevantly */
|
||||
ret = sendto(sock, data, ARRAY_SIZE(data), 0,
|
||||
(struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
|
||||
zassert_true(ret < 0, "Could send data");
|
||||
|
||||
ret = device_set_power_state(dev, DEVICE_PM_ACTIVE_STATE,
|
||||
NULL, NULL);
|
||||
zassert_true(ret == 0, "Could not set state");
|
||||
|
||||
zassert_false(net_if_is_suspended(iface), "net iface is suspended");
|
||||
|
||||
ret = device_set_power_state(dev, DEVICE_PM_ACTIVE_STATE,
|
||||
NULL, NULL);
|
||||
zassert_true(ret == -EALREADY, "Could change state");
|
||||
|
||||
/* Let's send some data, it should go through */
|
||||
ret = sendto(sock, data, ARRAY_SIZE(data), 0,
|
||||
(struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
|
||||
zassert_true(ret > 0, "Could not send data");
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(test_net_pm,
|
||||
ztest_unit_test(test_setup),
|
||||
ztest_unit_test(test_pm));
|
||||
ztest_run_test_suite(test_net_pm);
|
||||
}
|
8
tests/net/pm/testcase.yaml
Normal file
8
tests/net/pm/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
common:
|
||||
# There is nothing hw specific to be tested here
|
||||
# so let's limit the test to qemu_x86
|
||||
platform_whitelist: qemu_x86
|
||||
depends_on: netif
|
||||
tests:
|
||||
net.pm:
|
||||
tags: net
|
Loading…
Reference in a new issue