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

Merge pull request #15536 from fjmolinas/pr_openwsn_sock_selfhosted

pkg/openwsn: add sock_udp
This commit is contained in:
Martine Lenders 2020-12-11 11:22:50 +01:00 committed by GitHub
commit b6bf67114b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 2097 additions and 149 deletions

View File

@ -1,6 +1,6 @@
PKG_NAME=openwsn
PKG_URL=https://github.com/openwsn-berkeley/openwsn-fw.git
PKG_VERSION=028db872c0c60f756e16880a0c86d6282e421c71
PKG_VERSION=e2958a031ad50a6f3eeca3a98ad1ae85aa773a48
PKG_LICENSE=BSD-3-Clause
include $(RIOTBASE)/pkg/pkg.mk
@ -8,11 +8,14 @@ include $(RIOTBASE)/pkg/pkg.mk
# openwsn_% RIOT Modules or PSEUDOMODULES that don't have custom rules
IGNORE_MODULES := openwsn_leds \
openwsn_debugpins \
openwsn_6lo_frag \
openwsn_6lo_fragmentation \
openwsn_icmpv6_echo \
openwsn_iee802154e_security \
openwsn_radio \
openwsn_riotos \
openwsn_sock \
openwsn_sock_async \
openwsn_sock_udp \
openwsn_serial \
openwsn_sctimer \
openwsn_sctimer_rtt \
@ -42,14 +45,13 @@ OPENWSN_PATH_openapps = openapps
OPENWSN_PATH_openweb = openweb
OPENWSN_PATH_drivers = drivers/common
OPENWSN_PATH_crypto = drivers/common/crypto
OPENWSN_PATH_openos = kernel/openos
OPENWSN_PATH_cjoin = openapps/cjoin
OPENWSN_PATH_opencoap = openweb/opencoap
OPENWSN_PATH_coap = openweb/opencoap
OPENWSN_PATH_mac_low = openstack/02a-MAClow
OPENWSN_PATH_mac_high = openstack/02b-MAChigh
OPENWSN_PATH_iphc = openstack/03a-IPHC
OPENWSN_PATH_ipv6 = openstack/03b-IPv6
OPENWSN_PATH_transport = openstack/04-TRAN
OPENWSN_PATH_udp = openstack/04-TRAN
OPENWSN_PATH_crosslayers = openstack/cross-layers
all: $(OPENWSN_MODULES)

View File

