1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #16080 from jia200x/pr/gnrc_lorawan_netif

gnrc_lorawan: encode LoRaWAN port in netif header
This commit is contained in:
Leandro Lanzieri 2021-06-17 11:30:09 +02:00 committed by GitHub
commit ae81b808a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 193 additions and 95 deletions

View File

@ -1,24 +1,37 @@
# name of your application
APPLICATION = gnrc_lorawan
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += gnrc_netdev_default
USEMODULE += auto_init_gnrc_netif
USEMODULE += gnrc_lorawan
USEMODULE += gnrc_pktdump
USEMODULE += gnrc_neterr
BOARD ?= b-l072z-lrwan1
RIOTBASE ?= ../../
# Turn on developer helpers
DEVELHELP ?= 1
# use SX1276 by default
DRIVER ?= sx1276
BOARD ?= b-l072z-lrwan1
RIOTBASE ?= ../../
USEMODULE += $(DRIVER)
# Include board's default network devices and auto-initialization of GNRC
# interfaces
USEMODULE += gnrc_netdev_default
USEMODULE += auto_init_gnrc_netif
# Add support for GNRC LoRaWAN
USEMODULE += gnrc_lorawan
# Use GNRC pktdump to print downlink messages
USEMODULE += gnrc_pktdump
# Include the shell and shell commands.
USEMODULE += shell
USEMODULE += shell_commands
# Use GNRC Txtsnd to transmit LoRaWAN from the shell
USEMODULE += gnrc_txtsnd
# Uncomment as needed if a board doesn't include a LoRa radio by default
# USEMODULE += sx1272
# USEMODULE += sx1276
# As there is an 'app.config' we want to explicitly disable Kconfig by setting
# the variable to empty
SHOULD_RUN_KCONFIG ?=
include $(RIOTBASE)/Makefile.include
@ -33,6 +46,14 @@ include $(RIOTBASE)/Makefile.include
# Check if being configured via Kconfig
ifndef CONFIG_KCONFIG_USEMODULE_LORAWAN
# Tell GNRC to encode LoRaWAN port in the GNRC netif header.
# This allows us to use `gnrc_txtsnd` to send data from the shell using the
# `txtsnd` command.
#
# Note: From Release 22.01 all GNRC LoRaWAN packets will include the netif
# header. Therefore this flag will be removed after that
CFLAGS += -DCONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR
CFLAGS += -DCONFIG_LORAMAC_APP_KEY_DEFAULT=\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"
CFLAGS += -DCONFIG_LORAMAC_APP_EUI_DEFAULT=\"BBBBBBBBBBBBBBBB\"
CFLAGS += -DCONFIG_LORAMAC_DEV_EUI_DEFAULT=\"CCCCCCCCCCCCCCCC\"

View File

