Merge pull request #4835 from authmillenon/netdev2_test/feat/init

netdev2_test: initial import
pr/gpio
Peter Kietzmann 7 years ago
commit dcafbb8d0c

@ -22,6 +22,9 @@ endif
ifneq (,$(filter ieee802154,$(USEMODULE)))
DIRS += net/link_layer/ieee802154
endif
ifneq (,$(filter netdev2_test,$(USEMODULE)))
DIRS += net/netdev2_test
endif
ifneq (,$(filter ipv4_addr,$(USEMODULE)))
DIRS += net/network_layer/ipv4/addr
endif

@ -0,0 +1,306 @@
/*
* Copyright (C) 2016 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 sys_netdev2_test Netdev2 dummy test driver
* @ingroup drivers_netdev_netdev2
* @brief Provides a test dummy for the netdev2 interface.
*
* See the following simple packet traversal timer for an example. Note that
* this example assumes that the stack doesn't require any option values from
* the device and that the stack doesn't create packets on its own or looses
* packets (neither of those can be assumed for in-production stacks).
*
* ~~~~~~~~~~~ {.c}
* #include <stdint.h>
*
* #include "mutex.h"
* #include "net/af.h"
* #include "net/conn/udp.h"
* #include "net/ipv6/addr.h"
* #include "net/netdev2_test.h"
* #include "xtimer.h"
*
* #define PKT_NUMBER (1000)
*
* static netdev2_test_t dev;
* static uint32_t last_start;
* static uint32_t sum = 0;
* static mutex_t wait = MUTEX_INIT;
*
* int _send_timer(netdev2_t *dev, const struct iovec *vector, int count)
* {
* (void)dev;
* (void)vector;
* (void)count;
*
* sum += (xtimer_now() - last_start);
* mutex_unlock(&wait);
* }
*
* int main(void) {
* ipv6_addr_t dst = IPV6_ADDR_UNSPECIFIED;
*
* netdev2_test_setup(&dev, NULL);
* dev->driver->init((netdev2_t *)&dev)
* // initialize stack and connect `dev` to it
* // ...
* mutex_lock(&wait);
* for (int i = 0; i < PKT_NUMBER; i++) {
* last_start = xtimer_now();
* conn_udp_sendto("abcd", sizeof("abcd"), NULL, 0, &dst, sizeof(dst),
* AF_INET6, 0xcafe, 0xcafe);
* mutex_lock(&wait);
* }
* printf("Average send packet traversal time: %u\n", sum / PKT_NUMBER);
* mutex_unlock(&wait);
* return 0;
* }
* ~~~~~~~~~~~
*
* To provide options to the stack, the
* @ref netdev2_test_t::get_cbs "get callbacks" for the specific options need
* to be set.
* To catch lost packets and additional sent by the stack the send handler needs
* to be adapted accordingly.
*
* @{
*
* @file
* @brief @ref sys_netdev2_test definitions
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef NETDEV2_TEST_H_
#define NETDEV2_TEST_H_
#include "mutex.h"
#ifdef MODULE_NETDEV2_IEEE802154
#include "net/netdev2/ieee802154.h"
#endif
#include "net/netdev2.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Callback type to handle send command
*
* @param[in] dev network device descriptor
* @param[in] vector io vector array to send
* @param[in] count number of entries in vector
*
* @return number of bytes sent
* @return <= 0 on error
*/
typedef int (*netdev2_test_send_cb_t)(netdev2_t *dev,
const struct iovec *vector,
int count);
/**
* @brief Callback type to handle receive command
*
* @param[in] dev network device descriptor
* @param[out] buf buffer to write into or `NULL`
* @param[in] len maximum number of bytes to read
* @param[out] info status information for the received packet. Might
* be of different type for different netdev2 devices.
* May be NULL if not needed or applicable
*
* @return <=0 on error
* @return number of bytes read if buf != NULL
* @return currently received packet size if buf == NULL
*/
typedef int (*netdev2_test_recv_cb_t)(netdev2_t *dev, char *buf, int len,
void *info);
/**
* @brief Callback type to handle device initialization
*
* @param[in] dev network device descriptor
*
* @return <= on error
* @return 0 on success
*/
typedef int (*netdev2_test_init_cb_t)(netdev2_t *dev);
/**
* @brief Callback type to handle user-space ISR events
*
* @param[in] dev network device descriptor
*/
typedef void (*netdev2_test_isr_cb_t)(netdev2_t *dev);
/**
* @brief Callback type to handle get commands
*
* @param[in] dev network device descriptor
* @param[out] value pointer to store the option's value in
* @param[in] max_len maximal amount of bytes that fit into @p value
*
* @return number of bytes written to @p value
* @return <0 on error
*/
typedef int (*netdev2_test_get_cb_t)(netdev2_t *dev, void *value,
size_t max_len);
/**
* @brief Callback type to handle set commands
*
* @param[in] dev network device descriptor
* @param[out] value value to set
* @param[in] value_len the length of @p value
*
* @return number of bytes used from @p value
* @return <0 on error
*/
typedef int (*netdev2_test_set_cb_t)(netdev2_t *dev, void *value,
size_t value_len);
/**
* @brief Device descriptor for @ref sys_netdev2_test devices
*
* @extends netdev2_t
*/
typedef struct {
/**
* @brief netdev2 fields
* @{
*/
#ifdef MODULE_NETDEV2_IEEE802154
netdev2_ieee802154_t netdev; /**< superclass */
#else /* MODULE_NETDEV2_IEEE802154 */
netdev2_t netdev; /**< superclass */
#endif /* MODULE_NETDEV2_IEEE802154 */
/** @} */
/**
* @brief device specific fields
* @{
*/
netdev2_test_send_cb_t send_cb; /**< callback to handle send command */
netdev2_test_recv_cb_t recv_cb; /**< callback to handle receive command */
netdev2_test_init_cb_t init_cb; /**< callback to handle initialization events */
netdev2_test_isr_cb_t isr_cb; /**< callback to handle ISR events */
netdev2_test_get_cb_t get_cbs[NETOPT_NUMOF]; /**< callback to handle get command */
netdev2_test_set_cb_t set_cbs[NETOPT_NUMOF]; /**< callback to handle set command */
void *state; /**< external state for the device */
mutex_t mutex; /**< mutex for the device */
/** @} */
} netdev2_test_t;
/**
* @brief override send callback
*
* @param[in] dev a @ref sys_netdev2_test device
* @param[in] send_cb a send callback
*/
static inline void netdev2_test_set_send_cb(netdev2_test_t *dev,
netdev2_test_send_cb_t send_cb)
{
mutex_lock(&dev->mutex);
dev->send_cb = send_cb;
mutex_unlock(&dev->mutex);
}
/**
* @brief override receive callback
*
* @param[in] dev a @ref sys_netdev2_test device
* @param[in] recv_cb a receive callback
*/
static inline void netdev2_test_set_recv_cb(netdev2_test_t *dev,
netdev2_test_recv_cb_t recv_cb)
{
mutex_lock(&dev->mutex);
dev->recv_cb = recv_cb;
mutex_unlock(&dev->mutex);
}
/**
* @brief override initialization callback
*
* @param[in] dev a @ref sys_netdev2_test device
* @param[in] init_cb an initialization callback
*/
static inline void netdev2_test_set_init_cb(netdev2_test_t *dev,
netdev2_test_init_cb_t init_cb)
{
mutex_lock(&dev->mutex);
dev->init_cb = init_cb;
mutex_unlock(&dev->mutex);
}
/**
* @brief override ISR event handler callback
*
* @param[in] dev a @ref sys_netdev2_test device
* @param[in] isr_cb an ISR event handler callback
*/
static inline void netdev2_test_set_isr_cb(netdev2_test_t *dev,
netdev2_test_isr_cb_t isr_cb)
{
mutex_lock(&dev->mutex);
dev->isr_cb = isr_cb;
mutex_unlock(&dev->mutex);
}
/**
* @brief override get callback for a certain option type
*
* @param[in] dev a @ref sys_netdev2_test device
* @param[in] opt an option type
* @param[in] get_cb a get callback for @p opt
*/
static inline void netdev2_test_set_get_cb(netdev2_test_t *dev, netopt_t opt,
netdev2_test_get_cb_t get_cb)
{
mutex_lock(&dev->mutex);
dev->get_cbs[opt] = get_cb;
mutex_unlock(&dev->mutex);
}
/**
* @brief override get callback for a certain option type
*
* @param[in] dev a @ref sys_netdev2_test device
* @param[in] opt an option type
* @param[in] set_cb a set callback for @p opt
*/
static inline void netdev2_test_set_set_cb(netdev2_test_t *dev, netopt_t opt,
netdev2_test_set_cb_t set_cb)
{
mutex_lock(&dev->mutex);
dev->set_cbs[opt] = set_cb;
mutex_unlock(&dev->mutex);
}
/**
* @brief Setup a given @ref sys_netdev2_test device
*
* @param[in] dev a @ref sys_netdev2_test device to initialize
* @param[in] state external state for the device
*/
void netdev2_test_setup(netdev2_test_t *dev, void *state);
/**
* @brief Resets all callbacks for the device to NULL
*
* @param[in] dev a @ref sys_netdev2_test device to initialize
*/
void netdev2_test_reset(netdev2_test_t *dev);
#ifdef __cplusplus
}
#endif
#endif /* NETDEV2_TEST_H_ */
/** @} */

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

