Skip to content

Commit 4f9e3d1

Browse files
Mika TervonenMika Tervonen
authored andcommitted
Adaptation layer to remove oldest packet first
When running out of memory or reducing traffic adaptation will remove the oldest packets first instead of newest Also it needs to first remove all Lower priority packets before remove the next level of priorities
1 parent 20f1f64 commit 4f9e3d1

File tree

2 files changed

+74
-52
lines changed

2 files changed

+74
-52
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Features
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
8+
* Adaptation layer removes oldest packets first when stack needs to release memory or reduce traffic
89

910
### Changes
1011
*

source/6LoWPAN/adaptation_interface.c

Lines changed: 73 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link);
128128
static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t interfaceId);
129129

130130
/* Interface direct message pending queue functions */
131-
static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf);
132-
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr);
131+
static void lowpan_adaptation_tx_queue_write(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, buffer_t *buf);
132+
static buffer_t *lowpan_adaptation_tx_queue_read(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr);
133133

134134
/* Data direction and message length validation */
135135
static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *mle_entry);
@@ -223,8 +223,11 @@ static struct protocol_interface_info_entry *lowpan_adaptation_network_interface
223223
}
224224

225225

226-
static void lowpan_adaptation_tx_queue_level_update(fragmenter_interface_t *interface_ptr)
226+
static void lowpan_adaptation_tx_queue_level_update(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr)
227227
{
228+
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
229+
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
230+
228231
if (interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level + ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE ||
229232
interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level - ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE) {
230233
interface_ptr->directTxQueue_level = interface_ptr->directTxQueue_size;
@@ -233,14 +236,14 @@ static void lowpan_adaptation_tx_queue_level_update(fragmenter_interface_t *inte
233236
}
234237

235238

236-
static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf)
239+
static void lowpan_adaptation_tx_queue_write(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, buffer_t *buf)
237240
{
238241
buffer_t *lower_priority_buf = NULL;
239242

240-
ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) {
243+
ns_list_foreach(buffer_t, entry, &interface_ptr->directTxQueue) {
241244

242-
if (cur->priority < buf->priority) {
243-
lower_priority_buf = cur;
245+
if (entry->priority < buf->priority) {
246+
lower_priority_buf = entry;
244247
break;
245248
}
246249
}
@@ -251,18 +254,17 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
251254
ns_list_add_to_end(&interface_ptr->directTxQueue, buf);
252255
}
253256
interface_ptr->directTxQueue_size++;
254-
lowpan_adaptation_tx_queue_level_update(interface_ptr);
255-
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
257+
lowpan_adaptation_tx_queue_level_update(cur, interface_ptr);
256258
}
257259

258-
static void lowpan_adaptation_tx_queue_write_to_front(fragmenter_interface_t *interface_ptr, buffer_t *buf)
260+
static void lowpan_adaptation_tx_queue_write_to_front(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, buffer_t *buf)
259261
{
260262
buffer_t *lower_priority_buf = NULL;
261263

262-
ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) {
264+
ns_list_foreach(buffer_t, entry, &interface_ptr->directTxQueue) {
263265

264-
if (cur->priority <= buf->priority) {
265-
lower_priority_buf = cur;
266+
if (entry->priority <= buf->priority) {
267+
lower_priority_buf = entry;
266268
break;
267269
}
268270
}
@@ -273,11 +275,10 @@ static void lowpan_adaptation_tx_queue_write_to_front(fragmenter_interface_t *in
273275
ns_list_add_to_end(&interface_ptr->directTxQueue, buf);
274276
}
275277
interface_ptr->directTxQueue_size++;
276-
lowpan_adaptation_tx_queue_level_update(interface_ptr);
277-
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
278+
lowpan_adaptation_tx_queue_level_update(cur, interface_ptr);
278279
}
279280

280-
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr)
281+
static buffer_t *lowpan_adaptation_tx_queue_read(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr)
281282
{
282283
// Currently this function is called only when data confirm is received for previously sent packet.
283284
if (!interface_ptr->directTxQueue_size) {
@@ -293,8 +294,7 @@ static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interfa
293294
if (lowpan_buffer_tx_allowed(interface_ptr, buf)) {
294295
ns_list_remove(&interface_ptr->directTxQueue, buf);
295296
interface_ptr->directTxQueue_size--;
296-
lowpan_adaptation_tx_queue_level_update(interface_ptr);
297-
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
297+
lowpan_adaptation_tx_queue_level_update(cur, interface_ptr);
298298
return buf;
299299
}
300300
}
@@ -561,12 +561,24 @@ void lowpan_adaptation_free_heap(bool full_gc)
561561
lowpan_adaptation_free_low_priority_packets(interface_ptr->interface_id, priority, amount);
562562
}
563563
}
564+
buffer_t *lowpan_adaptation_get_oldest_packet(fragmenter_interface_t *interface_ptr, buffer_priority_t priority)
565+
{
566+
ns_list_foreach(buffer_t, entry, &interface_ptr->directTxQueue) {
567+
if (entry->priority == priority) {
568+
// Only Higher priority packets left no need to go through list anymore
569+
return entry;
570+
}
571+
}
572+
return NULL;
573+
574+
}
564575

565576
int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, buffer_priority_t max_priority, uint32_t requested_amount)
566577
{
567578
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);
579+
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
568580

569-
if (!interface_ptr) {
581+
if (!interface_ptr || !cur) {
570582
return -1;
571583
}
572584
uint32_t adaptation_memory = 0;
@@ -592,21 +604,36 @@ int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, buffer_p
592604
requested_amount = adaptation_memory - LOWPAN_MEM_LIMIT_MIN_MEMORY;
593605
}
594606

