tests: net: Add tests for network interface
Change-Id: I35f0b3f1794c65b08d32ca561b6189ee59a7a76c Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
76785f0bcd
commit
cc8eb4144b
5 changed files with 410 additions and 0 deletions
4
tests/net/iface/Makefile
Normal file
4
tests/net/iface/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
BOARD ?= qemu_x86
|
||||
CONF_FILE = prj.conf
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.test
|
22
tests/net/iface/prj.conf
Normal file
22
tests/net/iface/prj.conf
Normal file
|
@ -0,0 +1,22 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
CONFIG_NET_IPV4=n
|
||||
CONFIG_NET_MAX_CONTEXTS=4
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_RANDOM_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_IPV6_DAD=n
|
||||
CONFIG_NET_NBUF_TX_COUNT=10
|
||||
CONFIG_NET_NBUF_RX_COUNT=5
|
||||
CONFIG_NET_NBUF_DATA_COUNT=10
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_MAX_NEXTHOPS=8
|
||||
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_ZTEST=y
|
||||
#CONFIG_NET_DEBUG_IF=y
|
||||
#CONFIG_SYS_LOG_NET_LEVEL=4
|
4
tests/net/iface/src/Makefile
Normal file
4
tests/net/iface/src/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
obj-y = main.o
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys/net/ip
|
||||
|
||||
include $(ZEPHYR_BASE)/tests/Makefile.test
|
376
tests/net/iface/src/main.c
Normal file
376
tests/net/iface/src/main.c
Normal file
|
@ -0,0 +1,376 @@
|
|||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
#include <sections.h>
|
||||
|
||||
#include <ztest.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
|
||||
#define NET_LOG_ENABLED 1
|
||||
#include "net_private.h"
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_IF)
|
||||
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
/* Interface 1 addresses */
|
||||
static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* Interface 2 addresses */
|
||||
static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* Interface 3 addresses */
|
||||
static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* Extra address is assigned to ll_addr */
|
||||
static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
|
||||
0x04 } } };
|
||||
|
||||
static struct in6_addr in6addr_mcast = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
static struct net_if *iface1;
|
||||
static struct net_if *iface2;
|
||||
static struct net_if *iface3;
|
||||
|
||||
static bool test_failed;
|
||||
static bool test_started;
|
||||
static struct k_sem wait_data;
|
||||
|
||||
#define WAIT_TIME 250
|
||||
|
||||
struct net_if_test {
|
||||
uint8_t idx;
|
||||
uint8_t mac_addr[sizeof(struct net_eth_addr)];
|
||||
struct net_linkaddr ll_addr;
|
||||
};
|
||||
|
||||
static int net_iface_dev_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *net_iface_get_mac(struct device *dev)
|
||||
{
|
||||
struct net_if_test *data = dev->driver_data;
|
||||
|
||||
if (data->mac_addr[0] == 0x00) {
|
||||
/* 10-00-00-00-00 to 10-00-00-00-FF Documentation RFC7042 */
|
||||
data->mac_addr[0] = 0x10;
|
||||
data->mac_addr[1] = 0x00;
|
||||
data->mac_addr[2] = 0x00;
|
||||
data->mac_addr[3] = 0x00;
|
||||
data->mac_addr[4] = 0x00;
|
||||
data->mac_addr[5] = sys_rand32_get();
|
||||
}
|
||||
|
||||
data->ll_addr.addr = data->mac_addr;
|
||||
data->ll_addr.len = 6;
|
||||
|
||||
return data->mac_addr;
|
||||
}
|
||||
|
||||
static void net_iface_init(struct net_if *iface)
|
||||
{
|
||||
uint8_t *mac = net_iface_get_mac(net_if_get_device(iface));
|
||||
|
||||
net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr));
|
||||
}
|
||||
|
||||
static int sender_iface(struct net_if *iface, struct net_buf *buf)
|
||||
{
|
||||
if (!buf->frags) {
|
||||
DBG("No data to send!\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
if (test_started) {
|
||||
struct net_if_test *data = iface->dev->driver_data;
|
||||
|
||||
DBG("Sending at iface %d %p\n", net_if_get_by_iface(iface),
|
||||
iface);
|
||||
|
||||
if (net_nbuf_iface(buf) != iface) {
|
||||
DBG("Invalid interface %p, expecting %p\n",
|
||||
net_nbuf_iface(buf), iface);
|
||||
test_failed = true;
|
||||
}
|
||||
|
||||
if (net_if_get_by_iface(iface) != data->idx) {
|
||||
DBG("Invalid interface %d index, expecting %d\n",
|
||||
data->idx, net_if_get_by_iface(iface));
|
||||
test_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
k_sem_give(&wait_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct net_if_test net_iface1_data;
|
||||
struct net_if_test net_iface2_data;
|
||||
struct net_if_test net_iface3_data;
|
||||
|
||||
static struct net_if_api net_iface_api = {
|
||||
.init = net_iface_init,
|
||||
.send = sender_iface,
|
||||
};
|
||||
|
||||
#define _ETH_L2_LAYER DUMMY_L2
|
||||
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
|
||||
|
||||
NET_DEVICE_INIT_INSTANCE(net_iface1_test,
|
||||
"iface1",
|
||||
iface1,
|
||||
net_iface_dev_init,
|
||||
&net_iface1_data,
|
||||
NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&net_iface_api,
|
||||
_ETH_L2_LAYER,
|
||||
_ETH_L2_CTX_TYPE,
|
||||
127);
|
||||
|
||||
NET_DEVICE_INIT_INSTANCE(net_iface2_test,
|
||||
"iface2",
|
||||
iface2,
|
||||
net_iface_dev_init,
|
||||
&net_iface2_data,
|
||||
NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&net_iface_api,
|
||||
_ETH_L2_LAYER,
|
||||
_ETH_L2_CTX_TYPE,
|
||||
127);
|
||||
|
||||
NET_DEVICE_INIT_INSTANCE(net_iface3_test,
|
||||
"iface3",
|
||||
iface3,
|
||||
net_iface_dev_init,
|
||||
&net_iface3_data,
|
||||
NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&net_iface_api,
|
||||
_ETH_L2_LAYER,
|
||||
_ETH_L2_CTX_TYPE,
|
||||
127);
|
||||
|
||||
static void iface_setup(void)
|
||||
{
|
||||
struct net_if_mcast_addr *maddr;
|
||||
struct net_if_addr *ifaddr;
|
||||
int idx;
|
||||
|
||||
/* The semaphore is there to wait the data to be received. */
|
||||
k_sem_init(&wait_data, 0, UINT_MAX);
|
||||
|
||||
iface1 = net_if_get_by_index(0);
|
||||
iface2 = net_if_get_by_index(1);
|
||||
iface3 = net_if_get_by_index(2);
|
||||
|
||||
((struct net_if_test *)iface1->dev->driver_data)->idx = 0;
|
||||
((struct net_if_test *)iface2->dev->driver_data)->idx = 1;
|
||||
((struct net_if_test *)iface3->dev->driver_data)->idx = 2;
|
||||
|
||||
idx = net_if_get_by_iface(iface1);
|
||||
assert_equal(idx, 0, "Invalid index iface1");
|
||||
|
||||
idx = net_if_get_by_iface(iface2);
|
||||
assert_equal(idx, 1, "Invalid index iface2");
|
||||
|
||||
idx = net_if_get_by_iface(iface3);
|
||||
assert_equal(idx, 2, "Invalid index iface3");
|
||||
|
||||
DBG("Interfaces: [%d] iface1 %p, [%d] iface2 %p, [%d] iface3 %p\n",
|
||||
net_if_get_by_iface(iface1), iface1,
|
||||
net_if_get_by_iface(iface2), iface2,
|
||||
net_if_get_by_iface(iface3), iface3);
|
||||
|
||||
assert_not_null(iface1, "Interface 1");
|
||||
assert_not_null(iface2, "Interface 2");
|
||||
assert_not_null(iface3, "Interface 3");
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&my_addr1));
|
||||
assert_not_null(ifaddr, "addr1");
|
||||
}
|
||||
|
||||
/* For testing purposes we need to set the adddresses preferred */
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&ll_addr));
|
||||
assert_not_null(ifaddr, "ll_addr");
|
||||
}
|
||||
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&my_addr2));
|
||||
assert_not_null(ifaddr, "addr2");
|
||||
}
|
||||
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface2, &my_addr3,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&my_addr3));
|
||||
assert_not_null(ifaddr, "addr3");
|
||||
}
|
||||
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
net_ipv6_addr_create(&in6addr_mcast, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
|
||||
|
||||
maddr = net_if_ipv6_maddr_add(iface1, &in6addr_mcast);
|
||||
if (!maddr) {
|
||||
DBG("Cannot add multicast IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&in6addr_mcast));
|
||||
assert_not_null(maddr, "mcast");
|
||||
}
|
||||
|
||||
net_if_up(iface1);
|
||||
net_if_up(iface2);
|
||||
net_if_up(iface3);
|
||||
|
||||
/* The interface might receive data which might fail the checks
|
||||
* in the iface sending function, so we need to reset the failure
|
||||
* flag.
|
||||
*/
|
||||
test_failed = false;
|
||||
|
||||
test_started = true;
|
||||
}
|
||||
|
||||
static bool send_iface(struct net_if *iface, int val, bool expect_fail)
|
||||
{
|
||||
static uint8_t data[] = { 't', 'e', 's', 't', '\0' };
|
||||
struct net_buf *buf;
|
||||
int ret;
|
||||
|
||||
buf = net_nbuf_get_reserve_tx(0);
|
||||
net_nbuf_set_iface(buf, iface);
|
||||
|
||||
net_nbuf_append(buf, sizeof(data), data);
|
||||
|
||||
ret = net_send_data(buf);
|
||||
if (!expect_fail && ret < 0) {
|
||||
DBG("Cannot send test buffer (%d)\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!expect_fail && k_sem_take(&wait_data, WAIT_TIME)) {
|
||||
DBG("Timeout while waiting interface %d data\n", val);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void send_iface1(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
DBG("Sending data to iface 1 %p\n", iface1);
|
||||
|
||||
ret = send_iface(iface1, 1, false);
|
||||
|
||||
assert_true(ret, "iface 1");
|
||||
}
|
||||
|
||||
static void send_iface2(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
DBG("Sending data to iface 2 %p\n", iface2);
|
||||
|
||||
ret = send_iface(iface2, 2, false);
|
||||
|
||||
assert_true(ret, "iface 2");
|
||||
}
|
||||
|
||||
static void send_iface3(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
DBG("Sending data to iface 3 %p\n", iface3);
|
||||
|
||||
ret = send_iface(iface3, 3, false);
|
||||
|
||||
assert_true(ret, "iface 3");
|
||||
}
|
||||
|
||||
static void send_iface1_down(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
DBG("Sending data to iface 1 %p while down\n", iface1);
|
||||
|
||||
net_if_down(iface1);
|
||||
|
||||
ret = send_iface(iface1, 1, true);
|
||||
|
||||
assert_true(ret, "iface 1 down");
|
||||
}
|
||||
|
||||
static void send_iface1_up(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
DBG("Sending data to iface 1 %p again\n", iface1);
|
||||
|
||||
net_if_up(iface1);
|
||||
|
||||
ret = send_iface(iface1, 1, false);
|
||||
|
||||
assert_true(ret, "iface 1 up again");
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(net_iface_test,
|
||||
ztest_unit_test(iface_setup),
|
||||
ztest_unit_test(send_iface1),
|
||||
ztest_unit_test(send_iface2),
|
||||
ztest_unit_test(send_iface3),
|
||||
ztest_unit_test(send_iface1_down),
|
||||
ztest_unit_test(send_iface1_up)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(net_iface_test);
|
||||
}
|
4
tests/net/iface/testcase.ini
Normal file
4
tests/net/iface/testcase.ini
Normal file
|
@ -0,0 +1,4 @@
|
|||
[test]
|
||||
tags = net
|
||||
arch_whitelist = x86
|
||||
platform_whitelist = qemu_x86
|
Loading…
Add table
Add a link
Reference in a new issue