blob: 35aeb757f83b1e28e90a88dc78bd5a9856496899 [file] [log] [blame]
/*
* Copyright (c) 2023 Florian Grandel
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_ieee802154_mgmt_test, LOG_LEVEL_DBG);
#include <string.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/net/ieee802154_mgmt.h>
#include <zephyr/net/net_mgmt.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_pkt.h>
#include <zephyr/shell/shell.h>
#include <ieee802154_frame.h>
extern struct net_pkt *current_pkt;
extern struct k_sem driver_lock;
static struct net_if *iface;
static struct net_mgmt_event_callback scan_cb;
K_SEM_DEFINE(scan_lock, 0, 1);
#define EXPECTED_COORDINATOR_LQI 15U
#define EXPECTED_COORDINATOR_PAN_LE 0xcd, 0xab
#define EXPECTED_COORDINATOR_PAN_CPU_ORDER 0xabcd
#define EXPECTED_COORDINATOR_ADDR_LE 0xc2, 0xa3, 0x9e, 0x00, 0x00, 0x4b, 0x12, 0x00
#define EXPECTED_COORDINATOR_ADDR_BE 0x00, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2
static void scan_result_cb(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
struct net_if *iface)
{
struct ieee802154_context *ctx = net_if_l2_data(iface);
struct ieee802154_req_params *scan_ctx = ctx->scan_ctx;
uint8_t expected_coordinator_address[] = {EXPECTED_COORDINATOR_ADDR_BE};
/* No need for scan_ctx locking as we should execute exclusively. */
zassert_not_null(scan_ctx);
zassert_equal(EXPECTED_COORDINATOR_PAN_CPU_ORDER, scan_ctx->pan_id,
"Scan did not receive correct PAN id.");
zassert_equal(IEEE802154_EXT_ADDR_LENGTH, scan_ctx->len,
"Scan did not receive correct co-ordinator address length.");
zassert_mem_equal(expected_coordinator_address, scan_ctx->addr, IEEE802154_EXT_ADDR_LENGTH);
zassert_equal(EXPECTED_COORDINATOR_LQI, scan_ctx->lqi,
"Scan did not receive correct link quality indicator.");
k_sem_give(&scan_lock);
}
void test_beacon_request(struct ieee802154_mpdu *mpdu)
{
struct ieee802154_command *cmd = mpdu->command;
zassert_equal(1U, mpdu->payload_length, "Beacon request: invalid payload length.");
zassert_equal(IEEE802154_CFI_BEACON_REQUEST, cmd->cfi, "Not a beacon request.");
zassert_equal(IEEE802154_ADDR_MODE_SHORT, mpdu->mhr.fs->fc.dst_addr_mode,
"Beacon request: invalid destination address mode.");
zassert_equal(IEEE802154_BROADCAST_ADDRESS, mpdu->mhr.dst_addr->plain.addr.short_addr,
"Beacon request: destination address should be broadcast address.");
zassert_equal(IEEE802154_BROADCAST_PAN_ID, mpdu->mhr.dst_addr->plain.pan_id,
"Beacon request: destination PAN should be broadcast PAN.");
}
void test_scan_shell_cmd(void)
{
struct ieee802154_mpdu mpdu = {0};
int ret;
ret = shell_execute_cmd(NULL, "ieee802154 scan active 11 500");
zassert_equal(0, ret, "Active scan failed: %d", ret);
/* Expect the beacon to have been received and handled already by the scan command. */
zassert_equal(0, k_sem_take(&scan_lock, K_NO_WAIT), "Active scan: did not receive beacon.");
zassert_not_null(current_pkt);
if (!ieee802154_validate_frame(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt),
&mpdu)) {
NET_ERR("*** Could not parse beacon request.\n");
ztest_test_fail();
goto release_frag;
}
test_beacon_request(&mpdu);
release_frag:
net_pkt_frag_unref(current_pkt->frags);
current_pkt->frags = NULL;
}
ZTEST(ieee802154_l2_shell, test_active_scan)
{
uint8_t beacon_pkt[] = {
0x00, 0xd0, /* FCF */
0x11, /* Sequence Number: 17 */
EXPECTED_COORDINATOR_PAN_LE, /* Source PAN */
EXPECTED_COORDINATOR_ADDR_LE, /* Extended Source Address */
0x00, 0xc0, /* Superframe Specification: PAN coordinator + association permitted */
0x00, /* GTS */
0x00, /* Pending Addresses */
0x00, 0x00 /* Payload */
};
struct net_pkt *pkt;
pkt = net_pkt_rx_alloc_with_buffer(iface, sizeof(beacon_pkt), AF_UNSPEC, 0, K_FOREVER);
if (!pkt) {
NET_ERR("*** No buffer to allocate\n");
ztest_test_fail();
return;
}
net_pkt_set_ieee802154_lqi(pkt, EXPECTED_COORDINATOR_LQI);
net_buf_add_mem(pkt->buffer, beacon_pkt, sizeof(beacon_pkt));
if (net_recv_data(iface, pkt) < 0) {
NET_ERR("Recv data failed");
net_pkt_unref(pkt);
ztest_test_fail();
return;
}
net_mgmt_init_event_callback(&scan_cb, scan_result_cb, NET_EVENT_IEEE802154_SCAN_RESULT);
net_mgmt_add_event_callback(&scan_cb);
test_scan_shell_cmd();
net_mgmt_del_event_callback(&scan_cb);
}
static void *test_setup(void)
{
const struct device *dev = device_get_binding("fake_ieee802154");
k_sem_reset(&driver_lock);
if (!dev) {
NET_ERR("*** Could not get fake device\n");
return NULL;
}
iface = net_if_lookup_by_dev(dev);
if (!iface) {
NET_ERR("*** Could not get fake iface\n");
return NULL;
}
NET_INFO("Fake IEEE 802.15.4 network interface ready\n");
current_pkt = net_pkt_rx_alloc(K_FOREVER);
if (!current_pkt) {
NET_ERR("*** No buffer to allocate\n");
return false;
}
return NULL;
}
static void test_teardown(void *test_fixture)
{
ARG_UNUSED(test_fixture);
net_pkt_unref(current_pkt);
current_pkt = NULL;
}
ZTEST_SUITE(ieee802154_l2_shell, NULL, test_setup, NULL, NULL, test_teardown);