@ -15,7 +15,6 @@ Usage
It's necessary to join the LoRaWAN network either via OTAA or ABP.
All keys, addresses and EUIs are in network endian (big endian).
The application listens to downlinks on Port 2 by default.
Region need to be set in the Makefile.
## OTAA
@ -73,10 +72,15 @@ CFLAGS += -DCONFIG_LORAMAC_DEV_ADDR_DEFAULT=\"FFFFFFFF\"
## Send data
After join, send data using `send` command. E.g to send "Hello RIOT!" to port 2:
After join, send data using `txtsnd` command:
```
txtsnd <if> <hex_port> <data>
```
E.g to send "Hello RIOT!" to LoRaWAN port 123 (hex 0x7B) via interface 3:
```
send 3 "Hello RIOT!" 2
txtsnd 3 7B "Hello RIOT!"
```
## Changing datarate of transmission
@ -100,7 +104,7 @@ Send some data. The result of the Link Check request can be seen with
```
ifconfig 3 link_check
send 3 "Join the RIOT!"
txtsnd 3 01 "Join the RIOT!"
```
Check demodulation margin and number of gateways using `ifconfig`
@ -124,18 +128,43 @@ E.g send confirmable messages:
```
ifconfig 3 ack_req
send 3 "My confirmable message"
txtsnd 3 01 "My confirmable message"
```
And unconfirmable messages:
```
ifconfig 3 -ack_req
send 3 "My unconfirmable message"
txtsnd 3 01 "My unconfirmable message"
```
## Receiving data
Schedule a downlink for the LoRaWAN node in the Application Server. If using
TTN, this can be done under `Applications > <APP> > Devices > <DEV> > Overview`
and then check the `Downlink` section.
After sending data, the LoRaWAN Network Server will reply with the downlink
data. For simplicity, this application is configured to dump downlink data to
[GNRC pktdump](https://doc.riot-os.org/pktdump_8h.html).
E.g:
```
PKTDUMP: data received:
~~ SNIP 0 - size: 2 byte, type: NETTYPE_UNDEF (0)
00000000 AA AA
~~ SNIP 1 - size: 9 byte, type: NETTYPE_NETIF (-1)
if_pid: 3 rssi: -32768 lqi: 0
flags: 0x0
src_l2addr: (nil)
dst_l2addr: 01
~~ PKT - 2 snips, total size: 11 byte
```
This downlink was sent to port 1 (check `dst_l2addr` field)
Current state and future plans
============
==============================
The current GNRC LoRaWAN stack is still in an experimental state. It's still
not compliant with the LoRaWAN specification because some features like duty

View File

@ -0,0 +1,2 @@
CONFIG_KCONFIG_USEMODULE_GNRC_NETIF=y
CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR=y

View File

@ -31,81 +31,23 @@
#include "net/gnrc/netif.h"
#include "net/gnrc/pktbuf.h"
#include "net/gnrc/pktdump.h"
#include "net/gnrc/netreg.h"
#include "net/gnrc/pktdump.h"
#include "net/loramac.h"
#define LORAWAN_QUEUE_SIZE (4U)
static void _usage(void)
{
puts("usage: send <if_pid> <payload> [port]");
}
int tx_cmd(int argc, char **argv)
{
gnrc_pktsnip_t *pkt;
uint8_t port = CONFIG_LORAMAC_DEFAULT_TX_PORT; /* Default: 2 */
int interface;
if (argc < 3) {
_usage();
return 1;
}
interface = atoi(argv[1]);
/* handle optional parameters */
if (argc > 3) {
port = atoi(argv[3]);
if (port == 0 || port >= 224) {
printf("error: invalid port given '%d', "
"port can only be between 1 and 223\n", port);
return 1;
}
}
pkt = gnrc_pktbuf_add(NULL, argv[2], strlen(argv[2]), GNRC_NETTYPE_UNDEF);
/* register for returned packet status */
if (gnrc_neterr_reg(pkt) != 0) {
puts("Can not register for error reporting");
return 0;
}
gnrc_netapi_set(interface, NETOPT_LORAWAN_TX_PORT, 0, &port, sizeof(port));
gnrc_netif_send(gnrc_netif_get_by_pid(interface), pkt);
/* wait for packet status and check */
msg_t msg;
msg_receive(&msg);
if ((msg.type != GNRC_NETERR_MSG_TYPE) ||
(msg.content.value != GNRC_NETERR_SUCCESS)) {
printf("Error sending packet: (status: %d\n)", (int) msg.content.value);
}
else {
puts("Successfully sent packet");
}
return 0;
}
static const shell_command_t shell_commands[] = {
{ "send", "Send LoRaWAN data", tx_cmd },
{ NULL, NULL, NULL }
};
int main(void)
{
/* start the shell */
puts("Initialization successful - starting the shell now");
gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(CONFIG_LORAMAC_DEFAULT_TX_PORT,
/* Receive LoRaWAN packets in GNRC pktdump */
gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL,
gnrc_pktdump_pid);
gnrc_netreg_register(GNRC_NETTYPE_LORAWAN, &dump);
char line_buf[SHELL_DEFAULT_BUFSIZE];
gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump);
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
return 0;
}

View File