@ -3,9 +3,7 @@ ifneq (,$(filter openwsn_openstack,$(USEMODULE)))
USEMODULE += openwsn_ipv6
USEMODULE += openwsn_mac_low
USEMODULE += openwsn_mac_high
USEMODULE += openwsn_transport
USEMODULE += openwsn_crosslayers
USEMODULE += openwsn_drivers
USEMODULE += openwsn_sctimer
USEMODULE += openwsn_radio
@ -19,15 +17,12 @@ ifneq (,$(filter openwsn_openstack,$(USEMODULE)))
endif
ifneq (,$(filter openwsn_scheduler,$(USEMODULE)))
ifeq (,$(filter openwsn_openos,$(USEMODULE)))
# allow to mock the scheduler as needed
ifeq (,$(filter openwsn_scheduler_mock,$(USEMODULE)))
USEMODULE += openwsn_riotos
endif
endif
ifneq (,$(filter openwsn_openos,$(USEMODULE)))
USEMODULE += core_thread_flags
endif
ifneq (,$(filter openwsn_riotos,$(USEMODULE)))
USEMODULE += event
USEMODULE += event_callback
@ -39,10 +34,15 @@ ifneq (,$(filter openwsn_ipv6,$(USEMODULE)))
endif
ifneq (,$(filter openwsn_cjoin,$(USEMODULE)))
USEMODULE += openwsn_opencoap
USEMODULE += openwsn_coap
USEMODULE += openwsn_crypto
endif
ifneq (,$(filter openwsn_coap,$(USEMODULE)))
# The implementation of sock_udp used by openwsn_coap is asynchronous
USEMODULE += openwsn_sock_async
endif
ifneq (,$(filter openwsn_crypto,$(USEMODULE)))
USEMODULE += crypto_3des
USEMODULE += cipher_modes
@ -99,9 +99,24 @@ ifneq (,$(filter openwsn_debugpins,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio_irq
endif
ifneq (,$(filter sock_udp,$(USEMODULE)))
USEMODULE += ipv6_addr
USEMODULE += openwsn_udp
USEMODULE += openwsn_sock_udp
endif
ifneq (,$(filter openwsn_sock%,$(USEMODULE)))
USEMODULE += openwsn_sock
USEMODULE += core_mbox
USEMODULE += ztimer_usec
endif
ifneq (,$(filter openwsn_sock_async,$(USEMODULE)))
USEMODULE += sock_async
endif
ifneq (,$(filter shell_commands,$(USEMODULE)))
USEMODULE += l2util
endif
# This port currently requires setting ISR_STACKSIZE
FEATURES_BLACKLIST += arch_esp32 arch_esp8266 arch_riscv arch_avr8

View File

@ -1,9 +1,11 @@
PSEUDOMODULES += openwsn_serial \
openwsn_debugpins \
openwsn_6lo_frag \
openwsn_6lo_fragmentation \
openwsn_icmpv6_echo \
openwsn_iee802154e_security \
openwsn_leds \
openwsn_sock \
openwsn_sock_async \
openwsn_scheduler \
openwsn_sctimer \
openwsn_sctimer_rtt \
@ -32,44 +34,30 @@ INCLUDES += -I$(PKGDIRBASE)/openwsn \
-I$(PKGDIRBASE)/openwsn/openweb/opencoap \
-I$(RIOTBASE)/pkg/openwsn/include \
ifneq (,$(filter openwsn_openos,$(USEMODULE)))
INCLUDES += -I$(PKGDIRBASE)/openwsn/kernel/openos
endif
ifneq (,$(filter openwsn_riotos,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/pkg/openwsn/scheduler
DIRS += $(RIOTBASE)/pkg/openwsn/scheduler
endif
ifneq (,$(filter openwsn_sock_udp,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/pkg/openwsn/sock
DIRS += $(RIOTBASE)/pkg/openwsn/sock
endif
# Set OpenWSN configurations flags, see $(PKG_SOURCE_DIR)/openwsn-fw/inc/config.h
ifneq (,$(filter openwsn_cjoin,$(USEMODULE)))
CFLAGS += -DOPENWSN_CJOIN_C
CFLAGS += -DBOARD_CRYPTOENGINE_ENABLED
CFLAGS += -DBOARD_CRYPTOENGINE_ENABLED=1
endif
ifneq (,$(filter openwsn_transport,$(USEMODULE)))
CFLAGS += -DOPENWSN_UDP_C
endif
ifneq (,$(filter openwsn_opencoap,$(USEMODULE)))
CFLAGS += -DOPENWSN_COAP_C
endif
ifneq (,$(filter openwsn_6lo_frag,$(USEMODULE)))
CFLAGS += -DOPENWSN_6LO_FRAGMENTATION_C
endif
ifneq (,$(filter openwsn_icmpv6_echo,$(USEMODULE)))
CFLAGS += -DOPENWSN_ICMPV6ECHO_C
endif
ifneq (,$(filter openwsn_iee802154e_security,$(USEMODULE)))
CFLAGS += -DOPENWSN_IEEE802154E_SECURITY_C
endif
ifneq (,$(filter openwsn_adaptive_msf,$(USEMODULE)))
CFLAGS += -DOPENWSN_ADAPTIVE_MSF
ifneq (,$(filter openwsn_sock%,$(USEMODULE)))
CFLAGS += -DSOCK_HAS_IPV6
ifneq (,$(filter openwsn_sock_async,$(USEMODULE)))
CFLAGS += -DSOCK_HAS_ASYNC
endif
ifneq (,$(filter sock_async_event,$(USEMODULE)))
# Needed only if using event and not simple callbacks
CFLAGS += -DSOCK_HAS_ASYNC_CTX
endif
endif
# In OpenWSN the ISR stack is shared with the network stack. OpenWSN stack is

View File

@ -43,7 +43,7 @@ void eui64_get(uint8_t *addressToWrite)
_eui64_is_set = true;
}
memcpy(addressToWrite, _eui64.uint8, sizeof(_eui64.uint8));
#else
#elif MODULE_OPENWSN_RADIO_NETDEV
eui64_t eui64;
if (openwsn_radio.dev->driver->get(openwsn_radio.dev, NETOPT_ADDRESS_LONG,
@ -54,5 +54,7 @@ void eui64_get(uint8_t *addressToWrite)
else {
luid_get_eui64((eui64_t *) addressToWrite);
}
#else
memset(addressToWrite, 0, sizeof(eui64_t));
#endif
}

View File

@ -288,7 +288,7 @@
lower the stack footprint.
- `openwsn_cjoin`: this enabled the use of Constrained Join Protocol (CoJP)
- `openwsn_6lo_frag`: this enable 6LoWPAN fragmentation
- `openwsn_6lo_fragmentation`: this enable 6LoWPAN fragmentation
- `openwsn_iee802154e_security`: enable link layer security
- `openwsn_adaptive_msf`: allow the MSF algorithm to dynamically remove and
allocate slots

View File

@ -33,6 +33,15 @@ extern "C" {
#define OPENWSN_PANID (0xCAFE)
#endif
/**
* @brief Default NID for OpenWSN network
*
* @note Only one netif is currently possible in OpenWSN.
*/
#ifndef CONFIG_OPENWSN_NETIF_ID
#define CONFIG_OPENWSN_NETIF_ID (0x0001)
#endif
/**
* @brief Initializes OpenWSN thread
*

View File

@ -0,0 +1,3 @@
MODULE = openwsn_sock_udp
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,557 @@
/*
* Copyright (C) 2020 Inria
*
* 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 Timothy Claeys <timothy.claeys@inria.fr>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#include <errno.h>
#ifdef SOCK_HAS_ASYNC
#include "net/sock/async.h"
#endif
#include "net/ipv6/addr.h"
#include "net/iana/portrange.h"
#include "net/sock/udp.h"
#ifdef MODULE_ZTIMER_USEC
#include "ztimer.h"
#endif
#include "utlist.h"
#include "log.h"
#include "openwsn.h"
#include "opendefs.h"
#include "kernel/scheduler.h"
#include "cross-layers/packetfunctions.h"
#include "cross-layers/openqueue.h"
#include "cross-layers/openrandom.h"
#include "cross-layers/idmanager.h"
#include "04-TRAN/udp.h"
#define _MSG_TYPE_RECV_PKT (0x1601)
#ifdef MODULE_ZTIMER_USEC
#define _TIMEOUT_MAGIC (0xF38A0B63U)
#define _TIMEOUT_MSG_TYPE (0x8474)
#endif /* MODULE_ZTIMER_USEC */
static sock_udp_t *_udp_socket_list;
#ifdef MODULE_ZTIMER_USEC
static void _timeout_cb(void *arg)
{
msg_t timeout_msg = { .sender_pid = KERNEL_PID_UNDEF,
.type = _TIMEOUT_MSG_TYPE,
.content = { .value = _TIMEOUT_MAGIC } };
mbox_t *mbox = arg;
/* should be safe, because otherwise if mbox were filled this callback is
* senseless */
mbox_try_put(mbox, &timeout_msg);
}
#endif /* MODULE_ZTIMER_USEC */
static void _sock_transmit_internal(void)
{
OpenQueueEntry_t *pkt;
pkt = openqueue_getPacketByComponent(COMPONENT_SOCK_TO_UDP);
if (pkt == NULL) {
LOG_ERROR("%s: not pkt in queue\n", __FUNCTION__);
return;
}
udp_transmit(pkt);
}
static bool _sock_valid_af(uint8_t af)
{
/* only AF_INET6 is supported*/
return (af == AF_INET6);
}
static bool _sock_valid_addr(sock_udp_ep_t *ep)
{
assert(ep != NULL);
const uint8_t *p = (uint8_t *)&ep->addr;
for (uint8_t i = 0; i < sizeof(ep->addr); i++) {
if (p[i] != 0) {
return true;
}
}
return false;
}
static bool _sock_port_in_use(uint16_t port)
{
for (sock_udp_t *ptr = _udp_socket_list; ptr != NULL;
ptr = (sock_udp_t *)ptr->next) {
if (ptr->gen_sock.local.port == port) {
return true;
}
}
return false;
}
/**
* @brief returns a UDP port, and checks for reuse if required
*
* implements "Another Simple Port Randomization Algorithm" as specified in
* RFC 6056, see https://tools.ietf.org/html/rfc6056#section-3.3.2
*/
static uint16_t _get_dyn_port(void)
{
unsigned num = (IANA_DYNAMIC_PORTRANGE_MAX - IANA_DYNAMIC_PORTRANGE_MIN);
unsigned count = num;
do {
uint16_t port = IANA_DYNAMIC_PORTRANGE_MIN +
(openrandom_get16b() % num);
if (!_sock_port_in_use(port)) {
return port;
}
--count;
} while (count > 0);
return 0;
}
void sock_udp_init(void)
{
_udp_socket_list = NULL;
}
int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local,
const sock_udp_ep_t *remote, uint16_t flags)
{
/* sanity checks */
assert(sock);
assert(remote == NULL || remote->port != 0);
/* check that if set netifs match */
if ((local != NULL) && (remote != NULL) &&
(local->netif != SOCK_ADDR_ANY_NETIF) &&
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
(local->netif != remote->netif)) {
return -EINVAL;
}
/* if set netifs should match the only one available in OpenWSN*/
if ((local != NULL) &&
(local->netif != SOCK_ADDR_ANY_NETIF) &&
(local->netif != CONFIG_OPENWSN_NETIF_ID)) {
return -EINVAL;
}
if ((remote != NULL) &&
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
(remote->netif != CONFIG_OPENWSN_NETIF_ID)) {
return -EINVAL;
}
/* check local */
memset(&sock->gen_sock.local, 0, sizeof(sock_udp_ep_t));
if (local != NULL) {
uint16_t port = local->port;
if (!_sock_valid_af(local->family)) {
return -EAFNOSUPPORT;
}
if (port == 0U) {
port = _get_dyn_port();
if (port == 0U) {
return -EADDRINUSE;
}
}
else if (!(flags & SOCK_FLAGS_REUSE_EP)) {
/* a single IPV6 address is possible in OpenWSN, so only check
if port is in use */
if (_sock_port_in_use(port)) {
return -EADDRINUSE;
}
}
memcpy(&sock->gen_sock.local, local, sizeof(sock_udp_ep_t));
sock->gen_sock.local.port = port;
}
/* check and set remote */
memset(&sock->gen_sock.remote, 0, sizeof(sock_udp_ep_t));
if (remote != NULL) {
if (!_sock_valid_af(remote->family)) {
return -EAFNOSUPPORT;
}
if (!_sock_valid_addr((sock_udp_ep_t *)remote)) {
return -EINVAL;
}
memcpy(&sock->gen_sock.remote, remote, sizeof(sock_udp_ep_t));
}
/* if all ok and local != NULL, listen */
if (local != NULL) {
/* start mailbox */
mbox_init(&sock->mbox, sock->mbox_queue, OPENWSN_SOCK_MBOX_SIZE);
#ifdef SOCK_HAS_ASYNC
sock->async_cb = NULL;
#endif
/* update socket list */
LL_PREPEND(_udp_socket_list, sock);
}
/* set flags */
sock->gen_sock.flags = flags;
return 0;
}
ssize_t sock_udp_send_aux(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux)
{
(void)aux;
OpenQueueEntry_t *pkt;
open_addr_t dst_addr, src_addr;
memset(&dst_addr, 0, sizeof(open_addr_t));
memset(&src_addr, 0, sizeof(open_addr_t));
uint16_t src_port = 0, dst_port;
/* asserts for sock_udp_send "pre" */
assert((sock != NULL) || (remote != NULL));
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */
/* check remote */
if (remote != NULL) {
if (remote->port == 0) {
return -EINVAL;
}
else if (!_sock_valid_af(remote->family)) {
return -EAFNOSUPPORT;
}
else if (!_sock_valid_addr((sock_udp_ep_t *)remote)) {
return -EINVAL;
}
else if ((sock != NULL) &&
(sock->gen_sock.local.netif != SOCK_ADDR_ANY_NETIF) &&
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
(sock->gen_sock.local.netif != remote->netif)) {
return -EINVAL;
}
/* if set netifs should match the only one available in OpenWSN*/
if ((sock != NULL) &&
(((sock->gen_sock.local.netif != SOCK_ADDR_ANY_NETIF) &&
(sock->gen_sock.local.netif != CONFIG_OPENWSN_NETIF_ID)) ||
((remote->netif != SOCK_ADDR_ANY_NETIF) &&
(remote->netif != CONFIG_OPENWSN_NETIF_ID)))) {
return -EINVAL;
}
dst_addr.type = ADDR_128B;
memcpy(&dst_addr.addr_128b, &remote->addr, LENGTH_ADDR128b);
dst_port = remote->port;
}
/* if remote is null then check that sock has a remote */
else if (sock->gen_sock.remote.family == AF_UNSPEC) {
return -ENOTCONN;
}
/* set destination port and address based on sock remote */
else {
dst_port = sock->gen_sock.remote.port;
dst_addr.type = ADDR_128B;
memcpy(&dst_addr.addr_128b, &sock->gen_sock.remote.addr,
LENGTH_ADDR128b);
}
if ((sock == NULL) || (sock->gen_sock.local.family == AF_UNSPEC)) {
/* if no sock or unbound get a random port */
if ((src_port = _get_dyn_port()) == 0) {
return -EADDRINUSE;
}
}
else {
/* set src port from sock */
src_port = sock->gen_sock.local.port;
/* set addr if sock is not null or bound */
src_addr.type = ADDR_128B;
memcpy(&src_addr.addr_128b, &sock->gen_sock.local.addr,
LENGTH_ADDR128b);
}
/* get pkt buffer and take owner ship */
if ((pkt = openqueue_getFreePacketBuffer(COMPONENT_SOCK_TO_UDP)) == NULL) {
return -ENOMEM;
}
pkt->owner = COMPONENT_SOCK_TO_UDP;
pkt->creator = COMPONENT_SOCK_TO_UDP;
/* set addresses and ports */
pkt->l3_destinationAdd.type = ADDR_128B;
pkt->l3_sourceAdd.type = ADDR_128B;
memcpy(&pkt->l3_sourceAdd.addr_128b, &src_addr.addr_128b, LENGTH_ADDR128b);
memcpy(&pkt->l3_destinationAdd.addr_128b, &dst_addr.addr_128b,
LENGTH_ADDR128b);
pkt->l4_destination_port = dst_port;
pkt->l4_sourcePortORicmpv6Type = src_port;
/* set payload */
if (packetfunctions_reserveHeader(&pkt, len)) {
openqueue_freePacketBuffer(pkt);
return -ENOMEM;
}
memcpy(pkt->payload, data, len);
pkt->l4_payload = pkt->payload;
pkt->l4_length = pkt->length;
/* push task to scheduler send */
scheduler_push_task(_sock_transmit_internal, TASKPRIO_UDP);
return len;
}
void sock_udp_close(sock_udp_t *sock)
{
if (_udp_socket_list == NULL) {
return;
}
if (sock) {
LL_DELETE(_udp_socket_list, sock);
sock->next = NULL;
}
}
int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *ep)
{
if (sock->gen_sock.local.family == AF_UNSPEC) {
return -EADDRNOTAVAIL;
}
memcpy(ep, &sock->gen_sock.local, sizeof(sock_udp_ep_t));
return 0;
}
int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep)
{
if (sock->gen_sock.remote.family == AF_UNSPEC) {
return -ENOTCONN;
}
memcpy(ep, &sock->gen_sock.remote, sizeof(sock_udp_ep_t));
return 0;
}
ssize_t sock_udp_recv_aux(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
{
void *pkt = NULL, *ctx = NULL;
ssize_t res;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
res = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote, aux);
/* set data to copy, check if enough buffer space */
if (res >= 0) {
ssize_t tmp;
if ((ssize_t)max_len >= res) {
memset(data, 0, max_len);
if (res > 0) {
/* copy received data */
memcpy(data, pkt, res);
/* free packet */
tmp = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote,
aux);
assert(tmp == 0);
}
(void) tmp;
}
else {
res = -ENOBUFS;
/* free packet */
tmp = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote, aux);
assert(tmp == 0);
}
}
return res;
}
ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
{
(void) aux;
sock_udp_ep_t ep;
OpenQueueEntry_t *pkt = NULL;
msg_t msg;
assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL));
if (*buf_ctx != NULL) {
*data = NULL;
openqueue_freePacketBuffer(*buf_ctx);
*buf_ctx = NULL;
return 0;
}
if (sock->gen_sock.local.family == AF_UNSPEC) {
return -EADDRNOTAVAIL;
}
#ifdef MODULE_ZTIMER_USEC
ztimer_t timer;
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
timer.callback = _timeout_cb;
timer.arg = &sock->mbox;
ztimer_set(ZTIMER_USEC, &timer, timeout);
}
#endif /* MODULE_ZTIMER_USEC */
if (timeout != 0) {
mbox_get(&sock->mbox, &msg);
}
else {
if (!mbox_try_get(&sock->mbox, &msg)) {
return -EAGAIN;
}
}
#ifdef MODULE_ZTIMER_USEC
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
ztimer_remove(ZTIMER_USEC, &timer);
}
#endif /* MODULE_ZTIMER_USEC */
switch (msg.type) {
case _MSG_TYPE_RECV_PKT:
pkt = msg.content.ptr;
break;
#ifdef MODULE_ZTIMER_USEC
case _TIMEOUT_MSG_TYPE:
if (msg.content.value == _TIMEOUT_MAGIC) {
return -ETIMEDOUT;
}
#endif /* MODULE_ZTIMER_USEC */
/* Falls Through. */
default:
return -EINVAL;
}
if (pkt == NULL) {
return -EINVAL;
}
/* copy source port and address to end point */
ep.family = AF_INET6;
ep.port = pkt->l4_sourcePortORicmpv6Type;
ep.netif = CONFIG_OPENWSN_NETIF_ID;
memcpy(&ep.addr, pkt->l3_sourceAdd.addr_128b, LENGTH_ADDR128b);
if (remote != NULL) {
/* return remote if requested */
memcpy(remote, &ep, sizeof(sock_udp_ep_t));
}
if ((sock->gen_sock.remote.family != AF_UNSPEC) &&
/* check remote end-point if set */
((sock->gen_sock.remote.port != pkt->l4_sourcePortORicmpv6Type) ||
/* We only have IPv6 for now, so just comparing the whole end point
* should suffice */
((memcmp(&sock->gen_sock.remote.addr, &ipv6_addr_unspecified,
sizeof(ipv6_addr_t)) != 0) &&
(memcmp(&sock->gen_sock.remote.addr, &ep.addr,
sizeof(ipv6_addr_t)) != 0)))) {
openqueue_freePacketBuffer(pkt);
return -EPROTO;
}
*data = pkt->l4_payload;
*buf_ctx = pkt;
return pkt->l4_length;
}
#ifdef SOCK_HAS_ASYNC
void sock_udp_set_cb(sock_udp_t *sock, sock_udp_cb_t cb, void *cb_arg)
{
sock->async_cb = cb;
sock->async_cb_arg = cb_arg;
}
#ifdef SOCK_HAS_ASYNC_CTX
sock_async_ctx_t *sock_udp_get_async_ctx(sock_udp_t *sock)
{
return &sock->async_ctx;
}
#endif /* SOCK_HAS_ASYNC_CTX*/
#endif /* SOCK_HAS_ASYNC */
void sock_receive_internal(void)
{
OpenQueueEntry_t *pkt;
sock_udp_t *current;
pkt = openqueue_getPacketByComponent(COMPONENT_UDP_TO_SOCK);
if (pkt == NULL) {
LOG_ERROR("%s: not pkt in queue\n", __FUNCTION__);
return;
}
current = _udp_socket_list;
while (current != NULL) {
if (current->gen_sock.local.port == pkt->l4_destination_port &&
idmanager_isMyAddress(&pkt->l3_destinationAdd)) {
msg_t msg;
msg.type = _MSG_TYPE_RECV_PKT;
msg.content.ptr = pkt;
int ret = mbox_try_put(&current->mbox, &msg);
if (ret < 1) {
LOG_ERROR(
"openwsn_sock: dropped message to %p (was full)\n",
(void *)&current->mbox);
}
#ifdef SOCK_HAS_ASYNC
if (current->async_cb != NULL) {
current->async_cb(current, SOCK_ASYNC_MSG_RECV, NULL);
}
#endif /* SOCK_HAS_ASYNC */
break;
}
current = current->next;
}
if (current == NULL) {
openqueue_freePacketBuffer(pkt);
LOG_ERROR("%s: no associated socket found\n", __FUNCTION__);
}
}
void sock_senddone_internal(OpenQueueEntry_t *msg, owerror_t error)
{
/* In RIOT we can't know what message was sent... */
(void)msg;
#ifdef SOCK_HAS_ASYNC
OpenQueueEntry_t *pkt;
sock_udp_t *current;
pkt = openqueue_getPacketByComponent(COMPONENT_UDP);
if (pkt == NULL) {
LOG_ERROR("%s: not pkt in queue\n", __FUNCTION__);
return;
}
current = _udp_socket_list;
while (current != NULL) {
if (current->gen_sock.local.port == pkt->l4_sourcePortORicmpv6Type &&
current->async_cb != NULL) {
current->async_cb(current, SOCK_ASYNC_MSG_SENT, &error);
break;
}
current = current->next;
}
#else /* SOCK_HAS_ASYNC */
(void)error;
#endif /*SOCK_HAS_ASYNC */
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2020 Inria
*
* 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 pkg_openwsn_sock
* @{
*
* @file
* @brief OpenWSN-specific types
*
* @author Timothy Claeys <timothy.claeys@inria.fr>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#ifndef SOCK_TYPES_H
#define SOCK_TYPES_H
#include "mbox.h"
#include "net/af.h"
#ifdef SOCK_HAS_ASYNC
#include "net/sock/async/types.h"
#endif
#include "net/sock/udp.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default size for OpenWSN sock_udp_t::mbox_queue (as exponent of 2^n).
*
* As the queue size ALWAYS needs to be power of two, this option
* represents the exponent of 2^n, which will be used as the size of
* the queue.
*/
#ifndef CONFIG_OPENWSN_SOCK_MBOX_SIZE_EXP
#define CONFIG_OPENWSN_SOCK_MBOX_SIZE_EXP (3)
#endif
/**
* @brief Size for OpenWSN sock_udp_t::mbox_queue
*/
#ifndef OPENWSN_SOCK_MBOX_SIZE
#define OPENWSN_SOCK_MBOX_SIZE (1 << CONFIG_OPENWSN_SOCK_MBOX_SIZE_EXP)
#endif
/**
* @brief Forward declaration
* @internal
*/
typedef struct openwsn_gen_sock openwsn_gen_sock_t;
/**
* @brief Generic openwsn sock type
* @warning For network stack internal purposes only. Do not access members
* externally.
* @internal
*/
struct openwsn_gen_sock {
sock_udp_ep_t local; /**< local end-point */
sock_udp_ep_t remote; /**< remote end-point */
uint16_t flags; /**< option flags */
};
/**
* @brief UDP sock type
* @warning For network stack internal purposes only. Do not access members
* externally.
* @internal
*/
struct sock_udp {
struct sock_udp *next; /**< sock liked list */
openwsn_gen_sock_t gen_sock; /**< Generic socket */
mbox_t mbox; /**< @ref core_mbox target for the sock */
msg_t mbox_queue[OPENWSN_SOCK_MBOX_SIZE]; /**< queue for gnrc_sock_reg_t::mbox */
#ifdef MODULE_SOCK_ASYNC_EVENT
sock_async_ctx_t async_ctx; /**< asynchronous event context */
#endif
#ifdef SOCK_HAS_ASYNC
sock_udp_cb_t async_cb; /**< asynchronous callback */
void* async_cb_arg;
#endif
};
#ifdef __cplusplus
}
#endif
#endif /* SOCK_TYPES_H */
/** @} */

View File

@ -578,6 +578,7 @@ ifneq (,$(filter shell_commands,$(USEMODULE)))
endif
ifneq (,$(filter openwsn_%,$(USEMODULE)))
USEMODULE += netif
USEMODULE += ipv6_addr
endif
endif
@ -813,6 +814,15 @@ ifneq (,$(filter sock_async_event,$(USEMODULE)))
USEMODULE += event
endif
ifneq (,$(filter sock_async,$(USEMODULE)))
ifneq (,$(filter gnrc%,$(USEMODULE)))
USEMODULE += gnrc_sock_async
endif
ifneq (,$(filter openwsn%,$(USEMODULE)))
USEMODULE += openwsn_sock_async
endif
endif
ifneq (,$(filter sock_dns,$(USEMODULE)))
USEMODULE += sock_udp
USEMODULE += sock_util
@ -846,12 +856,17 @@ endif
ifneq (,$(filter gcoap,$(USEMODULE)))
USEMODULE += nanocoap
USEMODULE += sock_async
USEMODULE += sock_async_event
USEMODULE += sock_udp
USEMODULE += sock_util
USEMODULE += event_callback
USEMODULE += event_timeout
ifneq (,$(filter gnrc%,$(USEMODULE)))
USEMODULE += gnrc_sock_async
endif
ifneq (,$(filter openwsn%,$(USEMODULE)))
USEMODULE += openwsn_sock_udp
endif
endif
ifneq (,$(filter luid,$(USEMODULE)))

View File

@ -73,7 +73,9 @@ static const struct {
{ "icmpv6echo", COMPONENT_ICMPv6ECHO },
{ "icmpv6router", COMPONENT_ICMPv6ROUTER },
{ "icmpv6rpl", COMPONENT_ICMPv6RPL },
{ "udp", COMPONENT_OPENUDP },
{ "udp", COMPONENT_UDP },
{ "sock-udp", COMPONENT_SOCK_TO_UDP },
{ "udp-sock", COMPONENT_UDP_TO_SOCK },
{ "coap", COMPONENT_OPENCOAP },
{ "cjoin", COMPONENT_CJOIN },
{ "oscore", COMPONENT_OSCORE },

View File

@ -34,16 +34,19 @@ BOARD_WHITELIST = \
# OpenWSN Modules
USEPKG += openwsn
USEMODULE += openwsn_openstack
USEMODULE += sock_udp
# This example uses async
USEMODULE += sock_async
# Optional OpenWSN Modules
## Enable Constrained Join Protocol (CoJP)
USEMODULE += openwsn_cjoin
## Enable 6lowpan fragmentation
USEMODULE += openwsn_6lo_frag
USEMODULE += openwsn_6lo_fragmentation
## Enable link layer security
# USEMODULE += openwsn_iee802154e_security
## Enable MSF dynamic slot allocation
# USEMODULE += openwsn_adaptive_msf
# USEMODULE += openwsn_adaptive_msf
## Optional Module, but required for root nodes
# USEMODULE += openwsn_serial
@ -75,11 +78,11 @@ endif
# export OPENWSN_LOG_LEVEL ?= LOG_ERROR
## Test application Modules
USEMODULE += ipv6_addr
USEMODULE += ps
USEMODULE += od_string
USEMODULE += shell
USEMODULE += shell_commands
# ztimer is used instead of xtimer because it's a dependency of some
# OpenWSN modules.
USEMODULE += ztimer_usec

View File

@ -21,41 +21,10 @@
#include <stdio.h>
#include <stdlib.h>
#include "od.h"
#include "shell.h"
#include "opendefs.h"
#include "04-TRAN/udp.h"
#include "cross-layers/openqueue.h"
udp_resource_desc_t uinject_vars;
void uinject_sendDone(OpenQueueEntry_t *msg, owerror_t error)
{
(void)error;
printf("msg.l2_sendDoneError: %x\n", msg->l2_sendDoneError);
openqueue_freePacketBuffer(msg);
puts("Send success");
}
void uinject_receive(OpenQueueEntry_t *pkt)
{
printf("Received %i bytes on port %i\n", (int)pkt->length,
pkt->l4_destination_port);
od_hex_dump(pkt->payload, pkt->length, OD_WIDTH_DEFAULT);
openqueue_freePacketBuffer(pkt);
}
void uinject_init(void)
{
uinject_vars.port = WKP_UDP_INJECT;
uinject_vars.callbackReceive = &uinject_receive;
uinject_vars.callbackSendDone = &uinject_sendDone;
openudp_register(&uinject_vars);
}
extern int udp_cmd(int argc, char **argv);
extern void udp_cli_init(void);
static const shell_command_t shell_commands[] = {
{ "udp", "Send data over UDP and listen on UDP ports", udp_cmd },
@ -69,7 +38,7 @@ int main(void)
printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
printf("This board features a(n) %s MCU.\n", RIOT_MCU);
uinject_init();
udp_cli_init();
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* Copyright (C) 2018 Hamburg University of Applied Sciences
* Copyright (C) 2020 Inria
*
* 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
@ -15,9 +16,11 @@
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@ -25,30 +28,61 @@
#include "ztimer.h"
#include "net/ipv6.h"
#include "net/sock/udp.h"
#ifdef SOCK_HAS_ASYNC
#include "net/sock/async.h"
#endif
#include "od.h"
#include "opendefs.h"
#include "scheduler.h"
#include "02a-MAClow/IEEE802154E.h"
#include "03b-IPv6/icmpv6rpl.h"
#include "04-TRAN/udp.h"
#include "cross-layers/openqueue.h"
#include "cross-layers/idmanager.h"
#include "cross-layers/packetfunctions.h"
extern udp_resource_desc_t uinject_vars;
extern idmanager_vars_t idmanager_vars;
extern openudp_vars_t openudp_vars;
static uint16_t counter = 0;
static sock_udp_t _sock_udp;
OpenQueueEntry_t *pkt;
void _sock_udp_handler(sock_udp_t *sock, sock_async_flags_t type, void *arg)
{
if (type & SOCK_ASYNC_MSG_RECV) {
char buf[50];
sock_udp_ep_t remote;
int16_t res;
void push_pkt_cb(void){
owerror_t ret = openudp_send(pkt);
if (ret == E_FAIL) {
puts("could not send");
openqueue_freePacketBuffer(pkt);
if ((res = sock_udp_recv(sock, buf, sizeof(buf), 0, &remote)) >= 0) {
printf("Received %i bytes on port %i\n", res, remote.port);
od_hex_dump(buf, res, OD_WIDTH_DEFAULT);
}
}
if (type & SOCK_ASYNC_MSG_SENT) {
if (*((uint8_t *)arg) == E_FAIL) {
puts("Failed to Send");
}
else {
puts("Send Success");
}
}
}
void udp_cli_init(void)
{
memset(&_sock_udp, 0, sizeof(sock_udp_t));
sock_udp_ep_t local;
local.family = AF_INET6;
local.netif = SOCK_ADDR_ANY_NETIF;
local.port = WKP_UDP_ECHO;
if (sock_udp_create(&_sock_udp, &local, NULL, 0) < 0) {
puts("Could not create socket");
return;
}
sock_udp_set_cb(&_sock_udp, _sock_udp_handler, NULL);
}
static int udp_send(char *addr_str, char *port_str, char *data,
@ -59,7 +93,6 @@ static int udp_send(char *addr_str, char *port_str, char *data,
ipv6_addr_t addr;
data_len = strlen(data);
uint8_t asnArray[data_len];
/* parse destination address */
if (ipv6_addr_from_str(&addr, addr_str) == NULL) {
@ -70,58 +103,45 @@ static int udp_send(char *addr_str, char *port_str, char *data,
for (unsigned int i = 0; i < num; i++) {
printf("Send %u byte over UDP to [%s]:%s\n",
(unsigned)data_len, addr_str, port_str);
(unsigned)data_len, addr_str, port_str);
/* don't run if not in synch */
if (ieee154e_isSynch() == FALSE) {
puts("Error: Node not in sync, exit");
puts("Error: node is not synchronized, exit");
return 1;
}
/* don't run on dagroot */
if (idmanager_getIsDAGroot()) {
puts("Error: Node is DAGROOT, exit");
puts("Error: node is DAGROOT, exit");
return 1;
}
bool foundNeighbor = icmpv6rpl_getPreferredParentEui64(&parentNeighbor);
if (foundNeighbor==FALSE) {
puts("Error: No preferred parent EUI64, exit");
if (foundNeighbor == FALSE) {
puts("Error: no preferred parent EUI64, exit");
return 1;
}
/* get a free packet buffer */
pkt = openqueue_getFreePacketBuffer(COMPONENT_UINJECT);
if (pkt == NULL) {
puts("Error: could not create packet buffer, exit");
return 1;
sock_udp_ep_t remote;
remote.family = AF_INET6;
remote.netif = SOCK_ADDR_ANY_NETIF;
remote.port = atoi(port_str);
memcpy(&remote.addr.ipv6[0], &addr.u8[0], sizeof(addr.u8));
int res = sock_udp_send(&_sock_udp, data, data_len, &remote);
if (res == -EINVAL) {
puts("Error: EINVAL");
}
else if (res == -EAFNOSUPPORT) {
puts("Error: EAFNOSUPPORT");
}
else if (res == -ENOMEM) {
puts("Error: ENOMEM");
}
else if (res == -ENOBUFS) {
puts("Error: ENOBUFS");
}
pkt->owner = COMPONENT_UINJECT;
pkt->creator = COMPONENT_UINJECT;
pkt->l4_protocol = IANA_UDP;
pkt->l4_destination_port = atoi(port_str);
pkt->l4_sourcePortORicmpv6Type = uinject_vars.port;
pkt->l3_destinationAdd.type = ADDR_128B;
memcpy(&pkt->l3_destinationAdd.addr_128b[0], (void *)&addr, 16);
/* add payload */
packetfunctions_reserveHeader(&pkt, data_len);
memcpy(&pkt->payload[0], data, data_len);
packetfunctions_reserveHeader(&pkt, sizeof(uint16_t));
pkt->payload[1] = (uint8_t)((counter & 0xff00) >> 8);
pkt->payload[0] = (uint8_t)(counter & 0x00ff);
counter++;
packetfunctions_reserveHeader(&pkt, sizeof(asn_t));
ieee154e_getAsn(asnArray);
pkt->payload[0] = asnArray[0];
pkt->payload[1] = asnArray[1];
pkt->payload[2] = asnArray[2];
pkt->payload[3] = asnArray[3];
pkt->payload[4] = asnArray[4];
scheduler_push_task(push_pkt_cb, TASKPRIO_COAP);
ztimer_sleep(ZTIMER_USEC, delay);
}
@ -140,12 +160,13 @@ int udp_cmd(int argc, char **argv)
uint32_t delay = 1000000LU;
/* don't send as root */
if (idmanager_vars.isDAGroot) {
puts("Error: Node is root, exit");
puts("Error: node is root, exit");
return 1;
}
if (argc < 5) {
printf("usage: %s send <addr> <port> <hex data> [<num> [<delay in us>]]\n",
argv[0]);
printf(
"Usage: %s send <addr> <port> <hex data> [<num> [<delay in us>]]\n",
argv[0]);
return 1;
}
if (argc > 5) {
@ -158,35 +179,33 @@ int udp_cmd(int argc, char **argv)
}
else if (strcmp(argv[1], "server") == 0) {
if (argc < 3) {
printf("usage: %s server [start|list]\n", argv[0]);
printf("Usage: %s server [start|show]\n", argv[0]);
return 1;
}
if (strcmp(argv[2], "start") == 0) {
if (argc < 4) {
printf("usage %s server start <port>\n", argv[0]);
printf("Usage %s server start <port>\n", argv[0]);
return 1;
}
uint16_t port = atoi(argv[3]);
uinject_vars.port = port;
sock_udp_ep_t local;
sock_udp_get_local(&_sock_udp, &local);
local.port = port;
printf("Set UDP server port to %" PRIu16 "\n", port);
return 0;
}
else if (strcmp(argv[2], "list") == 0) {
udp_resource_desc_t* resource = openudp_vars.resources;
printf("Open UDP Ports: ");
while (NULL != resource) {
printf("%i ", resource->port);
resource = resource->next;
}
puts("");
else if (strcmp(argv[2], "show") == 0) {
sock_udp_ep_t local;
sock_udp_get_local(&_sock_udp, &local);
printf("Udp port: %i\n", local.port);
}
else {
puts("error: invalid command");
puts("Error: invalid command");
return 1;
}
}
else {
puts("error: invalid command");
puts("Error: invalid command");
return 1;
}

View File

@ -0,0 +1,49 @@
BOARD ?= samr21-xpro
include ../Makefile.tests_common
# list of arm boards that provide at86rf2xx radios, cc2538_rf or nrf52840
# radios
BOARD_WHITELIST = \
adafruit-clue \
adafruit-itsybitsy-nrf52 \
arduino-nano-33-ble \
cc2538dk \
feather-nrf52840 \
firefly \
fox \
iotlab-m3 \
iotlab-a8-m3 \
nrf52840-mdk \
nrf52840dk \
nrf52840dongle \
omote \
openmote-b \
openmote-cc2538 \
particle-argon \
particle-boron \
particle-xenon \
samr21-xpro \
samr30-xpro \
reel \
remote-pa \
remote-reva \
remote-revb \
#
USEPKG += openwsn
USEMODULE += openwsn_openstack
USEMODULE += openwsn_scheduler
USEMODULE += sock_udp
# Mock OpenWSN scheduler to handle the udp_transmit task.
USEMODULE += openwsn_scheduler_mock
EXTERNAL_MODULE_DIRS += $(CURDIR)/scheduler
# Explicitly include ztimer to enable timeout
USEMODULE += ztimer_usec
DISABLE_MODULE += auto_init_openwsn
CFLAGS +=-DCONFIG_OPENWSN_NETIF_ID=31
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,44 @@
/*
* 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.
*/
/**
* @ingroup tests
* @brief
* @{
*
* @file
* @brief
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @}
*/
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include "openwsn.h"
#ifdef __cplusplus
extern "C" {
#endif
#define _TEST_NETIF (CONFIG_OPENWSN_NETIF_ID)
#define _TEST_PORT_LOCAL (0x2c94)
#define _TEST_PORT_REMOTE (0xa615)
#define _TEST_TIMEOUT (1000000U)
#define _TEST_ADDR_LOCAL { 0x7f, 0xc4, 0x11, 0x5a, 0xe6, 0x91, 0x8d, 0x5d, \
0x8c, 0xd1, 0x47, 0x07, 0xb7, 0x6f, 0x9b, 0x48 }
#define _TEST_ADDR_REMOTE { 0xe8, 0xb3, 0xb2, 0xe6, 0x70, 0xd4, 0x55, 0xba, \
0x93, 0xcf, 0x11, 0xe1, 0x72, 0x44, 0xc5, 0x9d }
#define _TEST_ADDR_WRONG { 0x2a, 0xce, 0x5d, 0x4e, 0xc8, 0xbf, 0x86, 0xf7, \
0x85, 0x49, 0xb4, 0x19, 0xf2, 0x28, 0xde, 0x9b }
#ifdef __cplusplus
}
#endif
#endif /* CONSTANTS_H */

View File

@ -0,0 +1,793 @@
/*
* 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.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Test for UDP socks
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @}
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "net/sock/udp.h"
#include "net/ipv6/addr.h"
#include "test_utils/expect.h"
#include "stack.h"
#include "constants.h"
#define _TEST_BUFFER_SIZE (128)
static uint8_t _test_buffer[_TEST_BUFFER_SIZE];
static sock_udp_t _sock, _sock2;
#define CALL(fn) puts("Calling " # fn); fn; tear_down()
static void tear_down(void)
{
sock_udp_close(&_sock);
memset(&_sock, 0, sizeof(_sock));
memset(&_sock2, 0, sizeof(_sock2));
}
static void test_sock_udp_create__EADDRINUSE(void)
{
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
expect(0 == sock_udp_create(&_sock, &local, NULL, 0));
expect(-EADDRINUSE == sock_udp_create(&_sock2, &local, NULL, 0));
}
static void test_sock_udp_create__EAFNOSUPPORT(void)
{
/* port may not be NULL according to doc */
static const sock_udp_ep_t local = { .family = AF_UNSPEC,
.port = _TEST_PORT_LOCAL };
/* port may not be NULL according to doc */
static const sock_udp_ep_t remote = { .family = AF_UNSPEC,
.port = _TEST_PORT_REMOTE };
expect(-EAFNOSUPPORT ==
sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(-EAFNOSUPPORT ==
sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
}
static void test_sock_udp_create__EINVAL_addr(void)
{
/* port may not be NULL according to doc */
static const sock_udp_ep_t local =
{ .family = AF_INET6, .netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
/* port may not be NULL according to doc */
static const sock_udp_ep_t remote = { .family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_REMOTE };
expect(-EINVAL ==
sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
}
static void test_sock_udp_create__EINVAL_netif(void)
{
/* port may not be NULL according to doc */
static const sock_udp_ep_t local_1 =
{ .family = AF_INET6, .netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
/* port may not be NULL according to doc */
static const sock_udp_ep_t remote = { .family = AF_INET6,
.netif = (_TEST_NETIF + 1),
.port = _TEST_PORT_REMOTE,
.addr =
{ .ipv6 = _TEST_ADDR_REMOTE } };
expect(-EINVAL ==
sock_udp_create(&_sock, &local_1, &remote, SOCK_FLAGS_REUSE_EP));
static const sock_udp_ep_t local_2 = { .family = AF_INET6,
.netif = _TEST_NETIF + 1,
.port = _TEST_PORT_LOCAL };
expect(-EINVAL ==
sock_udp_create(&_sock, &local_2, &remote, SOCK_FLAGS_REUSE_EP));
}
static void test_sock_udp_create__no_endpoints(void)
{
sock_udp_ep_t ep;
expect(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
expect(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep));
expect(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
}
static void test_sock_udp_create__only_local(void)
{
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
sock_udp_ep_t ep;
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(0 == sock_udp_get_local(&_sock, &ep));
expect(AF_INET6 == ep.family);
expect(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
sizeof(ipv6_addr_t)) == 0);
expect(SOCK_ADDR_ANY_NETIF == ep.netif);
expect(_TEST_PORT_LOCAL == ep.port);
expect(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
}
static void test_sock_udp_create__only_local_port0(void)
{
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = 0U };
sock_udp_ep_t ep;
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(0 == sock_udp_get_local(&_sock, &ep));
expect(AF_INET6 == ep.family);
expect(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
sizeof(ipv6_addr_t)) == 0);
expect(SOCK_ADDR_ANY_NETIF == ep.netif);
expect(0U != ep.port);
expect(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
}
static void test_sock_udp_create__only_local_reuse_ep(void)
{
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
sock_udp_ep_t ep, ep2;
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(0 == sock_udp_create(&_sock2, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(0 == sock_udp_get_local(&_sock, &ep));
expect(0 == sock_udp_get_local(&_sock2, &ep2));
expect(AF_INET6 == ep.family);
expect(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
sizeof(ipv6_addr_t)) == 0);
expect(SOCK_ADDR_ANY_NETIF == ep.netif);
expect(_TEST_PORT_LOCAL == ep.port);
expect(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
expect(AF_INET6 == ep2.family);
expect(memcmp(&ipv6_addr_unspecified, &ep2.addr.ipv6,
sizeof(ipv6_addr_t)) == 0);
expect(SOCK_ADDR_ANY_NETIF == ep2.netif);
expect(_TEST_PORT_LOCAL == ep2.port);
expect(-ENOTCONN == sock_udp_get_remote(&_sock, &ep2));
sock_udp_close(&_sock2);
}
static void test_sock_udp_create__only_remote(void)
{
static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .family = AF_INET6,
.port = _TEST_PORT_REMOTE,
.addr =
{ .ipv6 = _TEST_ADDR_REMOTE } };
sock_udp_ep_t ep;
expect(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
expect(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep));
expect(0 == sock_udp_get_remote(&_sock, &ep));
expect(AF_INET6 == ep.family);
expect(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
expect(SOCK_ADDR_ANY_NETIF == ep.netif);
expect(_TEST_PORT_REMOTE == ep.port);
}
static void test_sock_udp_create__full(void)
{
static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t local =
{ .family = AF_INET6, .netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .family = AF_INET6,
.port = _TEST_PORT_REMOTE,
.addr =
{ .ipv6 = _TEST_ADDR_REMOTE } };
sock_udp_ep_t ep;
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(0 == sock_udp_get_local(&_sock, &ep));
expect(AF_INET6 == ep.family);
expect(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
sizeof(ipv6_addr_t)) == 0);
expect(_TEST_NETIF == ep.netif);
expect(_TEST_PORT_LOCAL == ep.port);
expect(0 == sock_udp_get_remote(&_sock, &ep));
expect(AF_INET6 == ep.family);
expect(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
expect(SOCK_ADDR_ANY_NETIF == ep.netif);
expect(_TEST_PORT_REMOTE == ep.port);
}
static void test_sock_udp_recv__EADDRNOTAVAIL(void)
{
expect(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
expect(-EADDRNOTAVAIL == sock_udp_recv(&_sock, _test_buffer,
sizeof(_test_buffer),
SOCK_NO_TIMEOUT, NULL));
}
static void test_sock_udp_recv__EAGAIN(void)
{
static const sock_udp_ep_t local =
{ .family = AF_INET6, .netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(-EAGAIN == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer),
0, NULL));
}
static void test_sock_udp_recv__ENOBUFS(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
_TEST_NETIF));
expect(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT,
NULL));
expect(_check_net());
}
static void test_sock_udp_recv__EPROTO(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_WRONG };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
_TEST_NETIF));
expect(-EPROTO == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer),
SOCK_NO_TIMEOUT, NULL));
expect(_check_net());
}
static void test_sock_udp_recv__ETIMEDOUT(void)
{
static const sock_udp_ep_t local =
{ .family = AF_INET6, .netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
puts(" * Calling sock_udp_recv()");
expect(-ETIMEDOUT == sock_udp_recv(&_sock, _test_buffer,
sizeof(_test_buffer), _TEST_TIMEOUT,
NULL));
printf(" * (timed out with timeout %lu)\n", (long unsigned)_TEST_TIMEOUT);
}
static void test_sock_udp_recv__socketed(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
static uint8_t test_data[] = "ABCD";
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT,
NULL);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(_check_net());
}
static void test_sock_udp_recv__socketed_with_remote(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
static uint8_t test_data[] = "ABCD";
sock_udp_ep_t result;
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT,
&result);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_PORT_REMOTE == result.port);
expect(_TEST_NETIF == result.netif);
expect(_check_net());
}
static void test_sock_udp_recv__socketed_with_port0(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static sock_udp_ep_t local = { .family = AF_INET6, .port = 0 };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
static uint8_t test_data[] = "ABCD";
sock_udp_ep_t result;
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(0 == sock_udp_get_local(&_sock, &local));
expect(0 != local.port);
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
local.port, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT,
&result);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_PORT_REMOTE == result.port);
expect(_TEST_NETIF == result.netif);
expect(_check_net());
}
static void test_sock_udp_recv__unsocketed(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static uint8_t test_data[] = "ABCD";
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT,
NULL);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(_check_net());
}
static void test_sock_udp_recv__unsocketed_with_remote(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static uint8_t test_data[] = "ABCD";
sock_udp_ep_t result;
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), SOCK_NO_TIMEOUT,
&result);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_PORT_REMOTE == result.port);
expect(_TEST_NETIF == result.netif);
expect(_check_net());
}
static void test_sock_udp_recv__with_timeout(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static uint8_t test_data[] = "ABCD";
sock_udp_ep_t result;
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), _TEST_TIMEOUT,
&result);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_PORT_REMOTE == result.port);
expect(_TEST_NETIF == result.netif);
expect(_check_net());
}
static void test_sock_udp_recv__non_blocking(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static uint8_t test_data[] = "ABCD";
sock_udp_ep_t result;
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), 0, &result);
expect(memcmp(test_data, _test_buffer, sizeof(test_data)) == 0);
expect(AF_INET6 == result.family);
expect(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
expect(_TEST_PORT_REMOTE == result.port);
expect(_TEST_NETIF == result.netif);
expect(_check_net());
}
static void test_sock_udp_recv_buf__success(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
static const sock_udp_ep_t local = { .family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
static uint8_t test_data[] = "ABCD";
void *data = NULL, *ctx = NULL;
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
_TEST_PORT_LOCAL, &test_data, sizeof(test_data),
_TEST_NETIF));
sock_udp_recv_buf(&_sock, &data, &ctx, SOCK_NO_TIMEOUT, NULL);
expect(data != NULL);
expect(memcmp(test_data, data, sizeof(test_data)) == 0);
expect(ctx != NULL);
expect(0 == sock_udp_recv_buf(&_sock, &data, &ctx, SOCK_NO_TIMEOUT, NULL));
expect(data == NULL);
expect(ctx == NULL);
expect(_check_net());
}
static void test_sock_udp_send__EAFNOSUPPORT(void)
{
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET,
.port = _TEST_PORT_REMOTE };
expect(-EAFNOSUPPORT == sock_udp_send(NULL, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_net());
}
static void test_sock_udp_send__EINVAL_addr(void)
{
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE,
.netif = _TEST_NETIF };
static const sock_udp_ep_t remote = { .family = AF_INET6,
.port = _TEST_PORT_REMOTE,
.netif = _TEST_NETIF };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(-EINVAL == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), &remote));
expect(_check_net());
}
static void test_sock_udp_send__EINVAL_netif(void)
{
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE,
.netif = _TEST_NETIF };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE,
.netif = _TEST_NETIF + 1 };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(-EINVAL == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), &remote));
expect(_check_net());
}
static void test_sock_udp_send__EINVAL_port(void)
{
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6 };
expect(-EINVAL == sock_udp_send(NULL, "ABCD", sizeof("ABCD"), &remote));
expect(_check_net());
}
static void test_sock_udp_send__ENOTCONN(void)
{
expect(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
expect(-ENOTCONN == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), NULL));
expect(_check_net());
}
static void test_sock_udp_send__socketed_no_local_no_netif(void)
{
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
NULL));
expect(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
SOCK_ADDR_ANY_NETIF, true));
expect(_check_net());
}
static void test_sock_udp_send__socketed_no_netif(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
NULL));
expect(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
SOCK_ADDR_ANY_NETIF, false));
expect(_check_net());
}
static void test_sock_udp_send__socketed_no_local(void)
{
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
NULL));
expect(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), _TEST_NETIF,
true));
expect(_check_net());
}
static void test_sock_udp_send__socketed(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
NULL));
expect(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
_TEST_NETIF, false));
expect(_check_net());
}
static void test_sock_udp_send__socketed_other_remote(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t sock_remote =
{ .addr = { .ipv6 = _TEST_ADDR_WRONG },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE +
_TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 ==
sock_udp_create(&_sock, &local, &sock_remote, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
_TEST_NETIF, false));
expect(_check_net());
}
static void test_sock_udp_send__unsocketed_no_local_no_netif(void)
{
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
SOCK_ADDR_ANY_NETIF, true));
expect(_check_net());
}
static void test_sock_udp_send__unsocketed_no_netif(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
SOCK_ADDR_ANY_NETIF, false));
expect(_check_net());
}
static void test_sock_udp_send__unsocketed_no_local(void)
{
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), _TEST_NETIF,
true));
expect(_check_net());
}
static void test_sock_udp_send__unsocketed(void)
{
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
.family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_LOCAL };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
expect(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
_TEST_NETIF, false));
expect(_check_net());
}
static void test_sock_udp_send__no_sock_no_netif(void)
{
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.port = _TEST_PORT_REMOTE };
expect(sizeof("ABCD") == sock_udp_send(NULL, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
SOCK_ADDR_ANY_NETIF, true));
expect(_check_net());
}
static void test_sock_udp_send__no_sock(void)
{
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
.family = AF_INET6,
.netif = _TEST_NETIF,
.port = _TEST_PORT_REMOTE };
expect(sizeof("ABCD") == sock_udp_send(NULL, "ABCD", sizeof("ABCD"),
&remote));
expect(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
_TEST_NETIF, true));
expect(_check_net());
}
int main(void)
{
_net_init();
tear_down();
CALL(test_sock_udp_create__EADDRINUSE());
CALL(test_sock_udp_create__EAFNOSUPPORT());
CALL(test_sock_udp_create__EINVAL_addr());
CALL(test_sock_udp_create__EINVAL_netif());
CALL(test_sock_udp_create__no_endpoints());
CALL(test_sock_udp_create__only_local());
CALL(test_sock_udp_create__only_local_port0());
CALL(test_sock_udp_create__only_local_reuse_ep());
CALL(test_sock_udp_create__only_remote());
CALL(test_sock_udp_create__full());
/* sock_udp_close() is tested in tear_down() */
/* sock_udp_get_local() is tested in sock_udp_create() tests */
/* sock_udp_get_remote() is tested in sock_udp_create() tests */
CALL(test_sock_udp_recv__EADDRNOTAVAIL());
CALL(test_sock_udp_recv__EAGAIN());
CALL(test_sock_udp_recv__ENOBUFS());
CALL(test_sock_udp_recv__EPROTO());
CALL(test_sock_udp_recv__ETIMEDOUT());
CALL(test_sock_udp_recv__socketed());
CALL(test_sock_udp_recv__socketed_with_remote());
CALL(test_sock_udp_recv__socketed_with_port0());
CALL(test_sock_udp_recv__unsocketed());
CALL(test_sock_udp_recv__unsocketed_with_remote());
CALL(test_sock_udp_recv__with_timeout());
CALL(test_sock_udp_recv__non_blocking());
CALL(test_sock_udp_recv_buf__success());
CALL(test_sock_udp_send__EAFNOSUPPORT());
CALL(test_sock_udp_send__EINVAL_addr());
CALL(test_sock_udp_send__EINVAL_netif());
CALL(test_sock_udp_send__EINVAL_port());
CALL(test_sock_udp_send__ENOTCONN());
CALL(test_sock_udp_send__socketed_no_local_no_netif());
CALL(test_sock_udp_send__socketed_no_netif());
CALL(test_sock_udp_send__socketed_no_local());
CALL(test_sock_udp_send__socketed());
CALL(test_sock_udp_send__socketed_other_remote());
CALL(test_sock_udp_send__unsocketed_no_local_no_netif());
CALL(test_sock_udp_send__unsocketed_no_netif());
CALL(test_sock_udp_send__unsocketed_no_local());
CALL(test_sock_udp_send__unsocketed());
CALL(test_sock_udp_send__no_sock_no_netif());
CALL(test_sock_udp_send__no_sock());
puts("ALL TESTS SUCCESSFUL");
return 0;
}

