Skip to content

Commit

Permalink
Out of memory improvement to remove packets from routing
Browse files Browse the repository at this point in the history
If there is out of memory situation remove packets from Adaptation layer
Only delete Low priority packets
Only delete packets if there is large amounts of packets

This should make recovery faster when we are running out of memory
caused by problems sending packets, but we are still used as router.
  • Loading branch information
Mika Tervonen committed Dec 18, 2020
1 parent 0a12aeb commit 8333faa
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Release vxx.x.x

### Features
* When running on low memory situation low priority packets are dropped to ensure higher priority packet routing
* Add support for FAN 1.1 PHY mode IDs (all) and Channel plan IDs 1, 2, and 5 for North American and Brazil domains. This change enables OFDM modulation usage for mentioned frequency bands.
* Wi-SUN timing parameters are selected based on Data rate and network size.
*
Expand Down
67 changes: 66 additions & 1 deletion source/6LoWPAN/adaptation_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ typedef struct {

#define LOWPAN_ACTIVE_UNICAST_ONGOING_MAX 10

/* Minimum buffer amount and memory size to ensure operation even in out of memory situation
*/
#define LOWPAN_MEM_LIMIT_MIN_QUEUE 10
#define LOWPAN_MEM_LIMIT_MIN_MEMORY 10000
#define LOWPAN_MEM_LIMIT_REMOVE_NORMAL 3000 // Remove when approaching memory limit
#define LOWPAN_MEM_LIMIT_REMOVE_MAX 10000 // Remove when at memory limit



static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link);

/* Adaptation interface local functions */
Expand Down Expand Up @@ -493,6 +502,63 @@ int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_
return 0;
}

void lowpan_adaptation_free_heap(bool full_gc)
{
ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) {
// Go through all interfaces and free small amount of memory
// This is not very radical, but gives time to recover wthout causing too harsh changes
lowpan_adaptation_free_low_priority_packets(interface_ptr->interface_id, full_gc ? LOWPAN_MEM_LIMIT_REMOVE_MAX : LOWPAN_MEM_LIMIT_REMOVE_NORMAL);
}
}

int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount)
{
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id);

if (!interface_ptr) {
return -1;
}
uint32_t adaptation_memory = 0;
uint16_t adaptation_packets = 0;
uint32_t memory_freed = 0;
uint16_t packets_freed = 0;

ns_list_foreach(buffer_t, entry, &interface_ptr->directTxQueue) {
adaptation_memory += sizeof(buffer_t) + entry->size;
adaptation_packets++;
}

if (interface_ptr->directTxQueue_size < LOWPAN_MEM_LIMIT_MIN_QUEUE) {
// Minimum reserved for operations
return 0;
}
if (adaptation_memory < LOWPAN_MEM_LIMIT_MIN_MEMORY) {
// Minimum reserved for operations
return 0;
}
if (adaptation_memory - requested_amount < LOWPAN_MEM_LIMIT_MIN_MEMORY) {
// only reduse to minimum
requested_amount = adaptation_memory - LOWPAN_MEM_LIMIT_MIN_MEMORY;
}

//Only remove last entries from TX queue with low priority
ns_list_foreach_reverse_safe(buffer_t, entry, &interface_ptr->directTxQueue) {
if (entry->priority == QOS_NORMAL) {
memory_freed += sizeof(buffer_t) + entry->size;
packets_freed++;
ns_list_remove(&interface_ptr->directTxQueue, entry);
interface_ptr->directTxQueue_size--;
lowpan_adaptation_tx_queue_level_update(interface_ptr);
socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL);
}
if (memory_freed > requested_amount) {
// Enough memory freed
break;
}
}
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);
return 0;
}

static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size)
{
Expand Down Expand Up @@ -1562,7 +1628,6 @@ int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_in
return 0;
}


int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child)
{
fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id);
Expand Down
7 changes: 6 additions & 1 deletion source/6LoWPAN/lowpan_adaptation_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id);

int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_api_s *mpx_api, uint16_t mpx_user_id);

void lowpan_adaptation_free_heap(bool full_gc);

int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount);


/**
* \brief call this before normatl TX. This function prepare buffer link spesific metadata and verify packet destination
* \brief call this before normal TX. This function prepare buffer link specific metadata and verify packet destination
*/
struct buffer *lowpan_adaptation_data_process_tx_preprocess(struct protocol_interface_info_entry *cur, struct buffer *buf);

Expand Down
4 changes: 3 additions & 1 deletion source/Core/ns_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "ipv6_stack/ipv6_routing_table.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "6LoWPAN/lowpan_adaptation_interface.h"
#include "NWK_INTERFACE/Include/protocol.h"

#define TRACE_GROUP "mntr"
Expand Down Expand Up @@ -73,7 +74,8 @@ typedef void (ns_maintenance_gc_cb)(bool full_gc);
*/
static ns_maintenance_gc_cb *ns_maintenance_gc_functions[] = {
ipv6_destination_cache_forced_gc,
ws_pae_controller_forced_gc
ws_pae_controller_forced_gc,
lowpan_adaptation_free_heap
};

static void ns_monitor_heap_gc(bool full_gc)
Expand Down
1 change: 1 addition & 0 deletions test/nanostack/unittest/Core/monitor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ TEST_SRC_FILES = \
../../stub/ns_list_stub.c \
../../stub/thread_common_stub.c \
../../stub/icmpv6_stub.c \
../../stub/adaptation_interface_stub.c \
../../stub/mld_stub.c \
../../stub/ipv6_routing_table_stub.c \
../../stub/protocol_core_stub.c \
Expand Down
9 changes: 9 additions & 0 deletions test/nanostack/unittest/stub/adaptation_interface_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_
return adaptation_interface_stub.expectedInt8;
}

void lowpan_adaptation_free_heap(bool full_gc)
{
}

int8_t lowpan_adaptation_free_low_priority_packets(int8_t interface_id, uint32_t requested_amount)
{
return 0;
}

void lowpan_adaptation_interface_data_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data_ind)
{

Expand Down

0 comments on commit 8333faa

Please sign in to comment.