Skip to content

Commit 4c1a89c

Browse files
author
Cruz Monrreal
authored
Merge pull request #7459 from hasnainvirk/issue_7232_7432
LoRaWAN: FRMPayload size validity
2 parents 1cbfa00 + ed9048f commit 4c1a89c

File tree

3 files changed

+76
-51
lines changed

3 files changed

+76
-51
lines changed

features/lorawan/LoRaRadio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ class LoRaRadio
281281
* @param iq_inverted Inverts IQ signals (LoRa only)
282282
* FSK : N/A (set to 0).
283283
* LoRa: [0: not inverted, 1: inverted]
284-
* @param timeout The transmission timeout [us].
284+
* @param timeout The transmission timeout [ms].
285285
*/
286286
virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev,
287287
uint32_t bandwidth, uint32_t datarate,

features/lorawan/lorastack/mac/LoRaMac.cpp

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ lorawan_status_t LoRaMac::schedule_tx()
10331033
{
10341034
channel_selection_params_t next_channel;
10351035
lorawan_time_t backoff_time = 0;
1036+
uint8_t fopts_len = 0;
10361037

10371038
if (_params.sys_params.max_duty_cycle == 255) {
10381039
return LORAWAN_STATUS_DEVICE_OFF;
@@ -1090,9 +1091,25 @@ lorawan_status_t LoRaMac::schedule_tx()
10901091
_params.rx_window2_delay = _params.sys_params.join_accept_delay2
10911092
+ _params.rx_window2_config.window_offset;
10921093
} else {
1093-
if (validate_payload_length(_params.tx_buffer_len,
1094+
1095+
// if the outgoing message is a proprietary message, it doesn't include any
1096+
// standard message formatting except port and MHDR.
1097+
if (_ongoing_tx_msg.type == MCPS_PROPRIETARY) {
1098+
fopts_len = 0;
1099+
} else {
1100+
fopts_len = _mac_commands.get_mac_cmd_length() + _mac_commands.get_repeat_commands_length();
1101+
}
1102+
1103+
// A check was performed for validity of FRMPayload in ::prepare_ongoing_tx() API.
1104+
// However, owing to the asynch nature of the send() API, we should check the
1105+
// validity again, as datarate may have changed since we last attempted to transmit.
1106+
if (validate_payload_length(_ongoing_tx_msg.f_buffer_size,
10941107
_params.sys_params.channel_data_rate,
1095-
_mac_commands.get_mac_cmd_length()) == false) {
1108+
fopts_len) == false) {
1109+
tr_error("Allowed FRMPayload = %d, FRMPayload = %d, MAC commands pending = %d",
1110+
_lora_phy->get_max_payload(_params.sys_params.channel_data_rate,
1111+
_params.is_repeater_supported),
1112+
_ongoing_tx_msg.f_buffer_size, fopts_len);
10961113
return LORAWAN_STATUS_LENGTH_ERROR;
10971114
}
10981115
_params.rx_window1_delay = _params.sys_params.recv_delay1
@@ -1215,27 +1232,9 @@ int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port,
12151232
uint8_t num_retries)
12161233
{
12171234
_ongoing_tx_msg.port = port;
1218-
1219-
uint8_t max_possible_size = get_max_possible_tx_size(length);
1220-
1221-
if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
1222-
max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
1223-
}
1224-
1225-
if (max_possible_size < length) {
1226-
tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
1227-
length, max_possible_size);
1228-
1229-
_ongoing_tx_msg.pending_size = length - max_possible_size;
1230-
_ongoing_tx_msg.f_buffer_size = max_possible_size;
1231-
memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size);
1232-
} else {
1233-
_ongoing_tx_msg.f_buffer_size = length;
1234-
_ongoing_tx_msg.pending_size = 0;
1235-
if (length > 0) {
1236-
memcpy(_ongoing_tx_msg.f_buffer, data, length);
1237-
}
1238-
}
1235+
uint8_t max_possible_size = 0;
1236+
uint8_t fopts_len = _mac_commands.get_mac_cmd_length()
1237+
+ _mac_commands.get_repeat_commands_length();
12391238

12401239
// Handles unconfirmed messages
12411240
if (flags & MSG_UNCONFIRMED_FLAG) {
@@ -1256,6 +1255,30 @@ int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port,
12561255
_ongoing_tx_msg.type = MCPS_PROPRIETARY;
12571256
_ongoing_tx_msg.fport = port;
12581257
_ongoing_tx_msg.nb_trials = 1;
1258+
// a proprietary frame only includes an MHDR field which contains MTYPE field.
1259+
// Everything else is at the discretion of the implementer
1260+
fopts_len = 0;
1261+
}
1262+
1263+
max_possible_size = get_max_possible_tx_size(fopts_len);
1264+
1265+
if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
1266+
max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
1267+
}
1268+
1269+
if (max_possible_size < length) {
1270+
tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
1271+
length, max_possible_size);
1272+
1273+
_ongoing_tx_msg.pending_size = length - max_possible_size;
1274+
_ongoing_tx_msg.f_buffer_size = max_possible_size;
1275+
memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size);
1276+
} else {
1277+
_ongoing_tx_msg.f_buffer_size = length;
1278+
_ongoing_tx_msg.pending_size = 0;
1279+
if (length > 0) {
1280+
memcpy(_ongoing_tx_msg.f_buffer, data, length);
1281+
}
12591282
}
12601283