View File

@ -0,0 +1,3 @@
MODULE := openwsn_scheduler_mock
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,3 @@
# Use an immediate variable to evaluate `MAKEFILE_LIST` now
USEMODULE_INCLUDES_openwsn_scheduler_mock := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_openwsn_scheduler_mock)

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2020 Inria
*
* 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.
*/
/**
* @ingroup pkg_openwsn
* @{
*
*
* @file
* @brief RIOT mock scheduler types variable declaration
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#ifndef SCHEDULER_TYPES_H
#define SCHEDULER_TYPES_H
#include "scheduler.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief OpenWSN scheduler variables structure
*/
typedef struct {
uint8_t last_task;
} scheduler_vars_t;
#ifdef __cplusplus
}
#endif
#endif /* SCHEDULER_TYPES_H */

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2020 Inria
*
* 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.
*/
/**
* @ingroup pkg_openwsn
* @{
*
* @file
* @brief OpenWSN scheduler mock
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#include "scheduler.h"
scheduler_vars_t scheduler_mock_vars;
void scheduler_init(void)
{
/* nothing to do here */
scheduler_mock_vars.last_task = TASKPRIO_NONE;
}
void scheduler_start(unsigned state)
{
irq_restore(state);
}
void scheduler_push_task(task_cbt cb, task_prio_t prio)
{
(void) cb;
scheduler_mock_vars.last_task = prio;
}

