mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
tests/pkg_openwsn: initial import
Co-authored-by: Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
This commit is contained in:
parent
844ccfbeb3
commit
985a706733
67
tests/pkg_openwsn/Makefile
Normal file
67
tests/pkg_openwsn/Makefile
Normal file
@ -0,0 +1,67 @@
|
||||
BOARD ?= iotlab-m3
|
||||
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# list of arm boards that provide at86rf2xx radios, can't require it so
|
||||
# add whitelist
|
||||
BOARD_WHITELIST = \
|
||||
fox \
|
||||
iotlab-m3 \
|
||||
iotlab-a8-m3 \
|
||||
samr21-xpro \
|
||||
samr30-xpro \
|
||||
#
|
||||
|
||||
## OpenWSN Modules
|
||||
USEPKG += openwsn
|
||||
USEMODULE += openwsn_openstack
|
||||
USEMODULE += openwsn_scheduler
|
||||
|
||||
# Optional Module required for root nodes
|
||||
# USEMODULE += openwsn_serial
|
||||
|
||||
# Optional Modules
|
||||
USEMODULE += openwsn_leds
|
||||
USEMODULE += openwsn_debugpins
|
||||
|
||||
ifneq (,$(filter openwsn_serial,$(USEMODULE)))
|
||||
# Uncomment to use STDIO_UART_DEV as the uart for OpenWSN openserial
|
||||
# USEMODULE += stdio_null
|
||||
ifneq (,$(filter iotlab-m3 iotlab-a8-m3,$(BOARD)))
|
||||
USEMODULE += stdio_null
|
||||
endif
|
||||
# OpenWSN serial module can't handle data at more than 115200 bauds/s,
|
||||
# depending on the platform this might be even lower (e.g. 57600 bauds
|
||||
# for iotlab-m3, 19200 for samr21-xpro).
|
||||
# NOTE: baudrate can'y be changed when testing over IotLab.
|
||||
OPENSERIAL_BAUD ?=
|
||||
ifneq (,$(OPENSERIAL_BAUD))
|
||||
CFLAGS += -DOPENWSN_UART_BAUDRATE=$(OPENSERIAL_BAUD)
|
||||
ifneq (,$(filter stdio_null,$(USEMODULE)))
|
||||
BAUD ?= $(OPENSERIAL_BAUD)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# To enable debugging prints on OpenWSN code
|
||||
# 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
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
# We want the highest possible frequency set for periph_rtt, but not all
|
||||
# platforms can configure this value. use highest possible RTT_FREQUENCY
|
||||
# for platforms that allow it
|
||||
ifneq (,$(filter stm32,$(CPU)))
|
||||
RTT_FREQUENCY ?= RTT_MAX_FREQUENCY
|
||||
CFLAGS += -DRTT_FREQUENCY=$(RTT_FREQUENCY)
|
||||
endif
|
316
tests/pkg_openwsn/README.md
Normal file
316
tests/pkg_openwsn/README.md
Normal file
@ -0,0 +1,316 @@
|
||||
# OpenWSN on RIOT
|
||||
|
||||
This test demonstrates the [OpenWSN](https://github.com/openwsn-berkeley/openwsn-fw) full
|
||||
stack (UDP, IPv6, RPL, 6TiSCH) running on RIOT. When flashed, it will initialize the stack
|
||||
and provide the user with some minimal shell commands to:
|
||||
|
||||
- print the own IPv6 address `ifconfig`
|
||||
- change the UDP destination port `udp server start <port>`
|
||||
- send a UDP packet `udp send <addr> <port> <data>`
|
||||
|
||||
A tun interface can also be set to allow traffic out of the network. This
|
||||
allows pinging nodes in the network from the host.
|
||||
|
||||
Please note that this port is still in experimental status. For further information
|
||||
about the port refer to the [pkg documentation](../../pkg/openwsn/doc.txt).
|
||||
|
||||
## Experimental setups
|
||||
|
||||
The following setup act as a starting point for testing and debugging. Either
|
||||
build and flash local nodes or incorporate the [FIT IoT-LAB](https://www.iot-lab.info/)
|
||||
Testbed. Please check the ports [documentation](../../pkg/openwsn/doc.txt) for information
|
||||
about supported hardware platforms.
|
||||
|
||||
This port currently needs `openvisualizer`, please make sure you follow the
|
||||
[pre-requisites](../../dist/tools/openvisualizer/makefile.openvisualizer.inc.mk)
|
||||
to install a patched version of `openvisualizer`.
|
||||
|
||||
An OpenWSN root node acts as a border router, it tunnels IEEE80215.4.E
|
||||
between `openvisualizer` and the network without looking at the frame content.
|
||||
This means that a root node will not be reachable when 'pinging' from the host
|
||||
or if trying to send udp packets to it.
|
||||
|
||||
Two test cases are described with different requirements:
|
||||
|
||||
1. From host [ping](#Communicating-with-host-(IPV6)) nodes in network over ipv6:
|
||||
```
|
||||
- 1 root node + tun interface
|
||||
- +1 leaf node
|
||||
```
|
||||
|
||||
2. Sending [UDP](#Communicating-over-udp) packets between nodes:
|
||||
```
|
||||
- 1 root node
|
||||
- +2 leaf node
|
||||
```
|
||||
|
||||
### Synchronization
|
||||
|
||||
There are 3 things that can be done to speed up and help nodes synchronization,
|
||||
all related to how often a node will receive an EB (enhanced beacon).
|
||||
|
||||
- disable channel hopping
|
||||
- increase EB_PORTION
|
||||
- reduce SLOTFRAME_LENGTH
|
||||
|
||||
If you want to disable channel hopping to speed up synchronization you can set
|
||||
a fix channel.
|
||||
|
||||
$ export CFLAGS=-DIEEE802154E_SINGLE_CHANNEL=17
|
||||
|
||||
Enhanced beacon are sent once per slotframe with a likelihood of 1/EB_PORTION.
|
||||
The default value is EB_PORTION = 10 (10%), reducing the value of EB_PORTION
|
||||
increases the frequency at which beacons are sent, this will also help nodes
|
||||
to stay synchronized.
|
||||
|
||||
$ export CFLAGS=-DEB_PORTION=4
|
||||
|
||||
EB gets an opportunity to be sent (depending on 1/EB_PORTION) once in every
|
||||
slotframe, reducing the soltframe length will cause EB to be sent more often.
|
||||
Beware that this could have an impact on the MSF (Minimal Scheduling Function).
|
||||
|
||||
$ export CFLAGS=-DSLOTFRAME_LENGTH=51
|
||||
|
||||
See [documentation](../../pkg/openwsn/doc.txt#Synchronization) for more on
|
||||
synchronization.
|
||||
|
||||
## IMPORTANT!
|
||||
|
||||
OpenWSN uses source routing and this means all network traffic must go through
|
||||
from the root node to OpenVisualizer. If the root node configuration can't
|
||||
handle the configured baudrate correctly this will lead to packet loss.
|
||||
|
||||
Currently these are the tested configurations:
|
||||
|
||||
(a) samr21-xpro network:
|
||||
- leaf nodes using `openwsn_sctimer_rtt`
|
||||
- root node using `openwsn_sctimer_rtt` and 19200 baudrate directly
|
||||
connected to UART pins (not through the usb debugger)
|
||||
|
||||
(b) iotlab-m3 network:
|
||||
- leaf nodes using `openwsn_sctimer_rtt` or `sctimer_ztimer`
|
||||
- root node using `openwsn_sctimer_rtt` and 57600 baudrate
|
||||
|
||||
For more details on this please refer to [pkg documentation](../../pkg/openwsn/doc.txt).
|
||||
|
||||
## Testing configuration (a) (three local samr21-xpro nodes)
|
||||
|
||||
1. figure out each node's serial number (`edbg -l` output might help)
|
||||
2. hook up the root node to an external USB-serial-converter. For that, connect
|
||||
the converter's RXD/TXD pins to the node's PA22/PA23.
|
||||
3. flash the root node:
|
||||
|
||||
$ SERIAL=${ROOT_SERIAL_NODE} OPENSERIAL_BAUD=19200 USEMODULE=openwsn_serial \
|
||||
BOARD=samr21-xpro make flash -j4
|
||||
|
||||
4. flash the leaf nodes:
|
||||
|
||||
$ BOARD=samr21-xpro make all -j4
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE0} make flash-only
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE1} make flash-only
|
||||
|
||||
5. open a shell to the leaf nodes
|
||||
so in two shell windows, do (one in each):
|
||||
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE0} make term
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE1} make term
|
||||
|
||||
6. in a third shell, launch openvisualizer:
|
||||
|
||||
$ BOARD=samr21-xpro PORT=<USB-serial-port, e.g., /dev/ttyUSB0> BAUD=19200 \
|
||||
make openv-termroot
|
||||
|
||||
## Testing configuration (b) (iotlab-m3 network on iotlab)
|
||||
|
||||
When using OpenVisualizer over iot-lab an ssh-tunnel is opened to connect to the
|
||||
IoT-LAB motes' TCP port. For this to work you will need:
|
||||
|
||||
- A valid IoT-LAB [account](https://www.iot-lab.info/testbed/signup)
|
||||
- Authenticate locally to IoT-LAB `$ iotlab-auth -u <login>`
|
||||
|
||||
1. Launch an experiment booking 3+ `iotlab-m3` nodes:
|
||||
|
||||
$ iotlab-experiment submit -d 120 -l 3,archi=m3:at86rf231+site=saclay
|
||||
$ iotlab-experiment wait
|
||||
$ iotlab-experiment get --nodes
|
||||
|
||||
Since multiple nodes where configured for the experiment `IOTLAB_NODE` needs
|
||||
to be specified for every node, `IOTLAB_NODE=m3-%.saclay.iot-lab.info`
|
||||
|
||||
2. flash the root node
|
||||
|
||||
$ IOTLAB_NODE=${ROOT_IOTLAB_NODE} USEMODULE=openwsn_serial \
|
||||
BOARD=iotlab-m3 make -C tests/pkg_openwsn flash
|
||||
|
||||
3. open a shell to the leaf nodes so in two shell windows, do (one in each):
|
||||
$ BOARD=iotlab-m3 make -C tests/pkg_openwsn all -j4
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE0} make -C tests/pkg_openwsn flash-only
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE1} make -C tests/pkg_openwsn flash-only
|
||||
|
||||
4. open a shell to the leaf nodes
|
||||
so in two shell windows, do (one in each):
|
||||
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE0} make -C tests/pkg_openwsn term
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE1} make -C tests/pkg_openwsn term
|
||||
|
||||
5. in a third shell, launch openvisualizer:
|
||||
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${ROOT_IOTLAB_NODE} make -C tests/pkg_openwsn openv-termroot
|
||||
|
||||
### Network Setup
|
||||
|
||||
If (a) and (b) where followed then on each lead node you should be able
|
||||
to see the ipv6 address:
|
||||
|
||||
main(): This is RIOT! (Version: 2020.04-devel-1649-g96fa9-pr_openwsn)
|
||||
OpenWSN UDP test
|
||||
You are running RIOT on a(n) iotlab-m3 board.
|
||||
This board features a(n) stm32f1 MCU.
|
||||
> ifconfig
|
||||
ifconfig
|
||||
Iface 3 HWaddr: 07:C2 NID: CA:FE
|
||||
|
||||
Long HWaddr: 96:35:9A:92:4E:3D:65:78
|
||||
inet6 addr: fe80::9635:9a92:4e3d:6578
|
||||
|
||||
IEEE802154E sync: 0
|
||||
6TiSCH joined: 0
|
||||
|
||||
NO RPL parent
|
||||
|
||||
|
||||
On the root node Openvisualizer is launched and the DAGroot is setup.
|
||||
|
||||
[OpenVisualizerServer:INFO] Extracting firmware definitions.
|
||||
[Utils:VERBOSE] Extracting firmware component names
|
||||
[Utils:VERBOSE] Extracting firmware log descriptions.
|
||||
[Utils:VERBOSE] Extracting 6top return codes.
|
||||
[Utils:VERBOSE] Extracting 6top states.
|
||||
[OpenVisualizerServer:INFO] Starting RPC server
|
||||
[OpenVisualizerServer:SUCCESS] Setting mote 43eb as root
|
||||
[ParserIEC:ERROR] 43eb [IEEE802154E] wrong state 1 in startSlot, at slotOffset 1
|
||||
[RPL:INFO] registering DAGroot 82-6b-de-ec-58-34-65-78
|
||||
|
||||
The root node will now start sending beacons and other nodes will synchronize, and
|
||||
join. If channel hopping is enabled this can take quite some time (see
|
||||
[Synchronization](../../pkg/openwsn/doc.txt#Synchronization). Once leaf nodes
|
||||
have joined the network when issuing `ifconfing` you should see:
|
||||
|
||||
ifconfig
|
||||
Iface 3 HWaddr: 0F:F4 NID: CA:FE
|
||||
|
||||
Long HWaddr: 06:84:F6:65:10:6B:11:14
|
||||
inet6 addr: bbbb::684:f665:106b:1114
|
||||
|
||||
IEEE802154E sync: 1
|
||||
6TiSCH joined: 1
|
||||
|
||||
RPL rank: 2816
|
||||
RPL parent: 2A:BA:F7:65:10:6B:11:14
|
||||
RPL children:
|
||||
RPL DODAG ID: bbbb::2aba:f765:106b:1114
|
||||
|
||||
|
||||
The root node should start receiving RPL DAOs:
|
||||
|
||||
[RPL:INFO] received RPL DAO from bbbb:0:0:0:ab8:fc65:106b:1114
|
||||
- parents:
|
||||
bbbb:0:0:0:2aba:f765:106b:1114
|
||||
- children:
|
||||
bbbb:0:0:0:684:f665:106b:1114
|
||||
|
||||
[RPL:INFO] received RPL DAO from bbbb:0:0:0:684:f665:106b:1114
|
||||
- parents:
|
||||
bbbb:0:0:0:2aba:f765:106b:1114
|
||||
- children:
|
||||
bbbb:0:0:0:ab8:fc65:106b:1114
|
||||
|
||||
[RPL:INFO] received RPL DAO from bbbb:0:0:0:684:f665:106b:1114
|
||||
- parents:
|
||||
bbbb:0:0:0:2aba:f765:106b:1114
|
||||
- children:
|
||||
bbbb:0:0:0:ab8:fc65:106b:1114
|
||||
|
||||
Once DAOs for all nodes start being received the network is setup and you
|
||||
should be able to send packets between nodes or ping from the host.
|
||||
|
||||
### Communicating over udp
|
||||
|
||||
On one node setup a udp-server:
|
||||
|
||||
> ifconfig
|
||||
ifconfig
|
||||
Iface 3 HWaddr: 0F:F4 NID: CA:FE
|
||||
|
||||
Long HWaddr: 06:84:F6:65:10:6B:11:14
|
||||
inet6 addr: bbbb::684:f665:106b:1114
|
||||
|
||||
IEEE802154E sync: 1
|
||||
6TiSCH joined: 1
|
||||
|
||||
RPL rank: 2816
|
||||
RPL parent: 2A:BA:F7:65:10:6B:11:14
|
||||
RPL children:
|
||||
RPL DODAG ID: bbbb::2aba:f765:106b:1114
|
||||
> udp server start 3000
|
||||
udp server start 3000
|
||||
Set UDP server port to 3000
|
||||
|
||||
On the other node send udp messages
|
||||
|
||||
> udp send bbbb::684:f665:106b:1114 3000 hello
|
||||
udp send bbbb::684:f665:106b:1114 3000 hello
|
||||
Send 5 byte over UDP to [bbbb::684:f665:106b:1114]:3000
|
||||
> msg.l2_sendDoneError: 0
|
||||
Send success
|
||||
|
||||
The first node should receive the message
|
||||
|
||||
> Received 12 bytes on port 3000
|
||||
00000000 A6 28 00 00 00 02 00 68 65 6C 6C 6F .(.....hello
|
||||
|
||||
### Communicating with host (IPV6)
|
||||
|
||||
OpenVisualizer can set up a tun interface to communicate with the host computer.
|
||||
This will require starting `OpenVisualizer` with root privileges. The only
|
||||
difference with the previous setup is that the root node must be setup as
|
||||
follows:
|
||||
|
||||
on iotlab:
|
||||
$ IOTLAB_NODE=${ROOT_IOTLAB_NODE} BOARD=iotlab-m3 \
|
||||
make -C tests/pkg_openwsn openv-termtun
|
||||
|
||||
on local boards:
|
||||
$ PORT=<USB-serial-port, e.g., /dev/ttyUSB0> BOARD=samr21-xpro \
|
||||
make -C tests/pkg_openwsn openv-termtun
|
||||
|
||||
Once DAOs are received you can ping nodes in the network from your host:
|
||||
|
||||
```
|
||||
$ ping6 -s 40 -i 5 bbbb:0:0:0:2ab5:fc65:106b:1114
|
||||
PING bbbb:0:0:0:2ab5:fc65:106b:1114(bbbb::2ab5:fc65:106b:1114) 40 data bytes
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=1 ttl=64 time=1064 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=2 ttl=64 time=2111 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=3 ttl=64 time=1141 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=4 ttl=64 time=2197 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=5 ttl=64 time=1228 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=6 ttl=64 time=2306 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=7 ttl=64 time=1324 ms
|
||||
|
||||
```
|
||||
|
||||
If openserial is used on the leaf node you would get the following output:
|
||||
|
||||
```
|
||||
16:02:38 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
16:02:44 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
16:02:48 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
16:02:54 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
```
|
||||
|
||||
Some considerations:
|
||||
- Nodes duty cycle is ~0.5%, so nodes get a chance to transmit roughly every
|
||||
2s, so the worst case scenario is ~4s RTT. This is increased for big payloads
|
||||
since it will lead to fragmentation.
|
||||
- If incoming packet rate is too fast the internal packet queue can be
|
||||
be overloaded.
|
324
tests/pkg_openwsn/main.c
Normal file
324
tests/pkg_openwsn/main.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Hamburg University of Applied Sciences
|
||||
*
|
||||
* 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 OpenWSN test application
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "od.h"
|
||||
#include "fmt.h"
|
||||
#include "shell.h"
|
||||
#include "openwsn.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
|
||||
#include "opendefs.h"
|
||||
#include "scheduler.h"
|
||||
#include "02a-MAClow/IEEE802154E.h"
|
||||
#include "02b-MAChigh/neighbors.h"
|
||||
#include "03b-IPv6/icmpv6rpl.h"
|
||||
#include "04-TRAN/openudp.h"
|
||||
#include "cjoin.h"
|
||||
#include "cross-layers/openqueue.h"
|
||||
#include "cross-layers/idmanager.h"
|
||||
#include "cross-layers/packetfunctions.h"
|
||||
|
||||
extern idmanager_vars_t idmanager_vars;
|
||||
extern icmpv6rpl_vars_t icmpv6rpl_vars;
|
||||
extern neighbors_vars_t neighbors_vars;
|
||||
extern openqueue_vars_t openqueue_vars;
|
||||
extern schedule_vars_t schedule_vars;
|
||||
extern scheduler_dbg_t scheduler_dbg;
|
||||
|
||||
udp_resource_desc_t uinject_vars;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
char *_array_2_string(const uint8_t *addr, size_t addr_len, char *out)
|
||||
{
|
||||
char *res = out;
|
||||
|
||||
assert((out != NULL) && ((addr != NULL) || (addr_len == 0U)));
|
||||
out[0] = '\0';
|
||||
for (size_t i = 0; i < addr_len; i++) {
|
||||
out += fmt_byte_hex((out), *(addr++));
|
||||
*(out++) = (i == (addr_len - 1)) ? '\0' : ':';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ifconfig_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
open_addr_t *hwaddr;
|
||||
open_addr_t temp_my128bID;
|
||||
|
||||
memcpy(&temp_my128bID.addr_128b[0], &idmanager_vars.myPrefix.prefix, 8);
|
||||
memcpy(&temp_my128bID.addr_128b[8], &idmanager_vars.my64bID.addr_64b, 8);
|
||||
|
||||
printf("Iface %d ", openwsn_get_pid());
|
||||
hwaddr = idmanager_getMyID(ADDR_16B);
|
||||
printf("\tHWaddr: %s ", _array_2_string(hwaddr->addr_16b, 2, addr_str));
|
||||
hwaddr = idmanager_getMyID(ADDR_PANID);
|
||||
printf("NID: %s\n", _array_2_string(hwaddr->panid, 2, addr_str));
|
||||
printf("\n");
|
||||
|
||||
hwaddr = idmanager_getMyID(ADDR_64B);
|
||||
printf("\t\tLong HWaddr: %s\n", _array_2_string(hwaddr->addr_64b, 8, addr_str));
|
||||
|
||||
ipv6_addr_to_str(addr_str, (ipv6_addr_t *)temp_my128bID.addr_128b,
|
||||
sizeof(addr_str));
|
||||
printf("\t\tinet6 addr: %s\n", addr_str);
|
||||
printf("\n");
|
||||
|
||||
|
||||
printf("\t\tIEEE802154E sync: %i\n", ieee154e_isSynch());
|
||||
printf("\t\t6TiSCH joined: %i\n", cjoin_getIsJoined());
|
||||
printf("\n");
|
||||
|
||||
if (idmanager_vars.isDAGroot) {
|
||||
puts("\t\tNode is DAG root");
|
||||
}
|
||||
else {
|
||||
if (icmpv6rpl_vars.haveParent) {
|
||||
printf("\t\tRPL rank: %i\n", icmpv6rpl_vars.myDAGrank);
|
||||
printf("\t\tRPL parent: %s\n", \
|
||||
_array_2_string(neighbors_vars.neighbors[icmpv6rpl_vars.
|
||||
ParentIndex].
|
||||
addr_64b.addr_64b, 8, addr_str));
|
||||
printf("\t\tRPL children:\n");
|
||||
for (uint8_t i = 0; i < MAXNUMNEIGHBORS; i++) {
|
||||
if ((neighbors_isNeighborWithHigherDAGrank(i)) == true) {
|
||||
printf("\t\t\t%s\n", \
|
||||
_array_2_string(neighbors_vars.neighbors[i].
|
||||
addr_64b.addr_64b, 8, addr_str));
|
||||
}
|
||||
}
|
||||
ipv6_addr_to_str(addr_str,
|
||||
(ipv6_addr_t *)icmpv6rpl_vars.dao.DODAGID,
|
||||
sizeof(addr_str));
|
||||
printf("\t\tRPL DODAG ID: %16s\n", addr_str);
|
||||
}
|
||||
else {
|
||||
puts("\t\tNO RPL parent");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nc_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (int i = 0; i < MAXNUMNEIGHBORS; i++) {
|
||||
_array_2_string(neighbors_vars.neighbors[i].addr_64b.addr_64b, 8,
|
||||
addr_str);
|
||||
if (memcmp(addr_str, "00:00:00:00:00:00:00:00", 8) != 0) {
|
||||
printf("%02i. %s\n", i, addr_str);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
char *name;
|
||||
int id;
|
||||
} names[] = {
|
||||
{ "?", COMPONENT_NULL },
|
||||
{ "owsn", COMPONENT_OPENWSN },
|
||||
{ "idmanager", COMPONENT_IDMANAGER },
|
||||
{ "oqueue", COMPONENT_OPENQUEUE },
|
||||
{ "oserial", COMPONENT_OPENSERIAL },
|
||||
{ "pktfuncs", COMPONENT_PACKETFUNCTIONS },
|
||||
{ "random", COMPONENT_RANDOM },
|
||||
{ "radio", COMPONENT_RADIO },
|
||||
{ "154", COMPONENT_IEEE802154 },
|
||||
{ "154e", COMPONENT_IEEE802154E },
|
||||
{ "6top2154e", COMPONENT_SIXTOP_TO_IEEE802154E },
|
||||
{ "154e26top", COMPONENT_IEEE802154E_TO_SIXTOP },
|
||||
{ "6top", COMPONENT_SIXTOP },
|
||||
{ "neigh", COMPONENT_NEIGHBORS },
|
||||
{ "sched", COMPONENT_SCHEDULE },
|
||||
{ "6topres", COMPONENT_SIXTOP_RES },
|
||||
{ "bridge", COMPONENT_OPENBRIDGE },
|
||||
{ "iphc", COMPONENT_IPHC },
|
||||
{ "frag", COMPONENT_FRAG },
|
||||
{ "fwd", COMPONENT_FORWARDING },
|
||||
{ "icmpv6", COMPONENT_ICMPv6 },
|
||||
{ "icmpv6ech", COMPONENT_ICMPv6ECHO },
|
||||
{ "icmpv6rtr", COMPONENT_ICMPv6ROUTER },
|
||||
{ "icmpv6rpl", COMPONENT_ICMPv6RPL },
|
||||
{ "udp", COMPONENT_OPENUDP },
|
||||
{ "coap", COMPONENT_OPENCOAP },
|
||||
{ "cjoin", COMPONENT_CJOIN },
|
||||
{ "openoscoap", COMPONENT_OPENOSCOAP },
|
||||
{ "c6t", COMPONENT_C6T },
|
||||
{ "uinject", COMPONENT_UINJECT },
|
||||
};
|
||||
|
||||
char *_get_name(int id)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(names); i++) {
|
||||
if (id == names[i].id) {
|
||||
return names[i].name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int q_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
bool queue = 1;
|
||||
|
||||
for (uint8_t i = 0; i < QUEUELENGTH; i++) {
|
||||
if (openqueue_vars.queue[i].creator || openqueue_vars.queue[i].owner) {
|
||||
queue = 0;
|
||||
uint8_t creator = openqueue_vars.queue[i].creator;
|
||||
uint8_t owner = openqueue_vars.queue[i].owner;
|
||||
printf("Creator: %.9s [%d], ", _get_name(creator), creator);
|
||||
printf("Owner: %.9s [%d]\n", _get_name(owner), owner);
|
||||
}
|
||||
}
|
||||
if (queue) {
|
||||
puts("openqueue empty");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int q_rmv(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: %s [creator]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t creator = atoi(argv[1]);
|
||||
if (creator == 0) {
|
||||
printf("error: invalid input value\n");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
printf("Removing entries created by: %.9s [%d]\n", _get_name(creator), creator);
|
||||
openqueue_removeAllCreatedBy(creator);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (int i = 0; i < MAXACTIVESLOTS; i++) {
|
||||
switch (schedule_vars.scheduleBuf[i].type) {
|
||||
case CELLTYPE_TX:
|
||||
printf("neigh: %s, slot: %03i, chan: %02i, type: TX\n", \
|
||||
_array_2_string(
|
||||
schedule_vars.scheduleBuf[i].neighbor.addr_64b,
|
||||
8, addr_str),
|
||||
schedule_vars.scheduleBuf[i].slotOffset, \
|
||||
schedule_vars.scheduleBuf[i].channelOffset);
|
||||
break;
|
||||
case CELLTYPE_RX:
|
||||
printf("slot: %03i, chan: %02i, type: RX\n", \
|
||||
schedule_vars.scheduleBuf[i].slotOffset, \
|
||||
schedule_vars.scheduleBuf[i].channelOffset);
|
||||
break;
|
||||
case CELLTYPE_TXRX:
|
||||
printf("neigh: %s, slot: %03i, chan: %02i, type: RXTX\n", \
|
||||
_array_2_string(
|
||||
schedule_vars.scheduleBuf[i].neighbor.addr_64b,
|
||||
8, addr_str),
|
||||
schedule_vars.scheduleBuf[i].slotOffset, \
|
||||
schedule_vars.scheduleBuf[i].channelOffset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sc_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
/* TODO allow other prefixes via shell ?!? */
|
||||
printf("Current tasks:%i\n", scheduler_dbg.numTasksCur);
|
||||
printf("Max tasks: %i\n", scheduler_dbg.numTasksMax);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int udp_cmd(int argc, char **argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "ifconfig", "Shows assigned IPv6 addresses", ifconfig_cmd },
|
||||
{ "nc", "Shows neighbor table", nc_cmd },
|
||||
{ "q", "Shows Openqueue", q_cmd },
|
||||
{ "q-rmv", "Remove entries from creator in queue", q_rmv },
|
||||
{ "as", "Shows active cells", as_cmd },
|
||||
{ "sc", "Shows scheduler (openos) dbg states", sc_cmd },
|
||||
{ "udp", "Send data over UDP and listen on UDP ports", udp_cmd },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("OpenWSN UDP test");
|
||||
|
||||
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();
|
||||
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
}
|
195
tests/pkg_openwsn/udp.c
Normal file
195
tests/pkg_openwsn/udp.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2018 Hamburg University of Applied Sciences
|
||||
*
|
||||
* 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 Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ztimer.h"
|
||||
#include "net/ipv6.h"
|
||||
|
||||
#include "opendefs.h"
|
||||
#include "scheduler.h"
|
||||
#include "02a-MAClow/IEEE802154E.h"
|
||||
#include "03b-IPv6/icmpv6rpl.h"
|
||||
#include "04-TRAN/openudp.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;
|
||||
|
||||
OpenQueueEntry_t *pkt;
|
||||
|
||||
void push_pkt_cb(void){
|
||||
owerror_t ret = openudp_send(pkt);
|
||||
if (ret == E_FAIL) {
|
||||
puts("could not send");
|
||||
openqueue_freePacketBuffer(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static int udp_send(char *addr_str, char *port_str, char *data,
|
||||
unsigned int num, unsigned int delay)
|
||||
{
|
||||
size_t data_len;
|
||||
open_addr_t parentNeighbor;
|
||||
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) {
|
||||
puts("Error: unable to parse destination address, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* don't run if not in synch */
|
||||
if (ieee154e_isSynch() == FALSE) {
|
||||
puts("Error: Node not in sync, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* don't run on dagroot */
|
||||
if (idmanager_getIsDAGroot()) {
|
||||
puts("Error: Node is DAGROOT, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool foundNeighbor = icmpv6rpl_getPreferredParentEui64(&parentNeighbor);
|
||||
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;
|
||||
}
|
||||
|
||||
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_reserveHeaderSize(pkt, data_len);
|
||||
memcpy(&pkt->payload[0], data, data_len);
|
||||
|
||||
packetfunctions_reserveHeaderSize(pkt, sizeof(uint16_t));
|
||||
pkt->payload[1] = (uint8_t)((counter & 0xff00) >> 8);
|
||||
pkt->payload[0] = (uint8_t)(counter & 0x00ff);
|
||||
counter++;
|
||||
|
||||
packetfunctions_reserveHeaderSize(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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udp_cmd(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: %s [send|server]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "send") == 0) {
|
||||
uint32_t num = 1;
|
||||
uint32_t delay = 1000000LU;
|
||||
/* don't send as root */
|
||||
if (idmanager_vars.isDAGroot) {
|
||||
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]);
|
||||
return 1;
|
||||
}
|
||||
if (argc > 5) {
|
||||
num = atoi(argv[5]);
|
||||
}
|
||||
if (argc > 6) {
|
||||
delay = atoi(argv[6]);
|
||||
}
|
||||
return udp_send(argv[2], argv[3], argv[4], num, delay);
|
||||
}
|
||||
else if (strcmp(argv[1], "server") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("usage: %s server [start|list]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(argv[2], "start") == 0) {
|
||||
if (argc < 4) {
|
||||
printf("usage %s server start <port>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
uint16_t port = atoi(argv[3]);
|
||||
uinject_vars.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 {
|
||||
puts("error: invalid command");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
puts("error: invalid command");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user