From 7fd0364d599a96cd609cb3cf91eeaa89220e24c0 Mon Sep 17 00:00:00 2001 From: Jose Alamos Date: Tue, 23 Feb 2021 13:49:42 +0100 Subject: [PATCH 1/4] net/netopt: deprecate NETOPT_LORAWAN_TX_PORT --- sys/include/net/netopt.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/include/net/netopt.h b/sys/include/net/netopt.h index 0a87aeaf9d..0089d9c5e8 100644 --- a/sys/include/net/netopt.h +++ b/sys/include/net/netopt.h @@ -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, From 7343c1c503be0051f1b766657bbb1e3a427ce789 Mon Sep 17 00:00:00 2001 From: Jose Alamos Date: Tue, 23 Feb 2021 13:57:42 +0100 Subject: [PATCH 2/4] gnrc_netif_lorawan: add netif hdr support --- sys/include/net/gnrc/netif/lorawan.h | 15 ++++ sys/net/gnrc/netif/Kconfig | 13 ++++ .../gnrc/netif/lorawan/gnrc_netif_lorawan.c | 75 ++++++++++++++++--- 3 files changed, 94 insertions(+), 9 deletions(-) diff --git a/sys/include/net/gnrc/netif/lorawan.h b/sys/include/net/gnrc/netif/lorawan.h index ed7647cf6f..1e55531215 100644 --- a/sys/include/net/gnrc/netif/lorawan.h +++ b/sys/include/net/gnrc/netif/lorawan.h @@ -29,6 +29,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 */ diff --git a/sys/net/gnrc/netif/Kconfig b/sys/net/gnrc/netif/Kconfig index de4cb01adb..35acd68d85 100644 --- a/sys/net/gnrc/netif/Kconfig +++ b/sys/net/gnrc/netif/Kconfig @@ -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 diff --git a/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c b/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c index 6dabb4a474..c19a00ffae 100644 --- a/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c +++ b/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c @@ -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" @@ -90,19 +91,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) @@ -251,23 +280,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) From 7cf5530cae26b88b06cfdc14c4091cbf2fa1acd6 Mon Sep 17 00:00:00 2001 From: Jose Alamos Date: Tue, 23 Feb 2021 14:54:06 +0100 Subject: [PATCH 3/4] examples/gnrc_lorawan: refactor --- examples/gnrc_lorawan/Makefile | 49 +++++++++++++++------- examples/gnrc_lorawan/README.md | 43 +++++++++++++++---- examples/gnrc_lorawan/app.config | 2 + examples/gnrc_lorawan/main.c | 72 ++++---------------------------- 4 files changed, 80 insertions(+), 86 deletions(-) create mode 100644 examples/gnrc_lorawan/app.config diff --git a/examples/gnrc_lorawan/Makefile b/examples/gnrc_lorawan/Makefile index 16c25c0bdd..b3dd1762ba 100644 --- a/examples/gnrc_lorawan/Makefile +++ b/examples/gnrc_lorawan/Makefile @@ -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\" diff --git a/examples/gnrc_lorawan/README.md b/examples/gnrc_lorawan/README.md index bdc859e2ed..17414cc6cc 100644 --- a/examples/gnrc_lorawan/README.md +++ b/examples/gnrc_lorawan/README.md @@ -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 +``` + +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 > > Devices > > 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 diff --git a/examples/gnrc_lorawan/app.config b/examples/gnrc_lorawan/app.config new file mode 100644 index 0000000000..293cd467ef --- /dev/null +++ b/examples/gnrc_lorawan/app.config @@ -0,0 +1,2 @@ +CONFIG_KCONFIG_USEMODULE_GNRC_NETIF=y +CONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR=y diff --git a/examples/gnrc_lorawan/main.c b/examples/gnrc_lorawan/main.c index bd14363813..bd1995c700 100644 --- a/examples/gnrc_lorawan/main.c +++ b/examples/gnrc_lorawan/main.c @@ -32,81 +32,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 [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; } From dca0b366acd13908260cd0082d49ba44196a2411 Mon Sep 17 00:00:00 2001 From: Jose Alamos Date: Mon, 1 Mar 2021 15:44:17 +0100 Subject: [PATCH 4/4] gnrc_lorawan: drop frame if port exceeds max app port --- sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c index ff6e2b1b49..41ca6c7eba 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c @@ -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;