Skip to content

Commit eaf8907

Browse files
author
Arto Kinnunen
authored
Limit amount of incoming packet based on memory (#2128)
Add new API to MAC layer to limit amount of incoming packets when there is not enough memory available.
1 parent 0c2b383 commit eaf8907

File tree

13 files changed

+137
-17
lines changed

13 files changed

+137
-17
lines changed

nanostack/sw_mac.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -82,11 +82,20 @@ extern struct fhss_api *ns_sw_mac_get_fhss_api(struct mac_api_s *mac_api);
8282
extern int ns_sw_mac_statistics_start(struct mac_api_s *mac_api, struct mac_statistics_s *mac_statistics);
8383

8484
/**
85-
* @brief Read current timestamp for compared storaged data timestamp.
85+
* @brief Read current timestamp.
8686
* @param mac_api MAC instance.
8787
* @return Current timestamp in us
8888
*/
89-
uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api);
89+
extern uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api);
90+
91+
/**
92+
* @brief Limit amount of incoming packets if system does not have enough free memory.
93+
* Memory statistics must been initialized in nsdynmemLIB to get this feature working.
94+
*
95+
* @param free_heap_percentage Percentage of free heap that must be available when packet arrives to MAC layer.
96+
* @return 0 in case of success, <0 otherwise.
97+
*/
98+
extern int ns_sw_mac_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage);
9099

91100
#ifdef __cplusplus
92101
}

source/MAC/IEEE802_15_4/mac_mcps_sap.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s
7474

7575
static int8_t mac_tasklet_event_handler = -1;
7676

77+
static uint32_t ns_dyn_mem_rate_limiting_threshold = 0xFFFFFFFF;
78+
7779
/**
7880
* Get PHY time stamp.
7981
*
@@ -686,6 +688,7 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
686688
{
687689
int8_t retval = -1;
688690
uint8_t status;
691+
689692
//allocate Data ind primitiv and parse packet to that
690693
mcps_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(mcps_data_ind_t));
691694

@@ -2068,13 +2071,20 @@ void mcps_sap_pre_parsed_frame_buffer_free(mac_pre_parsed_frame_t *buf)
20682071

20692072
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length)
20702073
{
2074+
// check that system has enough space to handle the new packet
2075+
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
2076+
if (ns_dyn_mem_stat && ns_dyn_mem_stat->heap_sector_allocated_bytes > ns_dyn_mem_rate_limiting_threshold) {
2077+
return NULL;
2078+
}
2079+
20712080
mac_pre_parsed_frame_t *buffer = ns_dyn_mem_temporary_alloc(sizeof(mac_pre_parsed_frame_t) + frame_length);
20722081

20732082
if (buffer) {
20742083
memset(buffer, 0, sizeof(mac_pre_parsed_frame_t) + frame_length);
20752084
buffer->frameLength = frame_length;
20762085
memcpy(mac_header_message_start_pointer(buffer), data_ptr, frame_length);
20772086
}
2087+
20782088
return buffer;
20792089
}
20802090

@@ -2298,3 +2308,15 @@ uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_set
22982308

22992309
return confirmation.status;
23002310
}
2311+
2312+
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
2313+
{
2314+
const mem_stat_t *ns_dyn_mem_stat = ns_dyn_mem_get_mem_stat();
2315+
2316+
if (ns_dyn_mem_stat && free_heap_percentage < 100) {
2317+
ns_dyn_mem_rate_limiting_threshold = ns_dyn_mem_stat->heap_sector_size / 100 * (100 - free_heap_percentage);
2318+
return 0;
2319+
}
2320+
2321+
return -1;
2322+
}

source/MAC/IEEE802_15_4/mac_mcps_sap.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -216,4 +216,6 @@ int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_
216216

217217
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload);
218218

219+
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
220+
219221
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */

source/MAC/IEEE802_15_4/sw_mac.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -715,3 +715,8 @@ uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api)
715715
mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_GET_TIMESTAMP, (uint8_t *)&time_stamp_buffer);
716716
return time_stamp_buffer;
717717
}
718+
719+
int ns_sw_mac_packet_ingress_rate_limit_by_mem(uint8_t free_heap_percentage)
720+
{
721+
return mcps_packet_ingress_rate_limit_by_memory(free_heap_percentage);
722+
}

