diff --git a/sys/include/net/gnrc/lorawan.h b/sys/include/net/gnrc/lorawan.h index 1571b3153c..a584a46214 100644 --- a/sys/include/net/gnrc/lorawan.h +++ b/sys/include/net/gnrc/lorawan.h @@ -24,6 +24,7 @@ #define NET_GNRC_LORAWAN_H #include "gnrc_lorawan_internal.h" +#include "assert.h" #ifdef __cplusplus extern "C" { @@ -320,6 +321,21 @@ void gnrc_lorawan_set_timer(gnrc_lorawan_t *mac, uint32_t us); */ void gnrc_lorawan_remove_timer(gnrc_lorawan_t *mac); +/** + * @brief Set unconfirmed uplink redundancy + * + * @pre @p redundancy <= 14 + * + * @param[in] mac pointer to the MAC descriptor + * @param[in] redundancy number of unconfirmed uplink retransmissions + */ +static inline void gnrc_lorawan_set_uncnf_redundancy(gnrc_lorawan_t *mac, + uint8_t redundancy) +{ + assert(redundancy <= (0xF - 1)); + mac->mcps.redundancy = redundancy; +} + #ifdef __cplusplus } #endif diff --git a/sys/include/net/loramac.h b/sys/include/net/loramac.h index 03dcd9e9fd..1ab6e09cdc 100644 --- a/sys/include/net/loramac.h +++ b/sys/include/net/loramac.h @@ -284,6 +284,21 @@ extern "C" { #define CONFIG_LORAMAC_DEFAULT_TX_MODE (LORAMAC_TX_CNF) #endif +/** + * @brief Default redundancy for unconfirmed uplink + * + * This corresponds to the number of unconfirmed uplink retransmissions when + * using ADR. This configuration does not affect confirmed uplinks. By + * default, uplinks are sent without retransmissions (this means, the device + * sends only one uplink packet) + * + * @note This value MUST NOT be greater than 14, since the LinkADRCommand it's + * already limited by a 4 bit value (therefore, 15 uplink transmissions) + */ +#ifndef CONFIG_LORAMAC_DEFAULT_REDUNDANCY +#define CONFIG_LORAMAC_DEFAULT_REDUNDANCY (0U) +#endif + /** * @brief Enable/disable adaptive datarate state * @@ -535,7 +550,7 @@ extern "C" { #define LORAMAC_PORT_MIN (1U) /** - * @brief Maximmu port value + * @brief Maximum port value */ #define LORAMAC_PORT_MAX (223U) diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c index 3a3cfa1ff8..3ed02d70b0 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c @@ -58,6 +58,7 @@ static inline void gnrc_lorawan_mcps_reset(gnrc_lorawan_t *mac) mac->mcps.waiting_for_ack = false; mac->mcps.fcnt = 0; mac->mcps.fcnt_down = 0; + gnrc_lorawan_set_uncnf_redundancy(mac, CONFIG_LORAMAC_DEFAULT_REDUNDANCY); } void gnrc_lorawan_set_rx2_dr(gnrc_lorawan_t *mac, uint8_t rx2_dr) @@ -164,8 +165,11 @@ void gnrc_lorawan_timeout_cb(gnrc_lorawan_t *mac) case LORAWAN_STATE_JOIN: gnrc_lorawan_trigger_join(mac); break; + case LORAWAN_STATE_IDLE: + gnrc_lorawan_event_retrans_timeout(mac); + break; default: - gnrc_lorawan_event_ack_timeout(mac); + assert(false); break; } } 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 26303d4231..13cd9ef75f 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c @@ -331,16 +331,33 @@ static void _transmit_pkt(gnrc_lorawan_t *mac) last_snip->iol_next = NULL; } -void gnrc_lorawan_event_ack_timeout(gnrc_lorawan_t *mac) +void gnrc_lorawan_event_retrans_timeout(gnrc_lorawan_t *mac) { _transmit_pkt(mac); } static void _handle_retransmissions(gnrc_lorawan_t *mac) { + /* Check if retransmission should be handled. + * + * If there was a confirmed uplink, follow the standard retransmission + * procedure. + * If it was an unconfirmed uplink, perform retransmissions only if + * there's redundancy > 0 */ if (mac->mcps.nb_trials-- == 0) { - _end_of_tx(mac, MCPS_CONFIRMED, -ETIMEDOUT); - } else { + if (mac->mcps.waiting_for_ack) { + /* If we are here, the node ran out of confirmed uplink retransmissions. + * This means, the transmission was not successful. */ + _end_of_tx(mac, MCPS_CONFIRMED, -ETIMEDOUT); + } + else { + /* In this case, we finished sending one or more unconfirmed + * (depending on the redundancy) */ + _end_of_tx(mac, MCPS_UNCONFIRMED, GNRC_LORAWAN_REQ_STATUS_SUCCESS); + } + } + else { + /* Schedule a retransmission */ gnrc_lorawan_set_timer(mac, 1000000 + random_uint32_range(0, 2000000)); } } @@ -358,14 +375,7 @@ void gnrc_lorawan_event_no_rx(gnrc_lorawan_t *mac) return; } - /* Otherwise check if retransmission should be handled */ - - if (mac->mcps.waiting_for_ack) { - _handle_retransmissions(mac); - } - else { - _end_of_tx(mac, MCPS_UNCONFIRMED, GNRC_LORAWAN_REQ_STATUS_SUCCESS); - } + _handle_retransmissions(mac); } void gnrc_lorawan_mcps_request(gnrc_lorawan_t *mac, @@ -416,7 +426,7 @@ void gnrc_lorawan_mcps_request(gnrc_lorawan_t *mac, mac->mcps.waiting_for_ack = waiting_for_ack; mac->mcps.ack_requested = false; - mac->mcps.nb_trials = CONFIG_LORAMAC_DEFAULT_RETX; + mac->mcps.nb_trials = waiting_for_ack ? CONFIG_LORAMAC_DEFAULT_RETX : mac->mcps.redundancy; mac->mcps.msdu = pkt; mac->last_dr = mcps_request->data.dr; diff --git a/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h b/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h index 933e7c169a..9990e17249 100644 --- a/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h +++ b/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h @@ -152,6 +152,7 @@ typedef struct { int nb_trials; /**< holds the remaining number of retransmissions */ int ack_requested; /**< whether the network server requested an ACK */ int waiting_for_ack; /**< true if the MAC layer is waiting for an ACK */ + uint8_t redundancy; /**< unconfirmed uplink redundancy */ char mhdr_mic[MHDR_MIC_BUF_SIZE]; /**< internal retransmissions buffer */ } gnrc_lorawan_mcps_t; @@ -392,11 +393,11 @@ void gnrc_lorawan_mlme_no_rx(gnrc_lorawan_t *mac); void gnrc_lorawan_event_no_rx(gnrc_lorawan_t *mac); /** - * @brief Mac callback for ACK timeout event + * @brief Mac callback for retransmission timeout event * * @param[in] mac pointer to the MAC descriptor */ -void gnrc_lorawan_event_ack_timeout(gnrc_lorawan_t *mac); +void gnrc_lorawan_event_retrans_timeout(gnrc_lorawan_t *mac); /** * @brief Get the maximum MAC payload (M value) for a given datarate. diff --git a/sys/net/link_layer/Kconfig.lorawan b/sys/net/link_layer/Kconfig.lorawan index bc5aeefdb1..3853b413f4 100644 --- a/sys/net/link_layer/Kconfig.lorawan +++ b/sys/net/link_layer/Kconfig.lorawan @@ -524,4 +524,16 @@ config LORAMAC_DEFAULT_MIN_RX_SYMBOLS system timer. Refer SX1276_settings_for_LoRaWAN_v2p2.pdf (AN1200.24) from Semtech for more information. +config LORAMAC_DEFAULT_REDUNDANCY + int "Default redundancy for unconfirmed uplinks" + depends on USEMODULE_GNRC_LORAWAN + default 0 + range 0 14 + help + This corresponds to the number of unconfirmed + uplink retransmissions when using ADR. This + configuration does not affect confirmed uplinks. + By default, uplinks are sent without retransmissions + (this means, the device sends only one uplink packet) + endif # KCONFIG_USEMODULE_LORAWAN