Skip to content

Commit 24168f8

Browse files
author
Jarkko Paso
authored
Do not send too old packets (ARMmbed#2632)
* Do not send packets that are queued on adaptation layer over 30 seconds * Do not allow new data request overtake existing one in MAC queue * Revert "Do not allow new data request overtake existing one in MAC queue" This reverts commit 5c660e0246139acd1dab99094fe3fdcf1138ad60. * Do not send any old packets * Return data request to adaptation layer after timeout * Fixed missing PHY timestamp cb in unit tests * Allow removing only normal priority buffers * Unit tests for removing old buffers from MAC queue * Cleaning * Timeout value defined for all buffer priorities * Updated unit tests * Updated change log
1 parent dbd83be commit 24168f8

File tree

6 files changed

+189
-44
lines changed

6 files changed

+189
-44
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Filter RPL parents based on DEVICE_MIN_SENS configuration with Threshold and Hysteresis.
77
* Filter EAPOL parents based on DEVICE_MIN_SENS configuration with Threshold and Hysteresis to prevent EAPOL failures caused by bad signal levels
88
* Adaptation layer removes oldest packets first when stack needs to release memory or reduce traffic
9+
* Use QoS specific timeout to drop old packets from TX queue to prioritize limited bandwidth.
910

1011
### Changes
1112
* Statistics for MAC data request latencies. Separated to adaptation layer and MAC queueing delays.

source/6LoWPAN/adaptation_interface.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ typedef struct {
120120
#define LOWPAN_MEM_LIMIT_REMOVE_MAX 10000 // Remove when at memory limit
121121
#define LOWPAN_MEM_LIMIT_REMOVE_EF_MODE 20000 // Remove when out of memory and we are in EF mode
122122

123+
#define LOWPAN_TX_BUFFER_AGE_LIMIT_LOW_PRIORITY 30 // Remove low priority packets older than limit (seconds)
124+
#define LOWPAN_TX_BUFFER_AGE_LIMIT_HIGH_PRIORITY 60 // Remove high priority packets older than limit (seconds)
125+
#define LOWPAN_TX_BUFFER_AGE_LIMIT_EF_PRIORITY 120 // Remove expedited forwarding packets older than limit (seconds)
126+
123127

124128

125129
static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link);
@@ -1294,6 +1298,23 @@ void lowpan_adaptation_interface_slow_timer(protocol_interface_info_entry_t *cur
12941298
}
12951299
}
12961300

