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:
parent
02151deae4
commit
df97f348e2
@ -24,6 +24,7 @@
|
|||||||
#define NET_GNRC_LORAWAN_H
|
#define NET_GNRC_LORAWAN_H
|
||||||
|
|
||||||
#include "gnrc_lorawan_internal.h"
|
#include "gnrc_lorawan_internal.h"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -58,6 +58,7 @@ static inline void gnrc_lorawan_mcps_reset(gnrc_lorawan_t *mac)
|
|||||||
mac->mcps.waiting_for_ack = false;
|
mac->mcps.waiting_for_ack = false;
|
||||||
mac->mcps.fcnt = 0;
|
mac->mcps.fcnt = 0;
|
||||||
mac->mcps.fcnt_down = 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)
|
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:
|
case LORAWAN_STATE_JOIN:
|
||||||
gnrc_lorawan_trigger_join(mac);
|
gnrc_lorawan_trigger_join(mac);
|
||||||
break;
|
break;
|
||||||
|
case LORAWAN_STATE_IDLE:
|
||||||
|
gnrc_lorawan_event_retrans_timeout(mac);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
gnrc_lorawan_event_ack_timeout(mac);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -331,16 +331,33 @@ static void _transmit_pkt(gnrc_lorawan_t *mac)
|
|||||||
last_snip->iol_next = NULL;
|
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);
|
_transmit_pkt(mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _handle_retransmissions(gnrc_lorawan_t *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) {
|
if (mac->mcps.nb_trials-- == 0) {
|
||||||
|
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);
|
_end_of_tx(mac, MCPS_CONFIRMED, -ETIMEDOUT);
|
||||||
} else {
|
}
|
||||||
|
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));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise check if retransmission should be handled */
|
|
||||||
|
|
||||||
if (mac->mcps.waiting_for_ack) {
|
|
||||||
_handle_retransmissions(mac);
|
_handle_retransmissions(mac);
|
||||||
}
|
|
||||||
else {
|
|
||||||
_end_of_tx(mac, MCPS_UNCONFIRMED, GNRC_LORAWAN_REQ_STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gnrc_lorawan_mcps_request(gnrc_lorawan_t *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.waiting_for_ack = waiting_for_ack;
|
||||||
mac->mcps.ack_requested = false;
|
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->mcps.msdu = pkt;
|
||||||
mac->last_dr = mcps_request->data.dr;
|
mac->last_dr = mcps_request->data.dr;
|
||||||
|
|||||||
@ -153,6 +153,7 @@ typedef struct {
|
|||||||
int nb_trials; /**< holds the remaining number of retransmissions */
|
int nb_trials; /**< holds the remaining number of retransmissions */
|
||||||
int ack_requested; /**< whether the network server requested an ACK */
|
int ack_requested; /**< whether the network server requested an ACK */
|
||||||
int waiting_for_ack; /**< true if the MAC layer is waiting for 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 */
|
char mhdr_mic[MHDR_MIC_BUF_SIZE]; /**< internal retransmissions buffer */
|
||||||
} gnrc_lorawan_mcps_t;
|
} 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);
|
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
|
* @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.
|
* @brief Get the maximum MAC payload (M value) for a given datarate.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user