From 11c9b8dac7286b9f495327049b0a9a707a025270 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Mon, 20 Jun 2016 12:15:29 +0200 Subject: [PATCH] tests: Add grounds for IEEE 802.15.4 stack tests. First test is a unit test for frame parsing Change-Id: I080d64a71fe4b6ff00e071a0cdee97ab9cd922d5 Signed-off-by: Tomasz Bursztyka --- tests/net/ieee802154/Makefile | 6 + tests/net/ieee802154/prj.mdef | 5 + tests/net/ieee802154/prj_x86.conf | 17 ++ tests/net/ieee802154/src/Makefile | 6 + .../ieee802154/src/ieee802154_fake_driver.c | 137 ++++++++++++ tests/net/ieee802154/src/ieee802154_test.c | 211 ++++++++++++++++++ tests/net/ieee802154/testcase.ini | 5 + 7 files changed, 387 insertions(+) create mode 100644 tests/net/ieee802154/Makefile create mode 100644 tests/net/ieee802154/prj.mdef create mode 100644 tests/net/ieee802154/prj_x86.conf create mode 100644 tests/net/ieee802154/src/Makefile create mode 100644 tests/net/ieee802154/src/ieee802154_fake_driver.c create mode 100644 tests/net/ieee802154/src/ieee802154_test.c create mode 100644 tests/net/ieee802154/testcase.ini diff --git a/tests/net/ieee802154/Makefile b/tests/net/ieee802154/Makefile new file mode 100644 index 00000000000..fa7f724b6bb --- /dev/null +++ b/tests/net/ieee802154/Makefile @@ -0,0 +1,6 @@ +BOARD ?= qemu_x86 +MDEF_FILE = prj.mdef +KERNEL_TYPE ?= nano +CONF_FILE = prj_$(ARCH).conf + +include $(ZEPHYR_BASE)/Makefile.inc diff --git a/tests/net/ieee802154/prj.mdef b/tests/net/ieee802154/prj.mdef new file mode 100644 index 00000000000..648f29b5c4e --- /dev/null +++ b/tests/net/ieee802154/prj.mdef @@ -0,0 +1,5 @@ +% Application : Network test + +% TASK NAME PRIO ENTRY STACK GROUPS +% =================================================== + TASK MAIN 7 main 2048 [EXE] diff --git a/tests/net/ieee802154/prj_x86.conf b/tests/net/ieee802154/prj_x86.conf new file mode 100644 index 00000000000..74c96def565 --- /dev/null +++ b/tests/net/ieee802154/prj_x86.conf @@ -0,0 +1,17 @@ +CONFIG_NETWORKING=y +CONFIG_NET_YAIP=y +CONFIG_NET_BUF=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_NO_ND=y +CONFIG_NET_IPV6_NO_DAD=y +CONFIG_NET_L2_IEEE802154=y +CONFIG_NET_L2_IEEE802154_DEBUG=y +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_NET_NBUF_RX_COUNT=5 +CONFIG_NET_NBUF_TX_COUNT=5 +CONFIG_NET_NBUF_DATA_COUNT=10 +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_NETWORK_IP_STACK_DEBUG_IPV6=y diff --git a/tests/net/ieee802154/src/Makefile b/tests/net/ieee802154/src/Makefile new file mode 100644 index 00000000000..7bcfc7f0105 --- /dev/null +++ b/tests/net/ieee802154/src/Makefile @@ -0,0 +1,6 @@ +ccflags-y += -I${ZEPHYR_BASE}/tests/include +ccflags-y += -I${ZEPHYR_BASE}/net/yaip/l2/ieee802154 +ccflags-y += -I${ZEPHYR_BASE}/net/yaip/ + +obj-y = ieee802154_test.o \ + ieee802154_fake_driver.o diff --git a/tests/net/ieee802154/src/ieee802154_fake_driver.c b/tests/net/ieee802154/src/ieee802154_fake_driver.c new file mode 100644 index 00000000000..02d996b1b95 --- /dev/null +++ b/tests/net/ieee802154/src/ieee802154_fake_driver.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016 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 +#include + +#include + +/** FAKE ieee802.15.4 driver **/ +#include + +extern struct net_buf *current_buf; +extern struct nano_sem driver_lock; + +static int fake_cca(struct device *dev) +{ + return 0; +} + +static int fake_set_channel(struct device *dev, uint16_t channel) +{ + TC_PRINT("Channel %u\n", channel); + + return 0; +} + +static int fake_set_pan_id(struct device *dev, uint16_t pan_id) +{ + TC_PRINT("PAN id 0x%x\n", pan_id); + + return 0; +} + +static int fake_set_short_addr(struct device *dev, uint16_t short_addr) +{ + TC_PRINT("Short address: 0x%x\n", short_addr); + + return 0; +} + +static int fake_set_ieee_addr(struct device *dev, const uint8_t *ieee_addr) +{ + TC_PRINT("IEEE address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + ieee_addr[0], ieee_addr[1], ieee_addr[2], ieee_addr[3], + ieee_addr[4], ieee_addr[5], ieee_addr[6], ieee_addr[7]); + + return 0; +} + +static int fake_set_txpower(struct device *dev, int16_t dbm) +{ + TC_PRINT("TX power %d dbm\n", dbm); + + return 0; +} + +static int fake_tx(struct device *dev, struct net_buf *buf) +{ + TC_PRINT("Sending buffer %p - length %u\n", + buf, net_buf_frags_len(buf)); + + current_buf = net_buf_ref(buf); + + nano_sem_give(&driver_lock); + + return 0; +} + +static int fake_start(struct device *dev) +{ + TC_PRINT("FAKE ieee802154 driver started\n"); + + return 0; +} + +static int fake_stop(struct device *dev) +{ + TC_PRINT("FAKE ieee802154 driver stopped\n"); + + return 0; +} + +static void fake_iface_init(struct net_if *iface) +{ + struct ieee802154_context *ctx = net_if_l2_data(iface); + static uint8_t mac[8] = { 0x00, 0x12, 0x4b, 0x00, + 0x00, 0x9e, 0xa3, 0xc2 }; + + net_if_set_link_addr(iface, mac, 8); + + ctx->pan_id = 0xabcd; + ctx->channel = 26; + ctx->sequence = 62; + + TC_PRINT("FAKE ieee802154 iface initialized\n"); +} + +static int fake_init(struct device *dev) +{ + fake_stop(dev); + + return 0; +} + +static struct ieee802154_radio_api fake_radio_api = { + .iface_api.init = fake_iface_init, + .iface_api.send = ieee802154_radio_send, + + .cca = fake_cca, + .set_channel = fake_set_channel, + .set_pan_id = fake_set_pan_id, + .set_short_addr = fake_set_short_addr, + .set_ieee_addr = fake_set_ieee_addr, + .set_txpower = fake_set_txpower, + .start = fake_start, + .stop = fake_stop, + .tx = fake_tx, +}; + +NET_DEVICE_INIT(fake, "fake_ieee802154", + fake_init, NULL, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &fake_radio_api, IEEE802154_L2, + NET_L2_GET_CTX_TYPE(IEEE802154_L2), 127); diff --git a/tests/net/ieee802154/src/ieee802154_test.c b/tests/net/ieee802154/src/ieee802154_test.c new file mode 100644 index 00000000000..5eb5088e05d --- /dev/null +++ b/tests/net/ieee802154/src/ieee802154_test.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016 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 +#include + +#include +#include + +#include +#include + +struct ieee802154_pkt_test { + char *name; + struct in6_addr src; + struct in6_addr dst; + uint8_t *pkt; + uint8_t length; + struct { + struct ieee802154_fcf_seq *fc_seq; + struct ieee802154_address_field *dst_addr; + struct ieee802154_address_field *src_addr; + } mhr_check; +}; + +uint8_t ns_pkt[] = { + 0x41, 0xd8, 0x3e, 0xcd, 0xab, 0xff, 0xff, 0xc2, 0xa3, 0x9e, 0x00, + 0x00, 0x4b, 0x12, 0x00, 0x7b, 0x09, 0x3a, 0x20, 0x01, 0x0d, 0xb8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x01, 0xff, 0x00, 0x00, 0x01, 0x87, 0x00, 0x2e, 0xad, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x00, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x74 +}; + +struct ieee802154_pkt_test test_ns_pkt = { + .name = "NS frame", + .src = { { { 0x20, 0x01, 0xdb, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }, + .dst = { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x01 } } }, + .pkt = ns_pkt, + .length = sizeof(ns_pkt), + .mhr_check.fc_seq = (struct ieee802154_fcf_seq *)ns_pkt, + .mhr_check.dst_addr = (struct ieee802154_address_field *)(ns_pkt + 3), + .mhr_check.src_addr = (struct ieee802154_address_field *)(ns_pkt + 7), +}; + +struct net_buf *current_buf; +struct nano_sem driver_lock; +struct net_if *iface; + +static void pkt_hexdump(uint8_t *pkt, uint8_t length) +{ + int i; + + TC_PRINT(" -> Packet content:\n"); + + for (i = 0; i < length;) { + int j; + + TC_PRINT("\t"); + + for (j = 0; j < 10 && i < length; j++, i++) { + TC_PRINT("%02x ", *pkt); + pkt++; + } + + TC_PRINT("\n"); + } +} + +static void ieee_addr_hexdump(uint8_t *addr, uint8_t length) +{ + int i; + + TC_PRINT(" -> IEEE 802.15.4 Address: "); + + for (i = 0; i < length-1; i++) { + TC_PRINT("%02x:", *addr); + addr++; + } + + TC_PRINT("%02x\n", *addr); +} + +static inline int test_packet_parsing(struct ieee802154_pkt_test *t) +{ + struct ieee802154_mpdu mpdu; + + TC_PRINT("- Parsing packet 0x%p of frame %s\n", t->pkt, t->name); + + if (!ieee802154_validate_frame(t->pkt, t->length, &mpdu)) { + TC_ERROR("*** Could not validate frame %s\n", t->name); + return TC_FAIL; + } + + if (mpdu.mhr.fs != t->mhr_check.fc_seq || + mpdu.mhr.dst_addr != t->mhr_check.dst_addr || + mpdu.mhr.src_addr != t->mhr_check.src_addr) { + TC_PRINT("d: %p vs %p -- s: %p vs %p\n", + mpdu.mhr.dst_addr, t->mhr_check.dst_addr, + mpdu.mhr.src_addr, t->mhr_check.src_addr); + TC_ERROR("*** Wrong MPDU information on frame %s\n", + t->name); + + return TC_FAIL; + } + + return TC_PASS; +} + +static inline int test_ns_sending(struct ieee802154_pkt_test *t) +{ + struct ieee802154_mpdu mpdu; + + TC_PRINT("- Sending NS packet\n"); + + if (net_ipv6_send_ns(iface, NULL, &t->src, &t->dst, &t->dst, false)) { + TC_ERROR("*** Could not create IPv6 NS packet\n"); + return TC_FAIL; + } + + nano_sem_take(&driver_lock, MSEC(10)); + + if (!current_buf) { + TC_ERROR("*** Could not send IPv6 NS packet\n"); + return TC_FAIL; + } + + pkt_hexdump(net_nbuf_ll(current_buf), net_buf_frags_len(current_buf)); + + if (!ieee802154_validate_frame(net_nbuf_ll(current_buf), + net_buf_frags_len(current_buf), &mpdu)) { + TC_ERROR("*** Sent packet is not valid\n"); + net_buf_unref(current_buf); + + return TC_FAIL; + } + + net_buf_unref(current_buf); + current_buf = NULL; + + return TC_PASS; +} + +static inline int initialize_test_environment(void) +{ + struct device *dev; + + nano_sem_init(&driver_lock); + + current_buf = NULL; + + dev = device_get_binding("fake_ieee802154"); + if (!dev) { + TC_ERROR("*** Could not get fake device\n"); + return TC_FAIL; + } + + iface = net_if_lookup_by_dev(dev); + if (!iface) { + TC_ERROR("*** Could not get fake iface\n"); + return TC_FAIL; + } + + TC_PRINT("Fake IEEE 802.15.4 network interface ready\n"); + + ieee_addr_hexdump(iface->link_addr.addr, 8); + + return TC_PASS; +} + +void main(void) +{ + int status = TC_FAIL; + + TC_PRINT("Starting ieee802154 stack test\n"); + + if (initialize_test_environment() != TC_PASS) { + goto end; + } + + if (test_packet_parsing(&test_ns_pkt) != TC_PASS) { + goto end; + } + + if (test_ns_sending(&test_ns_pkt) != TC_PASS) { + goto end; + } + + status = TC_PASS; + +end: + TC_END_RESULT(status); + TC_END_REPORT(status); +} diff --git a/tests/net/ieee802154/testcase.ini b/tests/net/ieee802154/testcase.ini new file mode 100644 index 00000000000..7f2bd8943da --- /dev/null +++ b/tests/net/ieee802154/testcase.ini @@ -0,0 +1,5 @@ +[test] +tags = net +arch_whitelist = x86 +platform_whitelist = qemu_x86 +build_only = true