1301+
static bool lowpan_adaptation_interface_check_buffer_timeout(buffer_t *buf)
1302+
{
1303+
// Convert from 100ms slots to seconds
1304+
uint32_t buffer_age_s = (protocol_core_monotonic_time - buf->adaptation_timestamp) / 10;
1305+
1306+
if ((buf->priority == QOS_NORMAL) && (buffer_age_s > LOWPAN_TX_BUFFER_AGE_LIMIT_LOW_PRIORITY)) {
1307+
return true;
1308+
} else if ((buf->priority == QOS_HIGH) && (buffer_age_s > LOWPAN_TX_BUFFER_AGE_LIMIT_HIGH_PRIORITY)) {
1309+
return true;
1310+
} else if ((buf->priority == QOS_NETWORK_CTRL) && (buffer_age_s > LOWPAN_TX_BUFFER_AGE_LIMIT_HIGH_PRIORITY)) {
1311+
return true;
1312+
} else if ((buf->priority == QOS_EXPEDITE_FORWARD) && (buffer_age_s > LOWPAN_TX_BUFFER_AGE_LIMIT_EF_PRIORITY)) {
1313+
return true;
1314+
}
1315+
return false;
1316+
}
1317+
12971318
int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf)
12981319
{
12991320
bool is_room_for_new_message;
@@ -1309,13 +1330,7 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
13091330
if (!interface_ptr) {
13101331
goto tx_error_handler;
13111332
}
1312-
// Set TX start timestamp
1313-
if (!buf->adaptation_timestamp) {
1314-
buf->adaptation_timestamp = protocol_core_monotonic_time;
1315-
if (!buf->adaptation_timestamp) {
1316-
buf->adaptation_timestamp--;
1317-
}
1318-
}
1333+
13191334
uint8_t traffic_class = buf->options.traffic_class >> IP_TCLASS_DSCP_SHIFT;
13201335

13211336
if (traffic_class == IP_DSCP_EF) {
@@ -1327,6 +1342,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
13271342
buffer_priority_set(buf, QOS_HIGH);
13281343
}
13291344

1345+
if (!buf->adaptation_timestamp) {
1346+
// Set TX start timestamp
1347+
buf->adaptation_timestamp = protocol_core_monotonic_time;
1348+
if (!buf->adaptation_timestamp) {
1349+
buf->adaptation_timestamp--;
1350+
}
1351+
} else if (lowpan_adaptation_interface_check_buffer_timeout(buf)) {
1352+
// Remove old buffers
1353+
socket_tx_buffer_event_and_free(buf, SOCKET_TX_FAIL);
1354+
return -1;
1355+
}
1356+
13301357
//Update priority status
13311358
lowpan_adaptation_priority_status_update(cur, interface_ptr, buf->priority);
13321359

source/MAC/IEEE802_15_4/mac_mcps_sap.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656

5757
// Used to set TX time (us) with FHSS. Must be <= 65ms.
5858
#define MAC_TX_PROCESSING_DELAY_INITIAL 2000
59+
// Give up on data request after given timeout (seconds)
60+
#define DATA_REQUEST_TIMEOUT_NORMAL_PRIORITY_S 30
61+
#define DATA_REQUEST_TIMEOUT_EF_PRIORITY_S 120
5962

6063
typedef struct {
6164
uint8_t address[8];
@@ -275,7 +278,7 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
275278
}
276279
break;
277280
case MAC_DATA_HIGH_PRIORITY:
278-
buffer->priority = MAC_PD_DATA_HIGH_PRIOTITY;
281+
buffer->priority = MAC_PD_DATA_HIGH_PRIORITY;
279282
break;
280283
case MAC_DATA_MEDIUM_PRIORITY:
281284
buffer->priority = MAC_PD_DATA_MEDIUM_PRIORITY;
@@ -1102,6 +1105,18 @@ static void mac_mcps_asynch_finish(protocol_interface_rf_mac_setup_s *rf_mac_set
11021105
}
11031106
}
11041107

