Skip to content

Commit 7ca6c24

Browse files
Mika TervonenMika Tervonen
authored andcommitted
Enable and modify memory limits for packet receiving
Modify memory cleanup function values based on stack memory size Enable packet ingress for low memory devices to prevent deadlocks
1 parent e2b028d commit 7ca6c24

File tree

7 files changed

+120
-24
lines changed

7 files changed

+120
-24
lines changed

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "mac_common_defines.h"
2929
#include "sw_mac.h"
3030
#include "ccmLIB.h"
31+
#include "Core/include/ns_monitor.h"
3132
#include "NWK_INTERFACE/Include/protocol.h"
3233
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
3334
#include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
@@ -1010,6 +1011,30 @@ static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notif
10101011

10111012
}
10121013

1014+
static void ws_bootstrap_memory_configuration()
1015+
{
1016+
/* Configure memory limits for garbage collection based on total memory size
1017+
* Starting from these values
1018+
* 5% for High mark
1019+
* 2% for critical mark
1020+
* 1% for Routing limit
1021+
* Memory High Critical Drop routing
1022+
* 32K RAM 3200 bytes 1280 Bytes 1024 bytes
1023+
* 64K RAM 3200 bytes 1280 Bytes 1024 bytes
1024+
* 128K RAM 6400 bytes 2560 Bytes 1280 bytes
1025+
* 320K RAM 16000 byte 6400 Bytes 3200 bytes
1026+
* 640K RAM 32000 byte 12800 Bytes 6400 bytes
1027+
* 1000K RAM 50000 bytes 20000 Bytes 10000 bytes
1028+
* 4000K RAM 120000 bytes 40000 Bytes 10000 bytes
1029+
* */
1030+
// In small memory devices there needs to lower limit so that there some change to be usable
1031+
// and there is no use for having very large values on high memory devices
1032+
ns_monitor_packet_ingress_rate_limit_by_memory(1024, 10000, 1);
1033+
1034+
ns_monitor_heap_gc_threshold_set(3200, 120000, 95, 1280, 40000, 98);
1035+
return;
1036+
}
1037+
10131038

10141039
static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
10151040
{
@@ -1066,7 +1091,8 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
10661091
dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC);
10671092
dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_dhcp_info_notify_cb);
10681093

1069-
1094+
// Configure memory limits and garbage collection values;
1095+
ws_bootstrap_memory_configuration();
10701096
ws_nud_table_reset(cur);
10711097

10721098
ws_bootstrap_candidate_table_reset(cur);

source/Core/include/ns_monitor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ int ns_monitor_clear(void);
3333

3434
void ns_monitor_timer(uint16_t seconds);
3535

36-
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical);
36+
int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage);
3737

38-
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
38+
int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage);
3939

4040
bool ns_monitor_packet_allocation_allowed(void);
4141

source/Core/ns_monitor.c

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ typedef struct ns_monitor__s {
6363

6464
static ns_monitor_t *ns_monitor_ptr = NULL;
6565

66-
static uint8_t ns_dyn_mem_rate_limiting_threshold_percentage = 0; // Percentage of free memory required to allow routing
66+
static ns_mem_heap_size_t ns_dyn_mem_rate_limiting_threshold = 0; // amount of free memory required to allow routing 0 = disabled
6767

6868
typedef void (ns_maintenance_gc_cb)(bool full_gc);
6969

@@ -176,32 +176,75 @@ int ns_monitor_clear(void)
176176
return -1;
177177
}
178178