@ -0,0 +1,144 @@
/*
* Copyright (C) 2016 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.
*/
/**
* @{
*
* @file
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include "net/netdev2_test.h"
static int _send(netdev2_t *netdev, const struct iovec *vector, int count);
static int _recv(netdev2_t *netdev, char *buf, int len, void *info);
static int _init(netdev2_t *dev);
static void _isr(netdev2_t *dev);
static int _get(netdev2_t *dev, netopt_t opt, void *value, size_t max_len);
static int _set(netdev2_t *dev, netopt_t opt, void *value, size_t value_len);
static const netdev2_driver_t _driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
void netdev2_test_setup(netdev2_test_t *dev, void *state)
{
netdev2_t *netdev = (netdev2_t *)dev;
netdev->driver = &_driver;
dev->state = state;
mutex_init(&dev->mutex);
netdev2_test_reset(dev);
}
void netdev2_test_reset(netdev2_test_t *dev)
{
mutex_lock(&dev->mutex);
dev->send_cb = NULL;
dev->recv_cb = NULL;
dev->init_cb = NULL;
dev->isr_cb = NULL;
memset(dev->get_cbs, 0, sizeof(dev->get_cbs));
memset(dev->set_cbs, 0, sizeof(dev->set_cbs));
mutex_unlock(&dev->mutex);
}
static int _send(netdev2_t *netdev, const struct iovec *vector, int count)
{
netdev2_test_t *dev = (netdev2_test_t *)netdev;
int res = count; /* assume everything would be fine */
mutex_lock(&dev->mutex);
if (dev->send_cb != NULL) {
res = dev->send_cb(netdev, vector, count);
}
mutex_unlock(&dev->mutex);
return res;
}
static int _recv(netdev2_t *netdev, char *buf, int len, void *info)
{
netdev2_test_t *dev = (netdev2_test_t *)netdev;
int res = (buf == NULL) ? 0 : len; /* assume everything would be fine */
mutex_lock(&dev->mutex);
if (dev->recv_cb != NULL) {
/* could fire context change and call _recv so we need to unlock */
mutex_unlock(&dev->mutex);
res = dev->recv_cb(netdev, buf, len, info);
}
else {
mutex_unlock(&dev->mutex);
}
return res;
}
static int _init(netdev2_t *netdev)
{
netdev2_test_t *dev = (netdev2_test_t *)netdev;
int res = 0; /* assume everything would be fine */
mutex_lock(&dev->mutex);
if (dev->init_cb != NULL) {
res = dev->init_cb(netdev);
}
mutex_unlock(&dev->mutex);
return res;
}
static void _isr(netdev2_t *netdev)
{
netdev2_test_t *dev = (netdev2_test_t *)netdev;
mutex_lock(&dev->mutex);
if (dev->isr_cb != NULL) {
mutex_unlock(&dev->mutex);
dev->isr_cb(netdev);
}
else {
mutex_unlock(&dev->mutex);
}
}
static int _get(netdev2_t *netdev, netopt_t opt, void *value, size_t max_len)
{
netdev2_test_t *dev = (netdev2_test_t *)netdev;
int res = -ENOTSUP; /* option assumed to be not supported */
mutex_lock(&dev->mutex);
if (dev->get_cbs[opt] != NULL) {
res = dev->get_cbs[opt](netdev, value, max_len);
}
mutex_unlock(&dev->mutex);
return res;
}
static int _set(netdev2_t *netdev, netopt_t opt, void *value, size_t value_len)
{
netdev2_test_t *dev = (netdev2_test_t *)netdev;
int res = -ENOTSUP; /* option assumed to be not supported */
mutex_lock(&dev->mutex);
if (dev->set_cbs[opt] != NULL) {
res = dev->set_cbs[opt](netdev, value, value_len);
}
mutex_unlock(&dev->mutex);
return res;
}
/** @} */