12611284
tr_info("RTS = %u bytes, PEND = %u, Port: %u",
@@ -1566,8 +1589,10 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
15661589

15671590
_mac_commands.parse_mac_commands_to_repeat();
15681591

1592+
// We always add Port Field. Spec leaves it optional.
1593+
_params.tx_buffer[pkt_header_len++] = frame_port;
1594+
15691595
if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
1570-
_params.tx_buffer[pkt_header_len++] = frame_port;
15711596

15721597
uint8_t *key = _params.keys.app_skey;
15731598
uint32_t key_length = sizeof(_params.keys.app_skey) * 8;
@@ -1759,35 +1784,30 @@ void LoRaMac::disconnect()
17591784
reset_mcps_indication();
17601785
}
17611786

1762-
uint8_t LoRaMac::get_max_possible_tx_size(uint8_t size)
1787+
uint8_t LoRaMac::get_max_possible_tx_size(uint8_t fopts_len)
17631788
{
17641789
uint8_t max_possible_payload_size = 0;
1765-
uint8_t current_payload_size = 0;
1766-
uint8_t fopt_len = _mac_commands.get_mac_cmd_length()
1767-
+ _mac_commands.get_repeat_commands_length();
1790+
uint8_t allowed_frm_payload_size = 0;
17681791

17691792
if (_params.sys_params.adr_on) {
17701793
_lora_phy->get_next_ADR(false, _params.sys_params.channel_data_rate,
17711794
_params.sys_params.channel_tx_power,
17721795
_params.adr_ack_counter);
17731796
}
17741797

1775-
current_payload_size = _lora_phy->get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported);
1798+
allowed_frm_payload_size = _lora_phy->get_max_payload(_params.sys_params.channel_data_rate,
1799+
_params.is_repeater_supported);
17761800

1777-
if (current_payload_size >= fopt_len) {
1778-
max_possible_payload_size = current_payload_size - fopt_len;
1801+
if (allowed_frm_payload_size >= fopts_len) {
1802+
max_possible_payload_size = allowed_frm_payload_size - fopts_len;
17791803
} else {
1780-
max_possible_payload_size = current_payload_size;
1781-
fopt_len = 0;
1804+
max_possible_payload_size = allowed_frm_payload_size;
1805+
fopts_len = 0;
17821806
_mac_commands.clear_command_buffer();
17831807
_mac_commands.clear_repeat_buffer();
17841808
}
17851809

1786-
if (validate_payload_length(size, _params.sys_params.channel_data_rate,
1787-
fopt_len) == false) {
1788-
return max_possible_payload_size;
1789-
}
1790-
return current_payload_size;
1810+
return max_possible_payload_size;
17911811
}
17921812

17931813
bool LoRaMac::nwk_joined()

features/lorawan/lorastack/mac/LoRaMac.h

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,18 @@ class LoRaMac {
9393
void disconnect(void);
9494

9595
/**
96-
* @brief Queries the LoRaMAC whether it is possible to send the next frame with
97-
* a given payload size. The LoRaMAC takes the scheduled MAC commands into
98-
* account and returns corresponding value.
96+
* @brief Queries the LoRaMAC the maximum possible FRMPayload size to send.
97+
* The LoRaMAC takes the scheduled MAC commands into account and returns
98+
* corresponding value.
9999
*
100-
* @param size [in] The size of the applicable payload to be sent next.
100+
* @param fopts_len [in] Number of mac commands in the queue pending.
101101
*
102102
* @return Size of the biggest packet that can be sent.
103103
* Please note that if the size of the MAC commands in the queue do
104104
* not fit into the payload size on the related datarate, the LoRaMAC will
105105
* omit the MAC commands.
106106
*/
107-
uint8_t get_max_possible_tx_size(uint8_t size);
107+
uint8_t get_max_possible_tx_size(uint8_t fopts_len);
108108

109109
/**
110110
* @brief nwk_joined Checks if device has joined to network
@@ -316,13 +316,18 @@ class LoRaMac {
316316

317317
/**
318318
* @brief prepare_ongoing_tx This will prepare (and override) ongoing_tx_msg.
319-
* @param port The application port number.
320-
* @param data A pointer to the data being sent. The ownership of the
321-
* buffer is not transferred.
322-
* @param length The size of data in bytes.
323-
* @param flags A flag used to determine what type of
324-
* message is being sent.
325-
* @param num_retries Number of retries for a confirmed type message
319+
* @param port The application port number.
320+
*
321+
* @param data A pointer to the data being sent. The ownership of the
322+
* buffer is not transferred.
323+
*
324+
* @param length The size of data in bytes.
325+
*
326+
* @param flags A flag used to determine what type of
327+
* message is being sent.
328+
*
329+
* @param num_retries Number of retries for a confirmed type message
330+
*
326331
* @return The number of bytes prepared for sending.
327332
*/
328333
int16_t prepare_ongoing_tx(const uint8_t port, const uint8_t *data,

0 commit comments

Comments
 (0)