View File

@ -0,0 +1,152 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
* 2020 Inria
*
* 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.
*/
/**
* @ingroup tests
* @{
*
* @file
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "net/ipv6/addr.h"
#include "openwsn.h"
#include "cross-layers/openqueue.h"
#include "cross-layers/openrandom.h"
#include "cross-layers/packetfunctions.h"
#include "cross-layers/idmanager.h"
#include "04-TRAN/udp.h"
#include "04-TRAN/sock_internal.h"
#include "02a-MAClow/IEEE802154E.h"
#include "scheduler.h"
#include "constants.h"
extern openqueue_vars_t openqueue_vars;
extern ieee154e_vars_t ieee154e_vars;
extern scheduler_vars_t scheduler_mock_vars;
extern void sock_udp_init(void);
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
uint16_t src_port, uint16_t dst_port,
void *data, size_t data_len, uint16_t netif)
{
(void) netif;
OpenQueueEntry_t *pkt;
if ((pkt = openqueue_getFreePacketBuffer(COMPONENT_UDP_TO_SOCK)) == NULL) {
return false;
}
pkt->owner = COMPONENT_UDP_TO_SOCK;
pkt->creator = COMPONENT_UDP_TO_SOCK;
/* set address*/
pkt->l3_destinationAdd.type = ADDR_128B;
pkt->l3_sourceAdd.type = ADDR_128B;
memcpy(&pkt->l3_destinationAdd.addr_128b, dst, LENGTH_ADDR128b);
memcpy(&pkt->l3_sourceAdd.addr_128b, src, LENGTH_ADDR128b);
/* set port */
pkt->l4_destination_port = dst_port;
pkt->l4_sourcePortORicmpv6Type = src_port;
/* set payload */
if (packetfunctions_reserveHeader(&pkt, data_len)) {
return false;
}
memcpy(pkt->payload, data, data_len);
pkt->l4_payload = pkt->payload;
pkt->l4_length = pkt->length;
/* set remaining fields */
pkt->l4_protocol_compressed = FALSE;
pkt->l4_protocol = IANA_UDP;
packetfunctions_reserveHeader(&pkt, sizeof(udp_ht));
packetfunctions_htons(pkt->l4_sourcePortORicmpv6Type, &(pkt->payload[0]));
packetfunctions_htons(pkt->l4_destination_port, &(pkt->payload[2]));
packetfunctions_htons(pkt->length, &(pkt->payload[4]));
packetfunctions_calculateChecksum(pkt,
(uint8_t * )&(((udp_ht *)pkt->payload)->
checksum));
/* set ID to match destination */
open_addr_t addr;
addr.type = ADDR_PREFIX;
memcpy(&addr.prefix, &dst->u8[0], sizeof(addr.prefix));
idmanager_setMyID(&addr);
addr.type = ADDR_64B;
memcpy(&addr.addr_64b, &dst->u8[8], sizeof(addr.addr_64b));
idmanager_setMyID(&addr);
/* mock receive push pkt to mailbox */
sock_receive_internal();
return true;
}
void _net_init(void)
{
openrandom_init();
openqueue_init();
sock_udp_init();
scheduler_init();
ieee154e_vars.isSync = true;
}
bool _check_net(void)
{
/* queue must me empty */
for (uint8_t i = 0; i < QUEUELENGTH; i++) {
if (openqueue_vars.queue[i].owner != COMPONENT_NULL) {
return false;
}
}
return true;
}
bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
uint16_t src_port, uint16_t dst_port,
void *data, size_t data_len, uint16_t netif,
bool random_src_port)
{
/* get packet from queue, there should be one! */
OpenQueueEntry_t *pkt;
pkt = openqueue_getPacketByComponent(COMPONENT_SOCK_TO_UDP);
if (pkt == NULL) {
return false;
}
/* check that UDP task was pushed */
if (scheduler_mock_vars.last_task != TASKPRIO_UDP) {
return false;
}
/* ignore checking the interface, there is only one possible interface*/
(void)netif;
/* check data matches, won't check the formed pkg its assumed that
OpenWSN writes this correctly to the payload buffer */
int ret = 0;
ret =
((memcmp(src, &pkt->l3_sourceAdd.addr_128b,
sizeof(ipv6_addr_t)) == 0) &&
(memcmp(dst, &pkt->l3_destinationAdd.addr_128b,
sizeof(ipv6_addr_t)) == 0) &&
(dst_port == pkt->l4_destination_port) &&
(random_src_port || (src_port == pkt->l4_sourcePortORicmpv6Type)) &&
(memcmp(data, pkt->l4_payload, data_len) == 0));
openqueue_freePacketBuffer(pkt);
return ret;
}

