From e49ba1660cd2fae3bce2fbeba4f48a5b6adc36df Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 10 Nov 2020 13:57:11 +0200 Subject: [PATCH] Squashed 'features/nanostack/sal-stack-nanostack/' changes from 09d9e24f2d..715ae9a693 715ae9a693 Merge remote-tracking branch 'origin/release_internal' into release_external 42c9807207 Nanostak trace level configuration (#2489) 6f5217119a Bug fix: socket reference count made 16-bit (#2490) f51669adc7 Bug fix: Do not print UFSI drift when fixed channel is used (#2488) 18fa0486e3 RPL DAO timeout update: 660e178506 Clear debug traces. cbac0bbca4 DIO init send block for node fed5d1c819 Created different MPL configuration based on network size 7ad7e81209 Wi-SUN recovery and BR BSI update: d207f4d9f9 Merge branch 'release_internal' into release_external d166c89427 MPL: buffered max limit increased to 8k (#2482) 0f6666a97e Fixed Unit test's 1ff9b1d6c6 LLC drop a packet if FHSS shedule is not configured. 7cecc28c98 Fixed missing asynch trigle setup stop at if down process 7a8b2bfd98 Wi-SUN fhss API default value setting fixes 164a3706c6 Fixed coverity issues from management API 8b5b433284 Corrected out of bounds access coverity warning (#2475) 4ffe6a12cc Multicast forwarding is separated from the routing flag 30f431581d Wi-SUN discovery staten enter upxdate 083b84e9c5 Iotthd 4308 (#2473) fcc33d559c Removed time increment from NVM time read function on interface up 9c8e3afc9f fhss_tx_handle update 5491a6b052 Fixed UFSI update print function (#2470) 86f64c58b6 FHSS WS: Check if BC schedule is stopped before computing timeout delay (#2469) a0b112a97b Corrected defects and coding style 2f4678a2f2 Corrected trace macro 5e967515ee Distributed key storage NVM writes to longer time period 9b3891fffb FHSS WS: handle blocked interrupts (#2466) a792e832de Added validation at MAC ack buffer handler 2a465b2e49 DNS configuration lifetime validation git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: 715ae9a69376af5c96d53e5445b0d280ee1edf28 --- .../sal-stack-nanostack/mbed_lib.json | 4 + .../nanostack/ws_bbr_api.h | 13 ++ .../nanostack/ws_management_api.h | 5 + .../source/6LoWPAN/Thread/thread_bbr_api.c | 7 +- .../source/6LoWPAN/ws/ws_bbr_api.c | 120 +++++++++++++++++- .../source/6LoWPAN/ws/ws_bbr_api_internal.h | 5 + .../source/6LoWPAN/ws/ws_bootstrap.c | 103 +++++++++------ .../source/6LoWPAN/ws/ws_cfg_settings.c | 77 ++++++++++- .../source/6LoWPAN/ws/ws_cfg_settings.h | 8 +- .../source/6LoWPAN/ws/ws_common.h | 6 + .../source/6LoWPAN/ws/ws_config.h | 37 +++++- .../source/6LoWPAN/ws/ws_llc_data_service.c | 13 +- .../source/6LoWPAN/ws/ws_management_api.c | 36 +++--- .../source/6LoWPAN/ws/ws_neighbor_class.c | 27 +++- .../source/6LoWPAN/ws/ws_pae_auth.c | 3 + .../source/6LoWPAN/ws/ws_pae_controller.c | 38 +++--- .../source/6LoWPAN/ws/ws_pae_key_storage.c | 86 ++++++++++++- .../source/6LoWPAN/ws/ws_pae_key_storage.h | 8 ++ .../source/6LoWPAN/ws/ws_pae_nvm_data.c | 24 ++-- .../source/6LoWPAN/ws/ws_pae_nvm_data.h | 30 ++++- .../source/6LoWPAN/ws/ws_pae_nvm_store.h | 2 +- .../source/6LoWPAN/ws/ws_pae_supp.c | 10 +- .../source/6LoWPAN/ws/ws_pae_time.c | 7 +- .../source/Common_Protocols/icmpv6.c | 11 ++ .../source/Core/include/ns_socket.h | 2 +- .../source/MAC/IEEE802_15_4/mac_mcps_sap.c | 9 ++ .../source/MAC/IEEE802_15_4/mac_pd_sap.c | 8 +- .../source/MAC/IEEE802_15_4/mac_pd_sap.h | 3 + .../sal-stack-nanostack/source/MPL/mpl.c | 2 +- .../source/RPL/rpl_downward.c | 49 ++++++- .../source/RPL/rpl_downward.h | 1 + .../source/RPL/rpl_upward.c | 8 +- .../source/Service_Libs/fhss/fhss_ws.c | 79 ++++++++++-- .../source/Service_Libs/fhss/fhss_ws.h | 2 + .../sal-stack-nanostack/source/nsconfig.h | 7 + 35 files changed, 690 insertions(+), 160 deletions(-) diff --git a/features/nanostack/sal-stack-nanostack/mbed_lib.json b/features/nanostack/sal-stack-nanostack/mbed_lib.json index 1fddbd2cbac6..ce65c8a038a9 100644 --- a/features/nanostack/sal-stack-nanostack/mbed_lib.json +++ b/features/nanostack/sal-stack-nanostack/mbed_lib.json @@ -5,6 +5,10 @@ "configuration": { "help": "Build time configuration. Refer to Handbook for valid values. Default: full stack", "value": "nanostack_full" + }, + "trace_max_level": { + "help": "One of mbed-trace level defines: TRACE_LEVEL_DEBUG, TRACE_LEVEL_INFO, TRACE_LEVEL_WARN or TRACE_LEVEL_ERROR", + "value": null } }, "macros": ["NS_USE_EXTERNAL_MBED_TLS"], diff --git a/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h b/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h index 9c1e4a03cb20..741953b2dec2 100644 --- a/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h +++ b/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h @@ -334,6 +334,19 @@ int ws_bbr_pan_configuration_get(int8_t interface_id, uint16_t *pan_id); */ int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id); +/** + * Sets Wi-SUN BSI + * + * Sets Wi-SUN PAN BSI. + * + * \param interface_id Network interface ID. + * \param new_bsi Identifier. + * + * \return 0, PAN BSI set. + * \return <0 PAN BSI set failed. + */ +int ws_bbr_bsi_set(int8_t interface_id, uint16_t new_bsi); + /** * Sets memory used for key storages * diff --git a/features/nanostack/sal-stack-nanostack/nanostack/ws_management_api.h b/features/nanostack/sal-stack-nanostack/nanostack/ws_management_api.h index a5feb7628743..300f2cab2c7b 100644 --- a/features/nanostack/sal-stack-nanostack/nanostack/ws_management_api.h +++ b/features/nanostack/sal-stack-nanostack/nanostack/ws_management_api.h @@ -382,6 +382,8 @@ int ws_management_channel_plan_set( * * Change the default configuration for Wi-SUN FHSS operation. * + * Calling with fhss_uc_dwell_interval = 0, fhss_broadcast_interval = 0xffffffff, + * fhss_bc_dwell_interval = 0 restores stack defaults * * \param interface_id Network interface ID. * \param fhss_uc_dwell_interval default to 250 ms. @@ -403,6 +405,7 @@ int ws_management_fhss_timing_configure( * Change the default configuration for Wi-SUN FHSS operation. * if application defined is used the behaviour is undefined * + * Calling with dwell_interval = 0, channel_function = 0xff, fixed_channel = 0xffff restores stack defaults * * \param interface_id Network interface ID. * \param channel_function Unicast channel function. @@ -458,6 +461,8 @@ int ws_management_fhss_unicast_channel_function_validate( * Change the default configuration for Wi-SUN FHSS operation. * if application defined is used the behaviour is undefined * + * Calling with dwell_interval = 0, channel_function = 0xff, + * broadcast_interval = 0xffffffff, fixed_channel = 0xffff restores stack defaults * * \param interface_id Network interface ID. * \param channel_function Broadcast channel function. diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/Thread/thread_bbr_api.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/Thread/thread_bbr_api.c index 812843edd9d5..bab9f73d6f9a 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/Thread/thread_bbr_api.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/Thread/thread_bbr_api.c @@ -629,13 +629,14 @@ static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8], static void thread_bbr_routing_enable(thread_bbr_t *this, bool multicast_routing_enabled) { + // Start multicast proxying + // We do not enable multicast forwarding as there is other default router present in network + multicast_fwd_set_forwarding(this->interface_id, multicast_routing_enabled); + if (this->routing_enabled) { return; } tr_info("br: enable routing"); - // Start multicast proxying - // We do not enable multicast forwarding as there is other default router present in network - multicast_fwd_set_forwarding(this->interface_id, multicast_routing_enabled); this->routing_enabled = true; } diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c index 83560e9298fc..d2b306d465f3 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c @@ -20,6 +20,8 @@ #include "ns_types.h" #include "ns_trace.h" #include "nsdynmemLIB.h" +#include "randLIB.h" +#include "common_functions.h" #include "net_interface.h" #include "socket_api.h" #include "eventOS_event.h" @@ -31,6 +33,7 @@ #include "6LoWPAN/ws/ws_bootstrap.h" #include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_pae_key_storage.h" +#include "6LoWPAN/ws/ws_pae_nvm_store.h" #include "RPL/rpl_control.h" #include "RPL/rpl_data.h" #include "Common_Protocols/icmpv6.h" @@ -61,6 +64,20 @@ static uint8_t current_instance_id = RPL_INSTANCE_ID; #define BBR_CHECK_INTERVAL 60 #define BBR_BACKUP_ULA_DELAY 300 +//TAG ID This must be update if NVM_BBR_INFO_LEN or data structure +#define NVM_BBR_INFO_TAG 1 +// BSI 2 bytes +#define NVM_BBR_INFO_LEN 2 + +typedef struct bbr_info_nvm_tlv { + uint16_t tag; /**< Unique tag */ + uint16_t len; /**< Number of the bytes after the length field */ + uint8_t data[NVM_BBR_INFO_LEN]; /**< Data */ +} bbr_info_nvm_tlv_t; + +//NVM file name +static const char *BBR_INFO_FILE = "pae_bbr_info"; + /* when creating BBR make ULA dodag ID always and when network becomes available add prefix to DHCP * * @@ -105,6 +122,52 @@ typedef struct dns_resolution { #define MAX_DNS_RESOLUTIONS 4 static dns_resolution_t pre_resolved_dns_queries[MAX_DNS_RESOLUTIONS] = {0}; +//BBR NVM info buffer + +#define BBR_NVM_BSI_OFFSET 0 +static bbr_info_nvm_tlv_t bbr_info_nvm_tlv = { + .tag = NVM_BBR_INFO_TAG, + .len = 0, + .data = {0} +}; + +static uint16_t ws_bbr_fhss_bsi = 0; + +static int8_t ws_bbr_nvm_info_read(bbr_info_nvm_tlv_t *tlv_entry) +{ + tlv_entry->tag = NVM_BBR_INFO_TAG; + tlv_entry->len = NVM_BBR_INFO_LEN; + + int8_t ret_val = ws_pae_nvm_store_tlv_file_read(BBR_INFO_FILE, (nvm_tlv_t *) &bbr_info_nvm_tlv); + + if (ret_val < 0 || tlv_entry->tag != NVM_BBR_INFO_TAG || tlv_entry->len != NVM_BBR_INFO_LEN) { + ws_pae_nvm_store_tlv_file_remove(BBR_INFO_FILE); + tlv_entry->len = 0; + return -1; + } + return 0; +} + +static void ws_bbr_nvm_info_write(bbr_info_nvm_tlv_t *tlv_entry) +{ + tlv_entry->tag = NVM_BBR_INFO_TAG; + tlv_entry->len = NVM_BBR_INFO_LEN; + ws_pae_nvm_store_tlv_file_write(BBR_INFO_FILE, (nvm_tlv_t *) tlv_entry); + tr_debug("BBR info NVM update"); +} + +static uint16_t ws_bbr_bsi_read(bbr_info_nvm_tlv_t *tlv_entry) +{ + if (tlv_entry->tag != NVM_BBR_INFO_TAG || tlv_entry->len != NVM_BBR_INFO_LEN) { + return 0; + } + return common_read_16_bit(tlv_entry->data + BBR_NVM_BSI_OFFSET); +} + +static void ws_bbr_bsi_write(bbr_info_nvm_tlv_t *tlv_entry, uint16_t bsi) +{ + common_write_16_bit(bsi, tlv_entry->data + BBR_NVM_BSI_OFFSET); +} static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version) { @@ -134,7 +197,6 @@ static void ws_bbr_rpl_version_increase(protocol_interface_info_entry_t *cur) ws_bbr_rpl_version_timer_start(cur, rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag)); } - void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase) { if (imin == 0 || doubling == 0) { @@ -785,6 +847,35 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur) return true; } + +void ws_bbr_init(protocol_interface_info_entry_t *interface) +{ + (void) interface; + //Read From NVM + if (ws_bbr_nvm_info_read(&bbr_info_nvm_tlv) < 0) { + //NVM value not available Randomize Value Here by first time + ws_bbr_fhss_bsi = randLIB_get_16bit(); + tr_debug("Randomized init value BSI %u", ws_bbr_fhss_bsi); + } else { + ws_bbr_fhss_bsi = ws_bbr_bsi_read(&bbr_info_nvm_tlv); + tr_debug("Read BSI %u from NVM", ws_bbr_fhss_bsi); + } +} + + +uint16_t ws_bbr_bsi_generate(protocol_interface_info_entry_t *interface) +{ + (void) interface; + //Give current one + uint16_t bsi = ws_bbr_fhss_bsi; + //Update value for next round + ws_bbr_fhss_bsi++; + //Store To NVN + ws_bbr_bsi_write(&bbr_info_nvm_tlv, ws_bbr_fhss_bsi); + ws_bbr_nvm_info_write(&bbr_info_nvm_tlv); + return bsi; +} + #endif //HAVE_WS_BORDER_ROUTER /* Public APIs @@ -1070,6 +1161,33 @@ int ws_bbr_rpl_parameters_validate(int8_t interface_id, uint8_t dio_interval_min #endif } +int ws_bbr_bsi_set(int8_t interface_id, uint16_t new_bsi) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + + //Check if new value is different than current active + if (cur && cur->ws_info && cur->lowpan_info & INTERFACE_NWK_ACTIVE) { + if (cur->ws_info->hopping_schdule.fhss_bsi == new_bsi) { + return 0; + } + tr_debug("New BSI %u to delayed activate", new_bsi); + ws_bootstrap_restart_delayed(cur->id); + } + + ws_bbr_bsi_write(&bbr_info_nvm_tlv, new_bsi); + ws_bbr_nvm_info_write(&bbr_info_nvm_tlv); + ws_bbr_fhss_bsi = new_bsi; + return 0; +#else + (void) new_bsi; + return -1; +#endif +} + + int ws_bbr_pan_configuration_set(int8_t interface_id, uint16_t pan_id) { (void) interface_id; diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api_internal.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api_internal.h index 4c24191cb895..78892b9f1da3 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api_internal.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api_internal.h @@ -37,6 +37,9 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur); bool ws_bbr_backbone_address_get(uint8_t *address); +uint16_t ws_bbr_bsi_generate(protocol_interface_info_entry_t *interface); +void ws_bbr_init(protocol_interface_info_entry_t *interface); + #else #define ws_bbr_seconds_timer( cur, seconds) @@ -46,6 +49,8 @@ bool ws_bbr_backbone_address_get(uint8_t *address); #define ws_bbr_dhcp_address_lifetime_set(cur, dhcp_address_lifetime) #define ws_bbr_ready_to_start(cur) true #define ws_bbr_backbone_address_get(address) 0 +#define ws_bbr_bsi_generate(interface) 0 +#define ws_bbr_init(interface) (void) 0 #endif //HAVE_WS_BORDER_ROUTER diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c index a2f8a0615817..825c924b1fef 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c @@ -670,6 +670,9 @@ static int8_t ws_fhss_border_router_configure(protocol_interface_info_entry_t *c if (ns_fhss_ws_configuration_get(cur->ws_info->fhss_api)) { memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); } + + //GET BSI from BBR module + fhss_configuration.bsi = ws_bbr_bsi_generate(cur); ws_fhss_set_defaults(cur, &fhss_configuration); ws_fhss_configure_channel_masks(cur, &fhss_configuration); ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); @@ -988,7 +991,10 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) tr_error("fhss initialization failed"); return -3; } - + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //BBR init like NVM read + ws_bbr_init(cur); + } // Save FHSS api cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); @@ -996,7 +1002,6 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) addr_interface_set_ll64(cur, NULL); cur->nwk_nd_re_scan_count = 0; - //WS_interface_up(cur); // Trigger discovery for bootstrap ret_val = nwk_6lowpan_up(cur); if (ret_val) { @@ -1045,6 +1050,15 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) return ret_val; } +static void ws_bootstrap_asynch_trickle_stop(protocol_interface_info_entry_t *cur) +{ + cur->ws_info->trickle_pas_running = false; + cur->ws_info->trickle_pa_running = false; + cur->ws_info->trickle_pcs_running = false; + cur->ws_info->trickle_pc_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; +} + static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) { if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { @@ -1058,7 +1072,7 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) ns_fhss_delete(cur->ws_info->fhss_api); cur->ws_info->fhss_api = NULL; // Reset WS information - // ws_common_reset(cur) + ws_bootstrap_asynch_trickle_stop(cur); ws_llc_reset(cur); if (nd_proxy_downstream_interface_unregister(cur->id) != 0) { tr_warn("nd proxy unregister failed"); @@ -1103,11 +1117,7 @@ void ws_bootstrap_configuration_reset(protocol_interface_info_entry_t *cur) cur->nwk_bootstrap_state = ER_ACTIVE_SCAN; cur->ws_info->network_pan_id = 0xffff; - cur->ws_info->trickle_pas_running = false; - cur->ws_info->trickle_pa_running = false; - cur->ws_info->trickle_pcs_running = false; - cur->ws_info->trickle_pc_running = false; - cur->ws_info->trickle_pc_consistency_block_period = 0; + ws_bootstrap_asynch_trickle_stop(cur); //cur->mac_security_key_usage_update_cb = ws_management_mac_security_key_update_cb; return; @@ -1482,12 +1492,6 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf ws_bootsrap_create_ll_address(ll_address, neighbor_info.neighbor->mac64); if (rpl_control_is_dodag_parent(cur, ll_address)) { - // automatic network size adjustment learned - if (cur->ws_info->cfg->gen.network_size == NETWORK_SIZE_AUTOMATIC && - cur->ws_info->pan_information.pan_size != pan_information.pan_size) { - ws_cfg_network_size_configure(cur, pan_information.pan_size); - } - cur->ws_info->pan_information.pan_size = pan_information.pan_size; cur->ws_info->pan_information.routing_cost = pan_information.routing_cost; cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method; @@ -1579,6 +1583,27 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry llc_neighbour_req_t neighbor_info; bool neighbour_pointer_valid; + //Validate BSI + if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + + if (cur->ws_info->ws_bsi_block.block_time && cur->ws_info->ws_bsi_block.old_bsi == ws_bs_ie.broadcast_schedule_identifier) { + tr_debug("Do not accept a old BSI: %u in time %"PRIu32, cur->ws_info->ws_bsi_block.old_bsi, cur->ws_info->ws_bsi_block.block_time); + //Refresh Block time when hear a old BSI + cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; + return; + } + + //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); + return; + } + } + + if (cur->ws_info->configuration_learned || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { //If we are border router or learned configuration we only update already learned neighbours. neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false); @@ -2486,6 +2511,13 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name); // Network key is valid, indicate border router IID to controller ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]); + //Update here Suplikant target by validated Primary Parent + if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_priority(mac_neighbor_info(cur)); + if (mac_neighbor) { + ws_pae_controller_set_target(cur, cur->ws_info->network_pan_id, mac_neighbor->mac64); + } + } // After successful DAO ACK connection to border router is verified cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; @@ -3228,6 +3260,9 @@ static void ws_bootstrap_event_handler(arm_event_s *event) case WS_DISCOVERY_START: tr_info("Discovery start"); + protocol_mac_reset(cur); + ws_llc_reset(cur); + lowpan_adaptation_interface_reset(cur->id); //Clear Pending Key Index State cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; cur->mac_parameters->mac_default_key_index = 0; @@ -3236,11 +3271,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) blacklist_clear(); // All trickle timers stopped to allow entry from any state - cur->ws_info->trickle_pa_running = false; - cur->ws_info->trickle_pc_running = false; - cur->ws_info->trickle_pas_running = false; - cur->ws_info->trickle_pcs_running = false; - cur->ws_info->trickle_pc_consistency_block_period = 0; + ws_bootstrap_asynch_trickle_stop(cur); if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { tr_info("Border router start network"); @@ -3329,11 +3360,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) case WS_CONFIGURATION_START: tr_info("Configuration start"); // Old configuration is considered invalid stopping all - cur->ws_info->trickle_pa_running = false; - cur->ws_info->trickle_pc_running = false; - cur->ws_info->trickle_pas_running = false; - cur->ws_info->trickle_pcs_running = false; - cur->ws_info->trickle_pc_consistency_block_period = 0; + ws_bootstrap_asynch_trickle_stop(cur); // Build list of possible neighbours and learn first broadcast schedule @@ -3342,11 +3369,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) case WS_OPERATION_START: tr_info("operation start"); // Advertisements stopped during the RPL scan - cur->ws_info->trickle_pa_running = false; - cur->ws_info->trickle_pc_running = false; - cur->ws_info->trickle_pas_running = false; - cur->ws_info->trickle_pcs_running = false; - cur->ws_info->trickle_pc_consistency_block_period = 0; + ws_bootstrap_asynch_trickle_stop(cur); // Activate RPL // Activate IPv6 stack ws_bootstrap_ip_stack_activate(cur); @@ -3362,11 +3385,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) case WS_ROUTING_READY: tr_info("Routing ready"); // stopped all to make sure we can enter here from any state - cur->ws_info->trickle_pa_running = false; - cur->ws_info->trickle_pc_running = false; - cur->ws_info->trickle_pas_running = false; - cur->ws_info->trickle_pcs_running = false; - cur->ws_info->trickle_pc_consistency_block_period = 0; + ws_bootstrap_asynch_trickle_stop(cur); // Indicate PAE controller that bootstrap is ready ws_pae_controller_bootstrap_done(cur); @@ -3547,11 +3566,7 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur) case ER_PANA_AUTH: tr_info("authentication start"); // Advertisements stopped during the EAPOL - cur->ws_info->trickle_pa_running = false; - cur->ws_info->trickle_pc_running = false; - cur->ws_info->trickle_pas_running = false; - cur->ws_info->trickle_pcs_running = false; - cur->ws_info->trickle_pc_consistency_block_period = 0; + ws_bootstrap_asynch_trickle_stop(cur); ws_fhss_configure(cur, false); int8_t new_default = cur->ws_info->weakest_received_rssi - 1; if ((new_default < CCA_DEFAULT_DBM) && (new_default >= CCA_LOW_LIMIT) && (new_default <= CCA_HIGH_LIMIT)) { @@ -3669,6 +3684,16 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s } } + if (cur->ws_info->ws_bsi_block.block_time) { + if (cur->ws_info->ws_bsi_block.block_time > seconds) { + cur->ws_info->ws_bsi_block.block_time -= seconds; + } else { + //Clear A BSI blokker + cur->ws_info->ws_bsi_block.block_time = 0; + cur->ws_info->ws_bsi_block.old_bsi = 0; + } + } + ws_llc_timer_seconds(cur, seconds); } diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c index 1898b426d88f..8366204e52a9 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c @@ -53,6 +53,7 @@ typedef struct ws_cfg_nw_size_s { ws_timing_cfg_t timing; /**< Timing configuration */ ws_bbr_cfg_t bbr; /**< RPL configuration */ ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */ + ws_mpl_cfg_t mpl; /**< Multicast timing configuration*/ } ws_cfg_nw_size_t; static uint32_t ws_test_temporary_entry_lifetime = 0; @@ -136,6 +137,8 @@ static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate *cfg = (ws_cfgs_t *) &nw_size_external_cfg->bbr; } else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.sec_prot) { *cfg = (ws_cfgs_t *) &nw_size_external_cfg->sec_prot; + } else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.mpl) { + *cfg = (ws_cfgs_t *) &nw_size_external_cfg->mpl; } else { *cfg = ws_cfg_ptr; } @@ -251,6 +254,7 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_ ws_cfg_timing_get(&nw_size_cfg.timing, NULL); ws_cfg_bbr_get(&nw_size_cfg.bbr, NULL); ws_cfg_sec_prot_get(&nw_size_cfg.sec_prot, NULL); + ws_cfg_mpl_get(&nw_size_cfg.mpl, NULL); ws_cfg_network_size_config_set_size set_function = NULL; @@ -300,12 +304,15 @@ int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_ old_network_size == NETWORK_SIZE_AUTOMATIC) { ws_cfg_sec_prot_set(cur, &ws_cfg.sec_prot, &nw_size_cfg.sec_prot, &set_flags); } + if (ws_cfg_mpl_validate(&ws_cfg.mpl, &nw_size_cfg.mpl) == CFG_SETTINGS_CHANGED || + old_network_size == NETWORK_SIZE_AUTOMATIC) { + ws_cfg_mpl_set(cur, &ws_cfg.mpl, &nw_size_cfg.mpl, &set_flags); + } // If is in an automatic network size mode, updates automatic configuration if (cfg->network_size == NETWORK_SIZE_AUTOMATIC && cur) { ws_cfg_network_size_configure(cur, cur->ws_info->pan_information.pan_size); } - return CFG_SETTINGS_OK; } @@ -319,6 +326,7 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1 ws_cfg_timing_get(&new_nw_size_cfg.timing, &flags); ws_cfg_bbr_get(&new_nw_size_cfg.bbr, &flags); ws_cfg_sec_prot_get(&new_nw_size_cfg.sec_prot, &flags); + ws_cfg_mpl_get(&new_nw_size_cfg.mpl, &flags); if (!nw_size_external_cfg) { nw_size_external_cfg = ns_dyn_mem_alloc(sizeof(ws_cfg_nw_size_t)); @@ -347,10 +355,12 @@ int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint1 ws_cfg_timing_set(cur, NULL, &new_nw_size_cfg.timing, &flags); ws_cfg_bbr_set(cur, NULL, &new_nw_size_cfg.bbr, &flags); ws_cfg_sec_prot_set(cur, NULL, &new_nw_size_cfg.sec_prot, &flags); + ws_cfg_mpl_set(cur, &ws_cfg.mpl, &new_nw_size_cfg.mpl, &flags); return CFG_SETTINGS_OK; } + static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) { // Configure the Wi-SUN parent configuration @@ -385,6 +395,14 @@ static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT; + + // Multicast timing configuration + cfg->mpl.mpl_trickle_imin = MPL_SMALL_IMIN; + cfg->mpl.mpl_trickle_imax = MPL_SMALL_IMAX; + cfg->mpl.mpl_trickle_k = MPL_SMALL_K; + cfg->mpl.mpl_trickle_timer_exp = MPL_SMALL_EXPIRATIONS; + cfg->mpl.seed_set_entry_lifetime = MPL_SMALL_SEED_LIFETIME; + } static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg) @@ -421,6 +439,13 @@ static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg) cfg->sec_prot.initial_key_imin = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = MEDIUM_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT; + + // Multicast timing configuration + cfg->mpl.mpl_trickle_imin = MPL_MEDIUM_IMIN; + cfg->mpl.mpl_trickle_imax = MPL_MEDIUM_IMAX; + cfg->mpl.mpl_trickle_k = MPL_MEDIUM_K; + cfg->mpl.mpl_trickle_timer_exp = MPL_MEDIUM_EXPIRATIONS; + cfg->mpl.seed_set_entry_lifetime = MPL_MEDIUM_SEED_LIFETIME; } static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg) @@ -457,6 +482,14 @@ static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg) cfg->sec_prot.initial_key_imin = LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; cfg->sec_prot.initial_key_retry_cnt = LARGE_NW_INITIAL_KEY_RETRY_COUNT; + + // Multicast timing configuration + cfg->mpl.mpl_trickle_imin = MPL_LARGE_IMIN; + cfg->mpl.mpl_trickle_imax = MPL_LARGE_IMAX; + cfg->mpl.mpl_trickle_k = MPL_LARGE_K; + cfg->mpl.mpl_trickle_timer_exp = MPL_LARGE_EXPIRATIONS; + cfg->mpl.seed_set_entry_lifetime = MPL_LARGE_SEED_LIFETIME; + } static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg) @@ -493,6 +526,13 @@ static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg) cfg->sec_prot.initial_key_imin = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = EXTRA_LARGE_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; cfg->sec_prot.initial_key_retry_cnt = EXTRA_LARGE_NW_INITIAL_KEY_RETRY_COUNT; + + // Multicast timing configuration + cfg->mpl.mpl_trickle_imin = MPL_XLARGE_IMIN; + cfg->mpl.mpl_trickle_imax = MPL_XLARGE_IMAX; + cfg->mpl.mpl_trickle_k = MPL_XLARGE_K; + cfg->mpl.mpl_trickle_timer_exp = MPL_XLARGE_EXPIRATIONS; + cfg->mpl.seed_set_entry_lifetime = MPL_XLARGE_SEED_LIFETIME; } static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg) @@ -529,6 +569,13 @@ static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg) cfg->sec_prot.initial_key_imin = SMALL_NW_INITIAL_KEY_TRICKLE_IMIN_SECS; cfg->sec_prot.initial_key_imax = SMALL_NW_INITIAL_KEY_TRICKLE_IMAX_SECS; cfg->sec_prot.initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT; + + // Multicast timing configuration for certification uses the LARGE values as it is the one mentioned ins specification + cfg->mpl.mpl_trickle_imin = MPL_XLARGE_IMIN; + cfg->mpl.mpl_trickle_imax = MPL_XLARGE_IMAX; + cfg->mpl.mpl_trickle_k = MPL_XLARGE_K; + cfg->mpl.mpl_trickle_timer_exp = MPL_XLARGE_EXPIRATIONS; + cfg->mpl.seed_set_entry_lifetime = MPL_XLARGE_SEED_LIFETIME; } static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg) @@ -832,11 +879,11 @@ int8_t ws_cfg_bbr_set(protocol_interface_info_entry_t *cur, ws_bbr_cfg_t *cfg, w static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg) { // MPL configuration - cfg->mpl_trickle_imin = DATA_MESSAGE_IMIN; - cfg->mpl_trickle_imax = DATA_MESSAGE_IMAX; - cfg->mpl_trickle_k = DATA_MESSAGE_K; - cfg->mpl_trickle_timer_exp = DATA_MESSAGE_TIMER_EXPIRATIONS; - cfg->seed_set_entry_lifetime = MPL_SEED_SET_ENTRY_TIMEOUT; + cfg->mpl_trickle_imin = MPL_MEDIUM_IMIN; + cfg->mpl_trickle_imax = MPL_MEDIUM_IMAX; + cfg->mpl_trickle_k = MPL_MEDIUM_K; + cfg->mpl_trickle_timer_exp = MPL_MEDIUM_EXPIRATIONS; + cfg->seed_set_entry_lifetime = MPL_MEDIUM_SEED_LIFETIME; return CFG_SETTINGS_OK; } @@ -869,6 +916,21 @@ int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg) int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg, uint8_t *flags) { uint8_t cfg_flags; + + // In Wi-SUN Border router will have modified settings to improve reliability + if (cur && cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + // Border router sends multiple packets to ensure start of sequence + if (new_cfg->mpl_trickle_timer_exp < MPL_BORDER_ROUTER_MIN_EXPIRATIONS) { + new_cfg->mpl_trickle_timer_exp = MPL_BORDER_ROUTER_MIN_EXPIRATIONS; + // Lifetime is calculated using the original IMAX + new_cfg->seed_set_entry_lifetime = new_cfg->mpl_trickle_imax * new_cfg->mpl_trickle_timer_exp * MPL_SAFE_HOP_COUNT; + } + // Border router should have shorter IMAX to speed startup + if (new_cfg->mpl_trickle_imax > MPL_BORDER_ROUTER_MAXIMUM_IMAX) { + new_cfg->mpl_trickle_imax = MPL_BORDER_ROUTER_MAXIMUM_IMAX; + } + } + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_mpl_validate, (ws_cfgs_t *) &ws_cfg.mpl, &cfg_flags, flags); if (ret != CFG_SETTINGS_CHANGED) { return ret; @@ -942,7 +1004,7 @@ int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg) return CFG_SETTINGS_ERROR_FHSS_CONF; } - if (new_cfg->fhss_bc_dwell_interval < 15) { + if (new_cfg->fhss_bc_dwell_interval < 100) { return CFG_SETTINGS_ERROR_FHSS_CONF; } @@ -1205,6 +1267,7 @@ int8_t ws_cfg_settings_get(protocol_interface_info_entry_t *cur, ws_cfg_t *cfg) ws_cfg_timing_get(&cfg->timing, NULL); ws_cfg_bbr_get(&cfg->bbr, NULL); ws_cfg_sec_prot_get(&cfg->sec_prot, NULL); + ws_cfg_mpl_get(&cfg->mpl, NULL); return CFG_SETTINGS_OK; } diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h index 48592b899a51..35490e332696 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h @@ -56,12 +56,12 @@ typedef struct ws_timing_cfg_s { * \brief Struct ws_rpl_cfg_t RPL configuration */ typedef struct ws_bbr_cfg_s { - uint8_t dio_interval_min; /**> DIO interval min; DEFAULT_DIO_INTERVAL_MIN; 2^value in milliseconds; range 1-255; default */ - uint8_t dio_interval_doublings; /**> DIO interval doublings; DEFAULT_DIO_INTERVAL_DOUBLINGS; range 1-8; default */ - uint8_t dio_redundancy_constant; /**> DIO redundancy constant; DEFAULT_DIO_REDUNDANCY_CONSTANT; range 0-10; default */ + uint8_t dio_interval_min; /**< DIO interval min; DEFAULT_DIO_INTERVAL_MIN; 2^value in milliseconds; range 1-255; default */ + uint8_t dio_interval_doublings; /**< DIO interval doublings; DEFAULT_DIO_INTERVAL_DOUBLINGS; range 1-8; default */ + uint8_t dio_redundancy_constant; /**< DIO redundancy constant; DEFAULT_DIO_REDUNDANCY_CONSTANT; range 0-10; default */ uint16_t dag_max_rank_increase; uint16_t min_hop_rank_increase; - uint32_t dhcp_address_lifetime; /**> DHCP address lifetime in seconds minimum 2 hours and maximum as days hours*/ + uint32_t dhcp_address_lifetime; /**< DHCP address lifetime in seconds minimum 2 hours and maximum as days hours*/ } ws_bbr_cfg_t; /** diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h index cb29ab6c35c1..5b468d27adb2 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h @@ -73,6 +73,11 @@ typedef struct { uint8_t index; } ws_pending_key_index_t; +typedef struct { + uint32_t block_time; + uint16_t old_bsi; +} ws_bsi_block_t; + typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t; typedef struct ws_info_s { @@ -89,6 +94,7 @@ typedef struct ws_info_s { parent_info_t parent_info[WS_PARENT_LIST_SIZE]; parent_info_list_t parent_list_free; parent_info_list_t parent_list_reserved; + ws_bsi_block_t ws_bsi_block; uint16_t aro_registration_timer; /**< Aro registration timer */ uint16_t rpl_version_timer; /**< RPL version update timeout */ uint32_t pan_timeout_timer; /**< routers will fallback to previous state after this */ diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h index 899b25afcd06..6efcf20c802e 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h @@ -130,14 +130,37 @@ extern uint8_t DEVICE_MIN_SENS; /* Multicast MPL data message parameters - * IMIN = 10 seconds, IMAX = 3 doublings */ - -#define DATA_MESSAGE_IMIN 10 -#define DATA_MESSAGE_TIMER_EXPIRATIONS 3 -#define DATA_MESSAGE_IMAX 80 -#define DATA_MESSAGE_K 8 -#define MPL_SEED_SET_ENTRY_TIMEOUT (DATA_MESSAGE_IMAX * 24 * 4) // 10 seconds per hop making this 240 seconds +#define MPL_SAFE_HOP_COUNT 6 + +/*Border router override to optimize the multicast startup*/ +#define MPL_BORDER_ROUTER_MIN_EXPIRATIONS 2 +#define MPL_BORDER_ROUTER_MAXIMUM_IMAX 40 + +/*Small network size*/ +#define MPL_SMALL_IMIN 1 +#define MPL_SMALL_IMAX 10 +#define MPL_SMALL_EXPIRATIONS 1 +#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_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*/ +#define MPL_LARGE_IMIN 5 +#define MPL_LARGE_IMAX 40 +#define MPL_LARGE_EXPIRATIONS 2 +#define MPL_LARGE_K 8 +#define MPL_LARGE_SEED_LIFETIME (MPL_LARGE_IMAX * MPL_SAFE_HOP_COUNT * (MPL_LARGE_EXPIRATIONS + 1)) // time that packet should get to safe distance +/*xtra large network size*/ +#define MPL_XLARGE_IMIN 10 +#define MPL_XLARGE_IMAX 80 +#define MPL_XLARGE_EXPIRATIONS 2 +#define MPL_XLARGE_K 8 +#define MPL_XLARGE_SEED_LIFETIME (MPL_XLARGE_IMAX * MPL_SAFE_HOP_COUNT * (MPL_XLARGE_EXPIRATIONS + 1)) // time that packet should get to safe distance /* DHCP client timeout configuration values * diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c index 306c90eed1ea..79748d453359 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c @@ -1259,6 +1259,16 @@ static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data return; } + if (!base->ie_params.hopping_schedule) { + tr_error("Missing FHSS configurations"); + mcps_data_conf_t data_conf; + memset(&data_conf, 0, sizeof(mcps_data_conf_t)); + data_conf.msduHandle = data->msduHandle; + data_conf.status = MLME_TRANSACTION_OVERFLOW; + user_cb->data_confirm(&base->mpx_data_base.mpx_api, &data_conf); + return; + } + if (user_id == MPX_KEY_MANAGEMENT_ENC_USER_ID) { ws_llc_mpx_eapol_request(base, user_cb, data); } else if (user_id == MPX_LOWPAN_ENC_USER_ID) { @@ -1643,10 +1653,11 @@ mpx_api_t *ws_llc_mpx_api_get(struct protocol_interface_info_entry *interface) int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, asynch_request_t *request) { llc_data_base_t *base = ws_llc_discover_by_interface(interface); - if (!base) { + if (!base || !base->ie_params.hopping_schedule) { return -1; } + //Calculate IE Buffer size request->wh_requested_ie_list.fc_ie = false; //Never should not be a part Asynch message request->wh_requested_ie_list.rsl_ie = false; //Never should not be a part Asynch message diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c index 135db220af5b..10fcebf54928 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c @@ -461,22 +461,22 @@ int ws_management_fhss_timing_configure( return -2; } - if (fhss_uc_dwell_interval > 0) { - cfg.fhss_uc_dwell_interval = fhss_uc_dwell_interval; - } else if (fhss_uc_dwell_interval == 0xff) { + if (fhss_uc_dwell_interval == 0) { cfg.fhss_uc_dwell_interval = cfg_default.fhss_uc_dwell_interval; + } else { + cfg.fhss_uc_dwell_interval = fhss_uc_dwell_interval; } - if (fhss_broadcast_interval > 0) { - cfg.fhss_bc_interval = fhss_broadcast_interval; - } else if (fhss_broadcast_interval == 0xffff) { + if (fhss_broadcast_interval > 0xffffff) { cfg.fhss_bc_interval = cfg_default.fhss_bc_interval; + } else if (fhss_broadcast_interval > 0) { + cfg.fhss_bc_interval = fhss_broadcast_interval; } - if (fhss_bc_dwell_interval > 0) { - cfg.fhss_bc_dwell_interval = fhss_bc_dwell_interval; - } else if (fhss_bc_dwell_interval == 0xff) { + if (fhss_bc_dwell_interval == 0) { cfg.fhss_bc_dwell_interval = cfg_default.fhss_bc_dwell_interval; + } else { + cfg.fhss_bc_dwell_interval = fhss_bc_dwell_interval; } if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { @@ -509,10 +509,10 @@ int ws_management_fhss_unicast_channel_function_configure( return -2; } - if (dwell_interval > 0) { - cfg.fhss_uc_dwell_interval = dwell_interval; - } else { + if (dwell_interval == 0) { cfg.fhss_uc_dwell_interval = cfg_default.fhss_uc_dwell_interval; + } else { + cfg.fhss_uc_dwell_interval = dwell_interval; } if (channel_function < 0xff) { cfg.fhss_uc_channel_function = channel_function; @@ -611,16 +611,16 @@ int ws_management_fhss_broadcast_channel_function_configure( return -2; } - if (dwell_interval > 0) { - cfg.fhss_bc_dwell_interval = dwell_interval; - } else { + if (dwell_interval == 0) { cfg.fhss_bc_dwell_interval = cfg_default.fhss_bc_dwell_interval; + } else { + cfg.fhss_bc_dwell_interval = dwell_interval; } - if (broadcast_interval > 0) { - cfg.fhss_bc_interval = broadcast_interval; - } else { + if (broadcast_interval > 0xffffff) { cfg.fhss_bc_interval = cfg_default.fhss_bc_interval; + } else if (broadcast_interval > 0) { + cfg.fhss_bc_interval = broadcast_interval; } if (channel_function != 0xff) { diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_neighbor_class.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_neighbor_class.c index 4cafc622a7a8..35647c1e1213 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_neighbor_class.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_neighbor_class.c @@ -102,14 +102,35 @@ static int own_ceil(float value) static void ws_neighbor_calculate_ufsi_drift(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8]) { if (ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp && ws_neighbor->fhss_data.uc_timing_info.ufsi) { + // No UFSI on fixed channel + if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_FIXED_CHANNEL) { + return; + } uint32_t seq_length = 0x10000; - if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_TR51CF) { + if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_TR51CF) { seq_length = ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels; } + uint32_t ufsi_prev_tmp = ws_neighbor->fhss_data.uc_timing_info.ufsi; + uint32_t ufsi_cur_tmp = ws_utt->ufsi; + if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_DH1CF) { + if (ufsi_cur_tmp < ufsi_prev_tmp) { + ufsi_cur_tmp += 0xffffff; + } + } // Convert 24-bit UFSI to real time before drift calculation - uint32_t time_since_seq_start_prev_ms = own_ceil((float)((uint64_t)ws_neighbor->fhss_data.uc_timing_info.ufsi * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000); - uint32_t time_since_seq_start_cur_ms = own_ceil((float)((uint64_t)ws_utt->ufsi * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000); + uint32_t time_since_seq_start_prev_ms = own_ceil((float)((uint64_t)ufsi_prev_tmp * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000); + uint32_t time_since_seq_start_cur_ms = own_ceil((float)((uint64_t)ufsi_cur_tmp * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000); uint32_t time_since_last_ufsi_us = timestamp - ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp; + + if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_TR51CF) { + uint32_t full_uc_schedule_ms = ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval * ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels; + uint32_t temp_ms = (time_since_last_ufsi_us / 1000) / full_uc_schedule_ms; + if (time_since_seq_start_cur_ms >= time_since_seq_start_prev_ms) { + temp_ms--; + } + time_since_seq_start_cur_ms += temp_ms * full_uc_schedule_ms + (full_uc_schedule_ms - time_since_seq_start_prev_ms) + time_since_seq_start_prev_ms; + } + uint32_t ufsi_diff_ms = time_since_seq_start_cur_ms - time_since_seq_start_prev_ms; int32_t ufsi_drift_ms = (int32_t)(time_since_last_ufsi_us / 1000 - ufsi_diff_ms); // Only trace if there is significant error diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c index 942f44379d64..47e73ace70b0 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c @@ -695,6 +695,9 @@ void ws_pae_auth_fast_timer(uint16_t ticks) ws_pae_auth_timer_stop(pae_auth); } } + + // Update key storage fast timer + ws_pae_key_storage_fast_timer(ticks); } void ws_pae_auth_slow_timer(uint16_t seconds) diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c index 0a7a0650d7af..57eb9a19c011 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c @@ -122,7 +122,7 @@ static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t * static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry); static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry); static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold); -static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_t *tlv_entry); +static void ws_pae_controller_nvm_frame_counter_write(frame_cnt_nvm_tlv_t *tlv_entry); static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters); static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id); static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash); @@ -801,8 +801,8 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller) } if (updated) { // Writes incremented frame counters - ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &controller->pae_nvm_buffer, controller->restart_cnt, controller->sec_keys_nw_info.pan_version, &controller->frame_counters); - ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &controller->pae_nvm_buffer); + ws_pae_nvm_store_frame_counter_tlv_create((frame_cnt_nvm_tlv_t *) &controller->pae_nvm_buffer, controller->restart_cnt, controller->sec_keys_nw_info.pan_version, &controller->frame_counters); + ws_pae_controller_nvm_frame_counter_write((frame_cnt_nvm_tlv_t *) &controller->pae_nvm_buffer); } } @@ -839,28 +839,28 @@ static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_p static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, sec_prot_gtk_keys_t *gtks) { - nvm_tlv_t *tlv = ws_pae_controller_nvm_tlv_get(interface_ptr); + nw_info_nvm_tlv_t *tlv = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr); if (!tlv) { return -1; } ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtks); - ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, tlv); + ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, (nvm_tlv_t *) tlv); return 0; } static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, sec_prot_gtk_keys_t *gtks) { - nvm_tlv_t *tlv_entry = ws_pae_controller_nvm_tlv_get(interface_ptr); + nw_info_nvm_tlv_t *tlv_entry = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr); if (!tlv_entry) { return -1; } - ws_pae_nvm_store_generic_tlv_create(tlv_entry, PAE_NVM_NW_INFO_TAG, PAE_NVM_NW_INFO_LEN); + ws_pae_nvm_store_generic_tlv_create((nvm_tlv_t *) tlv_entry, PAE_NVM_NW_INFO_TAG, PAE_NVM_NW_INFO_LEN); - if (ws_pae_nvm_store_tlv_file_read(NW_INFO_FILE, tlv_entry) < 0) { + if (ws_pae_nvm_store_tlv_file_read(NW_INFO_FILE, (nvm_tlv_t *) tlv_entry) < 0) { return -1; } @@ -1654,6 +1654,8 @@ void ws_pae_controller_slow_timer(uint16_t seconds) } ws_pae_controller_frame_counter_timer(seconds, entry); } + + ws_pae_current_time_update(seconds); } static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry) @@ -1727,8 +1729,8 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool if (update_needed || entry->frame_cnt_store_force_timer == 0) { tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10); // Writes modified frame counters - ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, entry->sec_keys_nw_info.pan_version, &entry->frame_counters); - ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &entry->pae_nvm_buffer); + ws_pae_nvm_store_frame_counter_tlv_create((frame_cnt_nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, entry->sec_keys_nw_info.pan_version, &entry->frame_counters); + ws_pae_controller_nvm_frame_counter_write((frame_cnt_nvm_tlv_t *) &entry->pae_nvm_buffer); // Reset force interval when ever values are stored entry->frame_cnt_store_force_timer = FRAME_COUNTER_STORE_FORCE_INTERVAL; @@ -1737,23 +1739,23 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters) { - nvm_tlv_t *tlv = ws_pae_nvm_store_generic_tlv_allocate_and_create( - PAE_NVM_FRAME_COUNTER_TAG, PAE_NVM_FRAME_COUNTER_LEN); + frame_cnt_nvm_tlv_t *tlv = (frame_cnt_nvm_tlv_t *) ws_pae_nvm_store_generic_tlv_allocate_and_create( + PAE_NVM_FRAME_COUNTER_TAG, PAE_NVM_FRAME_COUNTER_LEN); if (!tlv) { return -1; } - if (ws_pae_nvm_store_tlv_file_read(FRAME_COUNTER_FILE, tlv) < 0) { - ws_pae_nvm_store_generic_tlv_free(tlv); + if (ws_pae_nvm_store_tlv_file_read(FRAME_COUNTER_FILE, (nvm_tlv_t *) tlv) < 0) { + ws_pae_nvm_store_generic_tlv_free((nvm_tlv_t *) tlv); return -1; } if (ws_pae_nvm_store_frame_counter_tlv_read(tlv, restart_cnt, stored_time, pan_version, counters) < 0) { - ws_pae_nvm_store_generic_tlv_free(tlv); + ws_pae_nvm_store_generic_tlv_free((nvm_tlv_t *) tlv); return -1; } - ws_pae_nvm_store_generic_tlv_free(tlv); + ws_pae_nvm_store_generic_tlv_free((nvm_tlv_t *) tlv); return 0; } @@ -1798,9 +1800,9 @@ nvm_tlv_t *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interf return (nvm_tlv_t *) &controller->pae_nvm_buffer; } -static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_t *tlv_entry) +static void ws_pae_controller_nvm_frame_counter_write(frame_cnt_nvm_tlv_t *tlv_entry) { - ws_pae_nvm_store_tlv_file_write(FRAME_COUNTER_FILE, tlv_entry); + ws_pae_nvm_store_tlv_file_write(FRAME_COUNTER_FILE, (nvm_tlv_t *) tlv_entry); } diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c index b168edcf101d..7ee66a073a9a 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c @@ -21,6 +21,7 @@ #include "ns_list.h" #include "ns_trace.h" #include "nsdynmemLIB.h" +#include "randLIB.h" #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" @@ -57,6 +58,9 @@ /* Force key storage reference time update, if reference time differs more 31 days */ #define KEY_STORAGE_REF_TIME_UPDATE_FORCE_THRESHOLD GTK_DEFAULT_LIFETIME + 86400 +// Base scatter timer value, 3 seconds */ +#define KEY_STORAGE_SCATTER_TIMER_BASE_VALUE 30 + typedef enum { WRITE_SET = 0, TIME_SET, @@ -84,6 +88,7 @@ typedef struct { uint16_t free_entries; /**< Free entries in array */ bool allocated : 1; /**< Allocated */ bool modified : 1; /**< Array modified */ + bool pending_storing : 1; /**< Entry is pending storing to NVM */ } key_storage_array_t; typedef struct { @@ -95,6 +100,7 @@ typedef struct { uint16_t store_timer_timeout; /**< Storing timing timeout */ uint16_t store_timer; /**< Storing timer */ uint32_t restart_cnt; /**< Re-start counter */ + uint32_t scatter_timer; /**< NVM storing scatter timer */ } key_storage_params_t; static key_storage_params_t key_storage_params; @@ -107,7 +113,10 @@ static void ws_pae_key_storage_list_all_free(void); static sec_prot_keys_storage_t *ws_pae_key_storage_get(const void *instance, const uint8_t *eui64, key_storage_array_t **key_storage_array, bool return_free); static sec_prot_keys_storage_t *ws_pae_key_storage_replace(const void *instance, key_storage_array_t **key_storage_array); static void ws_pae_key_storage_trace(uint16_t field_set, sec_prot_keys_storage_t *key_storage, key_storage_array_t *key_storage_array); +static void ws_pae_key_storage_scatter_timer_timeout(void); +static void ws_pae_key_storage_fast_timer_start(void); static void ws_pae_key_storage_timer_expiry_set(void); +static void ws_pae_key_storage_fast_timer_ticks_set(void); static int8_t ws_pae_key_storage_array_time_update_entry(uint64_t time_difference, sec_prot_keys_storage_t *storage_array_entry); static int8_t ws_pae_key_storage_array_time_check_and_update_all(key_storage_array_t *key_storage_array, bool modified); static int8_t ws_pae_key_storage_array_counters_check_and_update_all(key_storage_array_t *key_storage_array); @@ -159,6 +168,7 @@ void ws_pae_key_storage_init(void) key_storage_params.replace_index = 0; key_storage_params.store_bitfield = 0, key_storage_params.restart_cnt = 0; + key_storage_params.scatter_timer = 0; } void ws_pae_key_storage_delete(void) @@ -189,6 +199,7 @@ static int8_t ws_pae_key_storage_allocate(const void *instance, uint16_t key_sto key_storage_array->free_entries = key_storage_array->entries; key_storage_array->instance = instance; key_storage_array->modified = false; + key_storage_array->pending_storing = false; ws_pae_nvm_store_key_storage_tlv_create((nvm_tlv_t *) key_storage_array->storage_array_handle, key_storage_array->size); @@ -329,10 +340,13 @@ static sec_prot_keys_storage_t *ws_pae_key_storage_replace(const void *instance, key_storage_params.replace_index++; tr_info("KeyS replace array: %p i: %i eui64: %s", (void *) entry->storage_array, replace_index, tr_array(storage_array[replace_index].ptk_eui_64, 8)); + break; } // If replace index is not found it means that index has gone past the last entry if (storage_array == NULL) { + tr_info("KeyS replace array first index"); + /* Gets first key storage array and sets the array and sets index to zero and sets (next) replace index to first */ key_storage_array_t *key_storage_array_entry = ns_list_get_first(&key_storage_array_list); @@ -648,6 +662,7 @@ int8_t ws_pae_key_storage_store(void) { uint8_t entry_offset = 0; uint64_t store_bitfield = 0; + bool start_scatter_timer = false; ns_list_foreach(key_storage_array_t, entry, &key_storage_array_list) { // Bitfield is set for all entries (also that are non-modified in this write) @@ -671,17 +686,20 @@ int8_t ws_pae_key_storage_store(void) continue; } - char filename[KEY_STORAGE_FILE_LEN]; - ws_pae_key_storage_filename_set(filename, entry_offset); - tr_info("KeyS write array: %p file: %s", (void *) entry->storage_array, filename); - nvm_tlv_t *tlv = (nvm_tlv_t *) entry->storage_array_handle; - ws_pae_nvm_store_tlv_file_write(filename, tlv); + entry->pending_storing = true; + start_scatter_timer = true; - // No longer pending for storing + // Item is pending for storing, reset modified flag entry->modified = false; entry_offset++; } + tr_info("KeyS storage store, bitf: %"PRIx64, store_bitfield); + + if (start_scatter_timer) { + ws_pae_key_storage_fast_timer_start(); + } + if (key_storage_params.store_bitfield != store_bitfield) { key_storage_params.store_bitfield = store_bitfield; nvm_tlv_t *tlv = ws_pae_nvm_store_generic_tlv_allocate_and_create( @@ -694,6 +712,38 @@ int8_t ws_pae_key_storage_store(void) return 0; } +static void ws_pae_key_storage_scatter_timer_timeout(void) +{ + uint8_t entry_offset = 0; + bool pending_entry = false; + + ns_list_foreach(key_storage_array_t, entry, &key_storage_array_list) { + if (!entry->pending_storing) { + entry_offset++; + continue; + } + pending_entry = true; + + char filename[KEY_STORAGE_FILE_LEN]; + ws_pae_key_storage_filename_set(filename, entry_offset); + tr_info("KeyS write array: %p file: %s", (void *) entry->storage_array, filename); + nvm_tlv_t *tlv = (nvm_tlv_t *) entry->storage_array_handle; + ws_pae_nvm_store_tlv_file_write(filename, tlv); + + // Item has been stored, reset pending storing and modified flag + entry->pending_storing = false; + entry->modified = false; + break; + } + + if (pending_entry) { + ws_pae_key_storage_fast_timer_ticks_set(); + return; + } + + tr_info("KeyS all pending entries stored"); +} + void ws_pae_key_storage_read(uint32_t restart_cnt) { key_storage_params.store_bitfield = 0; @@ -838,8 +888,30 @@ void ws_pae_key_storage_timer(uint16_t seconds) key_storage_params.store_timer = key_storage_params.store_timer_timeout; ws_pae_key_storage_store(); } +} - ws_pae_current_time_update(seconds); +void ws_pae_key_storage_fast_timer(uint16_t ticks) +{ + if (key_storage_params.scatter_timer == 0) { + return; + } else if (key_storage_params.scatter_timer > ticks) { + key_storage_params.scatter_timer -= ticks; + } else { + key_storage_params.scatter_timer = 0; + ws_pae_key_storage_scatter_timer_timeout(); + } +} + +static void ws_pae_key_storage_fast_timer_start(void) +{ + ws_pae_key_storage_fast_timer_ticks_set(); +} + +static void ws_pae_key_storage_fast_timer_ticks_set(void) +{ + // (0.625 - 1,375) * 3 seconds + key_storage_params.scatter_timer = randLIB_randomise_base(KEY_STORAGE_SCATTER_TIMER_BASE_VALUE, 0x5000, 0xB000); + tr_info("KeyS scatter timer %"PRIi32, key_storage_params.scatter_timer); } static void ws_pae_key_storage_timer_expiry_set(void) diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.h index b41162001807..c0ca7cac04a8 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.h @@ -153,6 +153,14 @@ bool ws_pae_key_storage_supp_delete(const void *instance, const uint8_t *eui64); */ void ws_pae_key_storage_timer(uint16_t seconds); +/** + * ws_pae_key_storage_fast_timer key storage fast timers + * + * \param ticks Ticks passed + * + */ +void ws_pae_key_storage_fast_timer(uint16_t ticks); + /** * ws_pae_key_storage_storing_interval_get gets key storage storing interval * diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.c index 793b7a48467a..fa26ab3f5c5f 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.c @@ -67,13 +67,13 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry) ns_dyn_mem_free(tlv_entry); } -void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) +void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) { int len; tlv_entry->tag = PAE_NVM_NW_INFO_TAG; tlv_entry->len = PAE_NVM_NW_INFO_LEN; - uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; + uint8_t *tlv = (uint8_t *) &tlv_entry->data[0]; tlv = common_write_16_bit(pan_id, tlv); @@ -119,7 +119,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_t *tlv_entry, uint16_t pan_id, } -int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) +int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) { if (!tlv_entry || !pan_id || !nw_name) { return -1; @@ -129,7 +129,7 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, return -1; } - uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; + uint8_t *tlv = (uint8_t *) &tlv_entry->data[0]; if (*pan_id == 0xffff) { // If application has not set pan_id read it from NVM @@ -184,12 +184,12 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, return 0; } -void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys) +void ws_pae_nvm_store_keys_tlv_create(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys) { tlv_entry->tag = PAE_NVM_KEYS_TAG; tlv_entry->len = PAE_NVM_KEYS_LEN; - uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; + uint8_t *tlv = (uint8_t *) &tlv_entry->data[0]; uint8_t *eui_64 = sec_prot_keys_ptk_eui_64_get(sec_keys); if (eui_64) { @@ -231,7 +231,7 @@ void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec tr_debug("NVM KEYS write"); } -int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys) +int8_t ws_pae_nvm_store_keys_tlv_read(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys) { if (!tlv_entry || !sec_keys) { return -1; @@ -241,7 +241,7 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec return -1; } - uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; + uint8_t *tlv = (uint8_t *) &tlv_entry->data[0]; // EUI-64 set */ if (*tlv++ == PAE_NVM_FIELD_SET) { @@ -281,12 +281,12 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec return 0; } -void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters) +void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters) { tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG; tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN; - uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; + uint8_t *tlv = (uint8_t *) &tlv_entry->data[0]; tlv = common_write_32_bit(restart_cnt, tlv); @@ -311,7 +311,7 @@ void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t re tr_debug("NVM FRAME COUNTER write"); } -int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters) +int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters) { if (!tlv_entry || !counters) { return -1; @@ -321,7 +321,7 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *r return -1; } - uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN; + uint8_t *tlv = (uint8_t *) &tlv_entry->data[0]; *restart_cnt = common_read_32_bit(tlv); tlv += 4; diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.h index d66e238fa0e9..23f164d4d8eb 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_data.h @@ -49,6 +49,24 @@ // key storage index bitfield (8) #define PAE_NVM_KEY_STORAGE_INDEX_LEN 8 +typedef struct nw_info_nvm_tlv { + uint16_t tag; /**< Unique tag */ + uint16_t len; /**< Number of the bytes after the length field */ + uint8_t data[PAE_NVM_NW_INFO_LEN]; /**< Data */ +} nw_info_nvm_tlv_t; + +typedef struct keys_nvm_tlv { + uint16_t tag; /**< Unique tag */ + uint16_t len; /**< Number of the bytes after the length field */ + uint8_t data[PAE_NVM_KEYS_LEN]; /**< Data */ +} keys_nvm_tlv_t; + +typedef struct frame_cnt_nvm_tlv { + uint16_t tag; /**< Unique tag */ + uint16_t len; /**< Number of the bytes after the length field */ + uint8_t data[PAE_NVM_FRAME_COUNTER_LEN]; /**< Data */ +} frame_cnt_nvm_tlv_t; + /** * ws_pae_nvm_store_generic_tlv_create create NVM generic storage TLV * @@ -77,7 +95,7 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry); * \return TLV entry or NULL * */ -void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); +void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); /** * ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV @@ -91,7 +109,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_t *tlv_entry, uint16_t pan_id, * \return >= 0 success * */ -int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); +int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); /** * ws_pae_nvm_store_keys_tlv_create create NVM keys TLV @@ -100,7 +118,7 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_t *tlv_entry, uint16_t *pan_id, * \param sec_keys security keys * */ -void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys); +void ws_pae_nvm_store_keys_tlv_create(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys); /** * ws_pae_nvm_store_nw_info_tlv_read read from NVM keys TLV @@ -112,7 +130,7 @@ void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec * \return >= 0 success * */ -int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys); +int8_t ws_pae_nvm_store_keys_tlv_read(keys_nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec_keys); /** * ws_pae_nvm_store_frame_counter_tlv_create create NVM frame counter TLV @@ -123,7 +141,7 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec * \param counters frame counters * */ -void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters); +void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters); /** * ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV @@ -138,7 +156,7 @@ void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t re * \return >= 0 success * */ -int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters); +int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters); /** * ws_pae_nvm_store_key_storage_index_tlv_create create NVM key storage index TLV diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_store.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_store.h index fb741da83315..bf18915c1b3b 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_store.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_nvm_store.h @@ -40,8 +40,8 @@ typedef struct nvm_tlv { typedef struct { nvm_tlv_t nvm_tlv; /**< NVM TLV */ - uint64_t reference_time; /**< Reference time used for timers (set when file is created) */ uint32_t reference_restart_cnt; /**< Reference re-start counter set when file is created) */ + uint64_t reference_time; /**< Reference time used for timers (set when file is created) */ } key_storage_nvm_tlv_entry_t; // tag + length diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c index e9d28a892f31..13c1e149ec37 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c @@ -415,25 +415,25 @@ static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp) static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp) { - nvm_tlv_t *tlv = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr); + keys_nvm_tlv_t *tlv = (keys_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr); if (!tlv) { return -1; } ws_pae_nvm_store_keys_tlv_create(tlv, &pae_supp->entry.sec_keys); - ws_pae_nvm_store_tlv_file_write(KEYS_FILE, tlv); + ws_pae_nvm_store_tlv_file_write(KEYS_FILE, (nvm_tlv_t *) tlv); return 0; } static int8_t ws_pae_supp_nvm_keys_read(pae_supp_t *pae_supp) { - nvm_tlv_t *tlv = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr); + keys_nvm_tlv_t *tlv = (keys_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr); if (!tlv) { return -1; } - ws_pae_nvm_store_generic_tlv_create(tlv, PAE_NVM_KEYS_TAG, PAE_NVM_KEYS_LEN); - if (ws_pae_nvm_store_tlv_file_read(KEYS_FILE_NAME, tlv) < 0) { + ws_pae_nvm_store_generic_tlv_create((nvm_tlv_t *) tlv, PAE_NVM_KEYS_TAG, PAE_NVM_KEYS_LEN); + if (ws_pae_nvm_store_tlv_file_read(KEYS_FILE_NAME, (nvm_tlv_t *) tlv) < 0) { return -1; } ws_pae_nvm_store_keys_tlv_read(tlv, &pae_supp->entry.sec_keys); diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_time.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_time.c index ad60f3d0e2fb..a962b9415d59 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_time.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_time.c @@ -33,9 +33,6 @@ // Wednesday, January 1, 2020 0:00:00 GMT #define CURRENT_TIME_INIT_VALUE 1577836800 -// Increment two hours in addition to maximum storing interval -#define CURRENT_TIME_INCREMENT_VALUE (2 * 3600) - static uint64_t current_time = CURRENT_TIME_INIT_VALUE; static ns_time_api_system_time_callback *system_time_callback = NULL; @@ -167,6 +164,8 @@ int8_t ws_pae_current_time_set(uint64_t time) { current_time = time; + tr_debug("Current time set: %"PRIi64, time); + if (system_time_callback) { uint64_t system_time = system_time_callback(); // System time has gone backwards @@ -174,8 +173,6 @@ int8_t ws_pae_current_time_set(uint64_t time) tr_error("FATAL: system time less than reference time or more than 12 months in future: %"PRIi64" reference time: %"PRIi64, system_time, current_time); return -1; } - } else { - current_time += FRAME_COUNTER_STORE_FORCE_INTERVAL + CURRENT_TIME_INCREMENT_VALUE; } return 0; diff --git a/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c b/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c index 1f8beaf6a32b..0d381eae7a8c 100644 --- a/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c +++ b/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c @@ -886,6 +886,11 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf) uint8_t dns_search_list_len = length - 8; // Length includes type and length //Cut Padding dns_search_list_len = icmpv6_dns_search_list_remove_pad(dns_search_list, dns_search_list_len); + + // validate lifetime to be at least same amount as default route lifetime + if (dns_lifetime > 0 && dns_lifetime < router_lifetime) { + dns_lifetime = router_lifetime; + } //tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime); // Add DNS server to DNS information storage. net_dns_server_search_list_set(cur->id, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime); @@ -899,6 +904,12 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf) } uint8_t dns_count = (dns_length - 1) / 2; uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved + + // validate lifetime to be at least same amount as default route lifetime + if (dns_lifetime > 0 && dns_lifetime < router_lifetime) { + dns_lifetime = router_lifetime; + } + for (int n = 0; n < dns_count; n++) { uint8_t *dns_srv_addr = dptr + 6 + n * 16; //tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime); diff --git a/features/nanostack/sal-stack-nanostack/source/Core/include/ns_socket.h b/features/nanostack/sal-stack-nanostack/source/Core/include/ns_socket.h index c4e6e638c27b..23ec4db7eca7 100644 --- a/features/nanostack/sal-stack-nanostack/source/Core/include/ns_socket.h +++ b/features/nanostack/sal-stack-nanostack/source/Core/include/ns_socket.h @@ -130,7 +130,7 @@ typedef struct socket { int8_t id; /*!< socket id */ uint8_t flags; /*!< Socket option flags */ int8_t tasklet; /*!< Receiver tasklet */ - uint8_t refcount; + uint16_t refcount; socket_family_t family; socket_type_t type; int8_t default_interface_id; diff --git a/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_mcps_sap.c index 38924cba934e..a47753c3a30f 100644 --- a/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1183,15 +1183,24 @@ static void mac_pd_data_confirm_failure_handle(protocol_interface_rf_mac_setup_s mcps_data_confirm_cb(rf_mac_setup, &mcps_data_conf, NULL); } + static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf) { protocol_interface_rf_mac_setup_s *rf_mac_setup = buf->mac_class_ptr; if (!rf_mac_setup->active_pd_data_request) { mcps_sap_pre_parsed_frame_buffer_free(buf); + tr_debug("RX ack without active buffer"); } else { mac_pre_build_frame_t *buffer = rf_mac_setup->active_pd_data_request; + //Validate here ack is proper to active buffer + if (!mac_pd_sap_ack_validation(rf_mac_setup, &buf->fcf_dsn, mac_header_message_start_pointer(buf))) { + tr_debug("Not a valid ACK for active tx process"); + mcps_sap_pre_parsed_frame_buffer_free(buf); + return; + } + if (mac_ack_sap_rx_handler(buf, rf_mac_setup)) { //Do not forward ACK payload but Accept ACK mcps_sap_pre_parsed_frame_buffer_free(buf); diff --git a/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.c b/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.c index 6b36a7f7d69d..dad7da84fd5b 100644 --- a/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -655,12 +655,16 @@ static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_set return 0; } -static bool mac_pd_sap_ack_validation(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_dsn, const uint8_t *data_ptr) +bool mac_pd_sap_ack_validation(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_dsn, const uint8_t *data_ptr) { - if (!rf_ptr->active_pd_data_request || !rf_ptr->active_pd_data_request->fcf_dsn.ackRequested) { + if (!rf_ptr->active_pd_data_request || (!rf_ptr->active_pd_data_request->fcf_dsn.ackRequested && !rf_ptr->active_pd_data_request->ExtendedFrameExchange)) { return false; //No active Data request anymore or no ACK request for current TX } + if (rf_ptr->active_pd_data_request->ExtendedFrameExchange && fcf_dsn->frametype == FC_DATA_FRAME) { + return true;//EFDE final message + } + if (fcf_dsn->frameVersion != rf_ptr->active_pd_data_request->fcf_dsn.frameVersion) { return false; } diff --git a/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.h b/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.h index fdde95acac06..396e92bc7f41 100644 --- a/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.h +++ b/features/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4/mac_pd_sap.h @@ -26,6 +26,7 @@ struct protocol_interface_rf_mac_setup; struct arm_phy_sap_msg_s; +struct mac_fcf_sequence_s; #define ENHANCED_ACK_NEIGHBOUR_POLL_MAX_TIME_US 3500 @@ -61,4 +62,6 @@ void mac_pd_sap_state_machine(struct protocol_interface_rf_mac_setup *rf_mac_set int8_t mac_data_edfe_force_stop(struct protocol_interface_rf_mac_setup *rf_ptr); +bool mac_pd_sap_ack_validation(struct protocol_interface_rf_mac_setup *rf_ptr, const struct mac_fcf_sequence_s *fcf_dsn, const uint8_t *data_ptr); + #endif /* MAC_PD_SAP_H_ */ diff --git a/features/nanostack/sal-stack-nanostack/source/MPL/mpl.c b/features/nanostack/sal-stack-nanostack/source/MPL/mpl.c index f8e0b93dc194..913745f0c96c 100644 --- a/features/nanostack/sal-stack-nanostack/source/MPL/mpl.c +++ b/features/nanostack/sal-stack-nanostack/source/MPL/mpl.c @@ -48,7 +48,7 @@ #define MPL_SEED_64_BIT 2 #define MPL_SEED_128_BIT 3 -#define MAX_BUFFERED_MESSAGES_SIZE 2048 +#define MAX_BUFFERED_MESSAGES_SIZE 8192 #define MAX_BUFFERED_MESSAGE_LIFETIME 600 // 1/10 s ticks static bool mpl_timer_running; diff --git a/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.c b/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.c index e97416c752f9..72ddf1281f66 100644 --- a/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.c +++ b/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.c @@ -115,6 +115,8 @@ static void rpl_downward_topo_sort_invalidate(rpl_instance_t *instance); /* The PCS mask */ #define PCSMASK(pcs) ((uint8_t)(0x100 - PCBIT(pcs))) +static bool rpl_instance_push_address_registration(protocol_interface_info_entry_t *interface, rpl_neighbour_t *neighbour, if_address_entry_t *addr); +static if_address_entry_t *rpl_interface_addr_get(protocol_interface_info_entry_t *interface, const uint8_t addr[16]); /* * 0 1 2 3 4 5 6 7 @@ -178,7 +180,7 @@ static void rpl_downward_target_refresh(rpl_dao_target_t *target) target->info.non_root.path_lifetime = 0; } -static bool rpl_instance_parent_selection_ready(rpl_instance_t *instance) +bool rpl_instance_parent_selection_ready(rpl_instance_t *instance) { rpl_neighbour_t *neighbour = ns_list_get_first(&instance->candidate_neighbours); if (neighbour && neighbour->dodag_parent && neighbour->dao_path_control) { @@ -723,7 +725,11 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance) instance->dao_in_transit = false; instance->dao_attempt = 0; instance->dao_retry_timer = 0; - instance->delay_dao_timer = 0; + // Primary parent deletion will trigger parent selection + // While waiting, leave dao_timer "running" to indicate DAO incomplete + // This is checked in rpl_upward_dio_timer to delay initial DIO sending + // If we stopped the timer, that code might think DAO registration was complete + instance->delay_dao_timer = 0xffff; return; } @@ -1537,6 +1543,25 @@ bool rpl_instance_dao_received(rpl_instance_t *instance, const uint8_t src[16], } #endif // HAVE_RPL_DAO_HANDLING +static uint16_t rpl_instance_address_registration_start(rpl_instance_t *instance, rpl_dao_target_t *pending_target) +{ + rpl_neighbour_t *pref_parent = rpl_instance_preferred_parent(instance); + protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_rpl_domain(instance->domain, -1); + if (!interface || !pref_parent) { + return 1; + } + if_address_entry_t *address = rpl_interface_addr_get(interface, pending_target->prefix); + if (!address) { + return 1; + } + if (!rpl_instance_push_address_registration(interface, pref_parent, address)) { + return 1; + } + tr_debug("Extra Address Confirmation trig...next dao trig 10s"); + return 100; + +} + void rpl_instance_dao_acked(rpl_instance_t *instance, const uint8_t src[16], int8_t interface_id, uint8_t dao_sequence, uint8_t status) { if (!instance->dao_in_transit || dao_sequence != instance->dao_sequence_in_transit) { @@ -1568,6 +1593,7 @@ void rpl_instance_dao_acked(rpl_instance_t *instance, const uint8_t src[16], int } bool more_to_do = false; + rpl_dao_target_t *pending_target = NULL; ns_list_foreach(rpl_dao_target_t, target, &instance->dao_targets) { if (target->root) { continue; @@ -1585,12 +1611,14 @@ void rpl_instance_dao_acked(rpl_instance_t *instance, const uint8_t src[16], int target->info.non_root.pc_assigned |= target->info.non_root.pc_assigning; } else { target->info.non_root.pc_to_retry |= target->info.non_root.pc_assigning; + } target->info.non_root.pc_assigning = 0; } target->info.non_root.pc_assigned &= target->path_control; if (target->info.non_root.pc_assigned != target->path_control) { more_to_do = true; + pending_target = target; } else { if (target->published && target->info.non_root.refresh_timer == 0) { uint32_t t; @@ -1612,7 +1640,14 @@ void rpl_instance_dao_acked(rpl_instance_t *instance, const uint8_t src[16], int } if (more_to_do) { - rpl_instance_dao_trigger(instance, 1); + uint16_t dao_trig_time = 1; + if (pending_target && rpl_policy_parent_confirmation_requested()) { + //Possible NS ARO trig + dao_trig_time = rpl_instance_address_registration_start(instance, pending_target); + } + + rpl_instance_dao_trigger(instance, dao_trig_time); + } else { rpl_control_event(instance->domain, RPL_EVENT_DAO_DONE); } @@ -1863,9 +1898,6 @@ static void rpl_instance_address_registration_cancel(rpl_instance_t *instance) instance->wait_response = NULL; instance->pending_neighbour_confirmation = false; - instance->delay_dao_timer = 0; - instance->dao_in_transit = false; - instance->dao_retry_timer = 0; } static void rpl_instance_address_registration_retry(rpl_dao_target_t *dao_target) @@ -1881,6 +1913,11 @@ void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint return; //No need validate any confirmation } + if (rpl_instance_am_root(instance)) { + rpl_instance_address_registration_cancel(instance); + return; + } + //Verify that we have selected parent and it have a dao path control if (!rpl_instance_parent_selection_ready(instance)) { rpl_instance_address_registration_cancel(instance); diff --git a/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.h b/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.h index c7cd66f27f17..73cceeb856c6 100644 --- a/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.h +++ b/features/nanostack/sal-stack-nanostack/source/RPL/rpl_downward.h @@ -46,6 +46,7 @@ void rpl_instance_parent_address_reg_timer_update(struct rpl_instance *instance, void rpl_instance_send_address_registration(rpl_instance_t *instance, const uint8_t addr[16]); bool rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status); struct rpl_dao_target *rpl_instance_get_active_target_confirmation(struct rpl_instance *instance); +bool rpl_instance_parent_selection_ready(struct rpl_instance *instance); #ifdef HAVE_RPL_DAO_HANDLING bool rpl_instance_dao_received(struct rpl_instance *instance, const uint8_t src[16], int8_t interface_id, bool multicast, const uint8_t *opts, uint16_t opts_len, uint8_t *status_out); diff --git a/features/nanostack/sal-stack-nanostack/source/RPL/rpl_upward.c b/features/nanostack/sal-stack-nanostack/source/RPL/rpl_upward.c index babb5d0716dc..dec173ef71d5 100644 --- a/features/nanostack/sal-stack-nanostack/source/RPL/rpl_upward.c +++ b/features/nanostack/sal-stack-nanostack/source/RPL/rpl_upward.c @@ -1836,11 +1836,12 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) if (rpl_dodag_am_leaf(dodag) && !instance->poison_count) { return; } + /* 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 (!instance->last_advertised_dodag_version && rpl_policy_parent_confirmation_requested()) { - // We dont have any valid address in interface - if (ns_list_count(&instance->dao_targets) == 0) { + 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_parent_selection_ready(instance)) { return; } /* Address registrations for parent ongoing*/ @@ -1852,6 +1853,7 @@ void rpl_upward_dio_timer(rpl_instance_t *instance, uint16_t ticks) return; } } + if (trickle_timer(&instance->dio_timer, &dodag->dio_timer_params, ticks)) { instance->dio_not_consistent = false; rpl_instance_dio_trigger(instance, NULL, NULL); diff --git a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c index c3d354bd9b44..43d1e39b1687 100644 --- a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c +++ b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c @@ -82,6 +82,7 @@ static int fhss_ws_manage_channel_table_allocation(fhss_structure_t *fhss_struct static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure); static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay); +static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay); static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure); static int32_t fhss_channel_index_from_mask(const uint32_t *channel_mask, int32_t channel_index, uint16_t number_of_channels); @@ -114,6 +115,11 @@ void fhss_ws_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void ( // Reduce the compensation (per millisecond) from timeout. time -= NS_TO_US(time_in_ms * fhss_structure->ws->drift_per_millisecond_ns); fhss_start_timer(fhss_structure, time, callback); + if (callback == fhss_unicast_handler) { + fhss_structure->ws->next_uc_timeout = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) + time; + } else if (callback == fhss_broadcast_handler) { + fhss_structure->ws->next_bc_timeout = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) + time; + } } fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer) @@ -285,6 +291,7 @@ static int32_t fhss_channel_index_from_mask(const uint32_t *channel_mask, int32_ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay) { + (void) delay; int32_t next_channel; fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); if (!fhss_structure) { @@ -298,8 +305,44 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay) fhss_structure->ws->broadcast_timer_running = false; return; } + + int32_t delay_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) - fhss_structure->ws->next_bc_timeout; + // Assume this was initial call for this function without timer + if (!fhss_structure->ws->bc_slot && !fhss_structure->ws->next_bc_timeout) { + delay_us = 0; + } + if (fhss_structure->ws->is_on_bc_channel == false) { - fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler); + // If callback was delayed longer than broadcast interval, BC slot must be updated + fhss_structure->ws->bc_slot += (US_TO_MS(delay_us) + (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval)) / fhss_structure->ws->fhss_configuration.fhss_broadcast_interval; + // We weren't on broadcast channel. Check if after delayed interrupt we still shouldn't go to broadcast channel. Setting is_on_bc_channel to true forces to skip BC dwell interval next. + if ((US_TO_MS(delay_us) % fhss_structure->ws->fhss_configuration.fhss_broadcast_interval) > fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) { + fhss_structure->ws->is_on_bc_channel = true; + // If delay + assumed timeout is longer than broadcast interval, delay value must be computed differently to make compensation work properly + if (US_TO_MS(delay_us) + (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) > fhss_structure->ws->fhss_configuration.fhss_broadcast_interval) { + delay_us = (MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) + delay_us) % MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval); + } + } else { + if (US_TO_MS(delay_us) + (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) > fhss_structure->ws->fhss_configuration.fhss_broadcast_interval) { + delay_us = ((MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) + delay_us) % MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval)) - MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval); + } + } + } else { + // If callback was delayed longer than broadcast interval, BC slot must be updated + fhss_structure->ws->bc_slot += (US_TO_MS(delay_us) + fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / fhss_structure->ws->fhss_configuration.fhss_broadcast_interval; + // We were on broadcast channel. Check if after delayed interrupt we should go broadcast channel again. Setting is_on_bc_channel to false forces to start BC dwell interval next. + if ((US_TO_MS(delay_us) % fhss_structure->ws->fhss_configuration.fhss_broadcast_interval) > (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval)) { + fhss_structure->ws->is_on_bc_channel = false; + } + delay_us %= MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval); + } + + if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) { + fhss_structure->ws->bc_slot %= fhss_structure->number_of_channels; + } + + if (fhss_structure->ws->is_on_bc_channel == false) { + fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler); fhss_structure->ws->is_on_bc_channel = true; next_channel = fhss_structure->ws->bc_channel = fhss_ws_calc_bc_channel(fhss_structure); @@ -315,7 +358,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay) } else { fhss_structure->ws->unicast_start_time_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api); uint32_t timeout = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval); - fhss_ws_start_timer(fhss_structure, timeout - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler); + fhss_ws_start_timer(fhss_structure, timeout - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler); fhss_structure->ws->is_on_bc_channel = false; // Should return to own (unicast) listening channel after broadcast channel next_channel = fhss_structure->rx_channel; @@ -413,8 +456,10 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_ { uint8_t dwell_time = fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval; uint16_t cur_slot = fhss_structure->ws->uc_slot; - if (cur_slot == 0) { - cur_slot = fhss_structure->number_of_uc_channels; + if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_TR51CF) { + if (cur_slot == 0) { + cur_slot = fhss_structure->number_of_uc_channels; + } } cur_slot--; uint32_t remaining_time_ms = 0; @@ -497,6 +542,8 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat fhss_stop_timer(fhss_structure, fhss_unicast_handler); fhss_stop_timer(fhss_structure, fhss_broadcast_handler); fhss_structure->ws->broadcast_timer_running = false; + fhss_structure->ws->is_on_bc_channel = false; + fhss_structure->ws->synchronization_time = 0; } fhss_structure->fhss_state = fhss_state; @@ -570,15 +617,11 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a } if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { fhss_ws_neighbor_timing_info_t *neighbor_timing_info = fhss_structure->ws->get_neighbor_info(api, destination_address); - if (!neighbor_timing_info) { + if (!neighbor_timing_info || neighbor_timing_info->uc_timing_info.unicast_number_of_channels == 0) { fhss_stats_update(fhss_structure, STATS_FHSS_UNKNOWN_NEIGHBOR, 1); return -2; } - if (neighbor_timing_info->uc_timing_info.unicast_number_of_channels == 0) { - return -1; - } - uint16_t destination_slot = fhss_ws_calculate_destination_slot(neighbor_timing_info, tx_time); int32_t tx_channel = neighbor_timing_info->uc_timing_info.fixed_channel; if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_TR51CF) { @@ -896,18 +939,34 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay) { + (void) delay; uint32_t timeout = 0; fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); if (!fhss_structure) { return; } + int32_t delay_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) - fhss_structure->ws->next_uc_timeout; + if (!fhss_structure->ws->uc_slot && !fhss_structure->ws->next_uc_timeout) { + delay_us = 0; + } + + // If callback was delayed longer than dwell time, UC slot must be updated + if ((fhss_structure->ws->fhss_configuration.ws_uc_channel_function != WS_FIXED_CHANNEL)) { + fhss_structure->ws->uc_slot += US_TO_MS(delay_us) / fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval; + if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_TR51CF) { + fhss_structure->ws->uc_slot %= fhss_structure->number_of_uc_channels; + } + } + delay_us %= MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval); + + timeout = fhss_ws_get_sf_timeout_callback(fhss_structure); if (!timeout) { fhss_stop_timer(fhss_structure, fhss_unicast_handler); fhss_structure->ws->unicast_timer_running = false; return; } - fhss_ws_start_timer(fhss_structure, timeout - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_unicast_handler); + fhss_ws_start_timer(fhss_structure, timeout - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_unicast_handler); fhss_structure->ws->unicast_timer_running = true; fhss_ws_update_uc_channel_callback(fhss_structure); // Unless we have broadcast schedule, we have to poll unicast queue when changing channel. This is randomized by the unicast schedule. diff --git a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.h b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.h index 26b8f4c969fe..b9e35665ecf3 100644 --- a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.h +++ b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.h @@ -40,6 +40,8 @@ struct fhss_ws { int32_t drift_per_millisecond_ns; int16_t *tr51_channel_table; uint8_t *tr51_output_table; + uint32_t next_uc_timeout; + uint32_t next_bc_timeout; bool unicast_timer_running; bool broadcast_timer_running; bool is_on_bc_channel; diff --git a/features/nanostack/sal-stack-nanostack/source/nsconfig.h b/features/nanostack/sal-stack-nanostack/source/nsconfig.h index dff8a5622d48..dfb182a5affb 100644 --- a/features/nanostack/sal-stack-nanostack/source/nsconfig.h +++ b/features/nanostack/sal-stack-nanostack/source/nsconfig.h @@ -54,6 +54,13 @@ #endif #endif /* HAVE_WS */ +/* Configure trace level for Nanostack */ +#ifdef MBED_CONF_NANOSTACK_TRACE_MAX_LEVEL +#ifdef MBED_TRACE_MAX_LEVEL +#undef MBED_TRACE_MAX_LEVEL +#endif /* MBED_TRACE_MAX_LEVEL */ +#define MBED_TRACE_MAX_LEVEL MBED_CONF_NANOSTACK_TRACE_MAX_LEVEL +#endif /* MBED_CONF_NANOSTACK_TRACE_MAX_LEVEL */ #endif // ifndef _NANOSTACK_SOURCE_CONFIG_H