@ -31,6 +31,21 @@ extern "C" {
*/
#define GNRC_NETIF_LORAWAN_FLAGS_LINK_CHECK (0x1U)
/**
* @brief Encode LoRaWAN port in GNRC netif header.
*
* When set, GNRC netif will interpret the destination address of the
* GNRC netif header as the LoRaWAN port. For downlinks, a GNRC netif header
* with the received port in destination field will be included in the
* first snip.
*
* @deprecated From Release 2021.10 all GNRC LoRaWAN packets will include
* the GNRC Netif header. Therefore this parameter will be removed
*/
#if defined(DOXYGEN)
#define CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR
#endif
/**
* @brief GNRC LoRaWAN interface descriptor
*/

View File

@ -640,6 +640,20 @@ typedef enum {
/**
* @brief (uint8_t) LoRaWAN TX application port
* - LoRaWAN: between 1 and 223 (included)
*
* @deprecated This option is deprecated and will be removed in the
* 2022.01 Release.
* The port is encoded now as a one byte
* destination address in a @ref net_gnrc_netif_hdr snip
* prepended in the packet.
* The user must take care of prepending the required snip
* during transmission. On reception, the
* snip is prepended automatically by the stack and shall be
* consumed by the user.
* During the deprecation period it is required to
* compile with @ref
* CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR
*
*/
NETOPT_LORAWAN_TX_PORT,

View File

@ -118,6 +118,11 @@ int gnrc_lorawan_parse_dl(gnrc_lorawan_t *mac, uint8_t *buf, size_t len,
return -1;
}
if (pkt->port > LORAMAC_PORT_MAX) {
DEBUG("gnrc_lorawan: packet with port > 223. Drop\n");
return -1;
}
if (buf < p_mic) {
pkt->enc_payload.iol_base = buf;
pkt->enc_payload.iol_len = p_mic - buf;

View File

@ -61,4 +61,17 @@ config GNRC_NETIF_PKTQ_TIMER_US
Set to -1 to deactivate dequeing by timer. For this it has to be ensured
that none of the notifications by the driver are missed!
config GNRC_NETIF_LORAWAN_NETIF_HDR
bool "Encode LoRaWAN port in GNRC netif header"
depends on USEMODULE_GNRC_LORAWAN
help
When set, GNRC Netif will interpret
the destination address of the GNRC netif header as
the LoRaWAN port. For downlinks, a GNRC netif header
with the received port in destination field will be
included in the first snip. From Release 2021.10 all
GNRC LoRaWAN packets will include the GNRC Netif
header. Therefore this parameter will be removed
endif # KCONFIG_USEMODULE_GNRC_NETIF

View File

@ -18,6 +18,7 @@
#include "net/gnrc/pktbuf.h"
#include "net/gnrc/netif.h"
#include "net/gnrc/netif/hdr.h"
#include "net/gnrc/netif/lorawan.h"
#include "net/gnrc/netif/internal.h"
#include "net/gnrc/lorawan.h"
@ -107,19 +108,47 @@ static inline void _set_be_addr(gnrc_lorawan_t *mac, uint8_t *be_addr)
void gnrc_lorawan_mcps_indication(gnrc_lorawan_t *mac, mcps_indication_t *ind)
{
(void)mac;
gnrc_netif_t *netif = container_of(mac, gnrc_netif_t, lorawan.mac);
gnrc_nettype_t nettype = IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)
? GNRC_NETTYPE_UNDEF
: GNRC_NETTYPE_LORAWAN;
uint32_t demux = IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)
? GNRC_NETREG_DEMUX_CTX_ALL
: ind->data.port;
assert(ind->data.port >= LORAMAC_PORT_MIN && ind->data.port <= LORAMAC_PORT_MAX);
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, ind->data.pkt->iol_base,
ind->data.pkt->iol_len,
GNRC_NETTYPE_LORAWAN);
nettype);
if (!pkt) {
DEBUG("gnrc_lorawan: mcps_indication: couldn't allocate pktbuf\n");
return;
}
if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_LORAWAN, ind->data.port,
pkt)) {
gnrc_pktbuf_release(pkt);
if (IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)) {
gnrc_pktsnip_t *netif_snip = gnrc_netif_hdr_build(NULL, 0,
&ind->data.port,
sizeof(ind->data.port));
if (netif_snip == NULL) {
DEBUG("gnrc_lorawan_netif: no space left in packet buffer\n");
goto release;
}
gnrc_netif_hdr_t *hdr = netif_snip->data;
gnrc_netif_hdr_set_netif(hdr, netif);
pkt = gnrc_pkt_append(pkt, netif_snip);
}
if (!gnrc_netapi_dispatch_receive(nettype, demux, pkt)) {
DEBUG("gnrc_lorawan_netif: unable to forward packet\n")
goto release;
}
return;
release:
gnrc_pktbuf_release(pkt);
}
void gnrc_lorawan_mlme_indication(gnrc_lorawan_t *mac, mlme_indication_t *ind)
@ -271,23 +300,51 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *payload)
mlme_request_t mlme_request;
mlme_confirm_t mlme_confirm;
gnrc_pktsnip_t *head;
uint8_t port;
int res = -EINVAL;
if (IS_ACTIVE(CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR)) {
gnrc_netif_hdr_t *netif_hdr;
const uint8_t *dst;
netif_hdr = payload->data;
dst = gnrc_netif_hdr_get_dst_addr(netif_hdr);
assert(payload->type == GNRC_NETTYPE_NETIF);
head = payload->next;
port = dst[0];
if (netif_hdr->dst_l2addr_len != sizeof(port)) {
goto end;
}
}
else {
head = payload;
port = netif->lorawan.port;
}
if (netif->lorawan.flags & GNRC_NETIF_LORAWAN_FLAGS_LINK_CHECK) {
mlme_request.type = MLME_LINK_CHECK;
gnrc_lorawan_mlme_request(&netif->lorawan.mac, &mlme_request,
&mlme_confirm);
}
mcps_request_t req =
{ .type = netif->lorawan.ack_req ? MCPS_CONFIRMED : MCPS_UNCONFIRMED,
.data =
{ .pkt = (iolist_t *)payload, .port = netif->lorawan.port,
{ .pkt = (iolist_t *)head, .port = port,
.dr = netif->lorawan.datarate } };
mcps_confirm_t conf;
gnrc_lorawan_mcps_request(&netif->lorawan.mac, &req, &conf);
if (conf.status < 0) {
gnrc_pktbuf_release_error(payload, conf.status);
res = conf.status;
end:
if (res < 0) {
gnrc_pktbuf_release_error(payload, res);
}
return conf.status;
return res;
}
static void _msg_handler(gnrc_netif_t *netif, msg_t *msg)