View File

@ -0,0 +1,88 @@
/*
* 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.
*/
/**
* @ingroup tests
* @brief
* @{
*
* @file
* @brief
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @}
*/
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
#include <stdint.h>
#include "net/ipv6/addr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initializes networking for tests
*/
void _net_init(void);
/**
* @brief Injects a received UDP packet into the stack
*
* @param[in] src The source address of the UDP packet
* @param[in] dst The destination address of the UDP packet
* @param[in] src_port The source port of the UDP packet
* @param[in] dst_port The destination port of the UDP packet
* @param[in] data The payload of the UDP packet
* @param[in] data_len The payload length of the UDP packet
* @param[in] netif The interface the packet came over, currently ignored
*
* @return true, if packet was successfully injected
* @return false, if an error occurred during injection
*/
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
uint16_t src_port, uint16_t dst_port,
void *data, size_t data_len, uint16_t netif);
/**
* @brief Checks networking state (e.g. packet buffer state)
*
* @return true, if networking component is still in valid state
* @return false, if networking component is in an invalid state
*/
bool _check_net(void);
/**
* @brief Checks if a UDP packet was sent by the networking component
*
* @param[in] src Expected source address of the UDP packet
* @param[in] dst Expected destination address of the UDP packet
* @param[in] src_port Expected source port of the UDP packet
* @param[in] dst_port Expected destination port of the UDP packet
* @param[in] data Expected payload of the UDP packet
* @param[in] data_len Expected payload length of the UDP packet
* @param[in] netif Expected interface the packet is supposed to
* be send over
* @param[in] random_src_port Do not check source port, it might be random
*
* @return true, if all parameters match as expected
* @return false, if not.
*/
bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
uint16_t src_port, uint16_t dst_port,
void *data, size_t data_len, uint16_t netif,
bool random_src_port);
#ifdef __cplusplus
}
#endif
#endif /* STACK_H */