@ -0,0 +1,17 @@
APPLICATION = netdev2_test
include ../Makefile.tests_common
DISABLE_MODULE = auto_init
FEATURES_REQUIRED += periph_timer # xtimer required for this application
USEMODULE += gnrc
USEMODULE += gnrc_neterr
USEMODULE += gnrc_netif
USEMODULE += gnrc_netdev2
USEMODULE += netdev2_test
USEMODULE += od
CFLAGS += -DGNRC_PKTBUF_SIZE=200
include $(RIOTBASE)/Makefile.include

@ -0,0 +1,359 @@
/*
* Copyright (C) 2016 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.
*/
/**
* @{
*
* @file
* @brief Show case application for netdev2_test
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include "msg.h"
#include "net/ethernet.h"
#include "net/gnrc.h"
#include "net/gnrc/netdev2/eth.h"
#include "net/netdev2_test.h"
#include "od.h"
#include "thread.h"
#include "utlist.h"
#define _EXP_LENGTH (64)
#define _MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF)
#define _MAC_PRIO (THREAD_PRIORITY_MAIN - 4)
#define _MAIN_MSG_QUEUE_SIZE (2)
#define _TEST_PAYLOAD1 "gO3Xt,fP)6* MR161Auk?W^mTb\"LmY^Qc5w1h:C<+n(*/@4k("
#define _TEST_PAYLOAD2 "*b/'XKkraEBexaU\\O-X&<Bl'n%35Ll+nDy,jQ+[Oe4:9( 4cI"
#define EXECUTE(test) \
puts("Executing " # test "()"); \
if (!test()) { \
puts(" + failed."); \
return 1; \
} \
else { \
puts(" + succeeded."); \
}
static uint8_t _dev_addr[] = { 0x6c, 0x5d, 0xff, 0x73, 0x84, 0x6f };
static const uint8_t _test_dst[] = { 0xf5, 0x19, 0x9a, 0x1d, 0xd8, 0x8f };
static const uint8_t _test_src[] = { 0x41, 0x9b, 0x9f, 0x56, 0x36, 0x46 };
static char _mac_stack[_MAC_STACKSIZE];
static gnrc_netdev2_t _gnrc_dev;
static netdev2_test_t _dev;
static msg_t _main_msg_queue[_MAIN_MSG_QUEUE_SIZE];
static uint8_t _tmp[_EXP_LENGTH];
static kernel_pid_t _mac_pid;
static uint8_t _tmp_len = 0;
static void _dev_isr(netdev2_t *dev);
static int _dev_recv(netdev2_t *dev, char *buf, int len, void *info);
static int _dev_send(netdev2_t *dev, const struct iovec *vector, int count);
static int _dev_get_addr(netdev2_t *dev, void *value, size_t max_len);
static int _dev_set_addr(netdev2_t *dev, void *value, size_t max_len);
/* tests getter */
static int test_get_addr(void)
{
uint8_t tmp[sizeof(_dev_addr)];
if (gnrc_netapi_get(_mac_pid, NETOPT_ADDRESS, 0, tmp, sizeof(tmp)) != sizeof(_dev_addr)) {
puts("Error getting device address");
return 0;
}
else if (memcmp(tmp, _dev_addr, sizeof(_dev_addr)) != 0) {
puts("Got wrong device address");
return 0;
}
return 1;
}
/* tests sending */
static int test_send(void)
{
ethernet_hdr_t *exp_mac = (ethernet_hdr_t *)_tmp;
uint8_t *exp_payload = _tmp + sizeof(ethernet_hdr_t);
gnrc_pktsnip_t *pkt, *hdr;
msg_t msg;
/* prepare packet for sending */
pkt = gnrc_pktbuf_add(NULL, _TEST_PAYLOAD1, sizeof(_TEST_PAYLOAD1) - 1,
GNRC_NETTYPE_UNDEF);
if (pkt == NULL) {
puts("Could not allocate send payload");
return 0;
}
hdr = gnrc_netif_hdr_build(NULL, 0, (uint8_t *)_test_dst, sizeof(_test_dst));
if (hdr == NULL) {
gnrc_pktbuf_release(pkt);
puts("Could not allocate send header");
return 0;
}
LL_PREPEND(pkt, hdr);
/* prepare expected data */
memcpy(exp_mac->dst, _test_dst, sizeof(_test_dst));
memcpy(exp_mac->src, _dev_addr, sizeof(_dev_addr));
exp_mac->type = byteorder_htons(ETHERTYPE_UNKNOWN);
memcpy(exp_payload, _TEST_PAYLOAD1, sizeof(_TEST_PAYLOAD1) - 1);
_tmp_len = sizeof(_TEST_PAYLOAD1) + sizeof(ethernet_hdr_t) - 1;
/* register for returned packet status */
if (gnrc_neterr_reg(pkt) != 0) {
puts("Can not register for error reporting");
return 0;
}
/* send packet to MAC layer */
gnrc_netapi_send(_mac_pid, pkt);
/* wait for packet status and check */
msg_receive(&msg);
if ((msg.type != GNRC_NETERR_MSG_TYPE) ||
(msg.content.value != GNRC_NETERR_SUCCESS)) {
puts("Error sending packet");
return 0;
}
return 1;
}
/* tests receiving */
static int test_receive(void)
{
ethernet_hdr_t *rcv_mac = (ethernet_hdr_t *)_tmp;
uint8_t *rcv_payload = _tmp + sizeof(ethernet_hdr_t);
gnrc_pktsnip_t *pkt, *hdr;
gnrc_netreg_entry_t me = { NULL, GNRC_NETREG_DEMUX_CTX_ALL,
thread_getpid() };
msg_t msg;
if (_dev.netdev.event_callback == NULL) {
puts("Device's event_callback not set");
return 0;
}
/* prepare receive buffer */
memcpy(rcv_mac->dst, _dev_addr, sizeof(_dev_addr));
memcpy(rcv_mac->src, _test_src, sizeof(_test_src));
/* no gnrc_ipv6 in compile unit => ETHERTYPE_IPV6 translates to
* GNRC_NETTYPE_UNDEF */
rcv_mac->type = byteorder_htons(ETHERTYPE_IPV6);
memcpy(rcv_payload, _TEST_PAYLOAD2, sizeof(_TEST_PAYLOAD2) - 1);
_tmp_len = sizeof(_TEST_PAYLOAD2) + sizeof(ethernet_hdr_t) - 1;
/* register for GNRC_NETTYPE_UNDEF */
gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &me);
/* fire ISR event */
_dev.netdev.event_callback((netdev2_t *)&_dev.netdev, NETDEV2_EVENT_ISR,
&_dev.netdev.isr_arg);
/* wait for packet from MAC layer*/
msg_receive(&msg);
/* check message */
if (msg.sender_pid != _mac_pid) {
puts("Unexpected sender of netapi receive message");
return 0;
}
if (msg.type != GNRC_NETAPI_MSG_TYPE_RCV) {
puts("Expected netapi receive message");
return 0;
}
pkt = (gnrc_pktsnip_t *)msg.content.ptr;
/* check payload */
if (pkt->size != _tmp_len - sizeof(ethernet_hdr_t)) {
puts("Payload of unexpected size");
}
if ((pkt->type != GNRC_NETTYPE_UNDEF) ||
(memcmp(pkt->data, _TEST_PAYLOAD2, pkt->size) != 0)) {
puts("Unexpected payload");
puts("===========================================================");
puts("expected");
puts("===========================================================");
od_hex_dump(_TEST_PAYLOAD2, pkt->size, OD_WIDTH_DEFAULT);
puts("===========================================================");
puts("send data");
puts("===========================================================");
od_hex_dump(pkt->data, pkt->size, OD_WIDTH_DEFAULT);
return 0;
}
hdr = pkt->next;
/* check netif header */
if ((hdr->type != GNRC_NETTYPE_NETIF) || (hdr->next != NULL) ||
(hdr->size) != (sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN))) {
puts("Malformed header received");
return 0;
}
if (memcmp(gnrc_netif_hdr_get_src_addr(hdr->data), _test_src,
ETHERNET_ADDR_LEN) != 0) {
char addr_str[ETHERNET_ADDR_LEN * 3];
puts("Unexpected source received");
puts("=================");
puts("expected");
puts("=================");
puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str),
_test_src,
ETHERNET_ADDR_LEN));
puts("=================");
puts("received source");
puts("=================");
puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str),
gnrc_netif_hdr_get_src_addr(hdr->data),
ETHERNET_ADDR_LEN));
return 0;
}
if (memcmp(gnrc_netif_hdr_get_dst_addr(hdr->data), _dev_addr,
ETHERNET_ADDR_LEN) != 0) {
char addr_str[ETHERNET_ADDR_LEN * 3];
puts("Unexpected destination received");
puts("=================");
puts("expected");
puts("=================");
puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str),
_dev_addr,
ETHERNET_ADDR_LEN));
puts("====================");
puts("received destination");
puts("====================");
puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str),
gnrc_netif_hdr_get_dst_addr(hdr->data),
ETHERNET_ADDR_LEN));
return 0;
}
gnrc_pktbuf_release(pkt);
gnrc_netreg_unregister(GNRC_NETTYPE_UNDEF, &me);
return 1;
}
static int test_set_addr(void)
{
static const uint8_t new_addr[] = { 0x71, 0x29, 0x5b, 0xc8, 0x52, 0x65 };
uint8_t tmp[sizeof(new_addr)];
if (gnrc_netapi_set(_mac_pid, NETOPT_ADDRESS, 0, (void *)new_addr,
sizeof(new_addr)) != sizeof(new_addr)) {
puts("Error setting device address");
return 0;
}
if (gnrc_netapi_get(_mac_pid, NETOPT_ADDRESS, 0, tmp,
sizeof(tmp)) != sizeof(tmp)) {
puts("Error setting device address");
return 0;
}
else if (memcmp(tmp, new_addr, sizeof(new_addr)) != 0) {
puts("Set to wrong device address");
return 0;
}
return 1;
}
int main(void)
{
/* initialization */
gnrc_pktbuf_init();
msg_init_queue(_main_msg_queue, _MAIN_MSG_QUEUE_SIZE);
netdev2_test_setup(&_dev, NULL);
netdev2_test_set_isr_cb(&_dev, _dev_isr);
netdev2_test_set_recv_cb(&_dev, _dev_recv);
netdev2_test_set_send_cb(&_dev, _dev_send);
netdev2_test_set_get_cb(&_dev, NETOPT_ADDRESS, _dev_get_addr);
netdev2_test_set_set_cb(&_dev, NETOPT_ADDRESS, _dev_set_addr);
gnrc_netdev2_eth_init(&_gnrc_dev, (netdev2_t *)(&_dev));
_mac_pid = gnrc_netdev2_init(_mac_stack, _MAC_STACKSIZE, _MAC_PRIO,
"gnrc_netdev_eth_test", &_gnrc_dev);
if (_mac_pid <= KERNEL_PID_UNDEF) {
puts("Could not start MAC thread\n");
return 1;
}
/* test execution */
EXECUTE(test_get_addr);
EXECUTE(test_send);
EXECUTE(test_receive);
EXECUTE(test_set_addr);
puts("ALL TESTS SUCCESSFUL");
return 0;
}
/* netdev2_test callbacks */
static void _dev_isr(netdev2_t *dev)
{
(void)dev;
if (dev->event_callback) {
dev->event_callback(dev, NETDEV2_EVENT_RX_COMPLETE, dev->isr_arg);
}
}
static int _dev_recv(netdev2_t *dev, char *buf, int len, void *info)
{
(void)dev;
(void)info;
if (buf == NULL) {
return _tmp_len;
}
else if (len < _tmp_len) {
return -ENOBUFS;
}
else {
memcpy(buf, _tmp, _tmp_len);
return _tmp_len;
}
}
static int _dev_send(netdev2_t *dev, const struct iovec *vector, int count)
{
int idx = 0;
(void)dev;
/* check packet content with expected data */
for (int i = 0; i < count; i++) {
if (memcmp(&(_tmp[idx]), vector[i].iov_base, vector[i].iov_len) != 0) {
printf("Unexpected send data (vector index = %d)\n", i);
puts("===========================================================");
puts("expected");
puts("===========================================================");
od_hex_dump(&_tmp[idx], vector[i].iov_len, OD_WIDTH_DEFAULT);
puts("===========================================================");
puts("send data");
puts("===========================================================");
od_hex_dump(vector[i].iov_base, vector[i].iov_len, OD_WIDTH_DEFAULT);
return -EINVAL;
}
idx += vector[i].iov_len;
}
if (idx != _tmp_len) {
printf("Unexpected send length: %d (expected: %d)\n", idx, _tmp_len);
return -EINVAL;
}
return idx;
}
static int _dev_get_addr(netdev2_t *dev, void *value, size_t max_len)
{
(void)dev;
if (max_len < sizeof(_dev_addr)) {
return -ENOBUFS;
}
memcpy(value, _dev_addr, sizeof(_dev_addr));
return sizeof(_dev_addr);
}
static int _dev_set_addr(netdev2_t *dev, void *value, size_t value_len)
{
(void)dev;
if (value_len != sizeof(_dev_addr)) {
return -EOVERFLOW;
}
memcpy(_dev_addr, value, sizeof(_dev_addr));
return sizeof(_dev_addr);
}
Loading…
Cancel
Save