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

net/gnrc_lorawan: implement uplink redundancy

This commit implements uplink redundancy in GNRC LoRaWAN. Uplink
redundancy is used to retransmit unconfirmed uplink frames. The
retransmission stops when either a downlink message is received or the
number of uplink retransmissions is reached.

This functionality doesn't affect confirmed uplinks.
This commit is contained in:
Jose Alamos 2021-02-08 15:13:16 +01:00
parent 02151deae4
commit df97f348e2
No known key found for this signature in database
GPG Key ID: F483EB800EF89DD9
4 changed files with 46 additions and 15 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -153,6 +153,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;
@ -393,11 +394,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.