net: tests: Add initial set of IPv6 tests
Change-Id: Ib68b38a809068ca14ee9307e9ea605f03611ebd3 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
fb9af2523d
commit
338c2be888
6 changed files with 479 additions and 0 deletions
7
tests/net/ipv6/Makefile
Normal file
7
tests/net/ipv6/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
BOARD ?= qemu_x86
|
||||
MDEF_FILE = prj.mdef
|
||||
KERNEL_TYPE ?= nano
|
||||
ARCH ?= x86
|
||||
CONF_FILE = prj_$(ARCH).conf
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.inc
|
5
tests/net/ipv6/prj.mdef
Normal file
5
tests/net/ipv6/prj.mdef
Normal file
|
@ -0,0 +1,5 @@
|
|||
% Application : Network test
|
||||
|
||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
||||
% ===================================================
|
||||
TASK MAIN 7 mainloop 2048 [EXE]
|
23
tests/net/ipv6/prj_x86.conf
Normal file
23
tests/net/ipv6/prj_x86.conf
Normal file
|
@ -0,0 +1,23 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
CONFIG_NET_IPV4=n
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_IPV6_ND=y
|
||||
CONFIG_NET_IPV6_DAD=y
|
||||
CONFIG_NET_NBUF_TX_COUNT=3
|
||||
CONFIG_NET_NBUF_RX_COUNT=4
|
||||
CONFIG_NET_NBUF_DATA_COUNT=7
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_IPV6=y
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_CORE=y
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_IF=y
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_UTILS=y
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF=y
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_CONN=y
|
||||
#CONFIG_NETWORK_IP_STACK_DEBUG_L2=y
|
||||
|
3
tests/net/ipv6/src/Makefile
Normal file
3
tests/net/ipv6/src/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
obj-y = main.o
|
||||
ccflags-y += -I${ZEPHYR_BASE}/tests/include
|
||||
ccflags-y += -I${ZEPHYR_BASE}/net/yaip
|
435
tests/net/ipv6/src/main.c
Normal file
435
tests/net/ipv6/src/main.c
Normal file
|
@ -0,0 +1,435 @@
|
|||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
#include <sections.h>
|
||||
|
||||
#include <tc_util.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#include "net_private.h"
|
||||
#include "icmpv6.h"
|
||||
#include "ipv6.h"
|
||||
|
||||
#if defined(CONFIG_NETWORK_IP_STACK_DEBUG_IPV6)
|
||||
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
static struct in6_addr my_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
static struct in6_addr peer_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } };
|
||||
static struct in6_addr mcast_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* ICMPv6 NS frame (74 bytes) */
|
||||
static const unsigned char icmpv6_ns_invalid[] = {
|
||||
/* IPv6 header starts here */
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3A, 0xFF,
|
||||
0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
/* ICMPv6 NS header starts here */
|
||||
0x87, 0x00, 0x7B, 0x9C, 0x60, 0x00, 0x00, 0x00,
|
||||
/* Target Address */
|
||||
0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
/* Source link layer address */
|
||||
0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0xD8,
|
||||
/* Target link layer address */
|
||||
0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0xD7,
|
||||
/* Source link layer address */
|
||||
0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0xD6,
|
||||
/* MTU option */
|
||||
0x05, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0xD5,
|
||||
};
|
||||
|
||||
/* ICMPv6 NS frame (64 bytes) */
|
||||
static const unsigned char icmpv6_ns_no_sllao[] = {
|
||||
/* IPv6 header starts here */
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3A, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
/* ICMPv6 NS header starts here */
|
||||
0x87, 0x00, 0x7B, 0x9C, 0x60, 0x00, 0x00, 0x00,
|
||||
/* Target Address */
|
||||
0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
};
|
||||
|
||||
static bool test_failed;
|
||||
static struct nano_sem wait_data;
|
||||
|
||||
#define WAIT_TIME (sys_clock_ticks_per_sec / 4)
|
||||
#define WAIT_TIME_LONG (sys_clock_ticks_per_sec)
|
||||
#define SENDING 93244
|
||||
#define MY_PORT 1969
|
||||
#define PEER_PORT 16233
|
||||
|
||||
struct net_test_ipv6 {
|
||||
uint8_t mac_addr[sizeof(struct net_eth_addr)];
|
||||
struct net_linkaddr ll_addr;
|
||||
};
|
||||
|
||||
int net_test_dev_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *net_test_get_mac(struct device *dev)
|
||||
{
|
||||
struct net_test_ipv6 *context = dev->driver_data;
|
||||
|
||||
if (context->mac_addr[0] == 0x00) {
|
||||
/* 10-00-00-00-00 to 10-00-00-00-FF Documentation RFC7042 */
|
||||
context->mac_addr[0] = 0x10;
|
||||
context->mac_addr[1] = 0x00;
|
||||
context->mac_addr[2] = 0x00;
|
||||
context->mac_addr[3] = 0x00;
|
||||
context->mac_addr[4] = 0x00;
|
||||
context->mac_addr[5] = sys_rand32_get();
|
||||
}
|
||||
|
||||
return context->mac_addr;
|
||||
}
|
||||
|
||||
static void net_test_iface_init(struct net_if *iface)
|
||||
{
|
||||
uint8_t *mac = net_test_get_mac(net_if_get_device(iface));
|
||||
|
||||
net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr));
|
||||
}
|
||||
|
||||
static int tester_send(struct net_if *iface, struct net_buf *buf)
|
||||
{
|
||||
if (!buf->frags) {
|
||||
TC_ERROR("No data to send!\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
/* TC_PRINT("Data to be sent, len %d\n", net_buf_frags_len(buf)); */
|
||||
|
||||
/* Feed this data back to us */
|
||||
if (net_recv_data(iface, buf) < 0) {
|
||||
TC_ERROR("Data receive failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
net_nbuf_unref(buf);
|
||||
test_failed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct net_test_ipv6 net_test_data;
|
||||
|
||||
static struct net_if_api net_test_if_api = {
|
||||
.init = net_test_iface_init,
|
||||
.send = tester_send,
|
||||
};
|
||||
|
||||
#define _ETH_L2_LAYER DUMMY_L2
|
||||
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
|
||||
|
||||
NET_DEVICE_INIT(net_test_ipv6, "net_test_ipv6",
|
||||
net_test_dev_init, &net_test_data, NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&net_test_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE,
|
||||
127);
|
||||
|
||||
static bool test_init(void)
|
||||
{
|
||||
struct net_if_addr *ifaddr;
|
||||
struct net_if_mcast_addr *maddr;
|
||||
struct net_if *iface = net_if_get_default();
|
||||
|
||||
if (!iface) {
|
||||
TC_ERROR("Interface is NULL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface, &my_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
TC_ERROR("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&my_addr));
|
||||
return false;
|
||||
}
|
||||
|
||||
net_ipv6_addr_create(&mcast_addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
|
||||
|
||||
maddr = net_if_ipv6_maddr_add(iface, &mcast_addr);
|
||||
if (!maddr) {
|
||||
TC_ERROR("Cannot add multicast IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&mcast_addr));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The semaphore is there to wait the data to be received. */
|
||||
nano_sem_init(&wait_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_send_ns_mcast(void)
|
||||
{
|
||||
int ret;
|
||||
struct in6_addr tgt;
|
||||
|
||||
net_ipv6_addr_create_solicited_node(&my_addr, &tgt);
|
||||
|
||||
ret = net_ipv6_send_ns(net_if_get_default(),
|
||||
NULL,
|
||||
&peer_addr,
|
||||
&my_addr,
|
||||
&tgt,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
TC_ERROR("Cannot send NS (%d)\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_send_ns(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_ipv6_send_ns(net_if_get_default(),
|
||||
NULL,
|
||||
&peer_addr,
|
||||
&my_addr,
|
||||
&my_addr,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
TC_ERROR("Cannot send NS (%d)\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_nbr_lookup_fail(void)
|
||||
{
|
||||
struct net_nbr *nbr;
|
||||
|
||||
nbr = net_ipv6_nbr_lookup(net_if_get_default(),
|
||||
&peer_addr);
|
||||
if (nbr) {
|
||||
TC_ERROR("Neighbor %s found in cache\n",
|
||||
net_sprint_ipv6_addr(&peer_addr));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_nbr_lookup_ok(void)
|
||||
{
|
||||
struct net_nbr *nbr;
|
||||
|
||||
nbr = net_ipv6_nbr_lookup(net_if_get_default(),
|
||||
&peer_addr);
|
||||
if (!nbr) {
|
||||
TC_ERROR("Neighbor %s not found in cache\n",
|
||||
net_sprint_ipv6_addr(&peer_addr));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_send_ns_extra_options(void)
|
||||
{
|
||||
struct net_buf *buf, *frag;
|
||||
struct net_if *iface;
|
||||
uint16_t reserve;
|
||||
|
||||
buf = net_nbuf_get_reserve_tx(0);
|
||||
|
||||
NET_ASSERT_INFO(buf, "Out of TX buffers");
|
||||
|
||||
iface = net_if_get_default();
|
||||
|
||||
reserve = net_if_get_ll_reserve(iface, NULL);
|
||||
|
||||
frag = net_nbuf_get_reserve_data(reserve);
|
||||
|
||||
net_buf_frag_add(buf, frag);
|
||||
|
||||
net_nbuf_set_ll_reserve(buf, reserve);
|
||||
net_nbuf_set_iface(buf, iface);
|
||||
net_nbuf_set_family(buf, AF_INET6);
|
||||
net_nbuf_set_ip_hdr_len(buf, sizeof(struct net_ipv6_hdr));
|
||||
|
||||
net_nbuf_ll_clear(buf);
|
||||
|
||||
memcpy(net_buf_add(frag, sizeof(icmpv6_ns_invalid)),
|
||||
icmpv6_ns_invalid, sizeof(icmpv6_ns_invalid));
|
||||
|
||||
if (net_recv_data(iface, buf) < 0) {
|
||||
TC_ERROR("Data receive for invalid NS failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_send_ns_no_options(void)
|
||||
{
|
||||
struct net_buf *buf, *frag;
|
||||
struct net_if *iface;
|
||||
uint16_t reserve;
|
||||
|
||||
buf = net_nbuf_get_reserve_tx(0);
|
||||
|
||||
NET_ASSERT_INFO(buf, "Out of TX buffers");
|
||||
|
||||
iface = net_if_get_default();
|
||||
|
||||
reserve = net_if_get_ll_reserve(iface, NULL);
|
||||
|
||||
frag = net_nbuf_get_reserve_data(reserve);
|
||||
|
||||
net_buf_frag_add(buf, frag);
|
||||
|
||||
net_nbuf_set_ll_reserve(buf, reserve);
|
||||
net_nbuf_set_iface(buf, iface);
|
||||
net_nbuf_set_family(buf, AF_INET6);
|
||||
net_nbuf_set_ip_hdr_len(buf, sizeof(struct net_ipv6_hdr));
|
||||
|
||||
net_nbuf_ll_clear(buf);
|
||||
|
||||
memcpy(net_buf_add(frag, sizeof(icmpv6_ns_no_sllao)),
|
||||
icmpv6_ns_no_sllao, sizeof(icmpv6_ns_no_sllao));
|
||||
|
||||
if (net_recv_data(iface, buf) < 0) {
|
||||
TC_ERROR("Data receive for invalid NS failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_prefix_timeout(void)
|
||||
{
|
||||
struct net_if_ipv6_prefix *prefix;
|
||||
struct in6_addr addr = { { { 0x20, 1, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1 } } };
|
||||
int len = 64, lifetime = 1;
|
||||
|
||||
prefix = net_if_ipv6_prefix_add(net_if_get_default(),
|
||||
&addr, len, lifetime);
|
||||
|
||||
net_if_ipv6_prefix_set_lf(prefix, false);
|
||||
net_if_ipv6_prefix_set_timer(prefix, lifetime);
|
||||
|
||||
nano_sem_take(&wait_data, SECONDS(lifetime * 3/2));
|
||||
|
||||
prefix = net_if_ipv6_prefix_lookup(net_if_get_default(),
|
||||
&addr, len);
|
||||
if (prefix) {
|
||||
TC_ERROR("Prefix %s/%d should have expired",
|
||||
net_sprint_ipv6_addr(&addr), len);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_prefix_timeout_overflow(void)
|
||||
{
|
||||
struct net_if_ipv6_prefix *prefix;
|
||||
struct in6_addr addr = { { { 0x20, 1, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1 } } };
|
||||
int len = 64, lifetime = 0xfffffffe;
|
||||
|
||||
prefix = net_if_ipv6_prefix_add(net_if_get_default(),
|
||||
&addr, len, lifetime);
|
||||
|
||||
net_if_ipv6_prefix_set_lf(prefix, false);
|
||||
net_if_ipv6_prefix_set_timer(prefix, lifetime);
|
||||
|
||||
if (nano_sem_take(&wait_data, SECONDS(lifetime * 3/2))) {
|
||||
TC_ERROR("Prefix %s/%d lock should still be there",
|
||||
net_sprint_ipv6_addr(&addr), len);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!net_if_ipv6_prefix_rm(net_if_get_default(), &addr, len)) {
|
||||
TC_ERROR("Prefix %s/%d should have been removed",
|
||||
net_sprint_ipv6_addr(&addr), len);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
bool (*func)(void);
|
||||
} tests[] = {
|
||||
{ "test init", test_init },
|
||||
{ "IPv6 send NS mcast", net_test_send_ns_mcast },
|
||||
{ "IPv6 neighbor lookup fail", net_test_nbr_lookup_fail },
|
||||
{ "IPv6 send NS", net_test_send_ns },
|
||||
{ "IPv6 neighbor lookup ok", net_test_nbr_lookup_ok },
|
||||
{ "IPv6 send NS extra options", net_test_send_ns_extra_options },
|
||||
{ "IPv6 send NS no options", net_test_send_ns_no_options },
|
||||
{ "IPv6 prefix timeout", net_test_prefix_timeout },
|
||||
{ "IPv6 prefix timeout overflow", net_test_prefix_timeout_overflow },
|
||||
};
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int count, pass;
|
||||
|
||||
for (count = 0, pass = 0; count < ARRAY_SIZE(tests); count++) {
|
||||
TC_START(tests[count].name);
|
||||
test_failed = false;
|
||||
if (!tests[count].func() || test_failed) {
|
||||
TC_END(FAIL, "failed\n");
|
||||
} else {
|
||||
TC_END(PASS, "passed\n");
|
||||
pass++;
|
||||
}
|
||||
|
||||
fiber_yield();
|
||||
}
|
||||
|
||||
TC_END_REPORT(((pass != ARRAY_SIZE(tests)) ? TC_FAIL : TC_PASS));
|
||||
}
|
6
tests/net/ipv6/testcase.ini
Normal file
6
tests/net/ipv6/testcase.ini
Normal file
|
@ -0,0 +1,6 @@
|
|||
[test]
|
||||
tags = net-ipv6
|
||||
build_only = true
|
||||
arch_whitelist = x86
|
||||
# Doesn't work for ia32_pci
|
||||
filter = CONFIG_SOC : "ia32"
|
Loading…
Add table
Add a link
Reference in a new issue