test/nanostack/unittest/mac/mac_mcps_sap/mac_mcps_saptest.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -128,3 +128,8 @@ TEST(mac_mcps_sap, test_mcps_sap_data_req_handler_ext)
128128
CHECK(test_mcps_sap_data_req_handler_ext());
129129
}
130130

131+
TEST(mac_mcps_sap, test_mcps_packet_ingress_rate_limit_by_memory)
132+
{
133+
CHECK(test_mcps_packet_ingress_rate_limit_by_memory());
134+
}
135+

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

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,7 +59,6 @@
5959

6060
static uint8_t tes_mac_mcps_mac64[8];
6161

62-
6362
static mac_pre_build_frame_t *tes_mac_mcps_temporary_buffer_get(uint16_t length)
6463
{
6564
mac_pre_build_frame_t *buf = malloc(sizeof(mac_pre_build_frame_t));
@@ -75,7 +74,6 @@ static mac_pre_build_frame_t *tes_mac_mcps_temporary_buffer_get(uint16_t length)
7574
return buf;
7675
}
7776

78-
7977
static void test_mac_buffer_init(mac_pre_parsed_frame_t *buffer, uint16_t header_length, uint16_t payload_length, uint8_t security_length)
8078
{
8179
buffer->mac_header_length = header_length;
@@ -2189,6 +2187,27 @@ bool test_mcps_sap_pre_parsed_frame_buffer_get()
21892187
if (memcmp(mac_header_message_start_pointer(buf), buffer, 8) != 0) {
21902188
return false;
21912189
}
2190+
ns_dyn_mem_free(buf);
2191+
2192+
// Test that if dynamic memory is low, then allocation fails
2193+
// Update memory stats: heap size = 1000, allocated 600
2194+
nsdynmemlib_stub.returnCounter = 1;
2195+
nsdynmemlib_mem_stats_stub.heap_sector_size = 1000;
2196+
nsdynmemlib_mem_stats_stub.heap_sector_allocated_bytes = 600;
2197+
// Set ingress limit to 50% = 500 bytes
2198+
mcps_packet_ingress_rate_limit_by_memory(50);
2199+
buf = mcps_sap_pre_parsed_frame_buffer_get(buffer, 8);
2200+
if (buf) {
2201+
return false;
2202+
}
2203+
2204+
// Test that allocation succeeds when there is enough heap
2205+
nsdynmemlib_stub.returnCounter = 1;
2206+
nsdynmemlib_mem_stats_stub.heap_sector_allocated_bytes = 400;
2207+
buf = mcps_sap_pre_parsed_frame_buffer_get(buffer, 8);
2208+
if (!buf || buf->frameLength != 8) {
2209+
return false;
2210+
}
21922211

21932212
ns_dyn_mem_free(buf);
21942213
return true;
@@ -3199,3 +3218,25 @@ bool test_mcps_sap_data_req_handler_ext()
31993218
test_mac_rf_mac_class_free(rf_mac_setup);
32003219
return true;
32013220
}
3221+
3222+
bool test_mcps_packet_ingress_rate_limit_by_memory()
3223+
{
3224+
3225+
int ret_val;
3226+
3227+
nsdynmemlib_mem_stats_stub.heap_sector_size = 1000;
3228+
3229+
// Too big percentage
3230+
ret_val = mcps_packet_ingress_rate_limit_by_memory(101);
3231+
if (ret_val == 0) {
3232+
return false;
3233+
}
3234+
3235+
// OK case
3236+
ret_val = mcps_packet_ingress_rate_limit_by_memory(50);
3237+
if (ret_val != 0) {
3238+
return false;
3239+
}
3240+
3241+
return true;
3242+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -63,6 +63,8 @@ bool test_mac_mcps_data_confirmation();
6363

6464
bool test_mcps_sap_data_req_handler_ext();
6565

66+
bool test_mcps_packet_ingress_rate_limit_by_memory();
67+
6668
#ifdef __cplusplus
6769
}
6870
#endif