595-
//Only remove last entries from TX queue with low priority
596-
ns_list_foreach_reverse_safe(buffer_t, entry, &interface_ptr->directTxQueue) {
597-
if (entry->priority <= max_priority) {
598-
memory_freed += sizeof(buffer_t) + entry->size;
599-
packets_freed++;
600-
ns_list_remove(&interface_ptr->directTxQueue, entry);
601-
interface_ptr->directTxQueue_size--;
602-
lowpan_adaptation_tx_queue_level_update(interface_ptr);
603-
socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL);
604-
}
605-
if (memory_freed > requested_amount) {
606-
// Enough memory freed
607+
/* Order of packets is
608+
* priority 4 oldest to newest
609+
* priority 3 oldest to newest
610+
* priority 2 oldest to newest
611+
* priority 1 oldest to newest
612+
* priority 0 oldest to newest
613+
* So we search oldest for lowest priority and delete that until that priority is empty
614+
* and then start deleting one higher priority packets from oldest first
615+
*/
616+
617+
buffer_priority_t priority = QOS_NORMAL;
618+
do {
619+
buffer_t *entry = lowpan_adaptation_get_oldest_packet(interface_ptr, priority);
620+
if (!entry) {
621+
if (priority < max_priority) {
622+
priority++;
623+
continue;
624+
}
625+
// No more packets available
607626
break;
608627
}
609-
}
628+
// This packet can be deleted
629+
memory_freed += sizeof(buffer_t) + entry->size;
630+
packets_freed++;
631+
ns_list_remove(&interface_ptr->directTxQueue, entry);
632+
interface_ptr->directTxQueue_size--;
633+
lowpan_adaptation_tx_queue_level_update(cur, interface_ptr);
634+
socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL);
635+
} while (memory_freed < requested_amount);
636+
610637
tr_info("Adaptation Free low priority packets memory: %" PRIi32 " queue: %d deallocated %" PRIi32 " bytes, %d packets, %" PRIi32 " requested", adaptation_memory, adaptation_packets, memory_freed, packets_freed, requested_amount);
611638
return 0;
612639
}
@@ -1210,8 +1237,7 @@ static void lowpan_adaptation_high_priority_state_enable(protocol_interface_info
12101237
interface_ptr->activeTxList_size--;
12111238
ns_dyn_mem_free(entry);
12121239
//Add message to tx queue front based on priority. Now same priority at buf is prioritised at order
1213-
lowpan_adaptation_tx_queue_write_to_front(interface_ptr, buf);
1214-
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
1240+
lowpan_adaptation_tx_queue_write_to_front(cur, interface_ptr, buf);
12151241
}
12161242
}
12171243
}
@@ -1260,13 +1286,11 @@ void lowpan_adaptation_interface_slow_timer(protocol_interface_info_entry_t *cur
12601286

12611287
if (lowpan_adaptation_high_priority_state_exit(interface_ptr)) {
12621288
//Activate Packets from TX queue
1263-
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
1289+
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(cur, interface_ptr);
12641290
while (buf_from_queue) {
12651291
lowpan_adaptation_interface_tx(cur, buf_from_queue);
1266-
buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
1292+
buf_from_queue = lowpan_adaptation_tx_queue_read(cur, interface_ptr);
12671293
}
1268-
//Update Average QUEUE
1269-
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
12701294
}
12711295
}
12721296

@@ -1319,17 +1343,17 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
13191343

13201344
if (!lowpan_buffer_tx_allowed(interface_ptr, buf)) {
13211345

1322-
if (buf->priority == QOS_NORMAL) {
1323-
1324-
if (random_early_detection_congestion_check(cur->random_early_detection)) {
1325-
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
1346+
if (random_early_detection_congestion_check(cur->random_early_detection)) {
1347+
// If we need to drop packet we drop oldest normal Priority packet.
1348+
buffer_t *dropped = lowpan_adaptation_get_oldest_packet(interface_ptr, QOS_NORMAL);
1349+
if (dropped) {
1350+
ns_list_remove(&interface_ptr->directTxQueue, dropped);
1351+
interface_ptr->directTxQueue_size--;
1352+
socket_tx_buffer_event_and_free(dropped, SOCKET_TX_FAIL);
13261353
protocol_stats_update(STATS_AL_TX_CONGESTION_DROP, 1);
1327-
goto tx_error_handler;
13281354
}
13291355
}
1330-
1331-
lowpan_adaptation_tx_queue_write(interface_ptr, buf);
1332-
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
1356+
lowpan_adaptation_tx_queue_write(cur, interface_ptr, buf);
13331357
return 0;
13341358
}
13351359

@@ -1605,13 +1629,11 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c
16051629
if (active_direct_confirm == true) {
16061630
//Check Possibility for exit from High Priority state
16071631
lowpan_adaptation_high_priority_state_exit(interface_ptr);
1608-
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
1632+
buffer_t *buf_from_queue = lowpan_adaptation_tx_queue_read(cur, interface_ptr);
16091633
while (buf_from_queue) {
16101634
lowpan_adaptation_interface_tx(cur, buf_from_queue);
1611-
buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr);
1635+
buf_from_queue = lowpan_adaptation_tx_queue_read(cur, interface_ptr);
16121636
}
1613-
//Update Average QUEUE
1614-
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
16151637
}
16161638
return 0;
16171639
}
@@ -1815,8 +1837,7 @@ int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_in
18151837
ns_list_remove(&interface_ptr->directTxQueue, entry);
18161838
interface_ptr->directTxQueue_size--;
18171839
//Update Average QUEUE
1818-
random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size);
1819-
lowpan_adaptation_tx_queue_level_update(interface_ptr);
1840+
lowpan_adaptation_tx_queue_level_update(cur, interface_ptr);
18201841
socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL);
18211842
}
18221843
}

0 commit comments

Comments
 (0)