View File

@ -0,0 +1,56 @@
#!/usr/bin/env python3
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
#
# 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.
import sys
from testrunner import run
def testfunc(child):
child.expect_exact(u"Calling test_sock_udp_create__EADDRINUSE()")
child.expect_exact(u"Calling test_sock_udp_create__EAFNOSUPPORT()")
child.expect_exact(u"Calling test_sock_udp_create__EINVAL_addr()")
child.expect_exact(u"Calling test_sock_udp_create__EINVAL_netif()")
child.expect_exact(u"Calling test_sock_udp_create__no_endpoints()")
child.expect_exact(u"Calling test_sock_udp_create__only_local()")
child.expect_exact(u"Calling test_sock_udp_create__only_local_reuse_ep()")
child.expect_exact(u"Calling test_sock_udp_create__only_remote()")
child.expect_exact(u"Calling test_sock_udp_create__full()")
child.expect_exact(u"Calling test_sock_udp_recv__EADDRNOTAVAIL()")
child.expect_exact(u"Calling test_sock_udp_recv__EAGAIN()")
child.expect_exact(u"Calling test_sock_udp_recv__ENOBUFS()")
child.expect_exact(u"Calling test_sock_udp_recv__EPROTO()")
child.expect_exact(u"Calling test_sock_udp_recv__ETIMEDOUT()")
child.expect_exact(u" * Calling sock_udp_recv()")
child.expect(r" \* \(timed out with timeout \d+\)")
child.expect_exact(u"Calling test_sock_udp_recv__socketed()")
child.expect_exact(u"Calling test_sock_udp_recv__socketed_with_remote()")
child.expect_exact(u"Calling test_sock_udp_recv__unsocketed()")
child.expect_exact(u"Calling test_sock_udp_recv__unsocketed_with_remote()")
child.expect_exact(u"Calling test_sock_udp_recv__with_timeout()")
child.expect_exact(u"Calling test_sock_udp_recv__non_blocking()")
child.expect_exact(u"Calling test_sock_udp_send__EAFNOSUPPORT()")
child.expect_exact(u"Calling test_sock_udp_send__EINVAL_addr()")
child.expect_exact(u"Calling test_sock_udp_send__EINVAL_netif()")
child.expect_exact(u"Calling test_sock_udp_send__EINVAL_port()")
child.expect_exact(u"Calling test_sock_udp_send__ENOTCONN()")
child.expect_exact(u"Calling test_sock_udp_send__socketed_no_local_no_netif()")
child.expect_exact(u"Calling test_sock_udp_send__socketed_no_netif()")
child.expect_exact(u"Calling test_sock_udp_send__socketed_no_local()")
child.expect_exact(u"Calling test_sock_udp_send__socketed()")
child.expect_exact(u"Calling test_sock_udp_send__socketed_other_remote()")
child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_local_no_netif()")
child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_netif()")
child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_local()")
child.expect_exact(u"Calling test_sock_udp_send__unsocketed()")
child.expect_exact(u"Calling test_sock_udp_send__no_sock_no_netif()")
child.expect_exact(u"Calling test_sock_udp_send__no_sock()")
child.expect_exact(u"ALL TESTS SUCCESSFUL")
if __name__ == "__main__":
sys.exit(run(testfunc))