test/nanostack/unittest/mac/sw_mac/sw_mactest.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -114,3 +114,8 @@ TEST(sw_mac, test_ns_sw_mac_virtual_client_unregister)
114114
CHECK(test_ns_sw_mac_virtual_client_unregister());
115115
}
116116

117+
TEST(sw_mac, test_ns_sw_mac_packet_ingress_rate_limit_by_mem)
118+
{
119+
CHECK(test_ns_sw_mac_packet_ingress_rate_limit_by_mem());
120+
}
121+

test/nanostack/unittest/mac/sw_mac/test_sw_mac.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -477,6 +477,20 @@ bool test_ns_sw_mac_virtual_client_unregister()
477477
return true;
478478
}
479479

480+
bool test_ns_sw_mac_packet_ingress_rate_limit_by_mem()
481+
{
482+
int ret_val;
483+
484+
mac_mcps_sap_stub.int8_value = 0;
485+
486+
ret_val = ns_sw_mac_packet_ingress_rate_limit_by_mem(99);
487+
if (ret_val != 0) {
488+
return false;
489+
}
490+
491+
return true;
492+
}
493+
480494
bool test_mlme_req()
481495
{
482496
arm_device_driver_list_s list;

test/nanostack/unittest/mac/sw_mac/test_sw_mac.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2017, Arm Limited and affiliates.
2+
* Copyright (c) 2016-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,6 +59,8 @@ bool test_ns_sw_mac_virtual_client_unregister();
5959
// Test registering FHSS to software MAC
6060
bool test_ns_sw_mac_fhss_register();
6161

62+
bool test_ns_sw_mac_packet_ingress_rate_limit_by_mem();
63+
6264
#ifdef __cplusplus
6365
}
6466
#endif

test/nanostack/unittest/stub/mac_mcps_sap_stub.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2014-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -152,6 +152,11 @@ uint8_t mcps_sap_purge_reg_handler(protocol_interface_rf_mac_setup_s *rf_mac_set
152152
return 0;
153153
}
154154

155+
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
156+
{
157+
return (int)mac_mcps_sap_stub.int8_value;
158+
}
159+
155160
int mac_convert_frame_type_to_fhss(uint8_t frame_type)
156161
{
157162
return 0;

test/nanostack/unittest/stub/nsdynmemLIB_stub.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014-2015, 2017-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2014-2015, 2017-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,13 +17,14 @@
1717
#include "nsdynmemLIB_stub.h"
1818
#include <stdint.h>
1919
#include <string.h>
20-
#include <nsdynmemLIB.h>
20+
#include "nsdynmemLIB.h"
2121
#include "platform/arm_hal_interrupt.h"
2222
#ifdef STANDARD_MALLOC
2323
#include <stdlib.h>
2424
#endif
2525

2626
nsdynmemlib_stub_data_t nsdynmemlib_stub;
27+
mem_stat_t nsdynmemlib_mem_stats_stub;
2728

2829
#if NSDYNMEMLIB_API_VERSION < 2
2930
typedef int16_t ns_mem_block_size_t;
@@ -61,3 +62,8 @@ void ns_dyn_mem_free(void *block)
6162
{
6263
free(block);
6364
}
65+
66+
const mem_stat_t *ns_dyn_mem_get_mem_stat(void)
67+
{
68+
return &nsdynmemlib_mem_stats_stub;
69+
}

test/nanostack/unittest/stub/nsdynmemLIB_stub.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015-2018, Arm Limited and affiliates.
2+
* Copyright (c) 2015-2019, Arm Limited and affiliates.
33
* SPDX-License-Identifier: Apache-2.0
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,13 +22,15 @@ extern "C" {
2222
#endif
2323

2424
#include "stdint.h"
25+
#include "nsdynmemLIB.h"
2526

2627
typedef struct {
2728
uint8_t returnCounter;
2829
void *expectedPointer;
2930
} nsdynmemlib_stub_data_t;
3031

3132
extern nsdynmemlib_stub_data_t nsdynmemlib_stub;
33+
extern mem_stat_t nsdynmemlib_mem_stats_stub;
3234

3335
#ifdef __cplusplus
3436
}

0 commit comments

Comments
 (0)