From 19d1dd747f5e7a823948261c68dfa6ead0689218 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 22 Sep 2023 17:13:39 +0300 Subject: [PATCH] tests: net: icmp: Add test cases for new ICMP API Tests cases for new ICMP API. Signed-off-by: Jukka Rissanen --- tests/net/icmp/CMakeLists.txt | 9 ++ tests/net/icmp/prj.conf | 21 +++ tests/net/icmp/src/main.c | 296 ++++++++++++++++++++++++++++++++++ tests/net/icmp/testcase.yaml | 22 +++ 4 files changed, 348 insertions(+) create mode 100644 tests/net/icmp/CMakeLists.txt create mode 100644 tests/net/icmp/prj.conf create mode 100644 tests/net/icmp/src/main.c create mode 100644 tests/net/icmp/testcase.yaml diff --git a/tests/net/icmp/CMakeLists.txt b/tests/net/icmp/CMakeLists.txt new file mode 100644 index 0000000000..a05c45522a --- /dev/null +++ b/tests/net/icmp/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(icmp) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/net/icmp/prj.conf b/tests/net/icmp/prj.conf new file mode 100644 index 0000000000..4116a90fdf --- /dev/null +++ b/tests/net/icmp/prj.conf @@ -0,0 +1,21 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_BUF=y +CONFIG_ZTEST_STACK_SIZE=1024 +CONFIG_NET_PKT_RX_COUNT=2 +CONFIG_NET_PKT_TX_COUNT=5 +CONFIG_NET_BUF_RX_COUNT=5 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_LOG=y +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y +CONFIG_MAIN_STACK_SIZE=1280 +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_IPV6_NBR_CACHE=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n diff --git a/tests/net/icmp/src/main.c b/tests/net/icmp/src/main.c new file mode 100644 index 0000000000..8ac4f5ee2f --- /dev/null +++ b/tests/net/icmp/src/main.c @@ -0,0 +1,296 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Use highest log level if both IPv4 and IPv6 are defined */ +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) + +#if CONFIG_NET_ICMPV4_LOG_LEVEL > CONFIG_NET_ICMPV6_LOG_LEVEL +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL +#else +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL +#endif + +#elif defined(CONFIG_NET_IPV4) +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV4_LOG_LEVEL +#elif defined(CONFIG_NET_IPV6) +#define ICMP_LOG_LEVEL CONFIG_NET_ICMPV6_LOG_LEVEL +#else +#define ICMP_LOG_LEVEL LOG_LEVEL_INF +#endif + +#include +LOG_MODULE_REGISTER(net_test, ICMP_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "net_private.h" +#include "icmpv4.h" +#include "icmpv6.h" +#include "ipv4.h" +#include "ipv6.h" + +#define PKT_WAIT_TIME K_SECONDS(1) +#define SEM_WAIT_TIME K_SECONDS(1) +#define TEST_DATA "dummy test data" + +static struct in6_addr send_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +static struct in6_addr recv_addr_6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; +static struct in_addr send_addr_4 = { { { 192, 0, 2, 1 } } }; +static struct in_addr recv_addr_4 = { { { 192, 0, 2, 2 } } }; + +static struct net_if *sender, *receiver; + +static struct test_icmp_context { + uint8_t mac[sizeof(struct net_eth_addr)]; + struct net_if *iface; + uint8_t test_data[sizeof(TEST_DATA)]; + struct k_sem tx_sem; + bool req_received; +} send_ctx, recv_ctx; + +static void test_iface_init(struct net_if *iface) +{ + struct test_icmp_context *ctx = net_if_get_device(iface)->data; + static int counter; + + /* Generate and assign MAC. */ + /* 00-00-5E-00-53-xx Documentation RFC 7042 */ + ctx->mac[0] = 0x00; + ctx->mac[1] = 0x00; + ctx->mac[2] = 0x5E; + ctx->mac[3] = 0x00; + ctx->mac[4] = 0x53; + ctx->mac[5] = ++counter; + + net_if_set_link_addr(iface, ctx->mac, sizeof(ctx->mac), NET_LINK_ETHERNET); + + ctx->iface = iface; +} + +static int test_sender(const struct device *dev, struct net_pkt *pkt) +{ + struct net_pkt *send_pkt; + + send_pkt = net_pkt_clone(pkt, PKT_WAIT_TIME); + + net_pkt_set_iface(send_pkt, recv_ctx.iface); + + (void)net_recv_data(recv_ctx.iface, send_pkt); + + net_pkt_unref(pkt); + + return 0; +} + +static int test_receiver(const struct device *dev, struct net_pkt *pkt) +{ + struct net_pkt *send_pkt; + + send_pkt = net_pkt_clone(pkt, PKT_WAIT_TIME); + + net_pkt_set_iface(send_pkt, send_ctx.iface); + + (void)net_recv_data(send_ctx.iface, send_pkt); + + net_pkt_unref(pkt); + + return 0; +} + +static struct dummy_api send_if_api = { + .iface_api.init = test_iface_init, + .send = test_sender, +}; + +static struct dummy_api recv_if_api = { + .iface_api.init = test_iface_init, + .send = test_receiver, +}; + +NET_DEVICE_INIT(test_sender_icmp, "test_sender_icmp", NULL, NULL, &send_ctx, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &send_if_api, + DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU); + +NET_DEVICE_INIT(test_receiver_icmp, "test_receiver_icmp", NULL, NULL, &recv_ctx, NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &recv_if_api, + DUMMY_L2, NET_L2_GET_CTX_TYPE(DUMMY_L2), NET_IPV6_MTU); + +static int icmp_handler(struct net_icmp_ctx *ctx, + struct net_pkt *pkt, + struct net_icmp_ip_hdr *hdr, + struct net_icmp_hdr *icmp_hdr, + void *user_data) +{ + struct test_icmp_context *test = user_data; + + if (hdr->family == AF_INET) { + struct net_ipv4_hdr *ip_hdr = hdr->ipv4; + + NET_DBG("Received Echo reply from %s to %s", + net_sprint_ipv4_addr(&ip_hdr->src), + net_sprint_ipv4_addr(&ip_hdr->dst)); + + } else if (hdr->family == AF_INET6) { + struct net_ipv6_hdr *ip_hdr = hdr->ipv6; + + NET_DBG("Received Echo Reply from %s to %s", + net_sprint_ipv6_addr(&ip_hdr->src), + net_sprint_ipv6_addr(&ip_hdr->dst)); + } else { + return -ENOENT; + } + + test->req_received = true; + k_sem_give(&test->tx_sem); + + net_pkt_unref(pkt); + + return 0; +} + +ZTEST(icmp_tests, test_icmpv6_echo_request) +{ + struct sockaddr_in6 dst6 = { 0 }; + struct net_icmp_ping_params params; + struct net_icmp_ctx ctx; + int ret; + + if (!IS_ENABLED(CONFIG_NET_IPV6)) { + return; + } + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV6_ECHO_REPLY, 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + dst6.sin6_family = AF_INET6; + +#if defined(CONFIG_NET_IPV6) + memcpy(&dst6.sin6_addr, &recv_addr_6, sizeof(recv_addr_6)); +#endif + + params.identifier = 1234; + params.sequence = 5678; + params.tc_tos = 1; + params.priority = 2; + params.data = send_ctx.test_data; + params.data_size = sizeof(send_ctx.test_data); + + ret = net_icmp_send_echo_request(&ctx, sender, + (struct sockaddr *)&dst6, + ¶ms, + &send_ctx); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + k_sem_take(&send_ctx.tx_sem, SEM_WAIT_TIME); + + zassert_true(send_ctx.req_received, "Did not receive Echo-Request"); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); + + send_ctx.req_received = false; +} + +ZTEST(icmp_tests, test_icmpv4_echo_request) +{ + struct sockaddr_in dst4 = { 0 }; + struct net_icmp_ping_params params; + struct net_icmp_ctx ctx; + int ret; + + if (!IS_ENABLED(CONFIG_NET_IPV4)) { + return; + } + + ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, 0, icmp_handler); + zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret); + + dst4.sin_family = AF_INET; + +#if defined(CONFIG_NET_IPV4) + memcpy(&dst4.sin_addr, &recv_addr_4, sizeof(recv_addr_4)); +#endif + + params.identifier = 1234; + params.sequence = 5678; + params.tc_tos = 1; + params.priority = 2; + params.data = send_ctx.test_data; + params.data_size = sizeof(send_ctx.test_data); + + ret = net_icmp_send_echo_request(&ctx, sender, + (struct sockaddr *)&dst4, + ¶ms, + &send_ctx); + zassert_equal(ret, 0, "Cannot send ICMP Echo-Request (%d)", ret); + + k_sem_take(&send_ctx.tx_sem, SEM_WAIT_TIME); + + zassert_true(send_ctx.req_received, "Did not receive Echo-Request"); + + ret = net_icmp_cleanup_ctx(&ctx); + zassert_equal(ret, 0, "Cannot cleanup ICMP (%d)", ret); + + send_ctx.req_received = false; +} + +static void *setup(void) +{ + if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) { + k_thread_priority_set(k_current_get(), + K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)); + } else { + k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9)); + } + +#if defined(CONFIG_NET_IPV6) + (void)net_if_ipv6_addr_add(send_ctx.iface, &send_addr_6, NET_ADDR_MANUAL, 0); + (void)net_if_ipv6_addr_add(recv_ctx.iface, &recv_addr_6, NET_ADDR_MANUAL, 0); +#else + ARG_UNUSED(send_addr_6); + ARG_UNUSED(recv_addr_6); +#endif + +#if defined(CONFIG_NET_IPV4) + (void)net_if_ipv4_addr_add(send_ctx.iface, &send_addr_4, NET_ADDR_MANUAL, 0); + (void)net_if_ipv4_addr_add(recv_ctx.iface, &recv_addr_4, NET_ADDR_MANUAL, 0); +#else + ARG_UNUSED(send_addr_4); + ARG_UNUSED(recv_addr_4); +#endif + + memcpy(send_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA)); + memcpy(recv_ctx.test_data, &(TEST_DATA), sizeof(TEST_DATA)); + + k_sem_init(&send_ctx.tx_sem, 0, 1); + k_sem_init(&recv_ctx.tx_sem, 0, 1); + + sender = net_if_lookup_by_dev(DEVICE_GET(test_sender_icmp)); + zassert_equal(sender, send_ctx.iface, "Invalid interface (%p vs %p)", + sender, send_ctx.iface); + + receiver = net_if_lookup_by_dev(DEVICE_GET(test_receiver_icmp)); + zassert_equal(receiver, recv_ctx.iface, "Invalid interface (%p vs %p)", + receiver, recv_ctx.iface); + + return NULL; +} + +ZTEST_SUITE(icmp_tests, NULL, setup, NULL, NULL, NULL); diff --git a/tests/net/icmp/testcase.yaml b/tests/net/icmp/testcase.yaml new file mode 100644 index 0000000000..cfe3f1ffac --- /dev/null +++ b/tests/net/icmp/testcase.yaml @@ -0,0 +1,22 @@ +common: + depends_on: netif + tags: net icmp +tests: + net.icmp.coop: + extra_configs: + - CONFIG_NET_TC_THREAD_COOPERATIVE=y + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 + net.icmp.preempt: + extra_configs: + - CONFIG_NET_TC_THREAD_PREEMPTIVE=y + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + - CONFIG_NET_IF_MAX_IPV4_COUNT=2 + net.icmp.no_ipv4: + extra_configs: + - CONFIG_NET_IPV4=n + - CONFIG_NET_IF_MAX_IPV6_COUNT=2 + net.icmp.no_ipv6: + extra_configs: + - CONFIG_NET_IPV6=n + - CONFIG_NET_IF_MAX_IPV4_COUNT=2