179-
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical)
179+
int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage)
180180
{
181-
if (ns_monitor_ptr && (percentage_critical <= 100) && (percentage_high < percentage_critical)) {
181+
if (ns_monitor_ptr && (critical_percentage <= 100) && (high_percentage < critical_percentage)) {
182182
ns_monitor_ptr->heap_high_watermark = SET_WATERMARK(
183183
ns_monitor_ptr->mem_stats->heap_sector_size,
184-
percentage_high
184+
high_percentage
185185
);
186+
if (ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_high_watermark < high_min) {
187+
ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - high_min;
188+
}
189+
190+
if (high_max && ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_high_watermark > high_max) {
191+
ns_monitor_ptr->heap_high_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - high_max;
192+
}
193+
186194
ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK(
187195
ns_monitor_ptr->mem_stats->heap_sector_size,
188-
percentage_critical
196+
critical_percentage
189197
);
190-
tr_debug("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size);
198+
if (ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_critical_watermark < critical_min) {
199+
ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - critical_min;
200+
}
201+
202+
if (critical_max && ns_monitor_ptr->mem_stats->heap_sector_size - ns_monitor_ptr->heap_critical_watermark > critical_max) {
203+
ns_monitor_ptr->heap_critical_watermark = ns_monitor_ptr->mem_stats->heap_sector_size - critical_max;
204+
}
205+
206+
tr_info("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size);
191207
return 0;
192208
}
193209

194210
return -1;
195211
}
196212

197-
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
213+
int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage)
198214
{
199-
if (free_heap_percentage < 100) {
200-
ns_dyn_mem_rate_limiting_threshold_percentage = free_heap_percentage;
215+
/* To make this function dynamic and useful in larger range of memories the minimum value can be given
216+
*
217+
* example limit(1024, 1)
218+
* 32k RAM Limit = 1024
219+
* 64k RAM Limit = 1024
220+
* 128k RAM Limit = 1280
221+
* 320k RAM Limit = 3200
222+
*/
223+
if (free_heap_percentage == 0 && minimum_required == 0) {
224+
// Disable rate limiting
225+
ns_dyn_mem_rate_limiting_threshold = 0;
201226
return 0;
202227
}
228+
if (free_heap_percentage > 100) {
229+
// Sanity check this should not be high at all, but dont want to limit without any good reason
230+
return -1;
231+
}
203232

204-
return -1;
233+
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
234+
if (ns_dyn_mem_stat && free_heap_percentage) {
235+
ns_dyn_mem_rate_limiting_threshold = ns_dyn_mem_stat->heap_sector_size / 100 * free_heap_percentage;
236+
}
237+
238+
if (ns_dyn_mem_rate_limiting_threshold < minimum_required) {
239+
ns_dyn_mem_rate_limiting_threshold = minimum_required;
240+
}
241+
242+
if (Maximum_allowed && ns_dyn_mem_rate_limiting_threshold > Maximum_allowed) {
243+
ns_dyn_mem_rate_limiting_threshold = Maximum_allowed;
244+
}
245+
tr_info("Monitor rate limit incoming packets at:%lu", (unsigned long)ns_dyn_mem_rate_limiting_threshold);
246+
247+
return 0;
205248
}
206249

207250
bool ns_monitor_packet_allocation_allowed(void)
@@ -212,8 +255,8 @@ bool ns_monitor_packet_allocation_allowed(void)
212255

213256
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
214257

215-
if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold_percentage) {
216-
if (ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_stat->heap_sector_size / 100 * (100 - ns_dyn_mem_rate_limiting_threshold_percentage)) {
258+
if (ns_dyn_mem_stat && ns_dyn_mem_rate_limiting_threshold) {
259+
if (ns_dyn_mem_stat->heap_sector_size - ns_dyn_mem_stat->heap_sector_allocated_bytes < ns_dyn_mem_rate_limiting_threshold) {
217260
// Packet allocation not allowed as memory is running low.
218261
return false;
219262
}

source/Service_Libs/utils/ns_conf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424

2525
int ns_conf_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical)
2626
{
27-
return ns_monitor_heap_gc_threshold_set(percentage_high, percentage_critical);
27+
return ns_monitor_heap_gc_threshold_set(0, 0, percentage_high, 0, 0, percentage_critical);
2828
}
2929

3030
int ns_conf_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage)
3131
{
32-
return ns_monitor_packet_ingress_rate_limit_by_memory(free_heap_percentage);
32+
return ns_monitor_packet_ingress_rate_limit_by_memory(0, 0, free_heap_percentage);
3333
}

test/nanostack/unittest/Core/monitor/test_monitor.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "NWK_INTERFACE/Include/protocol.h"
2222
#include "nsdynmemLIB_stub.h"
2323
#include "ipv6_routing_table_stub.h""
24+
#include "ns_monitor.h"
2425

2526
bool test_ns_monitor_init()
2627
{
@@ -68,44 +69,51 @@ bool test_ns_monitor_heap_gc_threshold_set()
6869
nsdynmemlib_stub.returnCounter = 1;
6970
ret_val = ns_monitor_init();
7071
if (ret_val != 0) {
72+
printf("Init Monitor FAIL %d\n", ret_val);
7173
return false;
7274
}
7375

7476
// high and critical are equal. NOK
75-
ret_val = ns_monitor_heap_gc_threshold_set(100, 100);
77+
ret_val = ns_monitor_heap_gc_threshold_set(0, 0, 100, 0, 0, 100);
7678
if (ret_val == 0) {
79+
printf("high and critical are equal. NOK\n");
7780
return false;
7881
}
7982

8083

8184
// high is bigger than critical. NOK
82-
ret_val = ns_monitor_heap_gc_threshold_set(100, 80);
85+
ret_val = ns_monitor_heap_gc_threshold_set(0, 0, 100, 0, 0, 80);
8386
if (ret_val == 0) {
87+
printf("high is bigger than critical. NOK\n");
8488
return false;
8589
}
8690

8791

8892
// Too big, NOK
89-
ret_val = ns_monitor_heap_gc_threshold_set(80, 101);
93+
ret_val = ns_monitor_heap_gc_threshold_set(0, 0, 80, 0, 0, 101);
9094
if (ret_val == 0) {
95+
printf("Too big, NOK\n");
9196
return false;
9297
}
9398

9499
// OK
95-
ret_val = ns_monitor_heap_gc_threshold_set(50, 80);
100+
ret_val = ns_monitor_heap_gc_threshold_set(0, 0, 50, 0, 0, 80);
96101
if (ret_val != 0) {
102+
printf("OK Failed\n");
97103
return false;
98104
}
99105

100106
// clear monitor
101107
ret_val = ns_monitor_clear();
102108
if (ret_val != 0) {
109+
printf("clear monitor\n");
103110
return false;
104111
}
105112

106113
// clear monitor again - NOK
107114
ret_val = ns_monitor_clear();
108115
if (ret_val == 0) {
116+
printf("clear monitor again - NOK\n");
109117
return false;
110118
}
111119

@@ -124,19 +132,22 @@ bool test_ns_monitor_timer()
124132
nsdynmemlib_stub.returnCounter = 1;
125133
ret_val = ns_monitor_init();
126134
if (ret_val != 0) {
135+
printf("init fail\n");
127136
return false;
128137
}
129138

130139
// nothing happens
131140
ns_monitor_timer(1);
132141
if (ipv6_routing_table_stub_called) {
142+
printf("nothing happens\n");
133143
return false;
134144
}
135145

136146
// allocation failure - critical gc
137147
nsdynmemlib_mem_stats_stub.heap_alloc_fail_cnt = 1;
138148
ns_monitor_timer(1);
139149
if (!ipv6_routing_table_stub_called) {
150+
printf("stub not called\n");
140151
return false;
141152
}
142153
ipv6_routing_table_stub_called = false;
@@ -145,45 +156,52 @@ bool test_ns_monitor_timer()
145156
nsdynmemlib_mem_stats_stub.heap_alloc_fail_cnt = 2;
146157
ns_monitor_timer(1);
147158
if (ipv6_routing_table_stub_called) {
159+
printf("allocation failure again - nothing happens\n");
148160
return false;
149161
}
150162
ipv6_routing_table_stub_called = false;
151163

152164
// Monitor state is changed to idle after allocation error
153165
ns_monitor_timer(100);
154166
if (ipv6_routing_table_stub_called) {
167+
printf("Monitor state is changed to idle after allocation error\n");
155168
return false;
156169
}
157170

158171
// Set thresholds and allocation - High GC
159-
ret_val = ns_monitor_heap_gc_threshold_set(40, 80);
172+
ret_val = ns_monitor_heap_gc_threshold_set(0, 0, 40, 0, 0, 80);
160173
if (ret_val != 0) {
174+
printf("Set thresholds and allocation - High GC\n");
161175
return false;
162176
}
163177
nsdynmemlib_mem_stats_stub.heap_sector_allocated_bytes = 45;
164178
ns_monitor_timer(100);
165179
if (!ipv6_routing_table_stub_called) {
180+
printf("stub 2 not called\n");
166181
return false;
167182
}
168183
ipv6_routing_table_stub_called = false;
169184

170185
// Timer elapses again - no GC
171186
ns_monitor_timer(100);
172187
if (ipv6_routing_table_stub_called) {
188+
printf("Timer elapses again - no GC\n");
173189
return false;
174190
}
175191

176192
// more memory allocated - Critical GC
177193
nsdynmemlib_mem_stats_stub.heap_sector_allocated_bytes = 95;
178194
ns_monitor_timer(100);
179195
if (!ipv6_routing_table_stub_called) {
196+
printf("more memory allocated - Critical GC\n");
180197
return false;
181198
}
182199
ipv6_routing_table_stub_called = false;
183200

184201
// clear monitor
185202
ret_val = ns_monitor_clear();
186203
if (ret_val != 0) {
204+
printf("clear monitor\n");
187205
return false;
188206
}
189207

test/nanostack/unittest/stub/mbed_trace_stub.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,19 @@ void mbed_trace_include_filters_set(char *filters)
9090

9191
void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...)
9292
{
93+
va_list arglist;
94+
printf("Trace: level %d [%s]", dlevel, grp);
95+
va_start(arglist, fmt);
96+
vprintf(fmt, arglist);
97+
printf("\n");
98+
va_end(arglist);
9399
}
94100

95101
void mbed_vtracef(uint8_t dlevel, const char *grp, const char *fmt, va_list ap)
96102
{
103+
printf("Trace: level %d [%s]", dlevel, grp);
104+
vprintf(fmt, ap);
105+
printf("\n");
97106
}
98107

99108
const char *mbed_trace_last(void)

test/nanostack/unittest/stub/ns_monitor_stub.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ void ns_monitor_timer(uint16_t seconds)
3737
{
3838
}
3939

40-
int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical)
40+
int ns_monitor_heap_gc_threshold_set(uint32_t high_min, uint32_t high_max, uint8_t high_percentage, uint32_t critical_min, uint32_t critical_max, uint8_t critical_percentage)
4141
{
4242
return 0;
4343
}
4444

45-
int ns_monitor_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
45+
int ns_monitor_packet_ingress_rate_limit_by_memory(uint32_t minimum_required, uint32_t Maximum_allowed, uint8_t free_heap_percentage)
4646
{
4747
return 0;
4848
}

0 commit comments

Comments
 (0)