1108+
static bool mcps_sap_check_buffer_timeout(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
1109+
{
1110+
// Convert from 1us slots to seconds
1111+
uint32_t buffer_age_s = (mac_mcps_sap_get_phy_timestamp(rf_mac_setup) - buffer->request_start_time_us) / 1000000;
1112+
if ((buffer->priority == MAC_PD_DATA_NORMAL_PRIORITY) && (buffer_age_s > DATA_REQUEST_TIMEOUT_NORMAL_PRIORITY_S)) {
1113+
return true;
1114+
} else if ((buffer->priority == MAC_PD_DATA_EF_PRIORITY) && (buffer_age_s > DATA_REQUEST_TIMEOUT_EF_PRIORITY_S)) {
1115+
return true;
1116+
}
1117+
return false;
1118+
}
1119+
11051120
void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_setup)
11061121
{
11071122
if (!rf_mac_setup) {
@@ -1121,22 +1136,31 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s
11211136
buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false);
11221137

11231138
if (buffer) {
1124-
//Here
1125-
if (buffer->ExtendedFrameExchange) {
1126-
//Update here state and store peer
1127-
memcpy(rf_mac_setup->mac_edfe_info->PeerAddr, buffer->DstAddr, 8);
1128-
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_CONNECTING;
1129-
}
1130-
rf_mac_setup->active_pd_data_request = buffer;
1131-
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
1139+
if (mcps_sap_check_buffer_timeout(rf_mac_setup, buffer)) {
1140+
// Buffer is quite old. Return it to adaptation layer with timeout event.
1141+
rf_mac_setup->mac_tx_result = MAC_TX_TIMEOUT;
11321142
if (buffer->ExtendedFrameExchange) {
11331143
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
11341144
}
1135-
rf_mac_setup->active_pd_data_request = NULL;
11361145
mac_mcps_asynch_finish(rf_mac_setup, buffer);
11371146
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
11381147
} else {
1139-
return;
1148+
if (buffer->ExtendedFrameExchange) {
1149+
//Update here state and store peer
1150+
memcpy(rf_mac_setup->mac_edfe_info->PeerAddr, buffer->DstAddr, 8);
1151+
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_CONNECTING;
1152+
}
1153+
rf_mac_setup->active_pd_data_request = buffer;
1154+
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
1155+
if (buffer->ExtendedFrameExchange) {
1156+
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
1157+
}
1158+
rf_mac_setup->active_pd_data_request = NULL;
1159+
mac_mcps_asynch_finish(rf_mac_setup, buffer);
1160+
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
1161+
} else {
1162+
return;
1163+
}
11401164
}
11411165
} else {
11421166
return;
@@ -2437,10 +2461,16 @@ static mac_pre_build_frame_t *mcps_sap_pd_req_queue_read(protocol_interface_rf_m
24372461

24382462
mac_pre_build_frame_t *buffer = queue;
24392463
mac_pre_build_frame_t *prev = NULL;
2440-
// With FHSS, check TX conditions
2464+
/* With FHSS, read buffer out from queue if:
2465+
* - Buffer has timed out, OR
2466+
* - Buffer is asynch request, OR
2467+
* - Queue is flushed, OR
2468+
* - Blacklisting AND FHSS allows buffer to be transmitted
2469+
*/
24412470
if (rf_mac_setup->fhss_api) {
24422471
while (buffer) {
2443-
if (buffer->asynch_request ||
2472+
if (mcps_sap_check_buffer_timeout(rf_mac_setup, buffer) ||
2473+
buffer->asynch_request ||
24442474
(flush == true) ||
24452475
((mcps_check_packet_blacklist(rf_mac_setup, buffer) == false) &&
24462476
(rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),

source/MAC/IEEE802_15_4/mac_mcps_sap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ typedef enum {
4848

4949
#define MAC_PD_DATA_NORMAL_PRIORITY 0 //Normal MCPS DATA REQ
5050
#define MAC_PD_DATA_MEDIUM_PRIORITY 1 //Indirect Data which is polled
51-
#define MAC_PD_DATA_HIGH_PRIOTITY 2 //Beacon request Beacon response
51+
#define MAC_PD_DATA_HIGH_PRIORITY 2 //Beacon request Beacon response
5252
#define MAC_PD_DATA_EF_PRIORITY 3 //Expedited forwarding
5353
#define MAC_PD_DATA_TX_IMMEDIATELY 4 //Only for packets whose transmission was interrupted by wrong channel type. E.g. unicast on broadcast channel.
5454

source/MAC/IEEE802_15_4/mac_mlme.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1837,7 +1837,7 @@ int8_t mac_mlme_beacon_tx(protocol_interface_rf_mac_setup_s *rf_ptr)
18371837
ptr += BEACON_OPTION_JOIN_PRIORITY_LEN;
18381838
}*/
18391839
}
1840-
buf->priority = MAC_PD_DATA_HIGH_PRIOTITY;
1840+
buf->priority = MAC_PD_DATA_HIGH_PRIORITY;
18411841
mcps_sap_pd_req_queue_write(rf_ptr, buf);
18421842
sw_mac_stats_update(rf_ptr, STAT_MAC_BEA_TX_COUNT, 0);
18431843
return 0;

test/nanostack/unittest/mac/mac_mcps_sap/test_mac_mcps_sap.c

Lines changed: 109 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,27 @@ static arm_device_driver_list_s *rf_client_driver_allocate()
238238
return driver;
239239
}
240240

241+
uint32_t test_timestamp = 1000000;
242+
static int8_t test_rf_extension(phy_extension_type_e extension, uint8_t *buf)
243+
{
244+
switch (extension) {
245+
case PHY_EXTENSION_GET_TIMESTAMP:
246+
buf[3] = test_timestamp >> 24;
247+
buf[2] = test_timestamp >> 16;
248+
buf[1] = test_timestamp >> 8;
249+
buf[0] = test_timestamp;
250+
test_timestamp += 100000;
251+
break;
252+
case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
253+
*buf = 1;
254+
break;
255+
case PHY_EXTENSION_READ_RX_TIME:
256+
common_write_32_bit(100, buf);
257+
default:
258+
break;
259+
}
260+
return 0;
261+
}
241262

242263
static protocol_interface_rf_mac_setup_s *test_mac_rf_mac_class_allocate(void)
243264
{
@@ -261,32 +282,11 @@ static protocol_interface_rf_mac_setup_s *test_mac_rf_mac_class_allocate(void)
261282
dev_driver->phy_header_length = 0;
262283
driver->phy_driver = dev_driver;
263284
rf_mac_setup->dev_driver = driver;
285+
rf_mac_setup->dev_driver->phy_driver->extension = test_rf_extension;
264286

265287
return rf_mac_setup;
266288
}
267289

268-
uint32_t test_timestamp = 1000000;
269-
static int8_t test_rf_extension(phy_extension_type_e extension, uint8_t *buf)
270-
{
271-
switch (extension) {
272-
case PHY_EXTENSION_GET_TIMESTAMP:
273-
buf[3] = test_timestamp >> 24;
274-
buf[2] = test_timestamp >> 16;
275-
buf[1] = test_timestamp >> 8;
276-
buf[0] = test_timestamp;
277-
test_timestamp += 100000;
278-
break;
279-
case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
280-
*buf = 1;
281-
break;
282-
case PHY_EXTENSION_READ_RX_TIME:
283-
common_write_32_bit(100, buf);
284-
default:
285-
break;
286-
}
287-
return 0;
288-
}
289-
290290
static int8_t test_rf_tx(uint8_t *data, uint16_t length, uint8_t tx_handle, data_protocol_e protocol)
291291
{
292292
return 0;
@@ -3046,6 +3046,93 @@ bool test_mac_mcps_trig_buffer_from_queue()
30463046
return false;
30473047
}
30483048
mac_mcps_buffer_queue_free(rf_mac_setup);
3049+
3050+
// Test removing old buffers from queue
3051+
rf_mac_setup->fhss_api = ns_fhss_create(0, 0, 0);
3052+
// Add 4 buffers in queue, buf and buf2 are too old and should be removed
3053+
buf = tes_mac_mcps_temporary_buffer_get(0);
3054+
buf2 = tes_mac_mcps_temporary_buffer_get(0);
3055+
mac_pre_build_frame_t *buf3 = tes_mac_mcps_temporary_buffer_get(0);
3056+
mac_pre_build_frame_t *buf4 = tes_mac_mcps_temporary_buffer_get(0);
3057+
buf->request_start_time_us = test_timestamp - 32000000;
3058+
buf2->request_start_time_us = test_timestamp - 31000000;
3059+
buf3->request_start_time_us = test_timestamp - 25000000;
3060+
buf4->request_start_time_us = test_timestamp - 23000000;
3061+
rf_mac_setup->pd_data_request_queue_to_go = buf;
3062+
rf_mac_setup->pd_data_request_queue_to_go->next = buf2;
3063+
rf_mac_setup->pd_data_request_queue_to_go->next->next = buf3;
3064+
rf_mac_setup->pd_data_request_queue_to_go->next->next->next = buf4;
3065+
rf_mac_setup->unicast_queue_size = 4;
3066+
fhss_config_stub.bool_value = false;
3067+
fhss_tx_condition = true;
3068+
// Trig should remove first two buffers and take third as active data request
3069+
mac_mcps_trig_buffer_from_queue(rf_mac_setup);
3070+
if (rf_mac_setup->active_pd_data_request != buf3) {
3071+
test_mac_rf_mac_class_free(rf_mac_setup);
3072+
printf("Fail: Remove old buffers, wrong buffer activated\r\n");
3073+
return false;
3074+
}
3075+
mac_mcps_buffer_queue_free(rf_mac_setup);
3076+
3077+
// Test removing old buffers with low priority from queue
3078+
rf_mac_setup->fhss_api = ns_fhss_create(0, 0, 0);
3079+
// Add 4 buffers in queue, buf and buf2 are too old but only first one should be removed
3080+
buf = tes_mac_mcps_temporary_buffer_get(0);
3081+
buf2 = tes_mac_mcps_temporary_buffer_get(0);
3082+
buf3 = tes_mac_mcps_temporary_buffer_get(0);
3083+
buf4 = tes_mac_mcps_temporary_buffer_get(0);
3084+
buf->request_start_time_us = test_timestamp - 32000000;
3085+
buf2->request_start_time_us = test_timestamp - 31000000;
3086+
buf3->request_start_time_us = test_timestamp - 25000000;
3087+
buf4->request_start_time_us = test_timestamp - 23000000;
3088+
// Change buf2 priority to medium
3089+
buf2->priority = MAC_PD_DATA_MEDIUM_PRIORITY;
3090+
rf_mac_setup->pd_data_request_queue_to_go = buf;
3091+
rf_mac_setup->pd_data_request_queue_to_go->next = buf2;
3092+
rf_mac_setup->pd_data_request_queue_to_go->next->next = buf3;
3093+
rf_mac_setup->pd_data_request_queue_to_go->next->next->next = buf4;
3094+
rf_mac_setup->unicast_queue_size = 4;
3095+
fhss_config_stub.bool_value = false;
3096+
fhss_tx_condition = true;
3097+
// Trig should remove first buffer and take second as active data request
3098+
mac_mcps_trig_buffer_from_queue(rf_mac_setup);
3099+
if (rf_mac_setup->active_pd_data_request != buf2) {
3100+
test_mac_rf_mac_class_free(rf_mac_setup);
3101+
printf("Fail: Remove old buffers with priority, wrong buffer activated\r\n");
3102+
return false;
3103+
}
3104+
mac_mcps_buffer_queue_free(rf_mac_setup);
3105+
3106+
// Test removing old buffers with EF priority from queue
3107+
rf_mac_setup->fhss_api = ns_fhss_create(0, 0, 0);
3108+
// Add 4 buffers in queue, buf(normal priority) and buf2(EF priority) are too old and should be removed
3109+
buf = tes_mac_mcps_temporary_buffer_get(0);
3110+
buf2 = tes_mac_mcps_temporary_buffer_get(0);
3111+
buf3 = tes_mac_mcps_temporary_buffer_get(0);
3112+
buf4 = tes_mac_mcps_temporary_buffer_get(0);
3113+
buf->request_start_time_us = test_timestamp - 32000000;
3114+
buf2->request_start_time_us = test_timestamp - 121000000;
3115+
buf3->request_start_time_us = test_timestamp - 100000000;
3116+
buf4->request_start_time_us = test_timestamp - 23000000;
3117+
// Change buf2 and buf3 priority to expedited forwarding
3118+
buf2->priority = MAC_PD_DATA_EF_PRIORITY;
3119+
buf3->priority = MAC_PD_DATA_EF_PRIORITY;
3120+
rf_mac_setup->pd_data_request_queue_to_go = buf;
3121+
rf_mac_setup->pd_data_request_queue_to_go->next = buf2;
3122+
rf_mac_setup->pd_data_request_queue_to_go->next->next = buf3;
3123+
rf_mac_setup->pd_data_request_queue_to_go->next->next->next = buf4;
3124+
rf_mac_setup->unicast_queue_size = 4;
3125+
fhss_config_stub.bool_value = false;
3126+
fhss_tx_condition = true;
3127+
// Trig should remove first two buffers and take third as active data request
3128+
mac_mcps_trig_buffer_from_queue(rf_mac_setup);
3129+
if (rf_mac_setup->active_pd_data_request != buf3) {
3130+
test_mac_rf_mac_class_free(rf_mac_setup);
3131+
printf("Fail: Remove old buffers with EF priority, wrong buffer activated\r\n");
3132+
return false;
3133+
}
3134+
mac_mcps_buffer_queue_free(rf_mac_setup);
3135+
30493136
// Free test setup struct
30503137
test_mac_rf_mac_class_free(rf_mac_setup);
30513138
return true;

0 commit comments

Comments
 (0)