From 61315d197624480acfe555a3031228e62a55b239 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 19 Jan 2021 11:28:52 +0200 Subject: [PATCH 1/7] Squashed 'connectivity/drivers/802.15.4_RF/atmel-rf-driver/' changes from ae4ef1b197..b1a8186d75 b1a8186d75 Merge pull request #105 from PelionIoT/sync_with_mbed_os 4b24dd04f0 Allow builds with Mbed OS version less than 6.0 81666bd114 Replace calls to deprecated functions in the Timer API c1b436b1f7 Merge pull request #104 from PelionIoT/IOTTHD-4408 6cd27661c0 Use given OFDM configuration 292da06289 Merge pull request #102 from ARMmbed/IOTTHD-4320 079dfa7dd8 Atmel & PA: Output power at 900MHz: -4 dBm with FSK/QPSK, less than -10 dBm with OFDM git-subtree-dir: connectivity/drivers/802.15.4_RF/atmel-rf-driver git-subtree-split: b1a8186d7571fb49e048bb91910cc18c17861bda --- source/AT86RF215Reg.h | 1 + source/NanostackRfPhyAT86RF215.cpp | 49 ++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/source/AT86RF215Reg.h b/source/AT86RF215Reg.h index 6846845cb0..47b8a46fd4 100644 --- a/source/AT86RF215Reg.h +++ b/source/AT86RF215Reg.h @@ -96,6 +96,7 @@ extern "C" { // RF_PAC #define TXPWR 0x1F +#define TXPWR_7 (7 << 0) #define TXPWR_11 (11 << 0) #define TXPWR_0 (0 << 0) #define TXPWR_31 (31 << 0) diff --git a/source/NanostackRfPhyAT86RF215.cpp b/source/NanostackRfPhyAT86RF215.cpp index d90e07261d..149395490e 100644 --- a/source/NanostackRfPhyAT86RF215.cpp +++ b/source/NanostackRfPhyAT86RF215.cpp @@ -30,9 +30,24 @@ #include #include "Timeout.h" #include "SPI.h" +#include "platform/mbed_version.h" #define TRACE_GROUP "AtRF" +#if (MBED_VERSION > MBED_ENCODE_VERSION(6, 0, 0)) +/* Mbed OS 6.0 introduces support for chrono time management */ +using namespace std::chrono_literals; +#define ATMEL_RF_TIME_65MS 65ms +#define ATMEL_RF_TIME_1US 1us +#define ATMEL_RF_ATTACH(timer_ref, signal_ref, timeout_ref) timer_ref.attach(signal_ref, timeout_ref) +#define ATMEL_RF_DRIVER_CHRONO_SUPPORTED +#else +#define ATMEL_RF_TIME_65MS 65000 +#define ATMEL_RF_TIME_1US 1 + +#define ATMEL_RF_ATTACH(timer_ref, signal_ref, timeout_ref) timer_ref.attach_us(signal_ref, timeout_ref) +#endif + #define RF_MTU_15_4_2011 127 #define RF_MTU_15_4G_2012 2047 @@ -196,7 +211,11 @@ static Se2435Pins *se2435_pa_pins = NULL; static uint32_t rf_get_timestamp(void) { +#ifdef ATMEL_RF_DRIVER_CHRONO_SUPPORTED + return (uint32_t)rf->tx_timer.elapsed_time().count(); +#else return (uint32_t)rf->tx_timer.read_us(); +#endif } static void rf_lock(void) @@ -485,7 +504,7 @@ static void rf_init_registers(rf_modules_e module) // Set low frequency offset bit rf_write_bbc_register_field(BBC_OFDMC, module, LFO, 0); // Configure using bandwidth option - rf_configure_by_ofdm_bandwidth_option(4, 300000, module); + rf_configure_by_ofdm_bandwidth_option(phy_current_config.ofdm_option, phy_current_config.datarate, module); // Set Gain control settings rf_write_rf_register_field(RF_AGCC, module, AVGS, AVGS_8_SAMPLES); rf_write_rf_register_field(RF_AGCC, module, AGCI, 0); @@ -499,8 +518,8 @@ static void rf_init_registers(rf_modules_e module) se2435_pa_pins->ANT_SEL = 0; // Enable external front end with configuration 3 rf_write_rf_register_field(RF_PADFE, module, PADFE, RF_FEMODE3); - // Output power at 900MHz: 0 dBm with FSK/QPSK, less than -5 dBm with OFDM - rf_tx_power = TXPWR_11; + // Output power at 900MHz: -4 dBm with FSK/QPSK, less than -10 dBm with OFDM + rf_tx_power = TXPWR_7; } // Set TX output power rf_write_rf_register_field(RF_PAC, module, TXPWR, rf_tx_power); @@ -564,17 +583,21 @@ static int8_t rf_start_csma_ca(uint8_t *data_ptr, uint16_t data_length, uint8_t mac_tx_handle = tx_handle; if (tx_time) { +#ifdef ATMEL_RF_DRIVER_CHRONO_SUPPORTED + std::chrono::microseconds backoff_time(tx_time - rf_get_timestamp()); +#else uint32_t backoff_time = tx_time - rf_get_timestamp(); +#endif // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately - if (backoff_time <= 65000) { - rf->cca_timer.attach_us(rf_csma_ca_timer_signal, backoff_time); + if (backoff_time <= ATMEL_RF_TIME_65MS) { + ATMEL_RF_ATTACH(rf->cca_timer, rf_csma_ca_timer_signal, backoff_time); TEST_CSMA_STARTED rf_unlock(); return 0; } } // Short timeout to start CCA immediately. - rf->cca_timer.attach_us(rf_csma_ca_timer_signal, 1); + ATMEL_RF_ATTACH(rf->cca_timer, rf_csma_ca_timer_signal, ATMEL_RF_TIME_1US); TEST_CSMA_STARTED rf_unlock(); return 0; @@ -607,12 +630,16 @@ static void rf_handle_cca_ed_done(void) if (cca_prepare_status == PHY_RESTART_CSMA) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_OK, 0, 0); if (tx_time) { +#ifdef ATMEL_RF_DRIVER_CHRONO_SUPPORTED + std::chrono::microseconds backoff_time(tx_time - rf_get_timestamp()); +#else uint32_t backoff_time = tx_time - rf_get_timestamp(); +#endif // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately - if (backoff_time > 65000) { - backoff_time = 1; + if (backoff_time > ATMEL_RF_TIME_65MS) { + backoff_time = ATMEL_RF_TIME_1US; } - rf->cca_timer.attach_us(rf_csma_ca_timer_signal, backoff_time); + ATMEL_RF_ATTACH(rf->cca_timer, rf_csma_ca_timer_signal, backoff_time); TEST_CSMA_STARTED } return; @@ -994,7 +1021,11 @@ static uint32_t rf_backup_timer_start(uint16_t bytes, uint32_t time_us) time_us = (uint32_t)(8000000 / phy_current_config.datarate) * bytes + PACKET_PROCESSING_TIME; } // Using cal_timer as backup timer +#ifdef ATMEL_RF_DRIVER_CHRONO_SUPPORTED + rf->cal_timer.attach(rf_backup_timer_signal, std::chrono::microseconds(time_us)); +#else rf->cal_timer.attach_us(rf_backup_timer_signal, time_us); +#endif return (rf_get_timestamp() + time_us); } From 2f56ffab52d78986aebc1a290f106f5cf58830f8 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 19 Jan 2021 11:38:58 +0200 Subject: [PATCH 2/7] Squashed 'connectivity/nanostack/sal-stack-nanostack-eventloop/' changes from 86cf0cca08..fb20d3f32c fb20d3f32c Merge remote-tracking branch 'origin/master' into release_for_mbed_os d182fa4b3a Follow Mbed OS coding style (#47) 806f54cea9 Use event id 0 for initialization event (#45) git-subtree-dir: connectivity/nanostack/sal-stack-nanostack-eventloop git-subtree-split: fb20d3f32c84e2a3b2335d01df36100b5b5881ec --- source/event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/event.c b/source/event.c index 337cd14ac4..1741f6b8f6 100644 --- a/source/event.c +++ b/source/event.c @@ -109,6 +109,7 @@ int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uin event_tmp->data.receiver = new->id; event_tmp->data.sender = 0; event_tmp->data.event_type = init_event_type; + event_tmp->data.event_id = 0; event_tmp->data.event_data = 0; event_core_write(event_tmp); @@ -197,7 +198,9 @@ void event_core_free_push(arm_event_storage_t *free) timer_sys_event_free(free); break; case ARM_LIB_EVENT_USER: + // *INDENT-OFF* // No need set state to UNQUEUED - we forget about it. + // *INDENT-ON* default: break; } From 084b722d1c3fa00e29d7ded181aaabbcc3f1f793 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 19 Jan 2021 11:42:08 +0200 Subject: [PATCH 3/7] Squashed 'connectivity/libraries/nanostack-libservice/' changes from 67d7b93ec6..a526cc3f41 a526cc3f41 Merge pull request #97 from PelionIoT/sync_from_mbed_os 2f82569918 Add license notice to Arm copyrighted source files ad7631083a Merge pull request #96 from PelionIoT/heap_lite_stats 18b742b2c7 Heap stat's enabled allways by default. 9b4cbaf101 Added extended block list to dynamic memory tracker (#95) 8ff6d31abb Added dynamic memory tracker and hooks to dynmem library (#93) cf2b133082 Merge pull request #92 from LDong-Arm/add_present_flag 9eb6f2dde7 Add config to generate macro MBED_CONF_NANOSTACK_LIBSERVICE_PRESENT git-subtree-dir: connectivity/libraries/nanostack-libservice git-subtree-split: a526cc3f41bfd0ec6a78e6998b8f8dcc1bd2afc9 --- Makefile | 1 + mbed-client-libservice/nsdynmemLIB.h | 10 +- mbed-client-libservice/nsdynmem_tracker.h | 46 ++ mbed-client-libservice/nsdynmem_tracker_lib.h | 104 ++++ mbed_lib.json | 10 +- source/nsdynmemLIB/nsdynmemLIB.c | 80 +-- source/nsdynmemtracker/nsdynmem_tracker_lib.c | 480 ++++++++++++++++++ .../unittest/nsdynmem/dynmemtest.cpp | 4 +- test/libService/unittest/nsnvmhelper/main.cpp | 13 + .../unittest/nsnvmhelper/nsnvmhelpertest.cpp | 13 + .../unittest/nsnvmhelper/test_ns_nvm_helper.c | 13 + .../unittest/nsnvmhelper/test_ns_nvm_helper.h | 13 + 12 files changed, 743 insertions(+), 44 deletions(-) create mode 100644 mbed-client-libservice/nsdynmem_tracker.h create mode 100644 mbed-client-libservice/nsdynmem_tracker_lib.h create mode 100644 source/nsdynmemtracker/nsdynmem_tracker_lib.c diff --git a/Makefile b/Makefile index 24fd3418e9..390ff1f777 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ source/libip6string/ip6tos.c \ source/libip6string/stoip6.c \ source/libList/ns_list.c \ source/nsdynmemLIB/nsdynmemLIB.c \ +source/nsdynmemtracker/nsdynmem_tracker_lib.c \ source/nvmHelper/ns_nvm_helper.c \ LIB := libservice.a diff --git a/mbed-client-libservice/nsdynmemLIB.h b/mbed-client-libservice/nsdynmemLIB.h index bf0056ba1a..ee91bfc8b1 100644 --- a/mbed-client-libservice/nsdynmemLIB.h +++ b/mbed-client-libservice/nsdynmemLIB.h @@ -37,6 +37,9 @@ extern "C" { typedef size_t ns_mem_block_size_t; //external interface unsigned heap block size type typedef size_t ns_mem_heap_size_t; //total heap size type. +// Can be used to enable tracking of dynamic memory allocations +#include "nsdynmem_tracker.h" + /*! * \enum heap_fail_t * \brief Dynamically heap system failure call back event types. @@ -64,7 +67,6 @@ typedef struct mem_stat_t { uint32_t heap_alloc_fail_cnt; /**< Counter for Heap allocation fail. */ } mem_stat_t; - typedef struct ns_mem_book ns_mem_book_t; /** @@ -99,7 +101,9 @@ extern int ns_dyn_mem_region_add(void *region_ptr, ns_mem_heap_size_t region_siz * \return 0, Free OK * \return <0, Free Fail */ +#if NSDYNMEM_TRACKER_ENABLED!=1 extern void ns_dyn_mem_free(void *heap_ptr); +#endif /** * \brief Allocate temporary data. @@ -111,7 +115,9 @@ extern void ns_dyn_mem_free(void *heap_ptr); * \return 0, Allocate Fail * \return >0, Pointer to allocated data sector. */ +#if NSDYNMEM_TRACKER_ENABLED!=1 extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size); +#endif /** * \brief Allocate long period data. @@ -123,7 +129,9 @@ extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size); * \return 0, Allocate Fail * \return >0, Pointer to allocated data sector. */ +#if NSDYNMEM_TRACKER_ENABLED!=1 extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size); +#endif /** * \brief Get pointer to the current mem_stat_t set via ns_dyn_mem_init. diff --git a/mbed-client-libservice/nsdynmem_tracker.h b/mbed-client-libservice/nsdynmem_tracker.h new file mode 100644 index 0000000000..c0fccdf97e --- /dev/null +++ b/mbed-client-libservice/nsdynmem_tracker.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file nsdynmem_tracker.h + * \brief Dynamical Memory Tracker definitions to override the default NS dynamic memory functionality + * Provides tracking and tracing of dynamic memory blocks + */ + +#ifndef NSDYNMEM_TRACKER_H_ +#define NSDYNMEM_TRACKER_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if NSDYNMEM_TRACKER_ENABLED==1 + +#define ns_dyn_mem_free(block) ns_dyn_mem_tracker_dyn_mem_free(block, __func__, __LINE__) +#define ns_dyn_mem_temporary_alloc(alloc_size) ns_dyn_mem_tracker_dyn_mem_temporary_alloc(alloc_size, __func__, __LINE__) +#define ns_dyn_mem_alloc(alloc_size) ns_dyn_mem_tracker_dyn_mem_alloc(alloc_size, __func__, __LINE__) + +void *ns_dyn_mem_tracker_dyn_mem_alloc(ns_mem_heap_size_t alloc_size, const char *function, uint32_t line); +void *ns_dyn_mem_tracker_dyn_mem_temporary_alloc(ns_mem_heap_size_t alloc_size, const char *function, uint32_t line); +void ns_dyn_mem_tracker_dyn_mem_free(void *block, const char *function, uint32_t line); + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* NSDYNMEM_TRACKER_H_ */ + + diff --git a/mbed-client-libservice/nsdynmem_tracker_lib.h b/mbed-client-libservice/nsdynmem_tracker_lib.h new file mode 100644 index 0000000000..aa76f390bf --- /dev/null +++ b/mbed-client-libservice/nsdynmem_tracker_lib.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * \file nsdynmem_tracker_lib.h + * \brief Dynamical Memory Tracker library API + * Provides tracking and tracing of dynamic memory blocks + */ + +#ifndef NSDYNMEM_TRACKER_LIB_H_ +#define NSDYNMEM_TRACKER_LIB_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if NSDYNMEM_TRACKER_ENABLED==1 + +// Memory block structure with caller information +typedef struct ns_dyn_mem_tracker_lib_mem_blocks_s { + void *block; /**< Allocated memory block */ + void *caller_addr; /**< Caller address */ + uint32_t size; /**< Allocation size */ + uint32_t total_size; /**< Total allocation size for all allocations */ + uint32_t lifetime; /**< Memory block lifetime in steps (e.g. seconds) */ + uint32_t ref_count; /**< Reference count */ + const char *function; /**< Caller function */ + uint16_t line; /**< Caller line in module */ + bool permanent : 1; /**< Permanent memory block */ + bool permanent_printed : 1; /**< Permanent memory block printed */ +} ns_dyn_mem_tracker_lib_mem_blocks_t; + +// Extended memory block structure that is used if same caller allocates multiple memory blocks +typedef struct ns_dyn_mem_tracker_lib_mem_blocks_ext_s { + void *block; /**< Allocated memory block */ + void *caller_addr; /**< Caller address */ + uint32_t size; /**< Allocation size */ +} ns_dyn_mem_tracker_lib_mem_blocks_ext_t; + +// Allocator information structure +typedef struct ns_dyn_mem_tracker_lib_allocators_s { + void *caller_addr; /**< Caller address */ + uint32_t alloc_count; /**< Number of allocations */ + uint32_t total_memory; /**< Total memory used by allocations */ + uint32_t min_lifetime; /**< Shortest lifetime among the allocations */ + const char *function; /**< Function name string */ + uint16_t line; /**< Module line */ +} ns_dyn_mem_tracker_lib_allocators_t; + +// Memory block array allocator / array size increase allocator +typedef ns_dyn_mem_tracker_lib_mem_blocks_t *ns_dyn_mem_tracker_lib_alloc_mem_blocks(ns_dyn_mem_tracker_lib_mem_blocks_t *blocks, uint16_t *mem_blocks_count); +// Extended memory block array allocator / array size increase allocator +typedef ns_dyn_mem_tracker_lib_mem_blocks_ext_t *ns_dyn_mem_tracker_lib_alloc_mem_blocks_ext(ns_dyn_mem_tracker_lib_mem_blocks_ext_t *blocks, uint32_t *mem_blocks_count); +// Extended memory block array index hash function to get memory block (allocation/search start) index from block address +typedef uint32_t ns_dyn_mem_tracker_lib_mem_block_index_hash(void *block, uint32_t ext_mem_blocks_count); + +typedef struct ns_dyn_mem_tracker_lib_conf_s { + ns_dyn_mem_tracker_lib_mem_blocks_t *mem_blocks; /**< Memory blocks array, if NULL calls allocator on init */ + ns_dyn_mem_tracker_lib_mem_blocks_ext_t *ext_mem_blocks; /**< Extended memory blocks array, if NULL calls allocator on init */ + ns_dyn_mem_tracker_lib_allocators_t *top_allocators; /**< Top allocators array */ + ns_dyn_mem_tracker_lib_allocators_t *permanent_allocators; /**< Permanent allocators */ + ns_dyn_mem_tracker_lib_allocators_t *to_permanent_allocators; /**< To permanent allocators */ + ns_dyn_mem_tracker_lib_allocators_t *max_snap_shot_allocators; /**< Snap shot of maximum memory used by allocators */ + ns_dyn_mem_tracker_lib_alloc_mem_blocks *alloc_mem_blocks; /**< Memory block array allocator / array size increase allocator */ + ns_dyn_mem_tracker_lib_alloc_mem_blocks_ext *ext_alloc_mem_blocks; /**< Extended memory block array allocator / array size increase allocator */ + ns_dyn_mem_tracker_lib_mem_block_index_hash *block_index_hash; /**< Hash function to get memory block index from block address */ + uint32_t allocated_memory; /**< Currently allocated memory */ + uint16_t mem_blocks_count; /**< Number of entries in memory blocks array */ + uint32_t ext_mem_blocks_count; /**< Number of entries in extended memory blocks array */ + uint16_t last_mem_block_index; /**< Last memory block in memory blocks array */ + uint16_t top_allocators_count; /**< Top allocators array count */ + uint16_t permanent_allocators_count; /**< Permanent allocators array count */ + uint16_t to_permanent_allocators_count; /**< To permanent allocators array count */ + uint16_t max_snap_shot_allocators_count; /**< Snap shot of maximum memory used by allocators array count */ + uint16_t to_permanent_steps_count; /**< How many steps before moving block to permanent allocators list */ +} ns_dyn_mem_tracker_lib_conf_t; + +int8_t ns_dyn_mem_tracker_lib_alloc(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, const char *function, uint32_t line, void *block, uint32_t alloc_size); +int8_t ns_dyn_mem_tracker_lib_free(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, const char *function, uint32_t line, void *block); +void ns_dyn_mem_tracker_lib_step(ns_dyn_mem_tracker_lib_conf_t *conf); +int8_t ns_dyn_mem_tracker_lib_allocator_lists_update(ns_dyn_mem_tracker_lib_conf_t *conf); +void ns_dyn_mem_tracker_lib_max_snap_shot_update(ns_dyn_mem_tracker_lib_conf_t *conf); + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* NSDYNMEM_TRACKER_LIB_H_ */ + + diff --git a/mbed_lib.json b/mbed_lib.json index 75957496a9..910933b45e 100644 --- a/mbed_lib.json +++ b/mbed_lib.json @@ -1,3 +1,11 @@ { - "name": "nanostack-libservice" + "name": "nanostack-libservice", + "macros": ["NSDYNMEM_TRACKER_ENABLED=MBED_CONF_NANOSTACK_LIBSERVICE_NSDYNMEM_TRACKER_ENABLED"], + "config": { + "present": 1, + "nsdynmem-tracker-enabled": { + "help": "Use to enable dynamic memory tracker", + "value": 0 + } + } } diff --git a/source/nsdynmemLIB/nsdynmemLIB.c b/source/nsdynmemLIB/nsdynmemLIB.c index 5f913d5758..99ba624e05 100644 --- a/source/nsdynmemLIB/nsdynmemLIB.c +++ b/source/nsdynmemLIB/nsdynmemLIB.c @@ -15,6 +15,7 @@ */ #include #include +#undef NSDYNMEM_TRACKER_ENABLED #include "nsdynmemLIB.h" #include "platform/arm_hal_interrupt.h" #include @@ -47,6 +48,7 @@ struct ns_mem_book { ns_mem_heap_size_t temporary_alloc_heap_limit; /* Amount of reserved heap temporary alloc can't exceed */ }; +static mem_stat_t default_stats; static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use // size of a hole_t in our word units @@ -162,12 +164,14 @@ ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size, ns_list_init(&book->holes_list); ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main[0])); - book->mem_stat_info_ptr = info_ptr; - //RESET Memory by Hea Len if (info_ptr) { - memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t)); - book->mem_stat_info_ptr->heap_sector_size = book->heap_size; + book->mem_stat_info_ptr = info_ptr; + } else { + book->mem_stat_info_ptr = &default_stats; } + //RESET Memory by Heap Len + memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t)); + book->mem_stat_info_ptr->heap_sector_size = book->heap_size; book->temporary_alloc_heap_limit = book->heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD); #endif //There really is no support to standard malloc in this library anymore @@ -234,9 +238,7 @@ int ns_mem_region_add(ns_mem_book_t *book, void *region_ptr, ns_mem_heap_size_t // adjust total heap size with new hole book->heap_size += region_size; - if (book->mem_stat_info_ptr) { - book->mem_stat_info_ptr->heap_sector_size = book->heap_size; - } + book->mem_stat_info_ptr->heap_sector_size = book->heap_size; // adjust temporary allocation limits to match new heap book->temporary_alloc_heap_limit = book->heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD); @@ -265,8 +267,8 @@ int ns_mem_set_temporary_alloc_free_heap_threshold(ns_mem_book_t *book, uint8_t #ifndef STANDARD_MALLOC ns_mem_heap_size_t heap_limit = 0; - if (!book || !book->mem_stat_info_ptr) { - // no book or mem_stats + if (!book) { + // no book return -1; } @@ -304,25 +306,25 @@ extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_ #ifndef STANDARD_MALLOC static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size) { - if (mem_stat_info_ptr) { - switch (type) { - case DEV_HEAP_ALLOC_OK: - mem_stat_info_ptr->heap_sector_alloc_cnt++; - mem_stat_info_ptr->heap_sector_allocated_bytes += size; - if (mem_stat_info_ptr->heap_sector_allocated_bytes_max < mem_stat_info_ptr->heap_sector_allocated_bytes) { - mem_stat_info_ptr->heap_sector_allocated_bytes_max = mem_stat_info_ptr->heap_sector_allocated_bytes; - } - mem_stat_info_ptr->heap_alloc_total_bytes += size; - break; - case DEV_HEAP_ALLOC_FAIL: - mem_stat_info_ptr->heap_alloc_fail_cnt++; - break; - case DEV_HEAP_FREE: - mem_stat_info_ptr->heap_sector_alloc_cnt--; - mem_stat_info_ptr->heap_sector_allocated_bytes -= size; - break; - } + + switch (type) { + case DEV_HEAP_ALLOC_OK: + mem_stat_info_ptr->heap_sector_alloc_cnt++; + mem_stat_info_ptr->heap_sector_allocated_bytes += size; + if (mem_stat_info_ptr->heap_sector_allocated_bytes_max < mem_stat_info_ptr->heap_sector_allocated_bytes) { + mem_stat_info_ptr->heap_sector_allocated_bytes_max = mem_stat_info_ptr->heap_sector_allocated_bytes; + } + mem_stat_info_ptr->heap_alloc_total_bytes += size; + break; + case DEV_HEAP_ALLOC_FAIL: + mem_stat_info_ptr->heap_alloc_fail_cnt++; + break; + case DEV_HEAP_FREE: + mem_stat_info_ptr->heap_sector_alloc_cnt--; + mem_stat_info_ptr->heap_sector_allocated_bytes -= size; + break; } + } static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_block_size_t requested_bytes) @@ -363,7 +365,7 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_ return NULL; } - if (book->mem_stat_info_ptr && direction == 1) { + if (direction == 1) { if (book->mem_stat_info_ptr->heap_sector_allocated_bytes > book->temporary_alloc_heap_limit) { /* Not enough heap for temporary memory allocation */ dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0); @@ -441,14 +443,14 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_ block_ptr[1 + data_size] = data_size; done: - if (book->mem_stat_info_ptr) { - if (block_ptr) { - //Update Allocate OK - dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t)); - } else { - //Update Allocate Fail, second parameter is used for stats - dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0); - } + + + if (block_ptr) { + //Update Allocate OK + dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t)); + } else { + //Update Allocate Fail, second parameter is used for stats + dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0); } platform_exit_critical(); @@ -619,10 +621,8 @@ void ns_mem_free(ns_mem_book_t *book, void *block) heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); } else { ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size); - if (book->mem_stat_info_ptr) { - //Update Free Counter - dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t)); - } + //Update Free Counter + dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t)); } } diff --git a/source/nsdynmemtracker/nsdynmem_tracker_lib.c b/source/nsdynmemtracker/nsdynmem_tracker_lib.c new file mode 100644 index 0000000000..9c2bcdfda4 --- /dev/null +++ b/source/nsdynmemtracker/nsdynmem_tracker_lib.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "ns_types.h" +#include "nsdynmem_tracker_lib.h" +#include "platform/arm_hal_interrupt.h" +#include "nsdynmemLIB.h" + +#if NSDYNMEM_TRACKER_ENABLED==1 + +static int8_t ns_dyn_mem_tracker_lib_find_free_index(ns_dyn_mem_tracker_lib_conf_t *conf, uint16_t *index); +static int8_t ns_dyn_mem_tracker_lib_find_caller_index(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, uint16_t *caller_index); +static int8_t ns_dyn_mem_tracker_lib_find_block_index(ns_dyn_mem_tracker_lib_conf_t *conf, void *block, uint16_t *block_index); +static int8_t ns_dyn_mem_tracker_lib_ext_find_free_index(ns_dyn_mem_tracker_lib_conf_t *conf, uint32_t start_index, uint32_t *free_index); +static void ns_dyn_mem_tracker_lib_permanent_printed_value_set(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, bool new_value); +static int8_t ns_dyn_mem_tracker_lib_ext_find_block_index(ns_dyn_mem_tracker_lib_conf_t *conf, void *block, uint32_t start_index, uint32_t *block_index); + +int8_t ns_dyn_mem_tracker_lib_alloc(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, const char *function, uint32_t line, void *block, uint32_t alloc_size) +{ + // Allocation failed + if (block == NULL) { + return 0; + } + + platform_enter_critical(); + + // If dynamic memory blocks are not set, calls allocator + if (conf->mem_blocks == NULL) { + conf->mem_blocks = conf->alloc_mem_blocks(conf->mem_blocks, &conf->mem_blocks_count); + if (conf->mem_blocks == NULL) { + platform_exit_critical(); + return -1; + } + } + + uint16_t caller_index = 0; + if (ns_dyn_mem_tracker_lib_find_caller_index(conf, caller_addr, &caller_index) >= 0) { + if (conf->ext_mem_blocks == NULL) { + conf->ext_mem_blocks = conf->ext_alloc_mem_blocks(conf->ext_mem_blocks, &conf->ext_mem_blocks_count); + if (conf->ext_mem_blocks == NULL) { + platform_exit_critical(); + return -1; + } + } + + uint32_t free_index = 0; + uint32_t start_index = 0; + if (conf->block_index_hash != NULL) { + start_index = conf->block_index_hash(block, conf->ext_mem_blocks_count); + } + if (ns_dyn_mem_tracker_lib_ext_find_free_index(conf, start_index, &free_index) < 0) { + conf->ext_mem_blocks = conf->ext_alloc_mem_blocks(conf->ext_mem_blocks, &conf->ext_mem_blocks_count); + if (conf->ext_mem_blocks == NULL) { + platform_exit_critical(); + return -1; + } + if (conf->block_index_hash != NULL) { + start_index = conf->block_index_hash(block, conf->ext_mem_blocks_count); + } + if (ns_dyn_mem_tracker_lib_ext_find_free_index(conf, start_index, &free_index) < 0) { + platform_exit_critical(); + return -1; + } + } + + // Updates memory blocks array entry + conf->mem_blocks[caller_index].ref_count++; + conf->mem_blocks[caller_index].total_size += alloc_size; + conf->mem_blocks[caller_index].lifetime = 0; + conf->mem_blocks[caller_index].permanent = false; + conf->mem_blocks[caller_index].permanent_printed = false; + + conf->ext_mem_blocks[free_index].block = block; + conf->ext_mem_blocks[free_index].caller_addr = caller_addr; + conf->ext_mem_blocks[free_index].size = alloc_size; + + conf->allocated_memory += alloc_size; + + platform_exit_critical(); + return 0; + } + + uint16_t free_index = 0; + if (ns_dyn_mem_tracker_lib_find_free_index(conf, &free_index) < 0) { + conf->mem_blocks = conf->alloc_mem_blocks(conf->mem_blocks, &conf->mem_blocks_count); + if (conf->mem_blocks == NULL || (ns_dyn_mem_tracker_lib_find_free_index(conf, &free_index) < 0)) { + platform_exit_critical(); + return -1; + } + } + + conf->mem_blocks[free_index].block = block; + conf->mem_blocks[free_index].caller_addr = caller_addr; + conf->mem_blocks[free_index].size = alloc_size; + conf->mem_blocks[free_index].total_size = alloc_size; + conf->mem_blocks[free_index].lifetime = 0; + conf->mem_blocks[free_index].ref_count = 1; + conf->mem_blocks[free_index].function = function; + conf->mem_blocks[free_index].line = line; + conf->mem_blocks[free_index].permanent = false; + conf->mem_blocks[free_index].permanent_printed = false; + + if (free_index > conf->last_mem_block_index) { + conf->last_mem_block_index = free_index; + } + + conf->allocated_memory += alloc_size; + + platform_exit_critical(); + + return 0; +} + +int8_t ns_dyn_mem_tracker_lib_free(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, const char *function, uint32_t line, void *block) +{ + (void) function; + (void) line; + (void) caller_addr; + + // No memory block or no allocations made + if (block == NULL || conf->mem_blocks == NULL) { + return 0; + } + + platform_enter_critical(); + + uint16_t block_index = 0; + if (ns_dyn_mem_tracker_lib_find_block_index(conf, block, &block_index) >= 0) { + // If last block for allocator clears the allocator + if (conf->mem_blocks[block_index].ref_count <= 1) { + conf->mem_blocks[block_index].ref_count = 0; + conf->mem_blocks[block_index].caller_addr = NULL; + conf->mem_blocks[block_index].total_size = 0; + conf->mem_blocks[block_index].function = NULL; + conf->mem_blocks[block_index].line = 0; + } else { + // Other blocks exists + conf->mem_blocks[block_index].ref_count--; + conf->mem_blocks[block_index].total_size -= conf->mem_blocks[block_index].size; + } + + conf->allocated_memory -= conf->mem_blocks[block_index].size; + + // Clears block specific fields + conf->mem_blocks[block_index].block = NULL; + conf->mem_blocks[block_index].size = 0; + // Resets lifetime and permanent settings + conf->mem_blocks[block_index].lifetime = 0; + conf->mem_blocks[block_index].permanent = false; + conf->mem_blocks[block_index].permanent_printed = false; + + platform_exit_critical(); + return 0; + } + + if (conf->ext_mem_blocks == NULL) { + platform_exit_critical(); + return -1; + } + + uint32_t ext_block_index = 0; + uint32_t start_index = 0; + if (conf->block_index_hash != NULL) { + start_index = conf->block_index_hash(block, conf->ext_mem_blocks_count); + } + if (ns_dyn_mem_tracker_lib_ext_find_block_index(conf, block, start_index, &ext_block_index) < 0) { + platform_exit_critical(); + return -1; + } + + void *ext_caller_addr = conf->ext_mem_blocks[ext_block_index].caller_addr; + + uint16_t caller_index; + if (ns_dyn_mem_tracker_lib_find_caller_index(conf, ext_caller_addr, &caller_index) < 0) { + platform_exit_critical(); + return -1; + } + + conf->mem_blocks[caller_index].ref_count--; + conf->mem_blocks[caller_index].total_size -= conf->ext_mem_blocks[ext_block_index].size; + + conf->allocated_memory -= conf->ext_mem_blocks[ext_block_index].size; + + // Clears extended block + conf->ext_mem_blocks[ext_block_index].block = NULL; + conf->ext_mem_blocks[ext_block_index].caller_addr = NULL; + conf->ext_mem_blocks[ext_block_index].size = 0; + + // Resets lifetime and permanent settings + conf->mem_blocks[block_index].lifetime = 0; + conf->mem_blocks[block_index].permanent = false; + conf->mem_blocks[block_index].permanent_printed = false; + + // If last block for allocator clears the allocator + if (conf->mem_blocks[block_index].ref_count == 0) { + conf->mem_blocks[block_index].block = NULL; + conf->mem_blocks[block_index].caller_addr = NULL; + conf->mem_blocks[block_index].size = 0; + conf->mem_blocks[block_index].total_size = 0; + conf->mem_blocks[block_index].function = NULL; + conf->mem_blocks[block_index].line = 0; + } + + platform_exit_critical(); + + return 0; +} + +void ns_dyn_mem_tracker_lib_step(ns_dyn_mem_tracker_lib_conf_t *conf) +{ + platform_enter_critical(); + + if (conf->mem_blocks_count != 0) { + for (uint32_t index = 0; index <= conf->last_mem_block_index; index++) { + if (conf->mem_blocks[index].block != NULL) { + conf->mem_blocks[index].lifetime++; + } + } + } + + platform_exit_critical(); +} + +int8_t ns_dyn_mem_tracker_lib_allocator_lists_update(ns_dyn_mem_tracker_lib_conf_t *conf) +{ + platform_enter_critical(); + + ns_dyn_mem_tracker_lib_mem_blocks_t *blocks = conf->mem_blocks; + ns_dyn_mem_tracker_lib_allocators_t *top_allocators = conf->top_allocators; + ns_dyn_mem_tracker_lib_allocators_t *permanent_allocators = conf->permanent_allocators; + ns_dyn_mem_tracker_lib_allocators_t *to_permanent_allocators = conf->to_permanent_allocators; + + uint16_t top_allocators_count = conf->top_allocators_count; + uint16_t permanent_allocators_count = conf->permanent_allocators_count; + uint16_t to_permanent_allocators_count = conf->to_permanent_allocators_count; + + memset(top_allocators, 0, top_allocators_count * sizeof(ns_dyn_mem_tracker_lib_allocators_t)); + memset(permanent_allocators, 0, permanent_allocators_count * sizeof(ns_dyn_mem_tracker_lib_allocators_t)); + memset(to_permanent_allocators, 0, to_permanent_allocators_count * sizeof(ns_dyn_mem_tracker_lib_allocators_t)); + + // Maximum set as permanent in one go + uint8_t to_permanent_count = 0; + + // Maximum to print of permanent entries + uint8_t permanent_count = 0; + + for (uint32_t index = 0; index <= conf->last_mem_block_index; index++) { + if (blocks[index].block != NULL) { + void *caller_addr = blocks[index].caller_addr; + + // Checks if caller address has already been counted + bool next = false; + for (uint32_t list_index = 0; list_index < top_allocators_count; list_index++) { + if (top_allocators[list_index].caller_addr == caller_addr) { + next = true; + break; + } + } + if (next) { + // Already on list, continue + continue; + } + + // Checks whether all reference are marked permanent + if (blocks[index].permanent) { + if (!blocks[index].permanent_printed && permanent_count < permanent_allocators_count) { + permanent_allocators[permanent_count].caller_addr = caller_addr; + permanent_allocators[permanent_count].alloc_count = blocks[index].ref_count; + permanent_allocators[permanent_count].total_memory = blocks[index].total_size; + permanent_allocators[permanent_count].min_lifetime = blocks[index].lifetime; + permanent_allocators[permanent_count].function = blocks[index].function; + permanent_allocators[permanent_count].line = blocks[index].line; + + permanent_count++; + blocks[index].permanent_printed = true; + } + continue; + } else { + // Checks whether lifetime threshold has been reached, traces and skips + if (blocks[index].lifetime > conf->to_permanent_steps_count && to_permanent_count < to_permanent_allocators_count) { + blocks[index].permanent = true; + + to_permanent_allocators[to_permanent_count].caller_addr = caller_addr; + to_permanent_allocators[to_permanent_count].alloc_count = blocks[index].ref_count; + to_permanent_allocators[to_permanent_count].total_memory = blocks[index].total_size; + to_permanent_allocators[to_permanent_count].min_lifetime = blocks[index].lifetime; + to_permanent_allocators[to_permanent_count].function = blocks[index].function; + to_permanent_allocators[to_permanent_count].line = blocks[index].line; + + to_permanent_count++; + continue; + } + } + + // Add to list if allocation count is larger than entry on the list + for (uint16_t list_index = 0; list_index < top_allocators_count; list_index++) { + if (blocks[index].ref_count >= top_allocators[list_index].alloc_count) { + if (list_index != (top_allocators_count - 1)) { + uint8_t index_count = (top_allocators_count - list_index - 1); + uint32_t size = index_count * sizeof(ns_dyn_mem_tracker_lib_allocators_t); + memmove(&top_allocators[list_index + 1], &top_allocators[list_index], size); + } + top_allocators[list_index].caller_addr = caller_addr; + top_allocators[list_index].alloc_count = blocks[index].ref_count; + top_allocators[list_index].total_memory = blocks[index].total_size; + top_allocators[list_index].min_lifetime = blocks[index].lifetime; + top_allocators[list_index].function = blocks[index].function; + top_allocators[list_index].line = blocks[index].line; + break; + } + } + } + } + + if (permanent_count < permanent_allocators_count) { + ns_dyn_mem_tracker_lib_permanent_printed_value_set(conf, NULL, false); + } + + platform_exit_critical(); + + return 0; +} + +void ns_dyn_mem_tracker_lib_max_snap_shot_update(ns_dyn_mem_tracker_lib_conf_t *conf) +{ + platform_enter_critical(); + + ns_dyn_mem_tracker_lib_mem_blocks_t *blocks = conf->mem_blocks; + ns_dyn_mem_tracker_lib_allocators_t *max_snap_shot_allocators = conf->max_snap_shot_allocators; + + uint16_t max_snap_shot_allocators_count = conf->max_snap_shot_allocators_count; + + memset(max_snap_shot_allocators, 0, max_snap_shot_allocators_count * sizeof(ns_dyn_mem_tracker_lib_allocators_t)); + + for (uint32_t index = 0; index <= conf->last_mem_block_index; index++) { + if (blocks[index].block != NULL) { + void *caller_addr = blocks[index].caller_addr; + + // Checks if caller address has already been counted + bool next = false; + for (uint16_t list_index = 0; list_index < max_snap_shot_allocators_count; list_index++) { + if (max_snap_shot_allocators[list_index].caller_addr == caller_addr) { + next = true; + break; + } + } + if (next) { + // Already on list, continue + continue; + } + + // Add to list if allocation count is larger than entry on the list + for (uint16_t list_index = 0; list_index < max_snap_shot_allocators_count; list_index++) { + if (blocks[index].total_size >= max_snap_shot_allocators[list_index].total_memory) { + if (list_index != (max_snap_shot_allocators_count - 1)) { + uint8_t index_count = (max_snap_shot_allocators_count - list_index - 1); + uint32_t size = index_count * sizeof(ns_dyn_mem_tracker_lib_allocators_t); + memmove(&max_snap_shot_allocators[list_index + 1], &max_snap_shot_allocators[list_index], size); + } + max_snap_shot_allocators[list_index].caller_addr = blocks[index].caller_addr; + max_snap_shot_allocators[list_index].alloc_count = blocks[index].ref_count; + max_snap_shot_allocators[list_index].total_memory = blocks[index].total_size; + max_snap_shot_allocators[list_index].min_lifetime = blocks[index].lifetime; + max_snap_shot_allocators[list_index].function = blocks[index].function; + max_snap_shot_allocators[list_index].line = blocks[index].line; + break; + } + } + } + } + + platform_exit_critical(); +} + +static void ns_dyn_mem_tracker_lib_permanent_printed_value_set(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, bool new_value) +{ + /* Search for all the references to the caller address from the allocation info and + set block permanent value */ + for (uint16_t search_index = 0; search_index <= conf->last_mem_block_index; search_index++) { + if (caller_addr == NULL || conf->mem_blocks[search_index].caller_addr == caller_addr) { + conf->mem_blocks[search_index].permanent_printed = new_value; + } + } +} + +static int8_t ns_dyn_mem_tracker_lib_find_free_index(ns_dyn_mem_tracker_lib_conf_t *conf, uint16_t *free_index) +{ + for (uint16_t index = 0; index < conf->mem_blocks_count; index++) { + if (conf->mem_blocks[index].caller_addr == NULL) { + *free_index = index; + return 0; + } + } + return -1; +} + +static int8_t ns_dyn_mem_tracker_lib_find_caller_index(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, uint16_t *caller_index) +{ + for (uint16_t index = 0; index <= conf->last_mem_block_index; index++) { + if (conf->mem_blocks[index].caller_addr == caller_addr) { + *caller_index = index; + return 0; + } + } + return -1; +} + +static int8_t ns_dyn_mem_tracker_lib_find_block_index(ns_dyn_mem_tracker_lib_conf_t *conf, void *block, uint16_t *block_index) +{ + for (uint16_t index = 0; index <= conf->last_mem_block_index; index++) { + if (conf->mem_blocks[index].block == block) { + *block_index = index; + return 0; + } + } + return -1; +} + +static int8_t ns_dyn_mem_tracker_lib_ext_find_free_index(ns_dyn_mem_tracker_lib_conf_t *conf, uint32_t start_index, uint32_t *free_index) +{ + for (uint32_t index = start_index; index < conf->ext_mem_blocks_count; index++) { + if (conf->ext_mem_blocks[index].caller_addr == NULL) { + *free_index = index; + return 0; + } + } + + if (start_index == 0) { + return -1; + } + + for (uint32_t index = 0; index < start_index; index++) { + if (conf->ext_mem_blocks[index].caller_addr == NULL) { + *free_index = index; + return 0; + } + } + + return -1; +} + +static int8_t ns_dyn_mem_tracker_lib_ext_find_block_index(ns_dyn_mem_tracker_lib_conf_t *conf, void *block, uint32_t start_index, uint32_t *block_index) +{ + for (uint32_t index = start_index; index < conf->ext_mem_blocks_count; index++) { + if (conf->ext_mem_blocks[index].block == block) { + *block_index = index; + return 0; + } + } + + if (start_index == 0) { + return -1; + } + + for (uint32_t index = 0; index < start_index; index++) { + if (conf->ext_mem_blocks[index].block == block) { + *block_index = index; + return 0; + } + } + + return -1; +} + +#endif diff --git a/test/libService/unittest/nsdynmem/dynmemtest.cpp b/test/libService/unittest/nsdynmem/dynmemtest.cpp index 1face7ca2a..8967d3cd2f 100644 --- a/test/libService/unittest/nsdynmem/dynmemtest.cpp +++ b/test/libService/unittest/nsdynmem/dynmemtest.cpp @@ -400,12 +400,12 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold) CHECK(info.heap_sector_alloc_cnt == 0); free(heap); - // Test6, feature is disabled if info is not set + // Test6, feature is disabled if info is coming anyway heap = (uint8_t *)malloc(size); CHECK(NULL != heap); ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL); ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0); - CHECK(ret_val == -1); + CHECK(ret_val == 0); CHECK(!heap_have_failed()); free(heap); } diff --git a/test/libService/unittest/nsnvmhelper/main.cpp b/test/libService/unittest/nsnvmhelper/main.cpp index 602aa1faac..1d4177e217 100644 --- a/test/libService/unittest/nsnvmhelper/main.cpp +++ b/test/libService/unittest/nsnvmhelper/main.cpp @@ -1,5 +1,18 @@ /* * Copyright (c) 2015 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "CppUTest/CommandLineTestRunner.h" diff --git a/test/libService/unittest/nsnvmhelper/nsnvmhelpertest.cpp b/test/libService/unittest/nsnvmhelper/nsnvmhelpertest.cpp index 32c3fc8384..df42b125bf 100644 --- a/test/libService/unittest/nsnvmhelper/nsnvmhelpertest.cpp +++ b/test/libService/unittest/nsnvmhelper/nsnvmhelpertest.cpp @@ -1,5 +1,18 @@ /* * Copyright (c) 2016 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include "CppUTest/TestHarness.h" #include "test_ns_nvm_helper.h" diff --git a/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.c b/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.c index 10b41c87d0..a83eb87723 100644 --- a/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.c +++ b/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.c @@ -1,5 +1,18 @@ /* * Copyright (c) 2016 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #include diff --git a/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.h b/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.h index 0d0af911e1..408a33f2d4 100644 --- a/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.h +++ b/test/libService/unittest/nsnvmhelper/test_ns_nvm_helper.h @@ -1,5 +1,18 @@ /* * Copyright (c) 2016 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #ifndef TEST_NS_NVM_HELPER_H #define TEST_NS_NVM_HELPER_H From aad453e0ac69b9de3b3e218c21a423bebd506174 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 19 Jan 2021 11:52:42 +0200 Subject: [PATCH 4/7] Squashed 'connectivity/nanostack/coap-service/' changes from 5aa54b8e62..4a126bd278 4a126bd278 Fix compiler and cppcheck warnings (#131) ca7ca7da30 Merge pull request #130 from PelionIoT/sync_from_mbedos 15d73dc6d4 (via Mbed OS)Remove call to function-like macro with no effect git-subtree-dir: connectivity/nanostack/coap-service git-subtree-split: 4a126bd278522e7b004de35ab0887394117f1213 --- source/coap_connection_handler.c | 22 ++++++++++++++++++++++ source/include/coap_security_handler.h | 1 + 2 files changed, 23 insertions(+) diff --git a/source/coap_connection_handler.c b/source/coap_connection_handler.c index fe4bbbde1a..4dca56c916 100644 --- a/source/coap_connection_handler.c +++ b/source/coap_connection_handler.c @@ -66,7 +66,9 @@ static NS_LIST_DEFINE(socket_list, internal_socket_t, link); static uint8_t max_handshakes = MAX_ONGOING_HANDSHAKES; static uint8_t max_sessions = MAX_SECURE_SESSION_COUNT; +#ifdef COAP_SECURITY_AVAILABLE static void timer_cb(void *param); +#endif static void recv_sckt_msg(void *cb_res); #ifdef COAP_SECURITY_AVAILABLE @@ -102,10 +104,13 @@ typedef struct secure_session { } secure_session_t; static NS_LIST_DEFINE(secure_session_list, secure_session_t, link); + +#ifdef COAP_SECURITY_AVAILABLE static int secure_session_sendto(int8_t socket_id, void *handle, const void *buf, size_t len); static int secure_session_recvfrom(int8_t socket_id, unsigned char *buf, size_t len); static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms); static int timer_status(int8_t timer_id); +#endif //COAP_SECURITY_AVAILABLE static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id) { @@ -119,6 +124,7 @@ static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id) return this; } +#ifdef COAP_SECURITY_AVAILABLE static bool is_secure_session_valid(secure_session_t *session) { ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) { @@ -128,6 +134,7 @@ static bool is_secure_session_valid(secure_session_t *session) } return false; } +#endif static void secure_session_delete(secure_session_t *this) { @@ -161,6 +168,7 @@ static int8_t virtual_socket_id_allocate() static secure_session_t *secure_session_create(internal_socket_t *parent, const uint8_t *address_ptr, uint16_t port, SecureConnectionMode secure_mode) { + (void) secure_mode; uint8_t handshakes = 0; if (!address_ptr) { return NULL; @@ -237,7 +245,9 @@ static void clear_secure_sessions(internal_socket_t *this) if (this) { ns_list_foreach_safe(secure_session_t, cur_ptr, &secure_session_list) { if (cur_ptr->parent == this) { +#ifdef COAP_SECURITY_AVAILABLE coap_security_send_close_alert(cur_ptr->sec_handler); +#endif //COAP_SECURITY_AVAILABLE secure_session_delete(cur_ptr); } } @@ -430,6 +440,7 @@ static int send_to_real_socket(int8_t socket_id, const ns_address_t *address, co return socket_sendmsg(socket_id, &msghdr, 0); } +#ifdef COAP_SECURITY_AVAILABLE static int secure_session_sendto(int8_t socket_id, void *handle, const void *buf, size_t len) { secure_session_t *session = handle; @@ -462,7 +473,9 @@ static int secure_session_sendto(int8_t socket_id, void *handle, const void *buf } return len; } +#endif //COAP_SECURITY_AVAILABLE +#ifdef COAP_SECURITY_AVAILABLE static int secure_session_recvfrom(int8_t socket_id, unsigned char *buf, size_t len) { (void)len; @@ -477,6 +490,7 @@ static int secure_session_recvfrom(int8_t socket_id, unsigned char *buf, size_t } return MBEDTLS_ERR_SSL_WANT_READ; } +#endif //COAP_SECURITY_AVAILABLE /** * Callback timer. Maybe called in interrupt context @@ -484,6 +498,7 @@ static int secure_session_recvfrom(int8_t socket_id, unsigned char *buf, size_t * TODO - might be better to use an event timer in conjunction with * CoAP tasklet */ +#ifdef COAP_SECURITY_AVAILABLE static void timer_cb(void *param) { secure_session_t *sec = param; @@ -515,7 +530,9 @@ static void timer_cb(void *param) } } } +#endif +#ifdef COAP_SECURITY_AVAILABLE static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms) { secure_session_t *sec = secure_session_find_by_timer_id(timer_id); @@ -538,7 +555,9 @@ static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms) } } } +#endif //COAP_SECURITY_AVAILABLE +#ifdef COAP_SECURITY_AVAILABLE static int timer_status(int8_t timer_id) { secure_session_t *sec = secure_session_find_by_timer_id(timer_id); @@ -547,6 +566,7 @@ static int timer_status(int8_t timer_id) } return TIMER_STATE_CANCELLED; } +#endif //COAP_SECURITY_AVAILABLE static int read_data(socket_callback_t *sckt_data, internal_socket_t *sock, ns_address_t *src_address, uint8_t dst_address[static 16]) { @@ -872,7 +892,9 @@ void connection_handler_close_secure_connection(coap_conn_handler_t *handler, ui if (handler->socket && handler->socket->is_secure) { secure_session_t *session = secure_session_find(handler->socket, destination_addr_ptr, port); if (session) { +#ifdef COAP_SECURITY_AVAILABLE coap_security_send_close_alert(session->sec_handler); +#endif //COAP_SECURITY_AVAILABLE session->session_state = SECURE_SESSION_CLOSED; session->last_contact_time = coap_service_get_internal_timer_ticks(); } diff --git a/source/include/coap_security_handler.h b/source/include/coap_security_handler.h index db0a1276d7..9529b53bec 100644 --- a/source/include/coap_security_handler.h +++ b/source/include/coap_security_handler.h @@ -23,6 +23,7 @@ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else +// cppcheck-suppress preprocessorErrorDirective #include MBEDTLS_CONFIG_FILE #endif From b0e699fe3e03f574aa2b6d74ff56a024d6e1d508 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 19 Jan 2021 11:53:20 +0200 Subject: [PATCH 5/7] Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 715ae9a693..3183d87e41 3183d87e41 Merge branch 'release_internal' into release_external 9e27a772f2 Disabled BR IID verify from DODAG ID 33ac7911cf Merge pull request #2548 from PelionIoT/sync_with_mbed_os 6f8b2829f4 compile out trace when not available 825373d3ef Add SPDX license identifier to Arm files 3ec3bc649d fixed warnings: static method defined but not used ee34352ceb Check if RX channel needs to be updated when RX slot detected (#2540) d59dc5d25e Fix doxygen 1.8.17 warnings (#2546) 1e0beb3e67 Update unit tests to support Ubuntu 2020_04 LTS (#2545) b9b2ffd96b Fixed FHSS get retry period (#2543) a0bf6aec91 Check if RX channel needs to be updated after broadcast received (#2539) fde325eee2 Wi-SUN Neighbour ARO registration failure handling update: 1e1f9c66b0 RPL dio Handler update: 0421502e27 Asynch message advertiment enable added to DAO done when disabled. 0374f74013 Corrected memory leak on key storage allocation on low memory situation 23c2f7ed05 Disable ASYNCH messages at enter Local repair state. c1df6b0d75 Added Poison_count check for First DIO time blocker. 944f934539 Added channel mask size to FHSS configuration (#2536) 20e79e05fc RPL Local repair disable clear advertised_dodag_membership_since_last_repair state 8a4638089a Fix doxygen comments (#2534) fe06236e43 MAC ACK RX guarantee update 2388a80700 MAC layer send ack allways when it requirement's 29b387b697 RPL dao dynamic timeout 00bbd02f85 Don't allow TX slot length go below allowed minimum (#2528) 8333faa401 Out of memory improvement to remove packets from routing 0a12aebff9 Support channel plan IDs 1, 2 and 5 with NA and BZ bands (#2526) ee4333da6f Wi-SUN Timing configuration is selected based on network size and data rate a5b2a26eb2 WS: API to set PHY mode and Channel plan IDs as defined by FAN 1.1 (#2520) b86a044911 Update nanostack v12.7.0 changelog (#2525) 35b95da122 Remove unnecessary files from release 0717432619 Merge remote-tracking branch 'origin/release_internal' into release_external f68126b85a Adaptation layer MCPS confirmation handle update e483a0748d Added OFDM configurations and FEC in RF config structure (#2513) b88abfa1c2 BUG fix: Fixed broken Brodcast MAC overflow handling 9cad47826a Random early detection congestion API update 00aed73abc Modified the Wi-SUN stack Latency estimates a bit slower 6b83d821ea Remove periodic PAN version increase from Wi-SUN border router ef670e21f3 Integrated ReD congestion packet drop to Wi-SUN bootstrap interface. b956d9e983 Revert "Improved transmission in high traffic (#2511)" (#2512) 01749c2116 Improved transmission in high traffic (#2511) 3158e966e0 Adaption layer queue trace update 5a32f4a7bb Update changelog, random_early_detection_congestion_check nameupdate and minor comment fix. b818f12c6d Extented network status for support dropped tx congestion packet. 11c0763f4d Added new service Random early detection f2c358dc2b Optimized medium NWK MPL parameters to 40 second multicast interval (#2508) c013bc7790 Added traces to EAPOL TX failure c29ee94a20 Changed TLS return value to int32_t 501a2c8578 Added trace for mbed TLS errors 9d7cd22aa6 Updated change log 1290225b95 Corrected radius message memory allocation 7b1c59695b Removed trace print's efb83934f6 Adaptation layer MCPS confirmation handle update ac1025e7e9 Bug Fix: Accept only next possible BSI for detect BR reboot and drop unkown's. 58f0e56fe4 Updated change log 102e525b9a Nanostack now indicates connection down on RPL local repair start 395791d535 FHSS WS: Do not allow broadcast TX on unicast channel (#2501) 72f8ecb8d2 Updated changelog.md 237620827c Activated higher priority by traffic class CS6 for NS/NA and RPL, EAPOL/ DHCP Relay messages. afbe9061b5 Adaptation layer update 13fb2bfdbb Update CHANGELOG.md af81c48993 DIO init TX filter update 13a872c6b9 Fix typos in github template (#2498) 1af20e1aee Initial version of CHANGELOG (#2497) d9874ede96 Feature update: Improved MAC TX queue purge 69264429f9 Wi-SUN Aro registration temporary address registation bug fix. d3170ed50a Removed generic event and wrong trace info. 0db3486a7a Removed trace from place which is normal and not needed a080f18d83 Added debug tarce for dropped unsecured and MPL packets. 51cd5646ed Wi-SUN NS probe update: 579f75684e Adaptation layer: Do not push CCA failed packet back to MAC (Wi-SUN) (#2487) git-subtree-dir: connectivity/nanostack/sal-stack-nanostack git-subtree-split: 3183d87e410d80b96042c143e586967dce2ff650 --- Doxyfile | 568 ++++++++++++------ nanostack/fhss_config.h | 3 + nanostack/mac_api.h | 4 +- nanostack/net_interface.h | 3 +- nanostack/net_nvm_api.h | 2 +- nanostack/net_polling_api.h | 2 +- nanostack/ns_mdns_api.h | 2 +- nanostack/nwk_stats_api.h | 1 + nanostack/platform/arm_hal_aes.h | 1 + nanostack/platform/arm_hal_phy.h | 22 + nanostack/socket_api.h | 6 +- nanostack/ws_bbr_api.h | 3 +- nanostack/ws_management_api.h | 165 +++-- .../Bootstraps/Generic/protocol_6lowpan.c | 6 +- source/6LoWPAN/ND/nd_router_object.c | 2 +- source/6LoWPAN/adaptation_interface.c | 244 ++++++-- source/6LoWPAN/lowpan_adaptation_interface.h | 7 +- source/6LoWPAN/ws/ws_bbr_api.c | 28 +- source/6LoWPAN/ws/ws_bootstrap.c | 184 +++++- source/6LoWPAN/ws/ws_cfg_settings.c | 109 +++- source/6LoWPAN/ws/ws_cfg_settings.h | 14 + source/6LoWPAN/ws/ws_common.c | 325 +++++++--- source/6LoWPAN/ws/ws_common.h | 17 +- source/6LoWPAN/ws/ws_common_defines.h | 2 + source/6LoWPAN/ws/ws_config.h | 13 +- source/6LoWPAN/ws/ws_eapol_auth_relay.c | 3 + source/6LoWPAN/ws/ws_eapol_pdu.c | 3 + source/6LoWPAN/ws/ws_eapol_relay.c | 3 + source/6LoWPAN/ws/ws_empty_functions.c | 18 + source/6LoWPAN/ws/ws_llc_data_service.c | 2 +- source/6LoWPAN/ws/ws_management_api.c | 68 +++ source/6LoWPAN/ws/ws_neighbor_class.c | 8 +- source/6LoWPAN/ws/ws_pae_key_storage.c | 1 + source/6LoWPAN/ws/ws_pae_supp.c | 20 +- source/Common_Protocols/icmpv6.c | 11 +- source/Common_Protocols/ipv6.c | 1 + source/Common_Protocols/tcp.c | 4 +- source/Core/include/ns_buffer.h | 4 +- source/Core/ns_monitor.c | 4 +- source/MAC/IEEE802_15_4/mac_defines.h | 5 + source/MAC/IEEE802_15_4/mac_filter.c | 26 +- source/MAC/IEEE802_15_4/mac_filter.h | 5 +- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 79 ++- source/MAC/IEEE802_15_4/mac_mcps_sap.h | 5 +- source/MAC/IEEE802_15_4/mac_mlme.c | 3 + source/MAC/IEEE802_15_4/mac_pd_sap.c | 75 ++- source/MPL/mpl.c | 6 + source/NWK_INTERFACE/Include/protocol.h | 2 + source/NWK_INTERFACE/Include/protocol_stats.h | 3 +- source/NWK_INTERFACE/protocol_stats.c | 3 + source/RPL/rpl_control.c | 39 +- source/RPL/rpl_downward.c | 23 +- source/RPL/rpl_structures.h | 3 +- source/RPL/rpl_upward.c | 16 +- .../radius_sec_prot/radius_client_sec_prot.c | 8 + .../protocols/tls_sec_prot/tls_sec_prot_lib.c | 3 +- source/Service_Libs/fhss/fhss_common.h | 1 + source/Service_Libs/fhss/fhss_ws.c | 45 +- source/Service_Libs/fhss/fhss_ws.h | 6 +- .../mdns/fnet/fnet_stack/fnet_config.h | 1 + .../fnet/fnet_stack/port/compiler/fnet_comp.h | 1 + .../port/compiler/fnet_comp_config.h | 1 + .../fnet/fnet_stack/services/fnet_services.h | 1 + .../services/fnet_services_config.h | 1 + .../fnet/fnet_stack/services/mdns/fnet_mdns.c | 1 + .../fnet/fnet_stack/services/mdns/fnet_mdns.h | 1 + .../fnet/fnet_stack/services/poll/fnet_poll.c | 1 + .../fnet_stack/services/serial/fnet_serial.h | 1 + .../mdns/fnet/fnet_stack/stack/fnet_debug.h | 1 + .../mdns/fnet/fnet_stack/stack/fnet_stdlib.c | 1 + .../random_early_detection.c | 157 +++++ .../random_early_detection.h | 47 ++ .../random_early_detection_api.h | 128 ++++ source/Service_Libs/utils/ns_conf.c | 2 +- source/libDHCPv6/dhcp_service_api.c | 12 +- sources.mk | 1 + 76 files changed, 2065 insertions(+), 532 deletions(-) create mode 100644 source/Service_Libs/random_early_detection/random_early_detection.c create mode 100644 source/Service_Libs/random_early_detection/random_early_detection.h create mode 100644 source/Service_Libs/random_early_detection/random_early_detection_api.h diff --git a/Doxyfile b/Doxyfile index 71d397e99a..9205be3d1b 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.8 +# Doxyfile 1.8.17 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -17,11 +17,11 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 @@ -46,10 +46,10 @@ PROJECT_NUMBER = PROJECT_BRIEF = "ARM 6LoWPAN/Thread/IPv6 Stack." -# With the PROJECT_LOGO tag one can specify an logo or icon that is included in -# the documentation. The maximum height of the logo should not exceed 55 pixels -# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo -# to the output directory. +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. PROJECT_LOGO = @@ -60,7 +60,7 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where @@ -76,7 +76,7 @@ CREATE_SUBDIRS = NO # U+3044. # The default value is: NO. -# ALLOW_UNICODE_NAMES = NO +ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this @@ -93,14 +93,22 @@ CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the @@ -135,7 +143,7 @@ ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. @@ -179,6 +187,16 @@ SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus @@ -205,9 +223,9 @@ MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a -# new page for each member. If set to NO, the documentation of a member will be -# part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO @@ -226,7 +244,12 @@ TAB_SIZE = 4 # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) ALIASES = @@ -264,19 +287,28 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. # -# Note For files without extension you can use no_extension as a placeholder. +# Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. @@ -285,7 +317,7 @@ EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -293,10 +325,19 @@ EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES @@ -318,7 +359,7 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -336,13 +377,20 @@ SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent @@ -401,7 +449,7 @@ LOOKUP_CACHE_SIZE = 0 # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. @@ -411,35 +459,41 @@ LOOKUP_CACHE_SIZE = 0 EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local methods, +# This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO only methods in the interface are +# included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. @@ -464,21 +518,21 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set -# to NO these classes will be included in the various overviews. This option has -# no effect if EXTRACT_ALL is enabled. +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO these declarations will be -# included in the documentation. +# declarations. If set to NO, these declarations will be included in the +# documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO these +# documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -492,21 +546,28 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES upper-case letters are also +# names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# (including Cygwin) ands Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES the +# their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -534,14 +595,14 @@ INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. +# name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. Note that +# name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. @@ -586,27 +647,25 @@ SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the -# todo list. This list is created by putting \todo commands in the -# documentation. +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the -# test list. This list is created by putting \test commands in the -# documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. @@ -631,8 +690,8 @@ ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES the list -# will mention the files that were used to generate the documentation. +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES @@ -677,7 +736,7 @@ LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. @@ -696,7 +755,7 @@ CITE_BIB_FILES = QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -704,7 +763,7 @@ QUIET = NO WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. @@ -721,12 +780,19 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO doxygen will only warn about wrong or incomplete parameter -# documentation, but not about the absence of documentation. +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated @@ -750,15 +816,16 @@ WARN_LOGFILE = # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with -# spaces. +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = nanostack doxygen +INPUT = nanostack \ + doxygen # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. @@ -766,12 +833,19 @@ INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen +# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = @@ -857,6 +931,10 @@ IMAGE_PATH = # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. INPUT_FILTER = @@ -866,11 +944,15 @@ INPUT_FILTER = # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER ) will also be used to filter the input files that are used for +# INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. @@ -918,7 +1000,7 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. +# entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO @@ -930,7 +1012,7 @@ REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. @@ -950,12 +1032,12 @@ SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version +# (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # @@ -977,6 +1059,35 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1007,7 +1118,7 @@ IGNORE_PREFIX = # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1073,10 +1184,10 @@ HTML_STYLESHEET = # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefor more robust against future updates. +# standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra stylesheet files is of importance (e.g. the last -# stylesheet in the list overrules the setting of the previous ones in the +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1093,9 +1204,9 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the stylesheet and background images according to +# will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1124,12 +1235,24 @@ HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: YES. +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. @@ -1153,13 +1276,13 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1198,7 +1321,7 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output @@ -1221,28 +1344,28 @@ GENERATE_HTMLHELP = NO CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# The GENERATE_CHI flag controls if a separate .chi index file is generated ( -# YES) or that it should be included in the master .chm file ( NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1274,7 +1397,7 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1282,7 +1405,7 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1291,7 +1414,7 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1299,7 +1422,7 @@ QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1307,7 +1430,7 @@ QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = @@ -1356,7 +1479,7 @@ DISABLE_INDEX = NO # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has @@ -1384,7 +1507,7 @@ ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1400,7 +1523,7 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # @@ -1411,9 +1534,15 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. @@ -1439,8 +1568,8 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest @@ -1482,7 +1611,7 @@ MATHJAX_CODEFILE = SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. There +# implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH # setting. When disabled, doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing @@ -1499,9 +1628,9 @@ SERVER_BASED_SEARCH = NO # external search engine pointed to by the SEARCHENGINE_URL option to obtain the # search results. # -# Doxygen ships with an example indexer ( doxyindexer) and search engine +# Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1512,9 +1641,9 @@ EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will return the search results when EXTERNAL_SEARCH is enabled. # -# Doxygen ships with an example indexer ( doxyindexer) and search engine +# Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Xapian (see: https://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1550,7 +1679,7 @@ EXTRA_SEARCH_MAPPINGS = # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. GENERATE_LATEX = NO @@ -1566,22 +1695,36 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. # -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). # The default file is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1599,9 +1742,12 @@ COMPACT_LATEX = NO PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names -# that should be included in the LaTeX output. To get the times font for -# instance you can specify -# EXTRA_PACKAGES=times +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} # If left blank no extra packages will be included. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1616,9 +1762,9 @@ EXTRA_PACKAGES = # Note: Only use a user-defined header if you know what you are doing! The # following commands have a special meaning inside the header: $title, # $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string, -# for the replacement values of the other commands the user is refered to -# HTML_HEADER. +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = @@ -1634,6 +1780,17 @@ LATEX_HEADER = LATEX_FOOTER = +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = + # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the LATEX_OUTPUT output # directory. Note that the files will be copied as-is; there are no commands or @@ -1652,7 +1809,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES to get a +# the PDF file directly from the LaTeX files. Set this option to YES, to get a # higher quality PDF documentation. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1687,17 +1844,33 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The # RTF output is optimized for Word 97 and may not look too pretty with other RTF # readers/editors. # The default value is: NO. @@ -1712,7 +1885,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1732,9 +1905,9 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the # default style sheet that doxygen normally uses. @@ -1743,17 +1916,27 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = +# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code +# with syntax highlighting in the RTF output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_SOURCE_CODE = NO + #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -1782,7 +1965,7 @@ MAN_EXTENSION = .3 # MAN_EXTENSION with the initial . removed. # This tag requires that the tag GENERATE_MAN is set to YES. -# MAN_SUBDIR = +MAN_SUBDIR = # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real @@ -1797,7 +1980,7 @@ MAN_LINKS = NO # Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. @@ -1811,7 +1994,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size # of the XML output. @@ -1820,11 +2003,18 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -1838,23 +2028,23 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the +# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the # program listings (including syntax highlighting and cross-referencing # information) to the DOCBOOK output. Note that enabling this will significantly # increase the size of the DOCBOOK output. # The default value is: NO. # This tag requires that the tag GENERATE_DOCBOOK is set to YES. -# DOCBOOK_PROGRAMLISTING = NO +DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen -# Definitions (see http://autogen.sf.net) file that captures the structure of -# the code including all documentation. Note that this feature is still -# experimental and incomplete at the moment. +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -1863,7 +2053,7 @@ GENERATE_AUTOGEN_DEF = NO # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module # file that captures the structure of the code including all documentation. # # Note that this feature is still experimental and incomplete at the moment. @@ -1871,7 +2061,7 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # output from the Perl module output. # The default value is: NO. @@ -1879,9 +2069,9 @@ GENERATE_PERLMOD = NO PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely # formatted so it can be parsed by a human reader. This is useful if you want to -# understand what is going on. On the other hand, if this tag is set to NO the +# understand what is going on. On the other hand, if this tag is set to NO, the # size of the Perl module output will be much smaller and Perl will parse it # just the same. # The default value is: YES. @@ -1901,14 +2091,14 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names -# in the source code. If set to NO only conditional compilation will be +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. # The default value is: NO. @@ -1924,7 +2114,7 @@ MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO -# If the SEARCH_INCLUDES tag is set to YES the includes files in the +# If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -2000,37 +2190,32 @@ TAGFILES = GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external class will be listed in the -# class index. If set to NO only the inherited external classes will be listed. +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. # The default value is: NO. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in -# the modules index. If set to NO, only the current project's groups will be +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. EXTERNAL_GROUPS = YES -# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in # the related pages index. If set to NO, only the current project's pages will # be listed. # The default value is: YES. EXTERNAL_PAGES = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to # NO turns the diagrams off. Note that this option also works with HAVE_DOT # disabled, but it is recommended to install and use dot, since it yields more @@ -2039,15 +2224,6 @@ PERL_PATH = /usr/bin/perl CLASS_DIAGRAMS = YES -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2055,7 +2231,7 @@ MSCGEN_PATH = DIA_PATH = -# If set to YES, the inheritance and collaboration graphs will hide inheritance +# If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2066,7 +2242,7 @@ HIDE_UNDOC_RELATIONS = YES # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO -# The default value is: NO. +# The default value is: YES. HAVE_DOT = NO @@ -2128,7 +2304,7 @@ COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. # The default value is: NO. @@ -2180,7 +2356,8 @@ INCLUDED_BY_GRAPH = YES # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2191,7 +2368,8 @@ CALL_GRAPH = NO # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2214,11 +2392,17 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, jpg, gif and svg. +# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, +# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, +# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2266,10 +2450,18 @@ DIAFILE_DIRS = # PlantUML is not used or called during a preprocessing step. Doxygen will # generate a warning when it encounters a \startuml command in this case and # will not generate output for the diagram. -# This tag requires that the tag HAVE_DOT is set to YES. -# Disabled for Nanostack -#PLANTUML_JAR_PATH = +PLANTUML_JAR_PATH = + +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes @@ -2307,7 +2499,7 @@ MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support # this, this feature is disabled by default. @@ -2324,7 +2516,7 @@ DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot # files that are used to generate the various graphs. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. diff --git a/nanostack/fhss_config.h b/nanostack/fhss_config.h index 5c55965733..545cb98cda 100644 --- a/nanostack/fhss_config.h +++ b/nanostack/fhss_config.h @@ -132,6 +132,9 @@ typedef struct fhss_ws_configuration { /** Wi-SUN specific unicast channel mask */ uint32_t unicast_channel_mask[8]; + /** Channel mask size */ + uint16_t channel_mask_size; + /** Vendor defined channel function. */ fhss_vendor_defined_cf *vendor_defined_cf; diff --git a/nanostack/mac_api.h b/nanostack/mac_api.h index a972554b92..8e545987ea 100644 --- a/nanostack/mac_api.h +++ b/nanostack/mac_api.h @@ -78,7 +78,7 @@ typedef enum { } mlme_primitive; /** - * \struct mac_description_storage_size_t + * \struct mac_description_storage_size_s * \brief Container for MAC storage sizes. */ typedef struct mac_description_storage_size_s { @@ -305,7 +305,7 @@ struct mac_api_s { }; /** - * \struct mac_statistics_t + * \struct mac_statistics_s * \brief MAC statistics structure. */ typedef struct mac_statistics_s { diff --git a/nanostack/net_interface.h b/nanostack/net_interface.h index 89905eeb16..89c942ccb1 100644 --- a/nanostack/net_interface.h +++ b/nanostack/net_interface.h @@ -103,7 +103,7 @@ typedef enum arm_library_event_type_e { #define SOCKET_BIND_DONE SOCKET_CONNECT_DONE /**< Backward compatibility */ #define SOCKET_BIND_FAIL SOCKET_CONNECT_FAIL /**< Backward compatibility */ #define SOCKET_BIND_AUTH_FAIL SOCKET_CONNECT_AUTH_FAIL /**< Backward compatibility */ -/* @} */ +/** @} */ /** Network security levels. */ typedef enum net_security_t { @@ -1228,3 +1228,4 @@ extern const cca_threshold_table_s *arm_nwk_get_cca_threshold_table(int8_t inter } #endif #endif /* NET_INTERFACE_H_ */ + diff --git a/nanostack/net_nvm_api.h b/nanostack/net_nvm_api.h index 646f41cff9..e790f63a87 100644 --- a/nanostack/net_nvm_api.h +++ b/nanostack/net_nvm_api.h @@ -89,7 +89,7 @@ typedef enum pana_client_nvm_update_process_t { } pana_client_nvm_update_process_t; /*! - * \struct wpan_nvm_params_t + * \struct wpan_nvm_params * \brief Network nvm parameters. */ typedef struct wpan_nvm_params { diff --git a/nanostack/net_polling_api.h b/nanostack/net_polling_api.h index 1b575e6d86..de22f7db7d 100644 --- a/nanostack/net_polling_api.h +++ b/nanostack/net_polling_api.h @@ -52,7 +52,7 @@ extern "C" { #endif /*! - * \enum net_host_mode_t + * \enum net_host_mode * \brief Sleepy host states. */ typedef enum net_host_mode { diff --git a/nanostack/ns_mdns_api.h b/nanostack/ns_mdns_api.h index 2cec738c3e..7a92fb2c36 100644 --- a/nanostack/ns_mdns_api.h +++ b/nanostack/ns_mdns_api.h @@ -36,7 +36,7 @@ typedef struct ns_mdns *ns_mdns_t; /**< Instance */ typedef struct ns_mdns_service *ns_mdns_service_t; /**< Service instance */ /*! - * \struct ns_mdns_service_param_t + * \struct ns_mdns_service_param * \brief Structure for mDNS service parameters */ typedef struct ns_mdns_service_param { diff --git a/nanostack/nwk_stats_api.h b/nanostack/nwk_stats_api.h index 5b05715d1d..a59d062e43 100644 --- a/nanostack/nwk_stats_api.h +++ b/nanostack/nwk_stats_api.h @@ -73,6 +73,7 @@ typedef struct nwk_stats_t { /* MAC */ uint16_t adapt_layer_tx_queue_size; /**< Adaptation layer direct TX queue size. */ uint16_t adapt_layer_tx_queue_peak; /**< Adaptation layer direct TX queue size peak. */ + uint32_t adapt_layer_tx_congestion_drop; /**< Adaptation layer direct TX randon early detection drop packet. */ } nwk_stats_t; /** diff --git a/nanostack/platform/arm_hal_aes.h b/nanostack/platform/arm_hal_aes.h index 891e03931b..e64c12050e 100644 --- a/nanostack/platform/arm_hal_aes.h +++ b/nanostack/platform/arm_hal_aes.h @@ -48,6 +48,7 @@ extern "C" { #define ARM_AES_MBEDTLS_CONTEXT_MIN 1 /**eth_mac_api) { // either PPP or Ethernet interface. - latency_estimate = 100; + latency_estimate = 1000; } else if (thread_info(cur_interface)) { // thread network - latency_estimate = 2000; + latency_estimate = 5000; } else if (ws_info(cur_interface)) { latency_estimate = ws_common_latency_estimate_get(cur_interface); } else { // 6LoWPAN ND - latency_estimate = 8000; + latency_estimate = 20000; } if (latency_estimate != 0) { diff --git a/source/6LoWPAN/ND/nd_router_object.c b/source/6LoWPAN/ND/nd_router_object.c index 53ff5ac59f..25441af0a3 100644 --- a/source/6LoWPAN/ND/nd_router_object.c +++ b/source/6LoWPAN/ND/nd_router_object.c @@ -930,7 +930,7 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin /* TODO - check hard upper limit on registrations? */ if (ws_info(cur_interface)) { - aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64); + aro_out->status = ws_common_allow_child_registration(cur_interface, aro_out->eui64, aro_out->lifetime); if (aro_out->status != ARO_SUCCESS) { aro_out->present = true; return true; diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index fac7616df6..74d783c8e6 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -42,13 +42,14 @@ #include "MLE/mle.h" #include "Service_Libs/mle_service/mle_service_api.h" #include "Common_Protocols/icmpv6.h" +#include "Common_Protocols/ip.h" #ifdef HAVE_RPL #include "RPL/rpl_data.h" #endif #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/ws/ws_common.h" - +#include "Service_Libs/random_early_detection/random_early_detection_api.h" #define TRACE_GROUP "6lAd" typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm); @@ -60,6 +61,8 @@ typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, bu #define tr_debug_extra(...) #endif +#define ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE 20 + typedef struct { uint16_t tag; /*!< Fragmentation datagram TAG ID */ uint16_t size; /*!< Datagram Total Size (uncompressed) */ @@ -93,6 +96,8 @@ typedef struct { fragmenter_tx_list_t activeUnicastList; //Unicast packets waiting data confirmation from MAC buffer_list_t directTxQueue; //Waiting free tx process uint16_t directTxQueue_size; + uint16_t directTxQueue_level; + uint16_t activeTxList_size; uint16_t indirect_big_packet_threshold; uint16_t max_indirect_big_packets_total; uint16_t max_indirect_small_packets_per_child; @@ -103,6 +108,17 @@ typedef struct { ns_list_link_t link; /*!< List link entry */ } fragmenter_interface_t; +#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 */ @@ -203,11 +219,22 @@ static struct protocol_interface_info_entry *lowpan_adaptation_network_interface } +static void lowpan_adaptation_tx_queue_level_update(fragmenter_interface_t *interface_ptr) +{ + if (interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level + ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE || + interface_ptr->directTxQueue_size == interface_ptr->directTxQueue_level - ADAPTION_DIRECT_TX_QUEUE_SIZE_THRESHOLD_TRACE) { + interface_ptr->directTxQueue_level = interface_ptr->directTxQueue_size; + tr_info("Adaptation layer TX queue size %u Active MAC tx request %u", interface_ptr->directTxQueue_level, interface_ptr->activeTxList_size); + } +} + + static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr, buffer_t *buf) { buffer_t *lower_priority_buf = NULL; ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) { + if (cur->priority < buf->priority) { lower_priority_buf = cur; break; @@ -220,6 +247,7 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p ns_list_add_to_end(&interface_ptr->directTxQueue, buf); } interface_ptr->directTxQueue_size++; + lowpan_adaptation_tx_queue_level_update(interface_ptr); protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size); } @@ -233,6 +261,7 @@ static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interfa if (lowpan_buffer_tx_allowed(interface_ptr, buf)) { ns_list_remove(&interface_ptr->directTxQueue, buf); interface_ptr->directTxQueue_size--; + lowpan_adaptation_tx_queue_level_update(interface_ptr); protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size); return buf; } @@ -365,6 +394,9 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si ns_list_init(&interface_ptr->indirect_tx_queue); ns_list_init(&interface_ptr->directTxQueue); ns_list_init(&interface_ptr->activeUnicastList); + interface_ptr->activeTxList_size = 0; + interface_ptr->directTxQueue_size = 0; + interface_ptr->directTxQueue_level = 0; ns_list_add_to_end(&fragmenter_interface_list, interface_ptr); @@ -390,13 +422,15 @@ int8_t lowpan_adaptation_interface_free(int8_t interface_id) ns_list_remove(&fragmenter_interface_list, interface_ptr); //free active tx process lowpan_list_free(&interface_ptr->activeUnicastList, false); + interface_ptr->activeTxList_size = 0; lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Free Indirect entry lowpan_list_free(&interface_ptr->indirect_tx_queue, true); buffer_free_list(&interface_ptr->directTxQueue); - + interface_ptr->directTxQueue_size = 0; + interface_ptr->directTxQueue_level = 0; //Free Dynamic allocated entries ns_dyn_mem_free(interface_ptr->fragment_indirect_tx_buffer); ns_dyn_mem_free(interface_ptr); @@ -415,6 +449,7 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id) //free active tx process lowpan_list_free(&interface_ptr->activeUnicastList, false); + interface_ptr->activeTxList_size = 0; lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); //Clean fragmented message flag interface_ptr->fragmenter_active = false; @@ -423,6 +458,8 @@ int8_t lowpan_adaptation_interface_reset(int8_t interface_id) lowpan_list_free(&interface_ptr->indirect_tx_queue, true); buffer_free_list(&interface_ptr->directTxQueue); + interface_ptr->directTxQueue_size = 0; + interface_ptr->directTxQueue_level = 0; return 0; } @@ -465,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) { @@ -597,6 +691,7 @@ static fragmenter_tx_entry_t *lowpan_adaptation_tx_process_init(fragmenter_inter return NULL; } ns_list_add_to_end(&interface_ptr->activeUnicastList, tx_entry); + interface_ptr->activeTxList_size++; } else { tx_entry = &interface_ptr->active_broadcast_tx_buf; } @@ -969,6 +1064,13 @@ static bool lowpan_buffer_tx_allowed(fragmenter_interface_t *interface_ptr, buff if (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf) { return false; } + + if (is_unicast && interface_ptr->activeTxList_size >= LOWPAN_ACTIVE_UNICAST_ONGOING_MAX) { + //New TX is not possible there is already too manyactive connecting + return false; + } + + // Do not accept more than one active unicast TX per destination if (is_unicast && lowpan_adaptation_is_destination_tx_active(&interface_ptr->activeUnicastList, buf)) { return false; @@ -992,6 +1094,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff goto tx_error_handler; } + uint8_t traffic_class = buf->options.traffic_class >> IP_TCLASS_DSCP_SHIFT; + + if (traffic_class == IP_DSCP_EF) { + buffer_priority_set(buf, QOS_EXPEDITE_FORWARD); + } else if (traffic_class == IP_DSCP_CS6) { + //Network Control + buffer_priority_set(buf, QOS_NETWORK_CTRL); + } else if (traffic_class) { + buffer_priority_set(buf, QOS_HIGH); + } + + //Check packet size bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr); if (fragmented_needed) { @@ -1010,7 +1124,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess; if (!lowpan_buffer_tx_allowed(interface_ptr, buf)) { + + if (buf->priority == QOS_NORMAL) { + + if (random_early_detection_congestion_check(cur->random_early_detection)) { + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); + protocol_stats_update(STATS_AL_TX_CONGESTION_DROP, 1); + goto tx_error_handler; + } + } + lowpan_adaptation_tx_queue_write(interface_ptr, buf); + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); return 0; } @@ -1166,6 +1291,7 @@ static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interfa } else if (buf->link_specific.ieee802_15_4.requestAck) { ns_list_remove(&interface_ptr->activeUnicastList, tx_ptr); ns_dyn_mem_free(tx_ptr); + interface_ptr->activeTxList_size--; } socket_tx_buffer_event_and_free(buf, socket_event); @@ -1205,7 +1331,6 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c tr_error("No data request for this confirmation %u", confirm->msduHandle); return -1; } - //Check status for buffer_t *buf = tx_ptr->buf; @@ -1229,64 +1354,58 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c buf->link_specific.ieee802_15_4.rf_channel_switch = false; } - switch (confirm->status) { - - case MLME_BUSY_CHAN: - lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); - break; - case MLME_SUCCESS: - - //Check is there more packets - if (lowpan_adaptation_tx_process_ready(tx_ptr)) { - bool triggered_from_indirect_cache = false; - if (tx_ptr->fragmented_data && active_direct_confirm) { - //Clean - interface_ptr->fragmenter_active = false; - } - - if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) { - triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr); - } - - lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); - - if (triggered_from_indirect_cache) { - return 0; - } - } else { - lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); + if (confirm->status == MLME_SUCCESS) { + //Check is there more packets + if (lowpan_adaptation_tx_process_ready(tx_ptr)) { + bool triggered_from_indirect_cache = false; + if (tx_ptr->fragmented_data && active_direct_confirm) { + interface_ptr->fragmenter_active = false; } - break; - case MLME_TX_NO_ACK: - case MLME_SECURITY_FAIL: - case MLME_TRANSACTION_EXPIRED: - default: - tr_error("MCPS Data fail by status %u", confirm->status); - if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) { - tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address + 2)); - } else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) { - tr_info("Dest addr: %s", trace_array(buf->dst_sa.address + 2, 8)); - } - -#ifdef HAVE_RPL - if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) { - if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { - protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); - } - } -#endif - if (tx_ptr->fragmented_data) { - tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end; - tx_ptr->buf->buf_ptr -= tx_ptr->orig_size; - if (active_direct_confirm) { - interface_ptr->fragmenter_active = false; - } + if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) { + triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr); } lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); - break; + if (triggered_from_indirect_cache) { + return 0; + } + } else { + lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); + } + } else if ((confirm->status == MLME_BUSY_CHAN) && !ws_info(cur)) { + lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); + } else { + + + if (confirm->status == MLME_TRANSACTION_OVERFLOW) { + tr_error("MCPS Data fail by MLME_TRANSACTION_OVERFLOW"); + } + + tr_error("MCPS Data fail by status %u", confirm->status); + if (buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) { + tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa.address + 2)); + } else if (buf->dst_sa.addr_type == ADDR_802_15_4_LONG) { + tr_info("Dest addr: %s", trace_array(buf->dst_sa.address + 2, 8)); + } + +#ifdef HAVE_RPL + if (confirm->status == MLME_TX_NO_ACK || confirm->status == MLME_UNAVAILABLE_KEY) { + if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { + protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); + } + } +#endif + if (tx_ptr->fragmented_data) { + tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end; + tx_ptr->buf->buf_ptr -= tx_ptr->orig_size; + if (active_direct_confirm) { + interface_ptr->fragmenter_active = false; + } + } + + lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); } // When confirmation is for direct transmission, push all allowed buffers to MAC if (active_direct_confirm == true) { @@ -1295,6 +1414,8 @@ int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *c lowpan_adaptation_interface_tx(cur, buf_from_queue); buf_from_queue = lowpan_adaptation_tx_queue_read(interface_ptr); } + //Update Average QUEUE + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); } return 0; } @@ -1492,10 +1613,21 @@ int8_t lowpan_adaptation_free_messages_from_queues_by_address(struct protocol_in } } + //Check next directTxQueue there may be pending packets also + ns_list_foreach_safe(buffer_t, entry, &interface_ptr->directTxQueue) { + if (lowpan_tx_buffer_address_compare(&entry->dst_sa, address_ptr, adr_type)) { + ns_list_remove(&interface_ptr->directTxQueue, entry); + interface_ptr->directTxQueue_size--; + //Update Average QUEUE + random_early_detetction_aq_calc(cur->random_early_detection, interface_ptr->directTxQueue_size); + lowpan_adaptation_tx_queue_level_update(interface_ptr); + socket_tx_buffer_event_and_free(entry, SOCKET_TX_FAIL); + } + } + 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); diff --git a/source/6LoWPAN/lowpan_adaptation_interface.h b/source/6LoWPAN/lowpan_adaptation_interface.h index 307dd9917b..13401df1f0 100644 --- a/source/6LoWPAN/lowpan_adaptation_interface.h +++ b/source/6LoWPAN/lowpan_adaptation_interface.h @@ -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); diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index d2b306d465..75a1178bfc 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -176,12 +176,12 @@ static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, //stable version for RPL so slow timer update is ok cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME; } else { - if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_SMALL) { - // handles also NETWORK_SIZE_CERTIFICATE + if (ws_cfg_network_config_get(cur) <= CONFIG_SMALL) { + // Also handles CONFIG_CERTIFICATE cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_SMALL; - } else if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_MEDIUM) { + } else if (ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM) { cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_MEDIUM; - } else if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_LARGE) { + } else if (ws_cfg_network_config_get(cur) <= CONFIG_LARGE) { cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_LARGE; } else { cur->ws_info->rpl_version_timer = RPL_VERSION_LIFETIME_RESTART_EXTRA_LARGE; @@ -712,11 +712,13 @@ void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur) return; } tr_debug("Border router version number update"); - if (configuration & BBR_REQUIRE_DAO_REFRESH) { + if (configuration & BBR_PERIODIC_VERSION_INC) { + // Periodically increase the version number. + // This removes need for DAO, but causes slowness in recovery + pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL; + } else { // Version number is not periodically increased forcing nodes to check Border router availability using DAO pan_version_timer = 0; - } else { - pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL; } cur->ws_info->pan_information.pan_version++; // Inconsistent for border router to make information distribute faster @@ -923,12 +925,16 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options) protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (protocol_6lowpan_rpl_root_dodag && - options != configuration) { - //Configuration changed delete previous setup - ws_bbr_routing_stop(cur); + if (options == configuration) { + return 0; } + //Configuration changed configuration = options; + if (protocol_6lowpan_rpl_root_dodag) { + // Already active needs to restart + ws_bbr_routing_stop(cur); + ws_bbr_pan_version_increase(cur); + } return 0; #else (void)interface_id; diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 825c924b1f..7ff5035fb7 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -20,6 +20,7 @@ #ifdef HAVE_WS #include "ns_types.h" #include "ns_trace.h" +#include "nsdynmemLIB.h" #include "net_interface.h" #include "eventOS_event.h" #include "randLIB.h" @@ -43,6 +44,7 @@ #include "Common_Protocols/icmpv6.h" #include "Common_Protocols/icmpv6_radv.h" #include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ip.h" #include "Service_Libs/Trickle/trickle.h" #include "Service_Libs/fhss/channel_list.h" #include "6LoWPAN/ws/ws_common_defines.h" @@ -75,6 +77,7 @@ #include "6LoWPAN/ws/ws_eapol_auth_relay.h" #include "6LoWPAN/ws/ws_eapol_relay.h" #include "libNET/src/net_dns_internal.h" +#include "Service_Libs/random_early_detection/random_early_detection_api.h" #define TRACE_GROUP "wsbs" @@ -111,6 +114,10 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create); static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry); +static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur); + +static void ws_bootstrap_asynch_trickle_stop(protocol_interface_info_entry_t *cur); +static void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur); typedef enum { WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/ @@ -163,7 +170,7 @@ void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_ent { mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT); - if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (neighbor && neighbor->link_lifetime <= valid_time) { //mlme_device_descriptor_t device_desc; neighbor->lifetime = valid_time; neighbor->link_lifetime = valid_time; @@ -426,19 +433,47 @@ static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighb ws_nud_state_clean(cur, nud_entry); } } +if_address_entry_t *ws_probe_aro_address(protocol_interface_info_entry_t *interface) +{ + if (interface->global_address_available) { + ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) { + if (addr_ipv6_scope(address->address, interface) > IPV6_SCOPE_LINK_LOCAL) { + return address; + } + } + } + return NULL; +} + static bool ws_nud_message_build(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *neighbor, bool nud_process) { //Send NS uint8_t ll_target[16]; + aro_t aro_temp; + //SET ARO and src address pointer to NULL by default + aro_t *aro_ptr = NULL; + uint8_t *src_address_ptr = NULL; + ws_bootsrap_create_ll_address(ll_target, neighbor->mac64); if (nud_process) { tr_info("NUD generate NS %u", neighbor->index); } else { tr_info("Probe generate NS %u", neighbor->index); + if_address_entry_t *gp_address = ws_probe_aro_address(cur); + if (gp_address) { + src_address_ptr = gp_address->address; + aro_temp.status = ARO_SUCCESS; + aro_temp.present = true; + memcpy(aro_temp.eui64, cur->mac, 8); + //Just Short Test + aro_temp.lifetime = 1; + aro_ptr = &aro_temp; + } } - buffer_t *buffer = icmpv6_build_ns(cur, ll_target, NULL, true, false, NULL); + buffer_t *buffer = icmpv6_build_ns(cur, ll_target, src_address_ptr, true, false, aro_ptr); if (buffer) { + buffer->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; protocol_push(buffer); return true; } @@ -592,8 +627,9 @@ static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration) { - ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); - ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); + fhss_configuration->channel_mask_size = cur->ws_info->hopping_schdule.number_of_channels; + ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id); + ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id); // using bitwise AND operation for user set channel mask to remove channels not allowed in this device for (uint8_t n = 0; n < 8; n++) { fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n]; @@ -1518,10 +1554,10 @@ static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_inter */ trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit); /* - * Optimized PAN discovery to select faster the parent if we hear solicit from someone else + * Optimized PAN discovery to select the parent faster if we hear solicit from someone else */ - if (ws_bootstrap_state_discovery(cur) && cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_MEDIUM && + if (ws_bootstrap_state_discovery(cur) && ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM && cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin * 2) { cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); @@ -1595,10 +1631,15 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry //When Config is learned and USE Parent BS is enabled compare is this new BSI if (cur->ws_info->configuration_learned && cur->ws_info->pan_information.use_parent_bs && ws_bs_ie.broadcast_schedule_identifier != cur->ws_info->hopping_schdule.fhss_bsi) { - tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier); - cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; - cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi; - ws_bootstrap_event_discovery_start(cur); + //Accept only next possible BSI number + if ((cur->ws_info->hopping_schdule.fhss_bsi + 1) != ws_bs_ie.broadcast_schedule_identifier) { + tr_debug("Do not accept a unknown BSI: %u", ws_bs_ie.broadcast_schedule_identifier); + } else { + tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier); + cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; + cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi; + ws_bootstrap_event_discovery_start(cur); + } return; } } @@ -2007,7 +2048,7 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt static uint32_t ws_probe_init_time_get(protocol_interface_info_entry_t *cur) { - if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_SMALL) { + if (ws_cfg_network_config_get(cur) <= CONFIG_SMALL) { return WS_SMALL_PROBE_INIT_BASE_SECONDS; } @@ -2359,11 +2400,30 @@ int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t static int ws_bootstrap_set_domain_rf_config(protocol_interface_info_entry_t *cur) { phy_rf_channel_configuration_s rf_configs; + memset(&rf_configs, 0, sizeof(phy_rf_channel_configuration_s)); + + uint8_t phy_mode_id = cur->ws_info->hopping_schdule.phy_mode_id; + if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) || + ((phy_mode_id >= 51) && (phy_mode_id <= 54)) || + ((phy_mode_id >= 68) && (phy_mode_id <= 70)) || + ((phy_mode_id >= 84) && (phy_mode_id <= 86))) { + rf_configs.modulation = M_OFDM; + rf_configs.datarate = ws_get_datarate_using_phy_mode_id(cur->ws_info->hopping_schdule.phy_mode_id); + rf_configs.ofdm_option = ws_get_ofdm_option_using_phy_mode_id(cur->ws_info->hopping_schdule.phy_mode_id); + rf_configs.ofdm_mcs = ws_get_ofdm_mcs_using_phy_mode_id(cur->ws_info->hopping_schdule.phy_mode_id); + } else { + if ((phy_mode_id >= 17) && (phy_mode_id <= 24)) { + rf_configs.fec = true; + } else { + rf_configs.fec = false; + } + rf_configs.modulation = M_2FSK; + rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); + rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); + } + rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000; rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing); - rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); - rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); - rf_configs.modulation = M_2FSK; rf_configs.number_of_channels = cur->ws_info->hopping_schdule.number_of_channels; ws_bootstrap_set_rf_config(cur, rf_configs); return 0; @@ -2522,6 +2582,12 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) // After successful DAO ACK connection to border router is verified cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; + + } + + if (!cur->ws_info->trickle_pa_running || !cur->ws_info->trickle_pc_running) { + //Enable wi-sun asynch adverisment + ws_bootstrap_advertise_start(cur); } ws_set_fhss_hop(cur); @@ -2536,6 +2602,12 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) * */ + } else if (event == RPL_EVENT_LOCAL_REPAIR_START) { + tr_debug("RPL local repair start"); + //Disable Asynchs + ws_bootstrap_asynch_trickle_stop(cur); + ws_nwk_event_post(cur, ARM_NWK_NWK_CONNECTION_DOWN); + } else if (event == RPL_EVENT_DAO_PARENT_ADD) { ws_address_parent_update(cur); } @@ -3024,9 +3096,9 @@ static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur) tr_debug("Start RPL learn"); // routers wait until RPL root is contacted ws_bootstrap_state_change(cur, ER_RPL_SCAN); - //For Large network and medium shuold do passive scan - if (cur->ws_info->cfg->gen.network_size > NETWORK_SIZE_SMALL) { - // Set timeout for check to 30 -60 seconds + //For Large network and medium should do passive scan + if (ws_cfg_network_config_get(cur) > CONFIG_SMALL) { + // Set timeout for check to 30 - 60 seconds cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_INITIAL_TIMEOUT / 2, WS_RPL_DIS_INITIAL_TIMEOUT); } /* While in Join State 4, if a non Border Router determines it has been unable to communicate with the PAN Border @@ -3073,7 +3145,7 @@ static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asy uint16_t channel_number = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel; async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32)); } else { - ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); + ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id); } async_req->channel_list.channel_page = CHANNEL_PAGE_10; @@ -3272,6 +3344,8 @@ static void ws_bootstrap_event_handler(arm_event_s *event) // All trickle timers stopped to allow entry from any state ws_bootstrap_asynch_trickle_stop(cur); + //Init Packet congestion + ws_bootstrap_packet_congestion_init(cur); if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { tr_info("Border router start network"); @@ -3761,4 +3835,78 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_ return 0; } +//Calculate max_packet queue size +static uint16_t ws_bootstrap_define_congestin_max_threshold(uint32_t heap_total_size, uint16_t packet_size, uint16_t packet_per_seconds, uint32_t max_delay, uint16_t min_packet_queue_size, uint16_t max_packet_queue_size) +{ + uint32_t max_packet_count = 0; + if (heap_total_size) { + //Claculate how many packet can be max queue to half of heap + max_packet_count = (heap_total_size / 2) / packet_size; + } + + //Calculate how many packet is possible to queue for guarantee given max delay + uint32_t max_delayded_queue_size = max_delay * packet_per_seconds; + + if (max_packet_count > max_delayded_queue_size) { + //Limit queue size by MAX delay + max_packet_count = max_delayded_queue_size; + } + + if (max_packet_count > max_packet_queue_size) { + //Limit queue size by Max + max_packet_count = max_packet_queue_size; + } else if (max_packet_count < min_packet_queue_size) { + //Limit queue size by Min + max_packet_count = min_packet_queue_size; + } + return (uint16_t)max_packet_count; +} + +static uint16_t ws_bootstrap_packet_per_seconds(protocol_interface_info_entry_t *cur, uint16_t packet_size) +{ + uint32_t data_rate = ws_common_datarate_get(cur); + + //calculate how many packet is possible send in paper + data_rate /= 8 * packet_size; + + //Divide optimal by / 5 because we split TX / RX slots and BC schedule + //With Packet size 500 it should return + //Return 15 for 300kBits + //Return 7 for 150kBits + //Return 2 for 50kBits + return data_rate / 5; +} + + + +static void ws_bootstrap_packet_congestion_init(protocol_interface_info_entry_t *cur) +{ + random_early_detection_free(cur->random_early_detection); + cur->random_early_detection = NULL; + + //TODO implement API for HEAP info request + uint32_t heap_size; + const mem_stat_t *mem_stats = ns_dyn_mem_get_mem_stat(); + if (mem_stats) { + heap_size = mem_stats->heap_sector_size; + } else { + heap_size = 0; + } + + uint16_t packet_per_seconds = ws_bootstrap_packet_per_seconds(cur, WS_CONGESTION_PACKET_SIZE); + + uint16_t min_th, max_th; + + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + max_th = ws_bootstrap_define_congestin_max_threshold(heap_size, WS_CONGESTION_PACKET_SIZE, packet_per_seconds, WS_CONGESTION_QUEUE_DELAY, WS_CONGESTION_BR_MIN_QUEUE_SIZE, WS_CONGESTION_BR_MAX_QUEUE_SIZE); + } else { + max_th = ws_bootstrap_define_congestin_max_threshold(heap_size, WS_CONGESTION_PACKET_SIZE, packet_per_seconds, WS_CONGESTION_QUEUE_DELAY, WS_CONGESTION_NODE_MIN_QUEUE_SIZE, WS_CONGESTION_NODE_MAX_QUEUE_SIZE); + } + + min_th = max_th / 2; + tr_info("Wi-SUN packet congestion minTh %u, maxTh %u, drop probability %u weight %u, Packet/Seconds %u", min_th, max_th, WS_CONGESTION_RED_DROP_PROBABILITY, RED_AVERAGE_WEIGHT_EIGHTH, packet_per_seconds); + cur->random_early_detection = random_early_detection_create(min_th, max_th, WS_CONGESTION_RED_DROP_PROBABILITY, RED_AVERAGE_WEIGHT_EIGHTH); + +} + #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_cfg_settings.c b/source/6LoWPAN/ws/ws_cfg_settings.c index 8366204e52..40e46940f3 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/source/6LoWPAN/ws/ws_cfg_settings.c @@ -79,6 +79,32 @@ typedef union { ws_sec_prot_cfg_t sec_prot; } ws_cfgs_t; + +typedef struct cfg_devices_in_config { + uint8_t max_for_small; + uint8_t max_for_medium; + uint8_t max_for_large; + uint8_t max_for_xlarge; +} cfg_devices_in_config_t; + +/* Table for amount of devices that certain configuration should be used + * + * larger data rates allow more devices to be used with faster settings. + * + * For example with network the size of 2000 devices we use + * Xlrage configuration with 50kbs data rate. + * Large configuration with 300kbs data rate. + * and with 600kbs data rate it is possible to use medium network settings. + * + */ +const cfg_devices_in_config_t devices_by_datarate[] = { + { 1, 4, 10, 25}, // Configuration for 50 -100kbs + { 1, 8, 15, 25}, // Configuration for 150kbs - 200kbs + { 2, 15, 25, 50}, // Configuration for 300kbs + { 3, 20, 40, 100}, // Configuration for 600kbs - 2400kbs +}; + + static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate valid_cb, ws_cfgs_t *external_cfg, uint8_t *cfg_flags, uint8_t *flags); static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg); @@ -258,13 +284,13 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_ ws_cfg_network_size_config_set_size set_function = NULL; - if (cfg->network_size == NETWORK_SIZE_CERTIFICATE) { + if (ws_cfg_network_config_get(cur) == CONFIG_CERTIFICATE) { set_function = ws_cfg_network_size_config_set_certificate; - } else if (cfg->network_size <= NETWORK_SIZE_SMALL || cfg->network_size == NETWORK_SIZE_AUTOMATIC) { + } else if (ws_cfg_network_config_get(cur) == CONFIG_SMALL || cfg->network_size == NETWORK_SIZE_AUTOMATIC) { set_function = ws_cfg_network_size_config_set_small; - } else if (cfg->network_size <= NETWORK_SIZE_MEDIUM) { + } else if (ws_cfg_network_config_get(cur) == CONFIG_MEDIUM) { set_function = ws_cfg_network_size_config_set_medium; - } else if (cfg->network_size <= NETWORK_SIZE_LARGE) { + } else if (ws_cfg_network_config_get(cur) == CONFIG_LARGE) { set_function = ws_cfg_network_size_config_set_large; } else { set_function = ws_cfg_network_size_config_set_xlarge; @@ -360,6 +386,47 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1 return CFG_SETTINGS_OK; } +cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_t *cur) +{ + // Get size of the network Amount of devices in the network + // Get the data rate of the network + // Adjust the configuration type based on the network size and data rate + + (void)cur; + + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return CONFIG_SMALL; + } + ws_phy_cfg_t phy_cfg; + if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) { + return CONFIG_SMALL; + } + + uint32_t data_rate = ws_get_datarate_using_operating_mode(phy_cfg.operating_mode); + uint8_t index; + if (data_rate < 150000) { + index = 0; + } else if (data_rate < 300000) { + index = 1; + } else if (data_rate < 600000) { + index = 2; + } else { + index = 3; + } + + if (cfg.network_size == NETWORK_SIZE_CERTIFICATE) { + return CONFIG_CERTIFICATE; + } else if (cfg.network_size <= devices_by_datarate[index].max_for_small) { + return CONFIG_SMALL; + } else if (cfg.network_size <= devices_by_datarate[index].max_for_medium) { + return CONFIG_MEDIUM; + } else if (cfg.network_size <= devices_by_datarate[index].max_for_large) { + return CONFIG_LARGE; + } + return CONFIG_XLARGE; +} + static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) { @@ -651,6 +718,8 @@ int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg) cfg->regulatory_domain = REG_DOMAIN_EU; cfg->operating_mode = OPERATING_MODE_3; cfg->operating_class = 2; + cfg->phy_mode_id = 255; + cfg->channel_plan_id = 255; return CFG_SETTINGS_OK; } @@ -671,12 +740,16 @@ int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg) // Regulator domain, operating mode or class has changed if (cfg->regulatory_domain != new_cfg->regulatory_domain || cfg->operating_mode != new_cfg->operating_mode || - cfg->operating_class != new_cfg->operating_class) { + cfg->operating_class != new_cfg->operating_class || + cfg->phy_mode_id != new_cfg->phy_mode_id || + cfg->channel_plan_id != new_cfg->channel_plan_id) { ws_hopping_schedule_t hopping_schdule = { .regulatory_domain = new_cfg->regulatory_domain, .operating_mode = new_cfg->operating_mode, - .operating_class = new_cfg->operating_class + .operating_class = new_cfg->operating_class, + .phy_mode_id = new_cfg->phy_mode_id, + .channel_plan_id = new_cfg->channel_plan_id }; // Check that new settings are valid @@ -698,11 +771,31 @@ int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, w if (ret != CFG_SETTINGS_CHANGED) { return ret; } - // Check settings and configure interface if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + // Set operating mode for FSK if given with PHY mode ID + if ((new_cfg->phy_mode_id == 1) || (new_cfg->phy_mode_id == 17)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_1a; + } else if ((new_cfg->phy_mode_id == 2) || (new_cfg->phy_mode_id == 18)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_1b; + } else if ((new_cfg->phy_mode_id == 3) || (new_cfg->phy_mode_id == 19)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_2a; + } else if ((new_cfg->phy_mode_id == 4) || (new_cfg->phy_mode_id == 20)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_2b; + } else if ((new_cfg->phy_mode_id == 5) || (new_cfg->phy_mode_id == 21)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3; + } else if ((new_cfg->phy_mode_id == 6) || (new_cfg->phy_mode_id == 22)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_4a; + } else if ((new_cfg->phy_mode_id == 7) || (new_cfg->phy_mode_id == 23)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_4b; + } else if ((new_cfg->phy_mode_id == 8) || (new_cfg->phy_mode_id == 24)) { + cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_5; + } else { + cur->ws_info->hopping_schdule.operating_mode = new_cfg->operating_mode; + } + cur->ws_info->hopping_schdule.phy_mode_id = new_cfg->phy_mode_id; + cur->ws_info->hopping_schdule.channel_plan_id = new_cfg->channel_plan_id; cur->ws_info->hopping_schdule.regulatory_domain = new_cfg->regulatory_domain; - cur->ws_info->hopping_schdule.operating_mode = new_cfg->operating_mode; cur->ws_info->hopping_schdule.operating_class = new_cfg->operating_class; if (ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule) < 0) { diff --git a/source/6LoWPAN/ws/ws_cfg_settings.h b/source/6LoWPAN/ws/ws_cfg_settings.h index 35490e3326..763d1ff56f 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.h +++ b/source/6LoWPAN/ws/ws_cfg_settings.h @@ -38,6 +38,8 @@ typedef struct ws_phy_cfg_s { uint8_t regulatory_domain; /**< PHY regulatory domain; default "KR" 0x09 */ uint8_t operating_class; /**< PHY operating class; default 1 */ uint8_t operating_mode; /**< PHY operating mode; default "1b" symbol rate 50, modulation index 1 */ + uint8_t phy_mode_id; /**< PHY mode ID; default 255 (not used) */ + uint8_t channel_plan_id; /**< Channel plan ID; default 255 (not used) */ } ws_phy_cfg_t; /** @@ -146,11 +148,23 @@ typedef struct ws_cfg_s { #define CFG_SETTINGS_ERROR_SEC_TIMER_CONF -17 /**< Security timers configuration error */ #define CFG_SETTINGS_ERROR_SEC_PROT_CONF -18 /**< Security protocols configuration error */ +/** Network configuration parameters sets for different network sizes*/ +typedef enum { + CONFIG_CERTIFICATE = 0, ///< Configuration used in Wi-SUN Certification + CONFIG_SMALL = 1, ///< Small networks that can utilize fast recovery + CONFIG_MEDIUM = 2, ///< Medium networks that can form quickly but require balance on load + CONFIG_LARGE = 3, ///< Large networks that needs to throttle joining and maintenance + CONFIG_XLARGE = 4 ///< Xlarge networks with very slow joining, maintenance and recovery profile +} cfg_network_size_type_e; + + int8_t ws_cfg_settings_init(void); int8_t ws_cfg_settings_default_set(void); int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur); int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size); +cfg_network_size_type_e ws_cfg_network_config_get(protocol_interface_info_entry_t *cur); + int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg); int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg, uint8_t *flags); diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 5a242cfa4b..bf1bca224f 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -53,33 +53,57 @@ uint8_t DEVICE_MIN_SENS = 174 - 93; uint16_t test_max_child_count_override = 0xffff; -int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class) +static int8_t ws_disable_channels_in_range(uint32_t *channel_mask, uint16_t number_of_channels, uint16_t range_start, uint16_t range_stop) { - uint32_t excluded_start_channel = 0xFFFFFFFF; - uint32_t excluded_end_channel = 0xFFFFFFFF; - - if (regulatory_domain == REG_DOMAIN_BZ) { - if (operating_class == 1) { - excluded_start_channel = 26; - excluded_end_channel = 64; - } else if (operating_class == 2) { - excluded_start_channel = 12; - excluded_end_channel = 32; - } else if (operating_class == 3) { - excluded_start_channel = 7; - excluded_end_channel = 21; + for (uint16_t i = 0; i < number_of_channels; i++) { + if (i >= range_start && i <= range_stop) { + channel_mask[0 + (i / 32)] &= ~(1 << (i % 32)); } } + return 0; +} +int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id) +{ // Clear channel mask for (uint8_t i = 0; i < 8; i++) { channel_mask[i] = 0; } - - // Set channel maks outside excluded channels + // Enable all channels for (uint16_t i = 0; i < number_of_channels; i++) { - if (i < excluded_start_channel || i > excluded_end_channel) { - channel_mask[0 + (i / 32)] |= (1 << (i % 32)); + channel_mask[0 + (i / 32)] |= (1 << (i % 32)); + } + // Disable unsupported channels per regional frequency bands + if (regulatory_domain == REG_DOMAIN_NA) { + if (channel_plan_id == 1) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 1, 7); + } else if (channel_plan_id == 5) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 5, 7); + } + } + if (regulatory_domain == REG_DOMAIN_BZ) { + if (channel_plan_id == 255) { + if (operating_class == 1) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 26, 64); + } else if (operating_class == 2) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 12, 32); + } else if (operating_class == 3) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 7, 21); + } + } else { + if (channel_plan_id == 1) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 1, 7); + ws_disable_channels_in_range(channel_mask, number_of_channels, 64, 64); + ws_disable_channels_in_range(channel_mask, number_of_channels, 72, 103); + ws_disable_channels_in_range(channel_mask, number_of_channels, 106, 111); + } else if (channel_plan_id == 2) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 24, 24); + ws_disable_channels_in_range(channel_mask, number_of_channels, 32, 47); + ws_disable_channels_in_range(channel_mask, number_of_channels, 52, 55); + } else if (channel_plan_id == 5) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 5, 10); + ws_disable_channels_in_range(channel_mask, number_of_channels, 19, 23); + } } } return 0; @@ -109,6 +133,10 @@ uint32_t ws_decode_channel_spacing(uint8_t channel_spacing) return 400000; } else if (CHANNEL_SPACING_600 == channel_spacing) { return 600000; + } else if (CHANNEL_SPACING_800 == channel_spacing) { + return 800000; + } else if (CHANNEL_SPACING_1200 == channel_spacing) { + return 1200000; } return 0; } @@ -129,6 +157,60 @@ uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode) return 0; } +uint32_t ws_get_datarate_using_phy_mode_id(uint8_t phy_mode_id) +{ + if (84 == phy_mode_id) { + return 150000; + } else if (85 == phy_mode_id) { + return 200000; + } else if ((68 == phy_mode_id) || (86 == phy_mode_id)) { + return 300000; + } else if ((34 == phy_mode_id) || (51 == phy_mode_id) || (69 == phy_mode_id)) { + return 400000; + } else if ((52 == phy_mode_id) || (70 == phy_mode_id)) { + return 600000; + } else if ((35 == phy_mode_id) || (53 == phy_mode_id)) { + return 800000; + } else if ((36 == phy_mode_id) || (54 == phy_mode_id)) { + return 1200000; + } else if (37 == phy_mode_id) { + return 1600000; + } else if (38 == phy_mode_id) { + return 2400000; + } + return 0; +} + +uint8_t ws_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id) +{ + if ((phy_mode_id >= 34) && (phy_mode_id <= 38)) { + return OFDM_OPTION_1; + } else if ((phy_mode_id >= 51) && (phy_mode_id <= 54)) { + return OFDM_OPTION_2; + } else if ((phy_mode_id >= 68) && (phy_mode_id <= 70)) { + return OFDM_OPTION_3; + } else if ((phy_mode_id >= 84) && (phy_mode_id <= 86)) { + return OFDM_OPTION_4; + } + return 0; +} + +uint8_t ws_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id) +{ + if (34 == phy_mode_id) { + return OFDM_MCS_2; + } else if ((35 == phy_mode_id) || (51 == phy_mode_id)) { + return OFDM_MCS_3; + } else if ((36 == phy_mode_id) || (52 == phy_mode_id) || (68 == phy_mode_id) || (84 == phy_mode_id)) { + return OFDM_MCS_4; + } else if ((37 == phy_mode_id) || (53 == phy_mode_id) || (69 == phy_mode_id) || (85 == phy_mode_id)) { + return OFDM_MCS_5; + } else if ((38 == phy_mode_id) || (54 == phy_mode_id) || (70 == phy_mode_id) || (86 == phy_mode_id)) { + return OFDM_MCS_6; + } + return 0; +} + phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode) { if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) { @@ -146,6 +228,38 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, return -1; } + // Validate PHY mode ID + if (hopping_schdule->phy_mode_id != 255) { + uint8_t phy_mode_id = hopping_schdule->phy_mode_id; + uint8_t phy_type = phy_mode_id >> 4; + uint8_t phy_mode = phy_mode_id & 0x0f; + // Invalid PHY type + if (phy_type > 5) { + return -1; + } + // Invalid OFDM mode + if (phy_type >= 2 && phy_mode > 6) { + return -1; + } + // Skip if PHY mode is for FSK modulation + if (!phy_mode_id || ((phy_mode_id > 8) && (phy_mode_id < 17)) || phy_mode_id > 24) { + // Validate OFDM configurations + if (((phy_mode_id >= 34) && (phy_mode_id <= 38)) || + ((phy_mode_id >= 51) && (phy_mode_id <= 54)) || + ((phy_mode_id >= 68) && (phy_mode_id <= 70)) || + ((phy_mode_id >= 84) && (phy_mode_id <= 86))) { + if (ws_get_datarate_using_phy_mode_id(phy_mode_id) == 0 || + ws_get_ofdm_option_using_phy_mode_id(phy_mode_id) == 0 || + ws_get_ofdm_mcs_using_phy_mode_id(phy_mode_id) == 0) { + //Unsupported PHY mode + return -1; + } + } else { + // Invalid PHY mode ID + return -1; + } + } + } hopping_schdule->channel_plan = 0; if (hopping_schdule->regulatory_domain == REG_DOMAIN_KR) { @@ -185,30 +299,60 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, return -1; } } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_NA) { - if (hopping_schdule->operating_class == 1) { - hopping_schdule->ch0_freq = 9022; - hopping_schdule->channel_spacing = CHANNEL_SPACING_200; - } else if (hopping_schdule->operating_class == 2) { - hopping_schdule->ch0_freq = 9024; - hopping_schdule->channel_spacing = CHANNEL_SPACING_400; - } else if (hopping_schdule->operating_class == 3) { - hopping_schdule->ch0_freq = 9026; - hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + if (hopping_schdule->channel_plan_id == 255) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 9026; + hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + } else { + return -1; + } } else { - return -1; + if (hopping_schdule->channel_plan_id == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->channel_plan_id == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->channel_plan_id == 5) { + hopping_schdule->ch0_freq = 9032; + hopping_schdule->channel_spacing = CHANNEL_SPACING_1200; + } else { + return -1; + } } } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_BZ) { - if (hopping_schdule->operating_class == 1) { - hopping_schdule->ch0_freq = 9022; - hopping_schdule->channel_spacing = CHANNEL_SPACING_200; - } else if (hopping_schdule->operating_class == 2) { - hopping_schdule->ch0_freq = 9024; - hopping_schdule->channel_spacing = CHANNEL_SPACING_400; - } else if (hopping_schdule->operating_class == 3) { - hopping_schdule->ch0_freq = 9026; - hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + if (hopping_schdule->channel_plan_id == 255) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 9026; + hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + } else { + return -1; + } } else { - return -1; + if (hopping_schdule->channel_plan_id == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->channel_plan_id == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->channel_plan_id == 5) { + hopping_schdule->ch0_freq = 9032; + hopping_schdule->channel_spacing = CHANNEL_SPACING_1200; + } else { + return -1; + } } } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_JP) { if (hopping_schdule->operating_class == 1) { @@ -236,7 +380,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, } else { return -1; } - hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class); + hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class, hopping_schdule->channel_plan_id); if (!hopping_schdule->number_of_channels) { return -1; } @@ -244,7 +388,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, return 0; } -uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class) +uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id) { if (regulatory_domain == REG_DOMAIN_KR) { if (operating_class == 1) { @@ -269,12 +413,22 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat return 10; } } else if (regulatory_domain == REG_DOMAIN_NA) { - if (operating_class == 1) { - return 129; - } else if (operating_class == 2) { - return 64; - } else if (operating_class == 3) { - return 42; + if (channel_plan_id == 255) { + if (operating_class == 1) { + return 129; + } else if (operating_class == 2) { + return 64; + } else if (operating_class == 3) { + return 42; + } + } else { + if (channel_plan_id == 1) { + return 136; + } else if (channel_plan_id == 2) { + return 64; + } else if (channel_plan_id == 5) { + return 24; + } } } else if (regulatory_domain == REG_DOMAIN_JP) { if (operating_class == 1) { @@ -285,12 +439,22 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat return 12; } } else if (regulatory_domain == REG_DOMAIN_BZ) { - if (operating_class == 1) { - return 129; - } else if (operating_class == 2) { - return 64; - } else if (operating_class == 3) { - return 42; + if (channel_plan_id == 255) { + if (operating_class == 1) { + return 129; + } else if (operating_class == 2) { + return 64; + } else if (operating_class == 3) { + return 42; + } + } else { + if (channel_plan_id == 1) { + return 136; + } else if (channel_plan_id == 2) { + return 64; + } else if (channel_plan_id == 5) { + return 24; + } } } else if (regulatory_domain == REG_DOMAIN_WW) { if (operating_class == 1) { @@ -366,10 +530,16 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8 } } +void ws_common_black_list_neighbour(const uint8_t *ll_address, uint8_t nd_status) +{ + if (nd_status == ARO_FULL) { + blacklist_update(ll_address, false); + } +} + void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address) { tr_warn("ARO registration Failure %s", trace_ipv6(ll_address)); - blacklist_update(ll_address, false); ws_bootstrap_aro_failure(cur, ll_address); } @@ -390,29 +560,41 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size) } } -static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64, uint32_t link_lifetime) { + if (link_lifetime > WS_NEIGHBOR_LINK_TIMEOUT) { + link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; + } /* * ARO registration from child can update the link timeout so we don't need to send extra NUD if ARO received */ mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, false, false); if (mac_neighbor) { - if (mac_neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (mac_neighbor->link_lifetime < link_lifetime) { //Set Stable timeout for temporary entry here + if (link_lifetime > WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME && mac_neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { + tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index); + } mac_neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; - tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index); + } //Refresh mac_neighbor->lifetime = mac_neighbor->link_lifetime; } } -uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64, uint16_t aro_timeout) { uint8_t child_count = 0; uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size); + if (aro_timeout == 0) { + //DeRegister Address Reg + return ARO_SUCCESS; + } + uint32_t link_lifetime = (aro_timeout * 60) + 1; + // Test API to limit child count if (test_max_child_count_override != 0xffff) { max_child_count = test_max_child_count_override; @@ -420,8 +602,9 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte //Validate Is EUI64 already allocated for any address if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) { - ws_common_neighbour_address_reg_link_update(interface, eui64); + ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime); tr_info("Child registration from old child"); + return ARO_SUCCESS; } @@ -431,20 +614,21 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte return ARO_TOPOLOGICALLY_INCORRECT; } - ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) { if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) { child_count++; } } + if (child_count >= max_child_count) { tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); return ARO_FULL; } - ws_common_neighbour_address_reg_link_update(interface, eui64); + ws_common_neighbour_address_reg_link_update(interface, eui64, link_lifetime); tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); + return ARO_SUCCESS; } @@ -464,21 +648,16 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur) { uint32_t latency = 0; - uint8_t network_size = cur->ws_info->cfg->gen.network_size; - if (network_size == NETWORK_SIZE_AUTOMATIC) { - network_size = cur->ws_info->pan_information.pan_size / 100; - } - - if (network_size <= NETWORK_SIZE_SMALL) { - // handles also NETWORK_SIZE_CERTIFICATE - latency = 4000; - } else if (network_size <= NETWORK_SIZE_MEDIUM) { - latency = 8000; - } else if (network_size <= NETWORK_SIZE_LARGE) { - latency = 16000; + if (ws_cfg_network_config_get(cur) <= CONFIG_SMALL) { + // Also has the certificate settings + latency = 5000; + } else if (ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM) { + latency = 10000; + } else if (ws_cfg_network_config_get(cur) <= CONFIG_LARGE) { + latency = 20000; } else { - latency = 24000; + latency = 30000; } return latency; diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 5b468d27ad..c4f92f5381 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -122,7 +122,7 @@ typedef struct ws_info_s { #ifdef HAVE_WS -int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class); +int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id); uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels); @@ -130,11 +130,17 @@ uint32_t ws_decode_channel_spacing(uint8_t channel_spacing); uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode); +uint32_t ws_get_datarate_using_phy_mode_id(uint8_t phy_mode_id); + +uint8_t ws_get_ofdm_option_using_phy_mode_id(uint8_t phy_mode_id); + +uint8_t ws_get_ofdm_mcs_using_phy_mode_id(uint8_t phy_mode_id); + phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode); int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule); -uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class); +uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id); int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur); @@ -144,11 +150,13 @@ void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); +void ws_common_black_list_neighbour(const uint8_t *ll_address, uint8_t nd_status); + void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); -uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64); +uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, const uint8_t *eui64, uint16_t aro_timeout); bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64); @@ -170,10 +178,11 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size); #define ws_info(cur) ((ws_info_t *) NULL) #define ws_common_seconds_timer(cur, seconds) #define ws_common_neighbor_update(cur, ll_address) ((void) 0) +#define ws_common_black_list_neighbour(ll_address, nd_status) ((void) 0) #define ws_common_aro_failure(cur, ll_address) #define ws_common_neighbor_remove(cur, ll_address) #define ws_common_fast_timer(cur, ticks) ((void) 0) -#define ws_common_allow_child_registration(cur, eui64) (2) +#define ws_common_allow_child_registration(cur, eui64, aro_timeout) (2) #define ws_common_negative_aro_mark(interface, eui64)(false) #define ws_common_latency_estimate_get(cur) 0 #define ws_common_datarate_get(cur) 0 diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 7ce70d0146..89a698b3d3 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -100,6 +100,8 @@ typedef struct ws_hopping_schedule_s { uint8_t regulatory_domain; /**< PHY regulatory domain default to "KR" 0x09 */ uint8_t operating_class; /**< PHY operating class default to 1 */ uint8_t operating_mode; /**< PHY operating mode default to "1b" symbol rate 50, modulation index 1 */ + uint8_t phy_mode_id; /**< PHY mode ID, default to 255 */ + uint8_t channel_plan_id; /**< Channel plan ID, default to 255 */ uint8_t channel_plan; /**< 0: use regulatory domain values 1: application defined plan */ uint8_t uc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ uint8_t bc_channel_function; /**< 0: Fixed channel, 1:TR51CF, 2: Direct Hash, 3: Vendor defined */ diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 6efcf20c80..f202cfea2f 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -144,9 +144,9 @@ extern uint8_t DEVICE_MIN_SENS; #define MPL_SMALL_K 8 #define MPL_SMALL_SEED_LIFETIME (MPL_SMALL_IMAX * MPL_SAFE_HOP_COUNT * (MPL_SMALL_EXPIRATIONS + 1)) // time that packet should get to safe distance /*Medium network size*/ -#define MPL_MEDIUM_IMIN 5 -#define MPL_MEDIUM_IMAX 20 -#define MPL_MEDIUM_EXPIRATIONS 2 +#define MPL_MEDIUM_IMIN 1 +#define MPL_MEDIUM_IMAX 32 +#define MPL_MEDIUM_EXPIRATIONS 1 #define MPL_MEDIUM_K 8 #define MPL_MEDIUM_SEED_LIFETIME (MPL_MEDIUM_IMAX * MPL_SAFE_HOP_COUNT * (MPL_MEDIUM_EXPIRATIONS + 1)) // time that packet should get to safe distance /*Large network size*/ @@ -221,6 +221,13 @@ extern uint8_t DEVICE_MIN_SENS; #define WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY 5 // During discovery state how many neighbours per pan #define WS_PARENT_LIST_MAX_PAN_IN_ACTIVE 2 // During active state two nodes per pan is allowed +#define WS_CONGESTION_PACKET_SIZE 500 // Packet length for calculate how much heap message queue can fit +#define WS_CONGESTION_QUEUE_DELAY 60 // Define message queue max length for given delay. This value is multiple by packet/seconds +#define WS_CONGESTION_RED_DROP_PROBABILITY 10 //10.0% +#define WS_CONGESTION_BR_MIN_QUEUE_SIZE 85000 / WS_CONGESTION_PACKET_SIZE +#define WS_CONGESTION_BR_MAX_QUEUE_SIZE 600000 / WS_CONGESTION_PACKET_SIZE +#define WS_CONGESTION_NODE_MIN_QUEUE_SIZE 10000 / WS_CONGESTION_PACKET_SIZE +#define WS_CONGESTION_NODE_MAX_QUEUE_SIZE 85000 / WS_CONGESTION_PACKET_SIZE /* * Modifications for base specification. * diff --git a/source/6LoWPAN/ws/ws_eapol_auth_relay.c b/source/6LoWPAN/ws/ws_eapol_auth_relay.c index cad3a52128..76f6221a74 100644 --- a/source/6LoWPAN/ws/ws_eapol_auth_relay.c +++ b/source/6LoWPAN/ws/ws_eapol_auth_relay.c @@ -26,6 +26,7 @@ #include "mac_api.h" #include "mac_mcps.h" #include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ip.h" #include "socket_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mpx_api.h" @@ -80,6 +81,8 @@ int8_t ws_eapol_auth_relay_start(protocol_interface_info_entry_t *interface_ptr, ns_dyn_mem_free(eapol_auth_relay); return -1; } + int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + socket_setsockopt(eapol_auth_relay->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); ns_list_add_to_end(&eapol_auth_relay_list, eapol_auth_relay); diff --git a/source/6LoWPAN/ws/ws_eapol_pdu.c b/source/6LoWPAN/ws/ws_eapol_pdu.c index f20530d466..b32892eaed 100644 --- a/source/6LoWPAN/ws/ws_eapol_pdu.c +++ b/source/6LoWPAN/ws/ws_eapol_pdu.c @@ -278,6 +278,9 @@ static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcp status = EAPOL_PDU_TX_OK; } else if (data->status == MLME_TX_NO_ACK) { status = EAPOL_PDU_TX_ERR_TX_NO_ACK; + tr_error("EAPOL TX err no ack"); + } else { + tr_error("EAPOL TX err"); } msdu->tx_status(eapol_pdu_data->interface_ptr, status, msdu->tx_identifier); } diff --git a/source/6LoWPAN/ws/ws_eapol_relay.c b/source/6LoWPAN/ws/ws_eapol_relay.c index 0bc7a5a472..41e01be8f1 100644 --- a/source/6LoWPAN/ws/ws_eapol_relay.c +++ b/source/6LoWPAN/ws/ws_eapol_relay.c @@ -26,6 +26,7 @@ #include "mac_api.h" #include "mac_mcps.h" #include "Common_Protocols/ipv6_constants.h" +#include "Common_Protocols/ip.h" #include "socket_api.h" #include "6LoWPAN/MAC/mac_helper.h" #include "6LoWPAN/MAC/mpx_api.h" @@ -89,6 +90,8 @@ int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint ns_dyn_mem_free(eapol_relay); return -1; } + int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + socket_setsockopt(eapol_relay->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); if (ws_eapol_pdu_cb_register(interface_ptr, &eapol_pdu_recv_cb_data) < 0) { ns_dyn_mem_free(eapol_relay); diff --git a/source/6LoWPAN/ws/ws_empty_functions.c b/source/6LoWPAN/ws/ws_empty_functions.c index 990c423df8..17443e8469 100644 --- a/source/6LoWPAN/ws/ws_empty_functions.c +++ b/source/6LoWPAN/ws/ws_empty_functions.c @@ -68,6 +68,24 @@ int ws_management_network_name_validate( return -1; } +int ws_management_phy_mode_id_set( + int8_t interface_id, + uint8_t phy_mode_id) +{ + (void)interface_id; + (void)phy_mode_id; + return -1; +} + +int ws_management_channel_plan_id_set( + int8_t interface_id, + uint8_t channel_plan_id) +{ + (void)interface_id; + (void)channel_plan_id; + return -1; +} + int ws_management_regulatory_domain_set( int8_t interface_id, uint8_t regulatory_domain, diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index 79748d4533..1f6f15abad 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -537,7 +537,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * ws_llc_mpx_eapol_send(base, message); } } else { - if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { + if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime <= WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME) { //Remove temp neighbour tr_debug("Remove Temp Entry by TX confirm"); mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor); diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index 10fcebf549..bdd2aadc9a 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -156,6 +156,74 @@ int ws_management_network_name_validate( return 0; } +int ws_management_phy_mode_id_set( + int8_t interface_id, + uint8_t phy_mode_id) +{ + protocol_interface_info_entry_t *cur; + + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_phy_cfg_t cfg; + ws_phy_cfg_t cfg_default; + if (ws_cfg_phy_get(&cfg, NULL) < 0) { + return -3; + } + + if (ws_cfg_phy_default_set(&cfg_default) < 0) { + return -3; + } + + if (phy_mode_id != 255) { + cfg.phy_mode_id = phy_mode_id; + } else { + cfg.phy_mode_id = cfg_default.phy_mode_id; + } + + if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) { + return -4; + } + + return 0; +} + +int ws_management_channel_plan_id_set( + int8_t interface_id, + uint8_t channel_plan_id) +{ + protocol_interface_info_entry_t *cur; + + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_phy_cfg_t cfg; + ws_phy_cfg_t cfg_default; + if (ws_cfg_phy_get(&cfg, NULL) < 0) { + return -3; + } + + if (ws_cfg_phy_default_set(&cfg_default) < 0) { + return -3; + } + + if (channel_plan_id != 255) { + cfg.channel_plan_id = channel_plan_id; + } else { + cfg.channel_plan_id = cfg_default.channel_plan_id; + } + + if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) { + return -4; + } + + return 0; +} + int ws_management_regulatory_domain_set( int8_t interface_id, uint8_t regulatory_domain, diff --git a/source/6LoWPAN/ws/ws_neighbor_class.c b/source/6LoWPAN/ws/ws_neighbor_class.c index 35647c1e12..ab24bf0ed8 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.c +++ b/source/6LoWPAN/ws/ws_neighbor_class.c @@ -254,7 +254,7 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t * } else { if (ws_us->channel_plan == 0) { - ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class); + ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class, own_shedule->channel_plan_id); } else if (ws_us->channel_plan == 1) { ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel; @@ -262,16 +262,16 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t * //Handle excluded channel and generate activate channel list if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) { - ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class); + ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id); ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) { - ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class); + ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id); ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) { if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) { - ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class); + ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id); ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); } } diff --git a/source/6LoWPAN/ws/ws_pae_key_storage.c b/source/6LoWPAN/ws/ws_pae_key_storage.c index 7ee66a073a..e8026364a3 100644 --- a/source/6LoWPAN/ws/ws_pae_key_storage.c +++ b/source/6LoWPAN/ws/ws_pae_key_storage.c @@ -186,6 +186,7 @@ static int8_t ws_pae_key_storage_allocate(const void *instance, uint16_t key_sto if (new_storage_array == NULL) { key_storage_array->storage_array_handle = ns_dyn_mem_alloc(key_storage_size); if (!key_storage_array->storage_array_handle) { + ns_dyn_mem_free(key_storage_array); return -1; } key_storage_array->allocated = true; diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 13c1e149ec..d3dc8a0220 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -269,6 +269,8 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid) { + (void) br_iid; + pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); if (!pae_supp) { return -1; @@ -276,24 +278,6 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, tr_info("NW key valid indication"); - // Store border router EUI-64 received on bootstrap complete - memcpy(pae_supp->comp_br_eui_64, br_iid, 8); - pae_supp->comp_br_eui_64[0] ^= 0x02; - pae_supp->comp_br_eui_64_set = true; - - // Get the EUI-64 used on 4WH handshake PTK generation - uint8_t *ptk_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys); - - /* If border router EUI-64 received on bootstrap complete does not match to - EUI-64 stored with keys, delete keys */ - if (!ptk_eui_64 || memcmp(ptk_eui_64, pae_supp->comp_br_eui_64, 8) != 0) { - tr_warn("Delete keys: PTK EUI-64 %s does not match to BR EUI-64 %s", - ptk_eui_64 ? tr_array(ptk_eui_64, 8) : "", tr_array(pae_supp->comp_br_eui_64, 8)); - sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys); - sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys); - sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys); - } - // Stored keys are valid pae_supp->nw_keys_used_cnt = 0; diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index 0d381eae7a..ba9bb0b684 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -357,6 +357,7 @@ static void icmpv6_na_wisun_aro_handler(protocol_interface_info_entry_t *cur_int (void)life_time; if (nd_status != ARO_SUCCESS) { + ws_common_black_list_neighbour(src_addr, nd_status); ws_common_aro_failure(cur_interface, src_addr); } } @@ -1110,6 +1111,7 @@ buffer_t *icmpv6_up(buffer_t *buf) || (buf->options.type == ICMPV6_TYPE_INFO_RPL_CONTROL && (buf->options.code != ICMPV6_CODE_RPL_DIO && buf->options.code != ICMPV6_CODE_RPL_DIS))) { + tr_warn("Drop: ICMP EP unsecured packet"); goto drop; } } @@ -1446,7 +1448,7 @@ static void icmpv6_aro_cb(buffer_t *buf, uint8_t status) ll_address[8] ^= 2; } if (rpl_control_address_register_done(buf->interface, ll_address, status)) { - // When RPL returns true neighbor should be blacklisted + // When RPL returns true neighbor should be deleted ws_common_aro_failure(buf->interface, ll_address); } } @@ -1526,7 +1528,11 @@ buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t ta /* If ARO Success sending is omitted, MAC ACK is used instead */ /* Setting callback for receiving ACK from adaptation layer */ if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success) { - buf->ack_receive_cb = icmpv6_aro_cb; + if (aro->lifetime > 1) { + buf->ack_receive_cb = icmpv6_aro_cb; + } else { + buf->ack_receive_cb = ack_receive_cb; + } } } if (unicast && (!aro && cur->ipv6_neighbour_cache.omit_na)) { @@ -1761,6 +1767,7 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited, tr_debug("Neighbour removed for negative response send"); return buffer_free(buf); } + buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; buf->ack_receive_cb = ack_remove_neighbour_cb; } diff --git a/source/Common_Protocols/ipv6.c b/source/Common_Protocols/ipv6.c index 11df4aafa4..8ccf5cb4a8 100644 --- a/source/Common_Protocols/ipv6.c +++ b/source/Common_Protocols/ipv6.c @@ -1416,6 +1416,7 @@ buffer_t *ipv6_forwarding_up(buffer_t *buf) #endif default: { if (buf->options.ll_security_bypass_rx) { + tr_warn("Drop: unsecured by BAD Next header %u", *nh_ptr); goto bad_nh; } buffer_socket_set(buf, socket_lookup_ipv6(*nh_ptr, &buf->dst_sa, &buf->src_sa, true)); diff --git a/source/Common_Protocols/tcp.c b/source/Common_Protocols/tcp.c index 311a0e96a7..2a0b6d498a 100644 --- a/source/Common_Protocols/tcp.c +++ b/source/Common_Protocols/tcp.c @@ -82,7 +82,7 @@ void tcp_test_drop_reset() } #endif -#ifdef FEA_TRACE_SUPPORT +#if defined(FEA_TRACE_SUPPORT) && MBED_CONF_MBED_TRACE_ENABLE && (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG) static const char *trace_tcp_flags(uint16_t flags) { static char buf[9]; @@ -1223,7 +1223,9 @@ buffer_t *tcp_up(buffer_t *buf) seg_len++; } +#if defined(FEA_TRACE_SUPPORT) && MBED_CONF_MBED_TRACE_ENABLE && (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG) tr_debug("TCP_UP: dst_p=%d, src_p=%d, flags=%s", buf->dst_sa.port, buf->src_sa.port, trace_tcp_flags(flags)); +#endif /* clear flags that will be ignored */ flags &= ~(TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG); diff --git a/source/Core/include/ns_buffer.h b/source/Core/include/ns_buffer.h index 0168495ff2..42defbc3cd 100644 --- a/source/Core/include/ns_buffer.h +++ b/source/Core/include/ns_buffer.h @@ -180,7 +180,9 @@ typedef enum { typedef enum { QOS_NORMAL = 0, QOS_HIGH = 1, - QOS_MAC_BEACON = 2 + QOS_NETWORK_CTRL = 2, + QOS_EXPEDITE_FORWARD = 3, + QOS_MAC_BEACON = 4 } buffer_priority_t; #define B_TO_MAC_MLME_MASK (B_DIR_MASK + B_FROM_MASK + B_TO_MASK ) diff --git a/source/Core/ns_monitor.c b/source/Core/ns_monitor.c index 17a46eb623..22d4c43e50 100644 --- a/source/Core/ns_monitor.c +++ b/source/Core/ns_monitor.c @@ -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" @@ -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) diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index 26f51cd520..51ce748424 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -26,6 +26,7 @@ struct cca_structure_s; struct buffer; struct mac_pre_build_frame; +struct mac_pre_parsed_frame_s; struct mlme_key_descriptor_s; struct arm_device_driver_list; struct fhss_api; @@ -204,6 +205,7 @@ typedef struct protocol_interface_rf_mac_setup { bool macBroadcastDisabled: 1; bool scan_active: 1; bool rf_csma_extension_supported: 1; + bool rf_pd_ack_buffer_is_in_use: 1; uint16_t mac_short_address; uint16_t pan_id; uint8_t mac64[8]; @@ -233,7 +235,9 @@ typedef struct protocol_interface_rf_mac_setup { struct mac_pre_build_frame *pd_data_request_queue_to_go; struct mac_pre_build_frame *pd_data_request_bc_queue_to_go; struct mac_pre_build_frame *active_pd_data_request; + struct mac_pre_parsed_frame_s *pd_rx_ack_buffer; /* MAC Beacon info */ + uint16_t allocated_ack_buffer_length; uint16_t max_beacon_payload_length; uint8_t *mac_beacon_payload; uint8_t mac_beacon_payload_size; @@ -253,6 +257,7 @@ typedef struct protocol_interface_rf_mac_setup { struct mac_pre_build_frame enhanced_ack_buffer; uint32_t enhanced_ack_handler_timestamp; arm_event_t mac_mcps_timer_event; + arm_event_storage_t mac_ack_event; uint16_t indirect_pending_bytes; arm_nwk_mlme_event_type_e mac_mlme_event; mac_event_t timer_mac_event; diff --git a/source/MAC/IEEE802_15_4/mac_filter.c b/source/MAC/IEEE802_15_4/mac_filter.c index 8903c7c8f4..a1a3ea9472 100644 --- a/source/MAC/IEEE802_15_4/mac_filter.c +++ b/source/MAC/IEEE802_15_4/mac_filter.c @@ -29,6 +29,7 @@ #include "mac_mcps.h" #include "MAC/IEEE802_15_4/mac_mcps_sap.h" #include "MAC/IEEE802_15_4/mac_header_helper_functions.h" +#include "MAC/rf_driver_storage.h" #define TRACE_GROUP "mFil" @@ -291,7 +292,7 @@ int_fast8_t mac_filter_add_long(int8_t interface_id, uint8_t mac64[8], int16_t l return 0; } -int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_frame_t *mac_frame) +int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, struct mac_fcf_sequence_s *fcf, struct arm_pd_sap_generic_ind_s *mac_frame) { filter_instance_t *this = filter_instance_find(interface_id); filter_t *filter_ptr = NULL; @@ -300,25 +301,24 @@ int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_f int16_t dbm_m; int16_t dbm_add; - if (!this || !mac_frame) { + if (!this) { return 0; } if (!this->enabled) { return 0; } + tr_debug_extra("mac_filter_modify_link_quality lqi %d dbm %d", mac_frame->link_quality, mac_frame->dbm); - tr_debug_extra("mac_filter_modify_link_quality lqi %d dbm %d", mac_frame->LQI, mac_frame->dbm); - - if (mac_frame->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_NONE) { + if (fcf->SrcAddrMode == MAC_ADDR_MODE_NONE) { return 0; } uint8_t srcAddress[8]; - mac_header_get_src_address(&mac_frame->fcf_dsn, mac_header_message_start_pointer(mac_frame), srcAddress); + mac_header_get_src_address(fcf, mac_frame->data_ptr, srcAddress); //Find filter for specific address - if (mac_frame->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_16_BIT) { + if (fcf->SrcAddrMode == MAC_ADDR_MODE_16_BIT) { uint16_t mac16 = common_read_16_bit(srcAddress); filter_ptr = filter_find_short(this, mac16); if (!filter_ptr && this->resolve_long_cb) { @@ -354,14 +354,14 @@ int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_f } //calculate - int16_t lqi = ((mac_frame->LQI * lqi_m) >> 8) + lqi_add; + int16_t lqi = ((mac_frame->link_quality * lqi_m) >> 8) + lqi_add; // Saturate if (lqi > 255) { - mac_frame->LQI = 255; + mac_frame->link_quality = 255; } else if (lqi < 0) { - mac_frame->LQI = 0; + mac_frame->link_quality = 0; } else { - mac_frame->LQI = lqi; + mac_frame->link_quality = lqi; } //calculate @@ -375,14 +375,14 @@ int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, mac_pre_parsed_f mac_frame->dbm = dbm; } - tr_debug_extra("mac_filter_modify_link_quality result lqi %d dbm %d", mac_frame->LQI, mac_frame->dbm); + tr_debug_extra("mac_filter_modify_link_quality result lqi %d dbm %d", mac_frame->link_quality, mac_frame->dbm); // If quality goes below treshold packet is dropped if ((dbm_m != 0x100 || dbm_add != 0) && (mac_frame->dbm < MAC_FILTER_SIGNAL_FLOOR)) { tr_debug_extra("Filter dropped packet signal too low"); return 1; } - if ((lqi_m != 0x100 || lqi_add != 0) && (mac_frame->LQI < 1)) { + if ((lqi_m != 0x100 || lqi_add != 0) && (mac_frame->link_quality < 1)) { tr_debug_extra("Filter dropped packet LQI < 1"); return 1; } diff --git a/source/MAC/IEEE802_15_4/mac_filter.h b/source/MAC/IEEE802_15_4/mac_filter.h index 784a9a884c..2df4e901cd 100644 --- a/source/MAC/IEEE802_15_4/mac_filter.h +++ b/source/MAC/IEEE802_15_4/mac_filter.h @@ -24,7 +24,8 @@ #ifndef MAC_FILTER_H_ #define MAC_FILTER_H_ -struct mac_pre_parsed_frame_s; +struct mac_fcf_sequence_s; +struct arm_pd_sap_generic_ind_s; /** * Modify the link quality values. @@ -41,6 +42,6 @@ struct mac_pre_parsed_frame_s; * return >0 Packet is ignored. * return 0 Packet is not dropped. */ -int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, struct mac_pre_parsed_frame_s *mac_frame); +int_fast8_t mac_filter_modify_link_quality(int8_t interface_id, struct mac_fcf_sequence_s *fcf, struct arm_pd_sap_generic_ind_s *mac_frame); #endif /* MAC_FILTER_H_ */ diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index a47753c3a3..899813b724 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -2372,6 +2372,18 @@ static mac_pre_build_frame_t *mcps_sap_pd_req_queue_read(protocol_interface_rf_m void mcps_sap_pre_parsed_frame_buffer_free(mac_pre_parsed_frame_t *buf) { + if (!buf) { + return; + } + + if (buf->mac_class_ptr && buf->fcf_dsn.frametype == FC_ACK_FRAME) { + struct protocol_interface_rf_mac_setup *rf_mac_setup = buf->mac_class_ptr; + if (rf_mac_setup->rf_pd_ack_buffer_is_in_use) { + rf_mac_setup->rf_pd_ack_buffer_is_in_use = false; + return; + } + } + ns_dyn_mem_free(buf); } @@ -2388,6 +2400,37 @@ mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data return buffer; } +mac_pre_parsed_frame_t *mcps_sap_pre_parsed_ack_buffer_get(protocol_interface_rf_mac_setup_s *rf_ptr, const uint8_t *data_ptr, uint16_t frame_length) +{ + + if (rf_ptr->rf_pd_ack_buffer_is_in_use) { +#ifdef __linux__ + tr_debug("mac ACK buffer get fail: already active"); +#endif + return NULL; + } + + if (frame_length > rf_ptr->allocated_ack_buffer_length) { + //Free Current + if (rf_ptr->pd_rx_ack_buffer) { + ns_dyn_mem_free(rf_ptr->pd_rx_ack_buffer); + rf_ptr->allocated_ack_buffer_length = 0; + } + rf_ptr->pd_rx_ack_buffer = ns_dyn_mem_alloc(sizeof(mac_pre_parsed_frame_t) + frame_length); + if (!rf_ptr->pd_rx_ack_buffer) { + return NULL; + } + rf_ptr->allocated_ack_buffer_length = frame_length; + } + memset(rf_ptr->pd_rx_ack_buffer, 0, sizeof(mac_pre_parsed_frame_t) + rf_ptr->allocated_ack_buffer_length); + rf_ptr->pd_rx_ack_buffer->frameLength = frame_length; + memcpy(mac_header_message_start_pointer(rf_ptr->pd_rx_ack_buffer), data_ptr, frame_length); + //Mark active ACK buffer state + rf_ptr->rf_pd_ack_buffer_is_in_use = true; + return rf_ptr->pd_rx_ack_buffer; +} + + static void mac_set_active_event(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t event_type) { rf_mac_setup->active_mac_events |= (1 << event_type); @@ -2458,21 +2501,36 @@ int8_t mcps_sap_pd_confirm_failure(void *mac_ptr) return eventOS_event_send(&event); } -void mcps_sap_pd_ack(void *ack_ptr) +int8_t mcps_sap_pd_ack(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_parsed_frame_t *buffer) { - if (mac_tasklet_event_handler < 0 || !ack_ptr) { - return; + if (mac_tasklet_event_handler < 0 || !buffer) { + return -1; } + + if (buffer->fcf_dsn.frametype == FC_ACK_FRAME) { + arm_event_storage_t *event = &rf_ptr->mac_ack_event; + event->data.data_ptr = buffer; + event->data.event_data = 0; + event->data.event_id = 0; + event->data.event_type = MCPS_SAP_DATA_ACK_CNF_EVENT; + event->data.priority = ARM_LIB_HIGH_PRIORITY_EVENT; + event->data.sender = 0; + event->data.receiver = mac_tasklet_event_handler; + eventOS_event_send_user_allocated(event); + + return 0; + } + arm_event_s event = { .receiver = mac_tasklet_event_handler, .sender = 0, .event_id = 0, - .data_ptr = ack_ptr, + .data_ptr = buffer, .event_type = MCPS_SAP_DATA_ACK_CNF_EVENT, .priority = ARM_LIB_HIGH_PRIORITY_EVENT, }; - eventOS_event_send(&event); + return eventOS_event_send(&event); } void mcps_sap_trig_tx(void *mac_ptr) @@ -2566,6 +2624,17 @@ void mac_mcps_buffer_queue_free(protocol_interface_rf_mac_setup_s *rf_mac_setup) mcps_sap_prebuild_frame_buffer_free(buffer); } } + + if (rf_mac_setup->pd_rx_ack_buffer) { + if (rf_mac_setup->rf_pd_ack_buffer_is_in_use) { + eventOS_cancel(&rf_mac_setup->mac_ack_event); + rf_mac_setup->rf_pd_ack_buffer_is_in_use = false; + } + ns_dyn_mem_free(rf_mac_setup->pd_rx_ack_buffer); + rf_mac_setup->pd_rx_ack_buffer = NULL; + rf_mac_setup->allocated_ack_buffer_length = 0; + } + } /** * Function return list start pointer diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.h b/source/MAC/IEEE802_15_4/mac_mcps_sap.h index fb212e20a2..3992ae3125 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.h +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.h @@ -36,6 +36,7 @@ struct mcps_purge_s; struct mcps_data_req_ie_list; struct channel_list_s; struct mcps_enhanced_frame_response_s; +struct mac_pre_parsed_frame_s; /** Address types */ typedef enum { @@ -100,6 +101,8 @@ void mcps_sap_pd_req_queue_write(struct protocol_interface_rf_mac_setup *rf_mac_ */ mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length); +mac_pre_parsed_frame_t *mcps_sap_pre_parsed_ack_buffer_get(struct protocol_interface_rf_mac_setup *rf_ptr, const uint8_t *data_ptr, uint16_t frame_length); + /** * Forward Buffer for MAC MCPS SAP layer event handler */ @@ -112,7 +115,7 @@ int8_t mcps_sap_pd_confirm(void *mac_ptr); int8_t mcps_sap_pd_confirm_failure(void *mac_ptr); -void mcps_sap_pd_ack(void *ack_ptr); +int8_t mcps_sap_pd_ack(struct protocol_interface_rf_mac_setup *rf_ptr, struct mac_pre_parsed_frame_s *buffer); int8_t mac_virtual_sap_data_cb(void *identifier, struct arm_phy_sap_msg_s *message); diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index 8229e29f3f..0e6ae5ca36 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -828,6 +828,9 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m tr_info("Number of channels: %u", config_params->number_of_channels); tr_info("Modulation: %u", config_params->modulation); tr_info("Modulation index: %u", config_params->modulation_index); + tr_info("FEC: %u", config_params->fec); + tr_info("OFDM MCS: %u", config_params->ofdm_mcs); + tr_info("OFDM option: %u", config_params->ofdm_option); return 0; default: return mac_mlme_handle_set_values(rf_mac_setup, set_req); diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index dad7da84fd..6a6b4a3f93 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -480,6 +480,8 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time); // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer if (tx_handle_retval == -1) { + // RX channel could have changed during CSMA-CA, must update using TX done callback + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, rf_ptr->active_pd_data_request->msduHandle); mac_sap_cca_fail_cb(rf_ptr, 0xffff); return PHY_TX_NOT_ALLOWED; } @@ -631,14 +633,19 @@ VALIDATE_TX_TIME: return 0; } +static int8_t mac_data_interface_waiting_ack(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read) +{ + if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != fcf_read->DSN) { + return -1; + } + + return 0; +} + static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf) { - if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != buf->fcf_dsn.DSN) { - return -1; - } - timer_mac_stop(rf_ptr); if (buf->fcf_dsn.framePending) { rf_ptr->mac_tx_result = MAC_TX_DONE_PENDING; @@ -647,7 +654,9 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set } rf_ptr->macRfRadioTxActive = false; rf_ptr->macTxProcessActive = false; - mcps_sap_pd_ack(buf); + if (mcps_sap_pd_ack(rf_ptr, buf) != 0) { + mcps_sap_pre_parsed_frame_buffer_free(buf); + } if (rf_ptr->fhss_api) { rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle); @@ -891,22 +900,35 @@ static int8_t mac_pd_sap_generate_edfe_response(protocol_interface_rf_mac_setup_ static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind) { // Unless receiving Ack, check that system has enough space to handle the new packet - if (fcf_read->frametype != FC_ACK_FRAME) { - if (!ns_monitor_packet_allocation_allowed()) { + mac_pre_parsed_frame_t *buffer = NULL; + if (fcf_read->frametype != FC_ACK_FRAME || rf_ptr->macProminousMode) { + if (!rf_ptr->macProminousMode && !ns_monitor_packet_allocation_allowed()) { // stack can not handle new packets for routing #ifdef __linux__ tr_debug("Packet ingress drop buffer allocation"); #endif return NULL; } - } - mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len); - if (!buffer) { + + buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len); + if (!buffer) { #ifdef __linux__ - tr_debug("macPD buffer allocate fail %u", pd_data_ind->data_len); + tr_debug("macPD buffer allocate fail %u", pd_data_ind->data_len); #endif - return NULL; + return NULL; + } + } else { + //Allocate ACK buffer + buffer = mcps_sap_pre_parsed_ack_buffer_get(rf_ptr, pd_data_ind->data_ptr, pd_data_ind->data_len); + if (!buffer) { +#ifdef __linux__ + tr_debug("macPD ACK buffer allocate fail %u", pd_data_ind->data_len); +#endif + return NULL; + + } } + //Copy Pre Parsed values buffer->fcf_dsn = *fcf_read; buffer->timestamp = mac_pd_sap_get_phy_rx_time(rf_ptr); @@ -1012,11 +1034,20 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) mac_fcf_sequence_t fcf_read; const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr); - buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind); - if (buffer && mac_filter_modify_link_quality(rf_ptr->mac_interface_id, buffer) == 1) { + // No need to send Ack - Check if RX channel needs to be updated + if (fcf_read.ackRequested == false) { + if (rf_ptr->fhss_api) { + rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0); + } + } + + //Modify link quality + if (mac_filter_modify_link_quality(rf_ptr->mac_interface_id, &fcf_read, pd_data_ind) == 1) { goto ERROR_HANDLER; } + if (!rf_ptr->macProminousMode) { + //Pre validate things before allocate buffer if (mac_pd_sap_validate_fcf(rf_ptr, &fcf_read, pd_data_ind)) { goto ERROR_HANDLER; } @@ -1024,12 +1055,26 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) pd_data_ind->data_len = 0; // Do not update RX drop in that case goto ERROR_HANDLER; } + //Ack can be send even buffer allocate fail if (mac_pd_sap_generate_ack(rf_ptr, &fcf_read, pd_data_ind)) { #ifdef __linux__ tr_debug("Drop a Data by ignored ACK generation"); #endif goto ERROR_HANDLER; } + if (fcf_read.frametype == FC_ACK_FRAME && mac_data_interface_waiting_ack(rf_ptr, &fcf_read)) { +#ifdef __linux__ + tr_debug("Drop a ACK not a proper DSN"); +#endif + goto ERROR_HANDLER; + } + + } + //Allocate Buffer + buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind); + + if (!rf_ptr->macProminousMode) { + if (buffer) { if (mac_pd_sap_parse_length_fields(buffer, pd_data_ind, ptr)) { goto ERROR_HANDLER; @@ -1098,7 +1143,7 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) //Mark session closed rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE; rf_ptr->mac_edfe_tx_active = false; - if (mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) { + if (mac_data_interface_waiting_ack(rf_ptr, &buffer->fcf_dsn) || mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) { mcps_sap_pre_parsed_frame_buffer_free(buffer); } return 0; diff --git a/source/MPL/mpl.c b/source/MPL/mpl.c index 913745f0c9..68c56b95c1 100644 --- a/source/MPL/mpl.c +++ b/source/MPL/mpl.c @@ -406,6 +406,7 @@ static mpl_buffered_message_t *mpl_buffer_create(buffer_t *buf, mpl_domain_t *do uint16_t ip_len = buffer_data_length(buf); while (mpl_total_buffered + ip_len > MAX_BUFFERED_MESSAGES_SIZE) { + tr_debug("MPL MAX buffered message size limit...free space"); mpl_free_space(); } @@ -427,6 +428,7 @@ static mpl_buffered_message_t *mpl_buffer_create(buffer_t *buf, mpl_domain_t *do mpl_buffered_message_t *message = ns_dyn_mem_alloc(sizeof(mpl_buffered_message_t) + ip_len); if (!message) { + tr_debug("No heap for new MPL message"); return NULL; } memcpy(message->message, buffer_data_pointer(buf), ip_len); @@ -475,6 +477,7 @@ static void mpl_buffer_transmit(mpl_domain_t *domain, mpl_buffered_message_t *me uint16_t ip_len = mpl_buffer_size(message); buffer_t *buf = buffer_get(ip_len); if (!buf) { + tr_debug("No heap for MPL transmit"); return; } @@ -939,6 +942,9 @@ bool mpl_forwarder_process_message(buffer_t *buf, mpl_domain_t *domain, bool see } message = mpl_buffer_create(buf, domain, seed, sequence, hop_limit); + if (!message) { + tr_debug("MPL Buffer Craete fail"); + } return true; } diff --git a/source/NWK_INTERFACE/Include/protocol.h b/source/NWK_INTERFACE/Include/protocol.h index 9880a5d2cc..a9f26329db 100644 --- a/source/NWK_INTERFACE/Include/protocol.h +++ b/source/NWK_INTERFACE/Include/protocol.h @@ -57,6 +57,7 @@ struct arm_device_driver_list; struct mlme_security_s; struct load_balance_api; struct nwk_wpan_nvm_api; +struct red_info_s; #define SLEEP_MODE_REQ 0x80 #define SLEEP_PERIOD_ACTIVE 0x40 @@ -445,6 +446,7 @@ struct protocol_interface_info_entry { struct auth_info *pana_sec_info_temp; br_info_t *border_router_setup; struct load_balance_api *lb_api; + struct red_info_s *random_early_detection; neigh_cache_s neigh_cache; pan_blaclist_cache_s pan_blaclist_cache; pan_coordinator_blaclist_cache_s pan_cordinator_black_list; diff --git a/source/NWK_INTERFACE/Include/protocol_stats.h b/source/NWK_INTERFACE/Include/protocol_stats.h index e8ee77f2ca..193a9538e9 100644 --- a/source/NWK_INTERFACE/Include/protocol_stats.h +++ b/source/NWK_INTERFACE/Include/protocol_stats.h @@ -44,7 +44,8 @@ typedef enum { STATS_BUFFER_HEADROOM_FAIL, STATS_ETX_1ST_PARENT, STATS_ETX_2ND_PARENT, - STATS_AL_TX_QUEUE_SIZE + STATS_AL_TX_QUEUE_SIZE, + STATS_AL_TX_CONGESTION_DROP } nwk_stats_type_t; diff --git a/source/NWK_INTERFACE/protocol_stats.c b/source/NWK_INTERFACE/protocol_stats.c index aedec1cbae..074dc07951 100644 --- a/source/NWK_INTERFACE/protocol_stats.c +++ b/source/NWK_INTERFACE/protocol_stats.c @@ -152,6 +152,9 @@ void protocol_stats_update(nwk_stats_type_t type, uint16_t update_val) nwk_stats_ptr->adapt_layer_tx_queue_peak = nwk_stats_ptr->adapt_layer_tx_queue_size; } break; + case STATS_AL_TX_CONGESTION_DROP: + nwk_stats_ptr->adapt_layer_tx_congestion_drop++; + break; } } } diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 37eacc4345..b6724d65fd 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -45,6 +45,7 @@ #include "NWK_INTERFACE/Include/protocol_stats.h" #include "Common_Protocols/ipv6_constants.h" #include "Common_Protocols/icmpv6.h" +#include "Common_Protocols/ip.h" #include "ipv6_stack/protocol_ipv6.h" #include "Service_Libs/etx/etx.h" /* slight ick */ @@ -1168,6 +1169,23 @@ malformed: goto invalid_parent; } + /* RFC 6550 8.3: A DIO from a sender with lesser DAGRank that causes no + * changes to the recipient's parent set, preferred parent, or Rank SHOULD + * be considered consistent with respect to the Trickle timer. + * + * Now, if we don't run parent selection immediately, how do we know if it's + * consistent or not? Compromise is to treat all lower ranked DIOs as + * consistent, and reset (and hold) the consistent counter to 0 if any of + * the above change. This actually seems better than the RFC 6550 rule, as + * it guarantees we will transmit if those change. The rule as stated + * would mean a large number of parent messages would stop us advertising + * a Rank change. + */ + if (version == rpl_instance_current_dodag_version(instance) && + (rpl_rank_compare(dodag, rank, rpl_instance_current_rank(instance)) & RPL_CMP_LESS)) { + rpl_instance_consistent_rx(instance); + } + /* Now we create the neighbour, if we don't already have a record */ if (!neighbour) { @@ -1207,23 +1225,6 @@ malformed: rpl_dodag_set_leaf(dodag, true); } - /* RFC 6550 8.3: A DIO from a sender with lesser DAGRank that causes no - * changes to the recipient's parent set, preferred parent, or Rank SHOULD - * be considered consistent with respect to the Trickle timer. - * - * Now, if we don't run parent selection immediately, how do we know if it's - * consistent or not? Compromise is to treat all lower ranked DIOs as - * consistent, and reset (and hold) the consistent counter to 0 if any of - * the above change. This actually seems better than the RFC 6550 rule, as - * it guarantees we will transmit if those change. The rule as stated - * would mean a large number of parent messages would stop us advertising - * a Rank change. - */ - if (version == rpl_instance_current_dodag_version(instance) && - (rpl_rank_compare(dodag, rank, rpl_instance_current_rank(instance)) & RPL_CMP_LESS)) { - rpl_instance_consistent_rx(instance); - } - rpl_instance_neighbours_changed(instance, dodag); return buffer_free(buf); @@ -1292,6 +1293,10 @@ void rpl_control_transmit(rpl_domain_t *domain, protocol_interface_info_entry_t /* Others set "0", which means use interface default */ buf->options.hop_limit = addr_ipv6_scope(buf->dst_sa.address, cur) <= IPV6_SCOPE_LINK_LOCAL ? 255 : 0; + if (code == ICMPV6_CODE_RPL_DAO || code == ICMPV6_CODE_RPL_DAO_ACK || buf->dst_sa.address[0] != 0xff) { + //DAO and DAO ACK and unicast traffic with Higher priority + buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + } if (dst == NULL && cur == NULL) { rpl_control_transmit_all_interfaces(domain, buf); diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 72ddf1281f..4b7fe15dd2 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -91,6 +91,7 @@ #include "Common_Protocols/icmpv6.h" #include "NWK_INTERFACE/Include/protocol.h" #include "ipv6_stack/ipv6_routing_table.h" +#include "Common_Protocols/ip.h" #include "net_rpl.h" #include "RPL/rpl_protocol.h" @@ -884,9 +885,24 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance) instance->requested_dao_ack = need_ack; instance->dao_in_transit = true; if (instance->dao_attempt < 16) { - uint32_t t = (uint32_t) rpl_policy_initial_dao_ack_wait(instance->domain, mop) << instance->dao_attempt; - t = randLIB_randomise_base(t, 0x4000, 0xC000); - instance->dao_retry_timer = t <= 0xffff ? t : 0xffff; + + uint32_t delay = rpl_policy_initial_dao_ack_wait(instance->domain, mop); + if (delay < dodag->dio_timer_params.Imin) { + //Use Imin Based on delay if it is longer than cache retry + delay = dodag->dio_timer_params.Imin; + } + //Multiply Delay by attempt + delay = delay << instance->dao_attempt; + + if (delay > 5400) { + //MAX base 540 seconds (9min) + delay = 5400; + } + + // 0.5 - 1.5 *t randomized base delay + delay = randLIB_randomise_base(delay, 0x4000, 0xC000); + + instance->dao_retry_timer = delay; } else { instance->dao_retry_timer = 0xffff; } @@ -1874,6 +1890,7 @@ static bool rpl_instance_push_address_registration(protocol_interface_info_entry if (!buf) { return false; } + buf->options.traffic_class = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; tr_info("Send ARO %s to %s", trace_ipv6(addr->address), trace_ipv6(neighbour->ll_address)); protocol_push(buf); return true; diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index f6a5a18bed..837d0fa9ab 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -180,6 +180,7 @@ struct rpl_instance { bool requested_dao_ack: 1; /* If we requested an ACK (so we retry if no ACK, rather than assuming success) */ bool pending_neighbour_confirmation: 1; /* if we have not finished address registration state to parent */ bool parent_was_selected: 1; + bool advertised_dodag_membership_since_last_repair: 1; /* advertised dodag membership since last repair */ uint8_t poison_count; uint8_t repair_dis_count; uint16_t repair_dis_timer; @@ -192,7 +193,7 @@ struct rpl_instance { rpl_dodag_version_t *current_dodag_version; /* Pointer to DODAG version we are a member of (if any) */ uint16_t current_rank; /* Current rank in current DODAG Version */ uint16_t parent_selection_timer; - rpl_dodag_version_t *last_advertised_dodag_version; /* Pointer to last DODAG version we advertised */ + trickle_t dio_timer; /* Trickle timer for DIO transmission */ rpl_dao_root_transit_children_list_t root_children; rpl_dao_target_list_t dao_targets; /* List of DAO targets */ diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index dec173ef71..2a606da2ea 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1665,8 +1665,9 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_ #endif } rpl_dodag_version_limit_greediness(dodag_version, rank); - - instance->last_advertised_dodag_version = dodag_version; + if (rank != RPL_RANK_INFINITE) { + instance->advertised_dodag_membership_since_last_repair = true; + } } static void rpl_instance_dis_timer(rpl_instance_t *instance, uint16_t seconds) @@ -1715,6 +1716,7 @@ void rpl_instance_set_local_repair(rpl_instance_t *instance, bool repair) instance->repair_dis_count = 0; } else { instance->repair_dis_timer = 0; + instance->advertised_dodag_membership_since_last_repair = false; } /* When repair ends, eliminate all higher-rank neighbours (potential sub-DODAG) from table */ @@ -1839,8 +1841,14 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) /* Delay sending first DIO if we are still potentially gathering info */ /* Important to always send DIOs if we ever have sent any, so we can indicate problems to others */ - if (!rpl_instance_am_root(instance) && !instance->last_advertised_dodag_version && rpl_policy_parent_confirmation_requested()) { - // We dont have any valid parent selected + if (!rpl_instance_am_root(instance) && !instance->poison_count && !instance->advertised_dodag_membership_since_last_repair && rpl_policy_parent_confirmation_requested()) { + + // We don't have DAO target generated + if (ns_list_count(&instance->dao_targets) == 0) { + return; + } + + // We don't have any valid parent selected if (!rpl_instance_parent_selection_ready(instance)) { return; } diff --git a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c index 6b729450a0..882df678fd 100644 --- a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c +++ b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c @@ -652,6 +652,14 @@ static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t radius_msg_length += AVP_TYPE_NAS_IPV6_ADDRESS_LEN; uint8_t *radius_msg_ptr = ns_dyn_mem_temporary_alloc(radius_msg_length); + if (radius_msg_ptr == NULL) { + if (data->send_radius_msg != NULL) { + ns_dyn_mem_free(data->send_radius_msg); + } + data->send_radius_msg = NULL; + data->send_radius_msg_len = 0; + return; + } uint8_t *radius_msg_start_ptr = radius_msg_ptr; *radius_msg_ptr++ = RADIUS_ACCESS_REQUEST; // code diff --git a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c index de1d86b515..1ba7f109ab 100644 --- a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c +++ b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c @@ -416,7 +416,7 @@ static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int l int8_t tls_sec_prot_lib_process(tls_security_t *sec) { - int ret = -1; + int32_t ret = -1; while (ret != MBEDTLS_ERR_SSL_WANT_READ) { ret = mbedtls_ssl_handshake_step(&sec->ssl); @@ -428,6 +428,7 @@ int8_t tls_sec_prot_lib_process(tls_security_t *sec) #endif if (ret && (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { + tr_error("TLS error: %" PRId32, ret); return TLS_SEC_PROT_LIB_ERROR; } diff --git a/source/Service_Libs/fhss/fhss_common.h b/source/Service_Libs/fhss/fhss_common.h index 724351d029..71c2d9a4d1 100644 --- a/source/Service_Libs/fhss/fhss_common.h +++ b/source/Service_Libs/fhss/fhss_common.h @@ -41,6 +41,7 @@ struct fhss_structure { uint8_t active_fhss_events; uint16_t number_of_channels; uint16_t number_of_uc_channels; + uint16_t number_of_bc_channels; uint16_t optimal_packet_length; fhss_states fhss_state; uint32_t fhss_timeout; diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 43d1e39b16..11b0ff28d8 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -195,7 +195,7 @@ void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) if (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval == 0 || fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval == 0) { return; } - uint32_t txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS; + uint32_t txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS_MAX; if (fhss_structure->callbacks.read_datarate) { /* Calculate minimum TX slot length which can fit optimal packet length twice. * Twice, because 0, 1, 4, 5... hop starts transmission at the beginning of TX slot and 2, 3, 6, 7... hop at the middle of TX slot @@ -217,9 +217,14 @@ void fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure) if (datarate) { txrx_slot_length_ms_tmp = ((fhss_structure->optimal_packet_length * 2) * (8000000 / datarate)) / 1000; // Do not allow using too high TX slot length. - if (txrx_slot_length_ms_tmp > WS_TXRX_SLOT_LEN_MS) { - tr_debug("TX slot length setting too high %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS); - txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS; + if (txrx_slot_length_ms_tmp > WS_TXRX_SLOT_LEN_MS_MAX) { + tr_debug("TX slot length setting too high %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS_MAX); + txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS_MAX; + } + // Do not allow using too low TX slot length. + if (txrx_slot_length_ms_tmp < WS_TXRX_SLOT_LEN_MS_MIN) { + tr_debug("TX slot length setting too low %"PRIu32"ms, using %"PRIu32"ms", txrx_slot_length_ms_tmp, (uint32_t)WS_TXRX_SLOT_LEN_MS_MIN); + txrx_slot_length_ms_tmp = WS_TXRX_SLOT_LEN_MS_MIN; } } } @@ -241,14 +246,14 @@ static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure) int32_t next_channel = fhss_structure->ws->fhss_configuration.broadcast_fixed_channel; if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) { - next_channel = tr51_get_bc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels, NULL); + next_channel = tr51_get_bc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_bc_channels, NULL); next_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.channel_mask, next_channel, fhss_structure->number_of_channels); - if (++fhss_structure->ws->bc_slot == fhss_structure->number_of_channels) { + if (++fhss_structure->ws->bc_slot == fhss_structure->number_of_bc_channels) { fhss_structure->ws->bc_slot = 0; } } else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_DH1CF) { fhss_structure->ws->bc_slot++; - next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels); + next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_bc_channels); next_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.channel_mask, next_channel, fhss_structure->number_of_channels); } else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_VENDOR_DEF_CF) { if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) { @@ -338,7 +343,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay) } if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) { - fhss_structure->ws->bc_slot %= fhss_structure->number_of_channels; + fhss_structure->ws->bc_slot %= fhss_structure->number_of_bc_channels; } if (fhss_structure->ws->is_on_bc_channel == false) { @@ -604,9 +609,14 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a if (!fhss_structure) { return -1; } - if (is_broadcast_addr) { + // Allow broadcast destination on broadcast channel + if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) { return 0; } + // Do not allow broadcast destination on unicast channel + if (is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == false)) { + return -3; + } // Do not allow unicast destination on broadcast channel if (!is_broadcast_addr && (fhss_structure->ws->is_on_bc_channel == true)) { return -1; @@ -919,7 +929,7 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t uint32_t cur_time_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api); uint32_t tx_trig_offset_us = (txrx_slot_length_us / 2) * calc_own_tx_trig_slot(fhss_structure->own_hop); - uint32_t next_tx_trig_slot_start_us = unicast_start_us + (txrx_slot_length_us * !fhss_ws_check_tx_allowed(fhss_structure)) + tx_trig_offset_us; + uint32_t next_tx_trig_slot_start_us = unicast_start_us + (txrx_slot_length_us * (fhss_structure->own_hop & 1)) + tx_trig_offset_us; uint32_t next_tx_trig_slot_end_us = next_tx_trig_slot_start_us + (txrx_slot_length_us / 2); while ((next_tx_trig_slot_start_us < cur_time_us) || ((next_tx_trig_slot_start_us - cur_time_us) > (uint32_t) MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval))) { if (cur_time_us < next_tx_trig_slot_end_us) { @@ -1076,13 +1086,13 @@ int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration) { - int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); + int channel_count_bc = channel_list_count_channels(fhss_configuration->channel_mask); int channel_count_uc = channel_list_count_channels(fhss_configuration->unicast_channel_mask); - if (channel_count <= 0) { + if (channel_count_bc <= 0 || fhss_configuration->channel_mask_size == 0) { return -1; } - if (fhss_structure->number_of_channels < channel_count || + if (fhss_structure->number_of_bc_channels < channel_count_bc || (channel_count_uc && fhss_structure->number_of_uc_channels < channel_count_uc)) { // Channel amount changed to largeneed to reallocate channel table ns_dyn_mem_free(fhss_structure->ws->tr51_channel_table); @@ -1090,7 +1100,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co ns_dyn_mem_free(fhss_structure->ws->tr51_output_table); fhss_structure->ws->tr51_output_table = NULL; - if (fhss_ws_manage_channel_table_allocation(fhss_structure, channel_count_uc > channel_count ? channel_count_uc : channel_count)) { + if (fhss_ws_manage_channel_table_allocation(fhss_structure, channel_count_uc > channel_count_bc ? channel_count_uc : channel_count_bc)) { return -1; } } @@ -1113,10 +1123,11 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co for (uint8_t i = 0; i < 8; i++) { fhss_structure->ws->fhss_configuration.unicast_channel_mask[i] = fhss_configuration->channel_mask[i]; } - channel_count_uc = channel_count; + channel_count_uc = channel_count_bc; } - fhss_structure->number_of_channels = channel_count; + fhss_structure->number_of_channels = fhss_configuration->channel_mask_size; + fhss_structure->number_of_bc_channels = channel_count_bc; fhss_structure->number_of_uc_channels = channel_count_uc; if (fhss_configuration->ws_uc_channel_function == WS_FIXED_CHANNEL) { fhss_structure->rx_channel = fhss_configuration->unicast_fixed_channel; @@ -1127,7 +1138,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co fhss_structure->ws->fhss_configuration.broadcast_fixed_channel, fhss_structure->ws->fhss_configuration.ws_uc_channel_function, fhss_structure->ws->fhss_configuration.ws_bc_channel_function, - fhss_structure->number_of_channels, + fhss_structure->number_of_bc_channels, fhss_structure->number_of_uc_channels, fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval, fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval, diff --git a/source/Service_Libs/fhss/fhss_ws.h b/source/Service_Libs/fhss/fhss_ws.h index b9e35665ec..c81bac463e 100644 --- a/source/Service_Libs/fhss/fhss_ws.h +++ b/source/Service_Libs/fhss/fhss_ws.h @@ -19,8 +19,10 @@ // TX slot length is optimised to this packet length #define OPTIMAL_PACKET_LENGTH 500 -// Default TX/RX slot length in milliseconds. Is used when datarate is not given by PHY. -#define WS_TXRX_SLOT_LEN_MS 100 +// Max TX/RX slot length in milliseconds. Is used when datarate is not given by PHY or calculated slot length exceeds maximum allowed. +#define WS_TXRX_SLOT_LEN_MS_MAX 100 +// Min TX/RX slot length in milliseconds. Is used when calculated slot length is under minimum allowed. +#define WS_TXRX_SLOT_LEN_MS_MIN 10 // Default minimum broadcast synchronization interval in seconds #define DEFAULT_MIN_SYNCH_INTERVAL 60 // Drift compensation allowed if at least SYNCH_COMPENSATION_MIN_INTERVAL (seconds) since last synchronization diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/fnet_config.h b/source/Service_Libs/mdns/fnet/fnet_stack/fnet_config.h index 85f2340c26..54bb282c4e 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/fnet_config.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/fnet_config.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp.h b/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp.h index 04881c1f84..d3109581b5 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2019 Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp_config.h b/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp_config.h index 81732fbf62..ab376cec25 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp_config.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler/fnet_comp_config.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2019 Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services.h b/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services.h index 197d0b4cc0..255b8ea950 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services_config.h b/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services_config.h index bb33a14c41..c93f83a0ca 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services_config.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/services/fnet_services_config.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.c b/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.c index 4ae61bef83..94561a3a5b 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.c +++ b/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.c @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, 2019 Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2016 by Andrey Butok. FNET Community. * *************************************************************************** diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.h b/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.h index 38511a37a7..ff3e2f7119 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns/fnet_mdns.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2016 by Andrey Butok. FNET Community. * *************************************************************************** diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/services/poll/fnet_poll.c b/source/Service_Libs/mdns/fnet/fnet_stack/services/poll/fnet_poll.c index 28234e0ba4..8dbd864af9 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/services/poll/fnet_poll.c +++ b/source/Service_Libs/mdns/fnet/fnet_stack/services/poll/fnet_poll.c @@ -1,5 +1,6 @@ /************************************************************************** * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/services/serial/fnet_serial.h b/source/Service_Libs/mdns/fnet/fnet_stack/services/serial/fnet_serial.h index 38afbb0baa..3bfde79520 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/services/serial/fnet_serial.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/services/serial/fnet_serial.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_debug.h b/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_debug.h index 5d19ddeeda..b918c9b10b 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_debug.h +++ b/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_debug.h @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc. * diff --git a/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_stdlib.c b/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_stdlib.c index 8fbdb2f77b..61c2580ce4 100644 --- a/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_stdlib.c +++ b/source/Service_Libs/mdns/fnet/fnet_stack/stack/fnet_stdlib.c @@ -1,6 +1,7 @@ /************************************************************************** * * Copyright (c) 2017, Arm Limited and affiliates. +* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2016 by Andrey Butok. FNET Community. * Copyright 2008-2010 by Freescale Semiconductor, Inc. * Copyright 2003 by Motorola SPS. diff --git a/source/Service_Libs/random_early_detection/random_early_detection.c b/source/Service_Libs/random_early_detection/random_early_detection.c new file mode 100644 index 0000000000..b1a4b73d74 --- /dev/null +++ b/source/Service_Libs/random_early_detection/random_early_detection.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nsconfig.h" +#include "ns_types.h" +#include "string.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "randLIB.h" +#include "Service_Libs/random_early_detection/random_early_detection.h" +#include "Service_Libs/random_early_detection/random_early_detection_api.h" + + +red_info_t *random_early_detection_create(uint16_t threshold_min, uint16_t threshold_max, uint8_t drop_max_p, uint16_t weight) +{ + //Weight must be between 1-256 + if (weight == 0 || weight > 256) { + return NULL; + } + + //Probability must be between 1-100 + if (drop_max_p == 0 || drop_max_p > 100) { + return NULL; + } + + //Max Threshold can't smaller or similar than min + if (threshold_max <= threshold_min) { + return NULL; + } + + red_info_t *red_info = ns_dyn_mem_alloc(sizeof(red_info_t)); + if (red_info) { + red_info->count = 0; + red_info->averageQ = 0; + red_info->parameters.drop_maX_P = drop_max_p; + red_info->parameters.threshold_max = threshold_max; + red_info->parameters.threshold_min = threshold_min; + red_info->parameters.weight = weight; + } + + return red_info; +} + + +void random_early_detection_free(struct red_info_s *red_info) +{ + ns_dyn_mem_free(red_info); +} + +//calculate average and return averaged value back +uint16_t random_early_detetction_aq_calc(red_info_t *red_info, uint16_t sampleLen) +{ + if (!red_info) { + return 0; + } + + if (red_info->parameters.weight == RED_AVERAGE_WEIGHT_DISABLED || red_info->averageQ == 0) { + red_info->averageQ = sampleLen * 256; + return sampleLen; + } + + // AQ = (1-weight) * average_queue + weight*sampleLen + // Now Sample is scaled by 256 which is not loosing so much tail at average + + //Weight Last Average part (1-weight) * average_queue with scaled 256 + uint32_t averageSum = ((256 - red_info->parameters.weight) * red_info->averageQ) / 256; + //Add new weighted sample lenght (weight*sampleLen) + averageSum += (red_info->parameters.weight * sampleLen); + + if (averageSum & 1) { + //If sum is ODD add 1 this will help to not stuck like 1,99 average to -> 2 + averageSum++; + } + //Store new average + red_info->averageQ = averageSum; + //Return always same format scaled than inn + return red_info->averageQ / 256; + +} + +uint16_t random_early_detetction_aq_read(red_info_t *red_info) +{ + if (!red_info) { + return 0; + } + return red_info->averageQ / 256; +} + + + +bool random_early_detection_congestion_check(red_info_t *red_info) +{ + if (!red_info) { + return false; + } + + //Calulate Average queue size + uint16_t sampleLen = red_info->averageQ / 256;; + + if (sampleLen <= red_info->parameters.threshold_min) { + //Can be added to queue without any RED operation + red_info->count = 0; + return false; + } + + if (sampleLen > red_info->parameters.threshold_max) { + //Always drop over threshold_max + red_info->count = 0; + return true; + } + + // Calculate probability for packet drop + // tempP = drop_maX_P *(AQ - threshold_min) / (threshold_max - threshold_min); + uint32_t tempP = (uint32_t) red_info->parameters.drop_maX_P * PROB_SCALE + * (sampleLen - red_info->parameters.threshold_min) + / (red_info->parameters.threshold_max - red_info->parameters.threshold_min); + + // Next Prob = tempP / (1 - count*tempP) + // This will increase probability and + + //Calculate first divider part + uint32_t Prob = red_info->count * tempP; + + //Check that divider it is not >= 0 + if (Prob >= PROB_SCALE_MAX) { + + red_info->count = 0; + return true; + } + + //Calculate only when count * tempP is smaller than scaler + Prob = (tempP * PROB_SCALE_MAX) / (PROB_SCALE_MAX - Prob); + if (Prob > randLIB_get_random_in_range(0, PROX_MAX_RANDOM)) { + //Drop packet + red_info->count = 0; + return true; + } + + //Increment count next round check + red_info->count++; + return false; + +} diff --git a/source/Service_Libs/random_early_detection/random_early_detection.h b/source/Service_Libs/random_early_detection/random_early_detection.h new file mode 100644 index 0000000000..9f81ed660c --- /dev/null +++ b/source/Service_Libs/random_early_detection/random_early_detection.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ +#define SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//This value cant be bigger than 655 +#define PROB_SCALE 512 +#define PROB_SCALE_MAX PROB_SCALE * 100 +#define PROX_MAX_RANDOM PROB_SCALE_MAX-1 + +typedef struct red_config_s { + uint16_t weight; /*< Weight for new sample len, 256 disabled average */ + uint16_t threshold_min; /*< Threshold Min value which start possibility start drop a packet */ + uint16_t threshold_max; /*< Threshold Max this value give max Probability for configured value over that every new packet will be dropped*/ + uint8_t drop_maX_P; /*< Max probability for drop packet between threshold_min and threshold_max threshold */ +} red_config_t; + +typedef struct red_info_s { + red_config_t parameters; /*< Random Early detetction parameters for queue avarge and packet drop */ + uint32_t averageQ; /*< Average queue size Scaled by 256 1.0 is 256 */ + uint16_t count; /*< Missed Packet drop's. This value is incremented when average queue is over min threshoild and packet is noot dropped */ +} red_info_t; + +#ifdef __cplusplus +} +#endif + +#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_H_ */ diff --git a/source/Service_Libs/random_early_detection/random_early_detection_api.h b/source/Service_Libs/random_early_detection/random_early_detection_api.h new file mode 100644 index 0000000000..dcefc35ec8 --- /dev/null +++ b/source/Service_Libs/random_early_detection/random_early_detection_api.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ +#define SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct red_info_s; + +#define RED_AVERAGE_WEIGHT_DISABLED 256 /*< Average is disabled */ +#define RED_AVERAGE_WEIGHT_HALF 128 /*< Average weight for new sample is 0.5*new + 0.5 to last one */ +#define RED_AVERAGE_WEIGHT_QUARTER 64 /*< Average weight for new sample is 1/4 + 3/4 to last one */ +#define RED_AVERAGE_WEIGHT_EIGHTH 32 /*< Average weight for new sample is 1/8 + 7/8 to last one */ + +/** + * \brief Create Random early detection data + * + * Function will config parameters how wide are Random Early detection drop will work. + * + * How to use parameters: + * + * Weight is definition how message queue Average (AQ) is calculated. Smaller weight will give smoother AQ update. + * + * AQ = (1-weight) * average_queue + weight*sampleLen; + * + * * RED_AVERAGE_WEIGHT_DISABLED disable Average by max weight to new sample length + * * RED_AVERAGE_WEIGHT_HALF last average*0.5 + 0.5*new sample: Smooth Average light packet filter + * * RED_AVERAGE_WEIGHT_QUARTER last average*0.75 + 0.25*new sample: Medium packet burst filtering + * * RED_AVERAGE_WEIGHT_EIGHTH last average*7/8 + 1/8*new sample: Good for filtering packet burst and big networks + * + * How to configure packet drop possibility: + * + * Define base Probability based current AQ, average length + * + * tempP = drop_maX_P *(AQ - threshold_min) / (threshold_max - threshold_min); + * + * Prob = tempP / (1 - count*tempP) + * + * threshold_min and threshold_max threshold define area for random early detection drop. When Average queue size go over Min threshold packet may drop by given maxProbability. + * System will work smoother if min -max threshold range is wide. Then random drop is may cover small data burst until Max threshold Avarage is reached. + * After Max every new packet will be dropped. + * + * Config Examples. + * + * Threshold values must be set how much device can buffer data. + * + * Small size data buffering: + * random_early_detection_create(32, 96, 10, RED_AVERAGE_WEIGHT_QUARTER) + * + * Medium size data buffering: + * random_early_detection_create(96, 256, 10, RED_AVERAGE_WEIGHT_EIGHTH) + * + * High size buffering: + * random_early_detection_create(256, 600, 10, RED_AVERAGE_WEIGHT_EIGHTH) + * + * \param threshold_min min average queue size which enable packet drop + * \param threshold_max average queue size when all new packets start drop + * \param drop_maX_P is percent probability to drop packet 100-1 are possible values + * \param weight accepted values 256-1, 256 is 1.0 weight which mean that new queue size overwrite old. 128 is 0.5 which gives 0.5 from old + 0.5 from new. + * \return Pointer for allocated structure, NULL if memory allocation fail + */ +struct red_info_s *random_early_detection_create(uint16_t threshold_min, uint16_t threshold_max, uint8_t drop_maX_P, uint16_t weight); + + +/** + * \brief Free Random early detection data + * + * + * \param red_info pointer to data + */ +void random_early_detection_free(struct red_info_s *red_info); + + +/** + * \brief Random early detection drop function + * + * \param red_info pointer, which is created user include all configurations + * \param sampleLen Current queue length + * \return true Drop packet + * \return false Packet can be added to queue + */ +bool random_early_detection_congestion_check(struct red_info_s *red_info); + +/** + * \brief Random early detection Average queue calculate + * + * Call this when add or remove from queue + * + * \param red_info pointer, which is created user include all configurations + * \param sampleLen Current queue length + * + * \return New average + */ +uint16_t random_early_detetction_aq_calc(struct red_info_s *red_info, uint16_t sampleLen); + +/** + * \brief Read Random early detection Average queue size + * + * Call this when add or remove from queue + * + * \param red_info pointer, which is created user include all configurations + * + * \return Current average + */ +uint16_t random_early_detetction_aq_read(struct red_info_s *red_info); + +#ifdef __cplusplus +} +#endif + +#endif /* SERVICE_LIBS_RANDOM_EARLY_DETECTION_RANDOM_EARLY_DETECTION_API_H_ */ diff --git a/source/Service_Libs/utils/ns_conf.c b/source/Service_Libs/utils/ns_conf.c index 93de03ce43..b2e0f26d15 100644 --- a/source/Service_Libs/utils/ns_conf.c +++ b/source/Service_Libs/utils/ns_conf.c @@ -17,7 +17,7 @@ #include "nsconfig.h" #include "ns_types.h" - +#include "eventOS_event.h" #include "Core/include/ns_monitor.h" #include "mac_api.h" // for mcps_packet_ingress_rate_limit_by_memory #include "MAC/IEEE802_15_4/mac_mcps_sap.h" // for mcps_packet_ingress_rate_limit_by_memory diff --git a/source/libDHCPv6/dhcp_service_api.c b/source/libDHCPv6/dhcp_service_api.c index c720a14c01..66cda2e6d4 100644 --- a/source/libDHCPv6/dhcp_service_api.c +++ b/source/libDHCPv6/dhcp_service_api.c @@ -29,9 +29,10 @@ #include "socket_api.h" #include "net_interface.h" #include "common_functions.h" + #include "libDHCPv6/libDHCPv6.h" #include "NWK_INTERFACE/Include/protocol.h" // just for protocol_core_monotonic_time - +#include "Common_Protocols/ip.h" #include "dhcp_service_api.h" #ifdef HAVE_DHCPV6 #define TRACE_GROUP "dhcp" @@ -437,7 +438,7 @@ void recv_dhcp_relay_msg(void *cb_res) uint8_t *ptr = msg_iov[1].iov_base; uint8_t msg_type = *ptr; - + int16_t tc = 0; if (msg_type == DHCPV6_RELAY_FORWARD) { tr_error("Drop not supported DHCPv6 forward at Agent"); goto cleanup; @@ -497,7 +498,10 @@ void recv_dhcp_relay_msg(void *cb_res) msg_iov[0].iov_len = 38; msg_iov[1].iov_len = msg_len; tr_debug("Forward Client msg to server"); + tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + } + socket_setsockopt(sckt_data->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0); cleanup: ns_dyn_mem_free(msg_iov[1].iov_base); @@ -845,6 +849,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) if (msg_tr_ptr->relay_start) { //Build Relay Reply only server do this + int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT; + socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); ns_iovec_t data_vector[2]; ns_msghdr_t msghdr; memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16); @@ -872,6 +878,8 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr) retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0); } else { + int16_t tc = 0; + socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc)); retval = socket_sendto(msg_tr_ptr->socket, &msg_tr_ptr->addr, msg_tr_ptr->msg_ptr, msg_tr_ptr->msg_len); } if (retval != 0) { diff --git a/sources.mk b/sources.mk index 2d895e803a..ef0ec51253 100644 --- a/sources.mk +++ b/sources.mk @@ -165,6 +165,7 @@ SRCS += \ source/Service_Libs/Trickle/trickle.c \ source/Service_Libs/whiteboard/whiteboard.c \ source/Service_Libs/pan_blacklist/pan_blacklist.c \ + source/Service_Libs/random_early_detection/random_early_detection.c \ source/6LoWPAN/Thread/thread_management_if.c \ source/6LoWPAN/Thread/thread_management_api.c \ source/6LoWPAN/Thread/thread_commissioning_api.c \ From 0810306ca403f9fda779e2c32d7945a79f945b2f Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 20 Jan 2021 11:43:43 +0200 Subject: [PATCH 6/7] Add random_early_detection to CMakeLists.txt --- .../sal-stack-nanostack/source/Service_Libs/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/CMakeLists.txt b/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/CMakeLists.txt index 89efeaccda..fbaac0925c 100644 --- a/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/CMakeLists.txt +++ b/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/CMakeLists.txt @@ -30,6 +30,7 @@ target_include_directories(mbed-nanostack-sal_stack ./nd_proxy ./nist_aes_kw ./pan_blacklist + ./random_early_detection ./utils ./whiteboard ) @@ -93,6 +94,8 @@ target_sources(mbed-nanostack-sal_stack nist_aes_kw/nist_aes_kw.c pan_blacklist/pan_blacklist.c + + random_early_detection/random_early_detection.c utils/isqrt.c utils/ns_conf.c From 4d13419f38f12e1a1c2b8e9ddd5c0c1779642eeb Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 20 Jan 2021 13:09:06 +0200 Subject: [PATCH 7/7] Add nsdynmem_tracker_lib.c to CMakeLists.txt --- connectivity/libraries/nanostack-libservice/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/connectivity/libraries/nanostack-libservice/CMakeLists.txt b/connectivity/libraries/nanostack-libservice/CMakeLists.txt index def9685498..9af5a22b1f 100644 --- a/connectivity/libraries/nanostack-libservice/CMakeLists.txt +++ b/connectivity/libraries/nanostack-libservice/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(mbed-nanostack-libservice source/libip4string/stoip4.c source/libip6string/stoip6.c source/nsdynmemLIB/nsdynmemLIB.c + source/nsdynmemtracker/nsdynmem_tracker_lib.c source/nvmHelper/ns_nvm_helper.c )