1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #1968 from authmillenon/basic_mac

sys: net: Initial import of a simple data-forwarding MAC protocol (nomac)
This commit is contained in:
Oleg Hahm 2015-01-14 08:19:51 +01:00
commit 5926697d21
11 changed files with 1009 additions and 0 deletions

View File

@ -16,6 +16,9 @@ endif
ifneq (,$(filter l2_ping,$(USEMODULE)))
DIRS += net/link_layer/ping
endif
ifneq (,$(filter nomac,$(USEMODULE)))
DIRS += net/link_layer/nomac
endif
ifneq (,$(filter transport_layer,$(USEMODULE)))
USEMODULE += udp
USEMODULE += tcp

View File

@ -1,3 +1,6 @@
ifneq (,$(filter nomac,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
ifneq (,$(filter transport_layer,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif

View File

@ -2,4 +2,8 @@ ifneq (,$(filter net_if,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/sys/net/include/
endif
ifneq (,$(filter nomac,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/sys/net/include/
endif
include $(RIOTBASE)/Makefile.base

View File

@ -67,6 +67,10 @@
#include "tcp.h"
#endif
#ifdef MODULE_NOMAC
#include "nomac.h"
#endif
#ifdef MODULE_NET_IF
#include "cpu-conf.h"
#include "cpu.h"
@ -241,6 +245,10 @@ void auto_init(void)
DEBUG("Auto init net_if module.\n");
l2_ping_init();
#endif
#ifdef MODULE_NOMAC
DEBUG("Auto init nomac module.\n");
nomac_init_module();
#endif
#ifdef MODULE_NET_IF
DEBUG("Auto init net_if module.\n");
auto_init_net_if();

107
sys/net/include/nomac.h Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup nomac Link layer with no medium access
* @ingroup net
* @brief Link layer protocol to speak with any transceiver driver
* directly without any medium access.
* @{
*
* @file
* @brief Link layer protocol to speak with any transceiver driver
* directly without any medium access.
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef __NOMAC_H_
#define __NOMAC_H_
#include <stdlib.h>
#include "netdev/base.h"
#include "netapi.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef NOMAC_REGISTRY_SIZE
/**
* @brief The size of NOMAC's registry of receiving threads.
*/
#define NOMAC_REGISTRY_SIZE (1)
#endif
/**
* @brief Recommended stack size for a NOMAC thread
* TODO: determine real minimal size based on thread_print_all() output
*/
#define NOMAC_CONTROL_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
/**
* @brief Basic configuration types
*
* @extends netapi_conf_type_t
*/
typedef enum {
NOMAC_PROTO = NETAPI_CONF_PROTO, /**< Set or get protocol */
NOMAC_CHANNEL = NETAPI_CONF_CARRIER, /**< Set or get channel */
NOMAC_ADDRESS = NETAPI_CONF_ADDRESS, /**< Set or get address */
NOMAC_NID = NETAPI_CONF_SUBNETS, /**< Set or get network id
* (e.g. PAN ID in 802.15.4)*/
NOMAC_MAX_PACKET_SIZE = NETAPI_CONF_MAX_PACKET_SIZE, /**< Set or get maximum
* packet size */
NOMAC_SRC_LEN = NETAPI_CONF_SRC_LEN, /**< Set or get default source length */
NOMAC_REGISTRY = NETAPI_CONF_REGISTRY, /**< get registered threads */
NOMAC_ADDRESS2 = NETDEV_OPT_ADDRESS_LONG, /**< Set or get alternative address
* format (e.g EUI-64 in 802.15.4) */
} nomac_conf_type_t;
/**
* @brief Initializes the module
*/
void nomac_init_module(void);
/**
* @brief Initialize new NOMAC layer.
*
* @param[in] stack Stack for the control thread
* @param[in] stacksize Size of *stack*
* @param[in] priority Priority for the control thread
* @param[in] name Name for the control thread
* @param[in] dev An *initialized* network device to use with this MAC
* layer
*
* @see @ref thread_create
*
* @return PID of NOMAC control thread on success
* @return -EINVAL if priority is invalid
* @return -EOVERFLOW if no slot for the new thread is available
*/
kernel_pid_t nomac_init(char *stack, int stacksize, char priority,
const char *name, netdev_t *dev);
#ifdef MODULE_NETDEV_DUMMY
/**
* @brief Re-updates the receive callback of a network device for testing
* purposes
*
* @param[in] dev A network device
*/
void nomac_update_callback(netdev_t *dev);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __NOMAC_H_ */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,295 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <errno.h>
#include <string.h>
#include "netapi.h"
#include "msg.h"
#include "netdev/base.h"
#include "thread.h"
#include "nomac.h"
#ifdef MODULE_NETDEV_DUMMY
#include "netdev_dummy.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
#define NOMAC_MSG_QUEUE_SIZE (16)
static struct {
kernel_pid_t registrar_pid; /**< Thread recipient is registered to */
kernel_pid_t recipient_pid; /**< Registered recipient thread */
} _nomac_registry[NOMAC_REGISTRY_SIZE];
static int _nomac_recv_cb(netdev_t *dev, void *src, size_t src_len, void *dest,
size_t dest_len, void *payload, size_t payload_len)
{
(void)dev;
kernel_pid_t current_pid = thread_getpid();
size_t offset;
netapi_rcv_pkt_t packet;
netapi_ack_t ack_mem;
msg_t msg_pkt, msg_ack;
packet.type = NETAPI_CMD_RCV;
packet.ack = &ack_mem;
packet.src = src;
packet.src_len = src_len;
packet.dest = dest;
packet.dest_len = dest_len;
msg_pkt.type = NETAPI_MSG_TYPE;
msg_pkt.content.ptr = (char *)(&packet);
for (unsigned int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
if (_nomac_registry[i].registrar_pid == current_pid) {
offset = 0;
while (offset < payload_len) {
netapi_ack_t *ack;
packet.data = (void *)(((char *)payload) + offset);
packet.data_len = payload_len - offset;
msg_send_receive(&msg_pkt, &msg_ack,
_nomac_registry[i].recipient_pid);
ack = (netapi_ack_t *)(msg_ack.content.ptr);
if ((msg_ack.type == NETAPI_MSG_TYPE) &&
(ack->type == NETAPI_CMD_ACK) &&
(ack->orig == NETAPI_CMD_RCV)) {
if (ack->result > 0) {
offset += (ack->result);
}
else {
DEBUG("Error code received for registrar %" PRIkernel_pid
" with recipient %" PRIkernel_pid ": %d",
_nomac_registry[i].registrar_pid,
_nomac_registry[i].recipient_pid,
-(ack->result));
return ack->result;
}
}
else {
DEBUG("Unexpected msg instead of ACK. Abort for registrar "
"\"%s\" with recipient \"%s\": msg.type = %d, "
"ack->type = %d, ack->orig = %d",
thread_getname(_nomac_registry[i].registrar_pid),
thread_getname(_nomac_registry[i].recipient_pid),
msg_ack.type, ack->type, ack->orig);
return -ENOMSG;
}
}
}
}
return payload_len;
}
static inline int _nomac_send(netdev_t *dev, netapi_snd_pkt_t *pkt)
{
return dev->driver->send_data(dev, pkt->dest, pkt->dest_len, pkt->ulh,
pkt->data, pkt->data_len);
}
static int _nomac_get_registry(netapi_conf_t *conf)
{
kernel_pid_t current_pid = thread_getpid();
kernel_pid_t registry[NOMAC_REGISTRY_SIZE];
uint8_t size = 0;
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
if ((size * sizeof(kernel_pid_t)) > (conf->data_len)) {
return -EOVERFLOW;
}
if (_nomac_registry[i].registrar_pid == current_pid) {
registry[size++] = _nomac_registry[i].recipient_pid;
}
}
conf->data_len = size * sizeof(kernel_pid_t);
memcpy(conf->data, registry, conf->data_len);
return 0;
}
static int _nomac_get_option(netdev_t *dev, netapi_conf_t *conf)
{
int res;
switch ((nomac_conf_type_t)conf->param) {
case NOMAC_PROTO:
case NOMAC_CHANNEL:
case NOMAC_ADDRESS:
case NOMAC_NID:
case NOMAC_MAX_PACKET_SIZE:
case NOMAC_ADDRESS2:
if ((res = dev->driver->get_option(dev, (netdev_opt_t)conf->param,
conf->data, &(conf->data_len))
) == 0) {
return (int)conf->data_len;
}
else {
return res;
}
case NOMAC_REGISTRY:
return _nomac_get_registry(conf);
default:
break;
}
return -ENOTSUP;
}
static int _nomac_set_option(netdev_t *dev, netapi_conf_t *conf)
{
switch ((nomac_conf_type_t)(conf->param)) {
case NOMAC_PROTO:
case NOMAC_CHANNEL:
case NOMAC_ADDRESS:
case NOMAC_NID:
case NOMAC_ADDRESS2:
return dev->driver->set_option(dev, (netdev_opt_t)conf->param,
conf->data, conf->data_len);
default:
break;
}
return -ENOTSUP;
}
static void *_nomac_runner(void *args)
{
netdev_t *dev = (netdev_t *)args;
msg_t msg_cmd, msg_ack, msg_queue[NOMAC_MSG_QUEUE_SIZE];
netapi_cmd_t *cmd;
netapi_ack_t *ack;
msg_ack.type = NETAPI_MSG_TYPE;
msg_init_queue(msg_queue, NOMAC_MSG_QUEUE_SIZE);
dev->driver->init(dev);
dev->driver->add_receive_data_callback(dev, _nomac_recv_cb);
while (1) {
msg_receive(&msg_cmd);
if (msg_cmd.type == NETDEV_MSG_EVENT_TYPE) {
dev->driver->event(dev, msg_cmd.content.value);
}
else if (msg_cmd.type == NETAPI_MSG_TYPE) {
cmd = (netapi_cmd_t *)(msg_cmd.content.ptr);
ack = cmd->ack;
msg_ack.content.ptr = (char *)ack;
switch (cmd->type) {
case NETAPI_CMD_SND:
ack->result = _nomac_send(dev, (netapi_snd_pkt_t *)cmd);
break;
case NETAPI_CMD_GET:
ack->result = _nomac_get_option(dev, (netapi_conf_t *)cmd);
break;
case NETAPI_CMD_SET:
ack->result = _nomac_set_option(dev, (netapi_conf_t *)cmd);
break;
case NETAPI_CMD_REG:
ack->result = -ENOBUFS;
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
if (_nomac_registry[i].registrar_pid == KERNEL_PID_UNDEF) {
netapi_reg_t *reg = (netapi_reg_t *)cmd;
_nomac_registry[i].registrar_pid = thread_getpid();
_nomac_registry[i].recipient_pid = reg->reg_pid;
ack->result = NETAPI_STATUS_OK;
break;
}
}
break;
case NETAPI_CMD_UNREG:
ack->result = NETAPI_STATUS_OK;
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
netapi_reg_t *reg = (netapi_reg_t *)cmd;
if (_nomac_registry[i].registrar_pid == thread_getpid() &&
_nomac_registry[i].recipient_pid == reg->reg_pid) {
_nomac_registry[i].recipient_pid = KERNEL_PID_UNDEF;
break;
}
}
break;
#ifdef MODULE_NETDEV_DUMMY
case NETAPI_CMD_FIRE_RCV:
ack->result = unittest_netdev_dummy_fire_rcv_event(dev,
((netapi_rcv_pkt_t *)cmd)->src,
((netapi_rcv_pkt_t *)cmd)->src_len,
((netapi_rcv_pkt_t *)cmd)->dest,
((netapi_rcv_pkt_t *)cmd)->dest_len,
((netapi_rcv_pkt_t *)cmd)->data,
((netapi_rcv_pkt_t *)cmd)->data_len);
break;
#endif
default:
ack->result = -ENOTSUP;
break;
}
ack->type = NETAPI_CMD_ACK;
ack->orig = cmd->type;
msg_reply(&msg_cmd, &msg_ack);
}
}
/* never reached */
return NULL;
}
void nomac_init_module(void)
{
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
_nomac_registry[i].registrar_pid = KERNEL_PID_UNDEF;
_nomac_registry[i].recipient_pid = KERNEL_PID_UNDEF;
}
}
kernel_pid_t nomac_init(char *stack, int stacksize, char priority,
const char *name, netdev_t *dev)
{
return thread_create(stack, stacksize, priority, CREATE_STACKTEST,
_nomac_runner, (void *)dev, name);
}
#ifdef MODULE_NETDEV_DUMMY
void nomac_update_callback(netdev_t *dev)
{
dev->driver->add_receive_data_callback(dev, _nomac_recv_cb);
}
#endif

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,4 @@
USEMODULE += netapi
USEMODULE += nomac
USEMODULE += netdev_dummy
USEMODULE += vtimer

View File

@ -0,0 +1,546 @@
/*
* Copyright (C) 2014 Martin Lenders
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include "clist.h"
#include "nomac.h"
#include "netdev_dummy.h"
#include "thread.h"
#include "vtimer.h"
#include "embUnit/embUnit.h"
#include "tests-nomac.h"
#define UNITTEST_DONE (TEST_UINT16)
#define UNITTESTS_NOMAC_NAME "unittests_nomac"
#define UNITTESTS_NOMAC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
#define UNITTESTS_NOMAC_QSIZE (4)
static char unittests_nomac_stack[UNITTESTS_NOMAC_STACKSIZE];
static char unittests_nomac_rcv_stack[KERNEL_CONF_STACKSIZE_IDLE];
static msg_t unittests_nomac_rcv_queue[UNITTESTS_NOMAC_QSIZE];
static netdev_t *dev = &(unittest_netdev_dummy_devs[0]);
static kernel_pid_t nomac_pid = KERNEL_PID_UNDEF;
static kernel_pid_t nomac_receiver = KERNEL_PID_UNDEF;
static kernel_pid_t main_pid = KERNEL_PID_UNDEF;
static char received_data[UNITTESTS_NETDEV_DUMMY_MAX_PACKET];
static char received_src[UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN];
static char received_dst[UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN];
static size_t received_data_len = 0, received_src_len = 0, received_dst_len = 0;
#define SET_OPTION_NUMBER (3)
#define GET_OPTION_NUMBER (7)
#define RANDOM_SET_OPTION ((TEST_UINT8 % SET_OPTION_NUMBER) + 1)
#define RANDOM_GET_OPTION (TEST_UINT8 % SET_OPTION_NUMBER)
static void _reset_received(void)
{
memset(received_data, 0, sizeof(received_data));
memset(received_src, 0, sizeof(received_src));
memset(received_dst, 0, sizeof(received_dst));
received_data_len = 0;
received_src_len = 0;
received_dst_len = 0;
}
static void _fill_received(netapi_rcv_pkt_t *rcv)
{
netapi_ack_t *ack = rcv->ack;
ack->type = NETAPI_CMD_ACK;
ack->orig = rcv->type;
if (rcv->type != NETAPI_CMD_RCV) {
ack->result = -ENOMSG;
return;
}
memcpy(received_src, rcv->src, rcv->src_len);
received_src_len = rcv->src_len;
memcpy(received_dst, rcv->dest, rcv->dest_len);
received_dst_len = rcv->dest_len;
memcpy(received_data, rcv->data, rcv->data_len);
received_data_len = rcv->data_len;
ack->result = received_data_len;
return;
}
static void *test_nomac_receive_thread(void *args)
{
msg_t msg_rcv, msg_ack, done;
netapi_rcv_pkt_t *rcv;
(void)args;
msg_init_queue(unittests_nomac_rcv_queue, UNITTESTS_NOMAC_QSIZE);
msg_ack.type = NETAPI_MSG_TYPE;
done.type = UNITTEST_DONE;
msg_receive(&msg_rcv);
if (msg_rcv.type != NETAPI_MSG_TYPE) {
msg_ack.type = 0; /* Send arbitrary reply, API handles this case */
msg_reply(&msg_rcv, &msg_ack);
msg_send(&done, main_pid);
return NULL;
}
rcv = (netapi_rcv_pkt_t *)(msg_rcv.content.ptr);
msg_ack.content.ptr = (char *)rcv->ack;
_fill_received(rcv);
msg_reply(&msg_rcv, &msg_ack);
msg_send(&done, main_pid);
return NULL;
}
static void set_up(void)
{
unittest_netdev_dummy_init();
dev->driver->init(dev);
nomac_update_callback(dev);
nomac_init_module();
}
static void set_up_with_thread(void)
{
set_up();
main_pid = thread_getpid();
nomac_receiver = thread_create(unittests_nomac_rcv_stack,
sizeof(unittests_nomac_stack),
PRIORITY_MAIN - 3, 0,
test_nomac_receive_thread, NULL,
"nomac_rcv");
}
static void tear_down(void)
{
_reset_received();
nomac_receiver = KERNEL_PID_UNDEF;
}
/*********************************************
* thread tests *
*********************************************/
static void test_nomac_thread(void)
{
TEST_ASSERT(KERNEL_PID_UNDEF != nomac_pid);
}
/*********************************************
* NETAPI_CMD_SND tests *
*********************************************/
static void test_nomac_send_data_dest_too_long(void)
{
char dest[] = TEST_STRING8;
char data[] = TEST_STRING64;
TEST_ASSERT_EQUAL_INT(-EAFNOSUPPORT, netapi_send_payload(nomac_pid, dest,
UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN + TEST_UINT8,
data, 1));
}
static void test_nomac_send_data_data_too_long(void)
{
char dest[] = TEST_STRING8;
char data[] = TEST_STRING64;
TEST_ASSERT_EQUAL_INT(-EMSGSIZE, netapi_send_payload(nomac_pid, dest,
UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN, data,
UNITTESTS_NETDEV_DUMMY_MAX_PACKET + TEST_UINT8));
}
static void test_nomac_send_data_send(void)
{
char dest[] = TEST_STRING64;
size_t dest_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN;
char data[] = TEST_STRING8;
#if UNITTESTS_NETDEV_DUMMY_MAX_PACKET < 8
size_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET;
#else
size_t data_len = 8;
#endif
TEST_ASSERT_EQUAL_INT((int)data_len, netapi_send_payload(nomac_pid,
dest, dest_len, data, data_len));
TEST_ASSERT_EQUAL_INT(0, unittest_netdev_dummy_check_transmitted(dev,
dest, dest_len, data, data_len));
}
#if UNITTESTS_NETDEV_DUMMY_MAX_PACKET > 4
static void test_nomac_send_data_send2(void)
{
netdev_hlist_t hlist_node = {NULL, NULL, NETDEV_PROTO_UNKNOWN, TEST_STRING8, 4};
netdev_hlist_t *hlist = NULL;
char dest[] = TEST_STRING64;
size_t dest_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN;
char data[] = TEST_STRING16;
#if UNITTESTS_NETDEV_DUMMY_MAX_PACKET < 12
size_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET - 4;
char expected[UNITTESTS_NETDEV_DUMMY_MAX_PACKET];
#else
size_t data_len = 8;
char expected[12];
#endif
memcpy(expected, TEST_STRING8, 4);
memcpy(&(expected[4]), TEST_STRING16, data_len);
clist_add((clist_node_t **)&hlist, (clist_node_t *)&hlist_node);
TEST_ASSERT_EQUAL_INT((int)sizeof(expected), netapi_send_packet(nomac_pid,
hlist, dest, dest_len, data, data_len));
TEST_ASSERT_EQUAL_INT(0, unittest_netdev_dummy_check_transmitted(dev,
dest, dest_len, expected, data_len + 4));
}
#endif
/*********************************************
* NETAPI_CMD_REG tests *
*********************************************/
static void test_nomac_reg_buffer_full(void)
{
for (int i = 0; i < NOMAC_REGISTRY_SIZE; i++) {
TEST_ASSERT_EQUAL_INT(0, netapi_register(nomac_pid, (kernel_pid_t)(i + 1), 0));
}
TEST_ASSERT_EQUAL_INT(-ENOBUFS,
netapi_register_current_thread(nomac_pid, 0));
}
static void test_nomac_register(void)
{
msg_t done;
char src[] = TEST_STRING64;
size_t src_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN;
char dest[] = TEST_STRING64;
size_t dest_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN;
char data[] = TEST_STRING8;
#if UNITTESTS_NETDEV_DUMMY_MAX_PACKET < 8
size_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET;
#else
size_t data_len = 8;
#endif
int res;
TEST_ASSERT(nomac_receiver != KERNEL_PID_UNDEF);
TEST_ASSERT_EQUAL_INT(0, netapi_register(nomac_pid, nomac_receiver, 0));
res = netapi_fire_receive_event(nomac_pid, src, src_len, dest, dest_len, data, data_len);
TEST_ASSERT_EQUAL_INT(0, res);
msg_receive(&done);
TEST_ASSERT_EQUAL_INT(UNITTEST_DONE, done.type);
TEST_ASSERT_EQUAL_INT(src_len, received_src_len);
TEST_ASSERT_EQUAL_INT(0, memcmp(received_src, src, src_len));
TEST_ASSERT_EQUAL_INT(dest_len, received_dst_len);
TEST_ASSERT_EQUAL_INT(0, memcmp(received_dst, dest, dest_len));
TEST_ASSERT_EQUAL_INT(data_len, received_data_len);
TEST_ASSERT_EQUAL_INT(0, memcmp(received_data, data, data_len));
}
/*********************************************
* NETAPI_CMD_GET tests *
*********************************************/
static void test_nomac_get_option_null_data(void)
{
size_t value_len = sizeof(unsigned int);
TEST_ASSERT_EQUAL_INT(-EFAULT, netapi_get_option(nomac_pid,
RANDOM_GET_OPTION, NULL, value_len));
}
static void test_nomac_get_option_overflow(void)
{
unsigned int value = TEST_UINT32;
TEST_ASSERT_EQUAL_INT(-EOVERFLOW, netapi_get_option(nomac_pid,
RANDOM_GET_OPTION, &value, 0));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
}
static void test_nomac_get_option_not_supported(void)
{
unsigned int value = TEST_UINT32;
size_t value_len = sizeof(unsigned int);
TEST_ASSERT_EQUAL_INT(-ENOTSUP, netapi_get_option(nomac_pid,
(netapi_conf_type_t)UINT32_MAX, &value,
value_len));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
}
static void test_nomac_get_option_get_protocol(void)
{
netdev_proto_t value = TEST_UINT8 % 9;
TEST_ASSERT_EQUAL_INT(sizeof(netdev_proto_t),
netapi_get_option(nomac_pid,
NOMAC_PROTO, &value,
sizeof(netdev_proto_t)));
TEST_ASSERT_EQUAL_INT(NETDEV_PROTO_UNKNOWN, value);
}
static void test_nomac_get_option_get_channel(void)
{
unsigned int value = TEST_UINT32;
TEST_ASSERT_EQUAL_INT(sizeof(unsigned int),
netapi_get_option(nomac_pid,
NOMAC_CHANNEL, &value,
sizeof(unsigned int)));
TEST_ASSERT_EQUAL_INT(0, value);
}
static void test_nomac_get_option_get_nid(void)
{
unsigned int value = TEST_UINT32;
TEST_ASSERT_EQUAL_INT(sizeof(unsigned int),
netapi_get_option(nomac_pid,
NOMAC_NID, &value,
sizeof(unsigned int)));
TEST_ASSERT_EQUAL_INT(0, value);
}
static void test_nomac_get_option_get_address(void)
{
uint8_t value[UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN];
TEST_ASSERT_EQUAL_INT(UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN,
netapi_get_option(nomac_pid,
NOMAC_ADDRESS, &value,
UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN));
for (int i = 0; i < UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN; i++) {
TEST_ASSERT_EQUAL_INT(0, value[i]);
}
}
static void test_nomac_get_option_get_long_address(void)
{
uint8_t value[UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN];
TEST_ASSERT_EQUAL_INT(UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN,
netapi_get_option(nomac_pid,
NOMAC_ADDRESS2, &value,
UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN));
for (int i = 0; i < UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN; i++) {
TEST_ASSERT_EQUAL_INT(0, value[i]);
}
}
/*********************************************
* NETAPI_CMD_SET tests *
*********************************************/
static void test_nomac_set_option_null_data(void)
{
size_t value_len = sizeof(unsigned int);
TEST_ASSERT_EQUAL_INT(-EFAULT, netapi_set_option(nomac_pid,
RANDOM_SET_OPTION, NULL, value_len));
}
static void test_nomac_set_option_inval(void)
{
unsigned int value = TEST_UINT32;
size_t value_len = 0;
TEST_ASSERT_EQUAL_INT(-EINVAL, netapi_set_option(nomac_pid,
RANDOM_SET_OPTION, &value, value_len));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
}
static void test_nomac_set_option_overflow(void)
{
unsigned int value = TEST_UINT32;
size_t value_len = UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN + TEST_UINT16;
TEST_ASSERT_EQUAL_INT(-EOVERFLOW, netapi_set_option(nomac_pid,
RANDOM_SET_OPTION, &value, value_len));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
}
static void test_nomac_set_option_not_supported(void)
{
unsigned int value = TEST_UINT32;
size_t value_len = sizeof(unsigned int);
TEST_ASSERT_EQUAL_INT(-ENOTSUP, netapi_set_option(nomac_pid,
(netapi_conf_type_t)UINT32_MAX, &value,
value_len));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
}
static void test_nomac_set_get_channel(void)
{
unsigned int value = TEST_UINT32;
size_t value_len = sizeof(unsigned int);
TEST_ASSERT_EQUAL_INT(0, netapi_set_option(nomac_pid,
NOMAC_CHANNEL, &value, value_len));
value = 0;
TEST_ASSERT_EQUAL_INT(sizeof(unsigned int),
netapi_get_option(nomac_pid, NOMAC_CHANNEL,
&value, value_len));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
TEST_ASSERT_EQUAL_INT(sizeof(unsigned int), value_len);
}
static void test_nomac_set_get_address(void)
{
char value[UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN];
size_t value_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN;
#if UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN < 12
strncpy(value, TEST_STRING12, UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN);
#else
strncpy(value, TEST_STRING12, 12);
#endif
TEST_ASSERT_EQUAL_INT(0, netapi_set_option(nomac_pid,
NOMAC_ADDRESS, value,
UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN));
#if UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN < 12
memset(value, 0, UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN);
#else
memset(value, 0, 12);
#endif
TEST_ASSERT_EQUAL_INT(UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN,
netapi_get_option(nomac_pid,
NOMAC_ADDRESS, value,
value_len));
#if UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN < 12
TEST_ASSERT(strncmp(value, TEST_STRING12,
UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN) == 0);
#else
TEST_ASSERT(strncmp(value, TEST_STRING12, 12) == 0);
#endif
}
static void test_nomac_set_get_nid(void)
{
unsigned int value = TEST_UINT32;
size_t value_len = sizeof(unsigned int);
TEST_ASSERT_EQUAL_INT(0, netapi_set_option(nomac_pid,
NOMAC_NID, &value, value_len));
value = 0;
TEST_ASSERT_EQUAL_INT(sizeof(unsigned int),
netapi_get_option(nomac_pid, NOMAC_NID,
&value, value_len));
TEST_ASSERT_EQUAL_INT(TEST_UINT32, value);
TEST_ASSERT_EQUAL_INT(sizeof(unsigned int), value_len);
}
static void test_nomac_set_get_long_address(void)
{
char value[UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN];
size_t value_len = UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN;
#if UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN < 12
strncpy(value, TEST_STRING12, UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN);
#else
strncpy(value, TEST_STRING12, 12);
#endif
TEST_ASSERT_EQUAL_INT(0, netapi_set_option(nomac_pid,
NOMAC_ADDRESS2, value,
UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN));
#if UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN < 12
memset(value, 0, UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN);
#else
memset(value, 0, 12);
#endif
TEST_ASSERT_EQUAL_INT(UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN,
netapi_get_option(nomac_pid,
NOMAC_ADDRESS2, value,
value_len));
#if UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN < 12
TEST_ASSERT(strncmp(value, TEST_STRING12,
UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN) == 0);
#else
TEST_ASSERT(strncmp(value, TEST_STRING12, 12) == 0);
#endif
TEST_ASSERT_EQUAL_INT(UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN, value_len);
}
/****************************
* ISR event tests *
****************************/
static void test_nomac_event_value(void)
{
msg_t m;
m.type = NETDEV_MSG_EVENT_TYPE;
m.content.value = TEST_UINT32;
msg_send(&m, nomac_pid);
vtimer_usleep(1000);
TEST_ASSERT_EQUAL_INT(TEST_UINT32, unittest_netdev_dummy_get_last_event(dev));
}
Test *tests_nomac_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
/* thread tests */
new_TestFixture(test_nomac_thread),
/* NETAPI_CMD_SND tests */
new_TestFixture(test_nomac_send_data_dest_too_long),
new_TestFixture(test_nomac_send_data_data_too_long),
new_TestFixture(test_nomac_send_data_send),
#if UNITTESTS_NETDEV_DUMMY_MAX_PACKET > 4
new_TestFixture(test_nomac_send_data_send2),
#endif
/* NETAPI_CMD_REG tests */
new_TestFixture(test_nomac_reg_buffer_full),
/* NETAPI_CMD_GET tests */
new_TestFixture(test_nomac_get_option_null_data),
new_TestFixture(test_nomac_get_option_overflow),
new_TestFixture(test_nomac_get_option_not_supported),
new_TestFixture(test_nomac_get_option_get_protocol),
new_TestFixture(test_nomac_get_option_get_channel),
new_TestFixture(test_nomac_get_option_get_address),
new_TestFixture(test_nomac_get_option_get_nid),
new_TestFixture(test_nomac_get_option_get_long_address),
/* NETAPI_CMD_SET tests */
new_TestFixture(test_nomac_set_option_null_data),
new_TestFixture(test_nomac_set_option_inval),
new_TestFixture(test_nomac_set_option_overflow),
new_TestFixture(test_nomac_set_option_not_supported),
new_TestFixture(test_nomac_set_get_channel),
new_TestFixture(test_nomac_set_get_address),
new_TestFixture(test_nomac_set_get_nid),
new_TestFixture(test_nomac_set_get_long_address),
/* ISR event tests */
new_TestFixture(test_nomac_event_value),
};
EMB_UNIT_TESTCALLER(nomac_tests, set_up, tear_down,
fixtures);
return (Test *)&nomac_tests;
}
Test *tests_nomac_threaded_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_nomac_register),
};
EMB_UNIT_TESTCALLER(nomac_tests, set_up_with_thread, tear_down,
fixtures);
return (Test *)&nomac_tests;
}
void tests_nomac(void)
{
set_up();
vtimer_init();
nomac_pid = nomac_init(unittests_nomac_stack,
UNITTESTS_NOMAC_STACKSIZE,
PRIORITY_MAIN - 1, UNITTESTS_NOMAC_NAME,
dev);
TESTS_RUN(tests_nomac_tests());
TESTS_RUN(tests_nomac_threaded_tests());
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2014 Martin Lenders
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @addtogroup unittests
* @{
*
* @file tests-nomac.h
* @brief Unittests for the ``nomac`` module
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef __TESTS_NOMAC_H_
#define __TESTS_NOMAC_H_
#include "embUnit.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief The entry point of this test suite.
*/
void tests_nomac(void);
#ifdef __cplusplus
}
#endif
#endif /* __TESTS_NETDEV_DUMMY_H_ */
/** @} */