From b9f37539182bfa5002208dba6885293e17700849 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Oct 2020 15:05:29 +0300 Subject: [PATCH] Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from d879e6db87..09d9e24f2d 09d9e24f2d Merge branch 'release_internal' into release_external 9a3278a1e3 Removed Black list reject from wi-sun neighbour request function 76fc9d77a1 Support SLAAC addressing method for Wi-SUN Border router 71c8bde863 Modified Wi-SUN etx to wait for Probes b720fbdfe0 Wi-SUN discovery and address registration update e73c8082ed Merge pull request #2460 from ARMmbed/sync_with_mbed_os 7994d9537b If PMK and PTK are not set do not store keys to NVM f8813e2d27 Follow Mbed OS coding style f6ed87754c (via mbedos) Possible invalid memory access on memcpy 40dc215294 Set frame counter increment to 1000000 a57acc84a8 ETX update 5373de2ff4 EAPOL parent TX feilure is reorder candidate list. 6b0e264869 Allowed separate default settings in WS API 850252b9f9 Fixed EAPOL brodcast synch at border router device. 2c1c07779a Corrected unit test 16e38ce688 Changed EAPOL negotiation limit on small nw to 20 21af9233ec Wi-sun ETX update 80e13f4435 Changed EAP-TLS retry trace to info trace level 52a5018fd1 WS: Use special retry configuration when discovery is started (#2450) 7e3b99c375 Merge branch 'release_internal' into release_external 50b7a641b4 Key update to MAC is forced when nw name changes f1f46f3873 Corrected identifier range alloc and added define for timeout f836d1d818 FHSS WS: spread broadcast messages better on BC channel (#2449) 9a1b35398c Merge branch 'release_internal' into release_external 5e40cb3852 Fix 0 length domain search list f0f5131833 Fixed coverity issue. 81b94e535d Added test harness API for set temporary neighbour lifetime longer b969fa3779 Merge branch 'release_internal' into release_external b66b834d0c Timed parent selection update git-subtree-dir: connectivity/nanostack/sal-stack-nanostack git-subtree-split: 09d9e24f2d3e97cd38139e5df3d9e79d2ee65f4e --- nanostack/net_ws_test.h | 13 ++ nanostack/ws_bbr_api.h | 1 + source/6LoWPAN/ws/ws_bbr_api.c | 15 +- source/6LoWPAN/ws/ws_bootstrap.c | 136 ++++++++++++------ source/6LoWPAN/ws/ws_cfg_settings.c | 27 +++- source/6LoWPAN/ws/ws_cfg_settings.h | 6 + source/6LoWPAN/ws/ws_common.c | 30 ++-- source/6LoWPAN/ws/ws_common.h | 1 + source/6LoWPAN/ws/ws_common_defines.h | 12 +- source/6LoWPAN/ws/ws_config.h | 6 +- source/6LoWPAN/ws/ws_empty_functions.c | 22 +++ source/6LoWPAN/ws/ws_llc_data_service.c | 4 +- source/6LoWPAN/ws/ws_management_api.c | 104 ++++++++++++-- source/6LoWPAN/ws/ws_pae_auth.c | 27 ++-- source/6LoWPAN/ws/ws_pae_auth.h | 3 +- source/6LoWPAN/ws/ws_pae_controller.c | 38 +++-- source/6LoWPAN/ws/ws_pae_key_storage.c | 12 +- source/6LoWPAN/ws/ws_pae_supp.c | 18 +-- source/6LoWPAN/ws/ws_pae_supp.h | 3 +- source/6LoWPAN/ws/ws_test_api.c | 13 ++ source/MAC/IEEE802_15_4/mac_mcps_sap.c | 3 + source/RPL/rpl_structures.h | 1 + source/RPL/rpl_upward.c | 8 +- .../radius_eap_tls_sec_prot.c | 4 +- .../radius_sec_prot/radius_client_sec_prot.c | 16 ++- source/Security/protocols/sec_prot_keys.c | 30 +++- source/Security/protocols/sec_prot_keys.h | 11 +- source/Security/protocols/sec_prot_lib.c | 24 ++-- source/Service_Libs/etx/etx.c | 92 ++++++++++-- source/Service_Libs/etx/etx.h | 11 ++ source/Service_Libs/fhss/fhss_ws.c | 10 +- source/libNET/src/net_dns.c | 16 ++- 32 files changed, 554 insertions(+), 163 deletions(-) diff --git a/nanostack/net_ws_test.h b/nanostack/net_ws_test.h index 3dfe75d875..6bd20c658a 100644 --- a/nanostack/net_ws_test.h +++ b/nanostack/net_ws_test.h @@ -204,6 +204,19 @@ void ws_test_skip_edfe_data_send(int8_t interface_id, bool skip); */ int8_t ws_test_drop_edfe_data_frames(int8_t interface_id, uint8_t number_of_dropped_frames); +/** + * Set neighbour temporary timeout value. + * + * Made only for test purpose for test EDFE certificatiomn test harness. + * + * \param interface_id Network interface ID. + * \param temporary_lifetime 0 to disable test harness, 240-2200 enable longer temporary neighbour lifetime. Values bigger than 2200 will be capped to 2200. + * + * \return 0 Success + * \return <0 Failure + */ +int ws_test_neighbour_temporary_lifetime_set(int8_t interface_id, uint32_t temporary_lifetime); + #ifdef __cplusplus } #endif diff --git a/nanostack/ws_bbr_api.h b/nanostack/ws_bbr_api.h index 85c4fd3d59..9c1e4a03cb 100644 --- a/nanostack/ws_bbr_api.h +++ b/nanostack/ws_bbr_api.h @@ -97,6 +97,7 @@ int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id); #define BBR_BB_WAIT 0x0004 /**< Wait backbone availability before starting Wi-SUN network */ #define BBR_DEFAULT_ROUTE 0x0008 /**< Add default route parameter to DIO */ #define BBR_REQUIRE_DAO_REFRESH 0x0010 /**< Do not increment PAN version number when active forces DAO update from nodes*/ +#define BBR_GUA_SLAAC 0x0020 /**< in Global prefix use SLAAC address generation to reduce traffic during bootstrap */ /** * Configure border router features. diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index eedd4ea623..83560e9298 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -492,6 +492,8 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) uint8_t local_prefix[8] = {0}; uint8_t global_prefix[8] = {0}; + uint8_t prefix_flags = 0; + uint32_t prefix_lifetime = 0; //tr_info("BBR status check"); @@ -596,7 +598,6 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) } // TODO add global prefix if (memcmp(global_prefix, ADDR_UNSPECIFIED, 8) != 0) { - tr_info("RPL global prefix activate %s", trace_ipv6_prefix(global_prefix, 64)); // Add default route to RPL // Enable default routing to backbone @@ -606,8 +607,12 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) return; } } + if (configuration & BBR_GUA_SLAAC) { + prefix_flags |= PIO_A; + prefix_lifetime = WS_ULA_LIFETIME; + } ws_bbr_dhcp_server_start(cur, global_prefix, cur->ws_info->cfg->bbr.dhcp_address_lifetime); - rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, 0, 0, 0, false); + rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_prefix, 64, prefix_flags, prefix_lifetime, prefix_lifetime, false); // no check for failure should have if (configuration & BBR_GUA_ROUTE) { @@ -626,7 +631,11 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) * There is no status checks on prefix adds so this makes sure they are not lost * DHCP validation should be done also */ - rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, 0, 0, false); + if (configuration & BBR_GUA_SLAAC) { + prefix_flags |= PIO_A; + prefix_lifetime = WS_ULA_LIFETIME; + } + rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, prefix_flags, prefix_lifetime, prefix_lifetime, false); if (configuration & BBR_GUA_ROUTE) { // Add also global prefix and route to RPL diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 808acb7bf2..a2f8a06158 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -110,6 +110,7 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur); static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create); +static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry); typedef enum { WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/ @@ -139,8 +140,8 @@ mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interf } // TODO only call these for new neighbour mlme_device_descriptor_t device_desc; - neighbor->lifetime = WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME; - neighbor->link_lifetime = WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME; + neighbor->lifetime = ws_cfg_neighbour_temporary_lifetime_get(); + neighbor->link_lifetime = ws_cfg_neighbour_temporary_lifetime_get(); mac_helper_device_description_write(interface, &device_desc, neighbor->mac64, neighbor->mac16, 0, false); mac_helper_devicetable_set(&device_desc, interface, neighbor->index, interface->mac_parameters->mac_default_key_index, true); @@ -289,6 +290,20 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_ } } +static void ws_bootstrap_configure_max_retries(protocol_interface_info_entry_t *cur, uint8_t max_mac_retries, uint8_t max_channel_retries) +{ + mac_helper_mac_mlme_max_retry_set(cur->id, max_mac_retries); + + const fhss_ws_configuration_t *fhss_configuration_cur = ns_fhss_ws_configuration_get(cur->ws_info->fhss_api); + if (fhss_configuration_cur && fhss_configuration_cur->config_parameters.number_of_channel_retries != max_channel_retries) { + fhss_ws_configuration_t fhss_configuration; + memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); + memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); + fhss_configuration.config_parameters.number_of_channel_retries = max_channel_retries; + ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); + } +} + static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur) { if (cur->bootStrapId < 0) { @@ -601,7 +616,6 @@ static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur) fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->cfg->fhss.fhss_bc_channel_function; fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->cfg->fhss.fhss_bc_dwell_interval; fhss_configuration.fhss_broadcast_interval = cur->ws_info->cfg->fhss.fhss_bc_interval; - fhss_configuration.config_parameters.number_of_channel_retries = WS_NUMBER_OF_CHANNEL_RETRIES; fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr); if (!fhss_api) { @@ -765,7 +779,7 @@ static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, llc_neighbour_req_t *neighbor_info) { - if (cur->ws_info->configuration_learned || !neighbor_info->ws_neighbor->broadcast_shedule_info_stored || !neighbor_info->ws_neighbor->broadcast_timing_info_stored) { + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || cur->ws_info->configuration_learned || !neighbor_info->ws_neighbor->broadcast_shedule_info_stored || !neighbor_info->ws_neighbor->broadcast_timing_info_stored) { return; } @@ -820,6 +834,7 @@ static void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entr */ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr_type, const uint8_t *addr_ptr) { + uint16_t etx; if (!addr_ptr || !interface) { return 0; @@ -839,7 +854,16 @@ uint16_t ws_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr return 0xffff; } - return etx_local_etx_read(interface->id, attribute_index); + etx = etx_local_etx_read(interface->id, attribute_index); + + // If we dont have valid ETX for children we assume good ETX. + // After enough packets is sent to children real calculated ETX is given. + // This might result in ICMP source route errors returned to Border router causing secondary route uses + if (etx == 0xffff && ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, mac_neighbor->mac64)) { + return 0x100; + } + + return etx; } bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_t *entry, bool unicast, uint8_t seq) { @@ -1152,7 +1176,7 @@ static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interf static parent_info_t *ws_bootstrap_candidate_parent_get_best(protocol_interface_info_entry_t *cur) { ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { - tr_info("candidate list a:%s panid:%x cost:%d size:%d rssi:%d age:%"PRIu32, trace_array(entry->addr, 8), entry->pan_id, entry->pan_information.routing_cost, entry->pan_information.pan_size, entry->signal_dbm, protocol_core_monotonic_time - entry->age); + tr_info("candidate list a:%s panid:%x cost:%d size:%d rssi:%d txFailure:%u age:%"PRIu32, trace_array(entry->addr, 8), entry->pan_id, entry->pan_information.routing_cost, entry->pan_information.pan_size, entry->signal_dbm, entry->tx_fail, protocol_core_monotonic_time - entry->age); } return ns_list_get_first(&cur->ws_info->parent_list_reserved); @@ -1250,21 +1274,14 @@ static parent_info_t *ws_bootstrap_candidate_parent_allocate(protocol_interface_ } else { // If there is no free entries always allocate the last one of reserved as it is the worst entry = ns_list_get_last(&cur->ws_info->parent_list_reserved); + + } + if (entry) { + entry->tx_fail = 0; } return entry; } -static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, const uint8_t *addr) -{ - ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { - if (memcmp(entry->addr, addr, 8) == 0) { - ns_list_remove(&cur->ws_info->parent_list_reserved, entry); - ns_list_add_to_end(&cur->ws_info->parent_list_free, entry); - return; - } - } -} - static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create) { ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { @@ -1278,6 +1295,23 @@ static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interfac return NULL; } +static void ws_bootstrap_candidate_parent_mark_failure(protocol_interface_info_entry_t *cur, const uint8_t *addr) +{ + parent_info_t *entry = ws_bootstrap_candidate_parent_get(cur, addr, false); + if (entry) { + ns_list_remove(&cur->ws_info->parent_list_reserved, entry); + if (entry->tx_fail >= 2) { + ns_list_add_to_end(&cur->ws_info->parent_list_free, entry); + } else { + entry->tx_fail++; + //New last + ns_list_add_to_end(&cur->ws_info->parent_list_reserved, entry); + ws_bootstrap_candidate_parent_sort(cur, entry); + } + + } +} + static bool ws_bootstrap_candidate_parent_compare(parent_info_t *p1, parent_info_t *p2) { // Return true if P2 is better @@ -1285,6 +1319,10 @@ static bool ws_bootstrap_candidate_parent_compare(parent_info_t *p1, parent_info // pan_cost // signal quality + if (p2->tx_fail > p1->tx_fail) { + return false; + } + if (ws_neighbor_class_rsl_from_dbm_calculate(p1->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) && ws_neighbor_class_rsl_from_dbm_calculate(p2->signal_dbm) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) { // above threshold is always better than not. @@ -1336,11 +1374,15 @@ static void ws_bootstrap_candidate_list_clean(struct protocol_interface_info_ent static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry) { + //Remove from the list + ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) { + if (entry == new_entry) { // own entry skip it continue; } + if (ws_bootstrap_candidate_parent_compare(entry, new_entry)) { // New entry is better //tr_debug("candidate list new is better"); @@ -1550,7 +1592,6 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry } if (neighbour_pointer_valid) { - etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64); //Update Neighbor Broadcast and Unicast Parameters ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); @@ -1639,7 +1680,6 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in llc_neighbour_req_t neighbor_info; if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { - etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64); ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); } @@ -1828,7 +1868,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent continue; } - if (cur->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (cur->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { continue; } @@ -1901,14 +1941,6 @@ static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_en return false; } - uint8_t ll_target[16]; - ws_bootsrap_create_ll_address(ll_target, mac_64); - - if (blacklist_reject(ll_target)) { - // Rejected by blacklist - return false; - } - ws_bootstrap_neighbor_table_clean(interface); neighbor_buffer->neighbor = ws_bootstrap_mac_neighbor_add(interface, mac_64); @@ -1948,6 +1980,15 @@ static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_pt ws_bootstrap_neighbor_delete(cur, entry_ptr); } +static uint32_t ws_probe_init_time_get(protocol_interface_info_entry_t *cur) +{ + if (cur->ws_info->cfg->gen.network_size <= NETWORK_SIZE_SMALL) { + return WS_SMALL_PROBE_INIT_BASE_SECONDS; + } + + return WS_NORMAL_PROBE_INIT_BASE_SECONDS; +} + static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { uint32_t time_from_start = entry_ptr->link_lifetime - entry_ptr->lifetime; @@ -1959,7 +2000,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, entry_ptr->index); etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, entry_ptr->index); - if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send || entry_ptr->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send || entry_ptr->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { return false; } @@ -2000,17 +2041,23 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, nud_proces = activate_nud; } else if (etx_entry->etx_samples < WS_NEIGHBOR_ETX_SAMPLE_MAX) { //Take Random number for trig a prope. + //Small network + //ETX Sample 0: random 1-4 + //ETX Sample 1: random 2-8 + //ETX Sample 2: random 4-16 + //Medium and large //ETX Sample 0: random 1-8 //ETX Sample 1: random 2-16 //ETX Sample 2: random 4-32 + ws_bootsrap_create_ll_address(ll_address, entry_ptr->mac64); if (!rpl_control_probe_parent_candidate(cur, ll_address)) { return false; } - - uint32_t probe_period = WS_PROBE_INIT_BASE_SECONDS << etx_entry->etx_samples; + uint32_t probe_period = ws_probe_init_time_get(cur) << etx_entry->etx_samples; uint32_t time_block = 1 << etx_entry->etx_samples; + if (time_from_start >= probe_period) { //tr_debug("Link Probe test %u Sample trig", etx_entry->etx_samples); activate_nud = true; @@ -2073,6 +2120,11 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) return -1; } + if (!etx_allow_drop_for_poor_measurements(WS_ETX_BAD_INIT_LINK_LEVEL, WS_ETX_MAX_BAD_LINK_DROP)) { + etx_storage_list_allocate(cur->id, 0); + return -1; + } + etx_max_update_set(WS_ETX_MAX_UPDATE); etx_max_set(WS_ETX_MAX); @@ -2182,8 +2234,6 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) set_req.value_size = sizeof(bool); cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req); - mac_helper_mac_mlme_max_retry_set(cur->id, WS_MAX_FRAME_RETRIES); - // Set the default parameters for MPL cur->mpl_proactive_forwarding = true; @@ -2443,7 +2493,8 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) } ws_set_fhss_hop(cur); - + // Set retry configuration for bootstrap ready state + ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES, WS_NUMBER_OF_CHANNEL_RETRIES); } else if (event == RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS) { /* * RPL goes to passive mode, but does not require any extra changed @@ -2643,8 +2694,6 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, ws_bootstrap_neighbor_set_stable(cur, entry->mac64); //Copy fhss temporary data *ws_neigh = entry->neigh_info_list; - //ETX Create here - etx_lqi_dbm_update(cur->id, entry->mpduLinkQuality, entry->signal_dbm, neigh_buffer.neighbor->index, neigh_buffer.neighbor->mac64); mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true); } ws_llc_free_multicast_temp_entry(cur, entry); @@ -2741,9 +2790,6 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) cur->ws_info->pan_timeout_timer = 0; cur->ws_info->weakest_received_rssi = 0; - // Clear learned neighbours - ws_bootstrap_neighbor_list_clean(cur); - // Clear learned candidate parents ws_bootstrap_candidate_table_reset(cur); @@ -2884,7 +2930,7 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_ // eapol parent selected is not working tr_debug("authentication TX failed"); - ws_bootstrap_candidate_parent_free(cur, target_eui_64); + ws_bootstrap_candidate_parent_mark_failure(cur, target_eui_64); // Go back for network scanning ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); @@ -2906,7 +2952,7 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_ static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id) { - ws_bootstrap_candidate_parent_free(cur, previous_eui_64); + ws_bootstrap_candidate_parent_mark_failure(cur, previous_eui_64); // Gets best target parent_info_t *parent_info = ws_bootstrap_candidate_parent_get_best(cur); @@ -3262,14 +3308,20 @@ static void ws_bootstrap_event_handler(arm_event_s *event) // Set PAE port to 10254 and authenticator relay to 10253 (and to own ll address) ws_pae_controller_authenticator_start(cur, PAE_AUTH_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT); + // Set retry configuration for bootstrap ready state + ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES, WS_NUMBER_OF_CHANNEL_RETRIES); + ws_bootstrap_event_operation_start(cur); break; } ws_pae_controller_supp_init(cur); - + // Clear learned neighbours + ws_bootstrap_neighbor_list_clean(cur); // Configure LLC for network discovery ws_bootstrap_network_discovery_configure(cur); ws_bootstrap_fhss_activate(cur); + // Set retry configuration for discovery state + ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES_BOOTSTRAP, WS_NUMBER_OF_CHANNEL_RETRIES_BOOTSTRAP); // Start network scan ws_bootstrap_start_discovery(cur); break; diff --git a/source/6LoWPAN/ws/ws_cfg_settings.c b/source/6LoWPAN/ws/ws_cfg_settings.c index 8eacf4802d..1898b426d8 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/source/6LoWPAN/ws/ws_cfg_settings.c @@ -55,6 +55,7 @@ typedef struct ws_cfg_nw_size_s { ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */ } ws_cfg_nw_size_t; +static uint32_t ws_test_temporary_entry_lifetime = 0; typedef int8_t (*ws_cfg_default_set)(void *cfg); typedef int8_t (*ws_cfg_validate)(void *cfg, void *new_cfg); typedef int8_t (*ws_cfg_set)(protocol_interface_info_entry_t *cur, void *cfg, void *new_cfg, uint8_t *flags); @@ -86,11 +87,8 @@ static void ws_cfg_network_size_config_set_xlarge(ws_cfg_nw_size_t *cfg); static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg); static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg); static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg); -static int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg); -static int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg); static int8_t ws_cfg_bbr_default_set(ws_bbr_cfg_t *cfg); static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg); -static int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg); static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg); static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg); @@ -600,7 +598,7 @@ int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, w return CFG_SETTINGS_OK; } -static int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg) +int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg) { // FHSS configuration cfg->regulatory_domain = REG_DOMAIN_EU; @@ -680,7 +678,7 @@ int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, w return CFG_SETTINGS_OK; } -static int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg) +int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg) { // Configure the Wi-SUN timing trickle parameters cfg->disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds @@ -900,7 +898,7 @@ int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *cfg, w return CFG_SETTINGS_OK; } -static int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg) +int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg) { // Set defaults for the device. user can modify these. cfg->fhss_uc_fixed_channel = 0xffff; @@ -1275,4 +1273,21 @@ int8_t ws_cfg_settings_set(protocol_interface_info_entry_t *cur, ws_cfg_t *new_c return ret_value; } +uint32_t ws_cfg_neighbour_temporary_lifetime_get(void) +{ + if (ws_test_temporary_entry_lifetime) { + return ws_test_temporary_entry_lifetime; + } + return WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME; +} +void ws_cfg_neighbour_temporary_lifetime_set(uint32_t lifetime) +{ + if (lifetime >= WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME || lifetime == 0) { + if (lifetime > WS_NEIGHBOR_LINK_TIMEOUT) { + lifetime = WS_NEIGHBOR_LINK_TIMEOUT; + } + ws_test_temporary_entry_lifetime = lifetime; + } +} + #endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_cfg_settings.h b/source/6LoWPAN/ws/ws_cfg_settings.h index bc46336229..48592b899a 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.h +++ b/source/6LoWPAN/ws/ws_cfg_settings.h @@ -159,10 +159,12 @@ int8_t ws_cfg_gen_get(ws_gen_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg); int8_t ws_cfg_gen_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg, uint8_t *flags); +int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg); int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg); int8_t ws_cfg_phy_set(protocol_interface_info_entry_t *cur, ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg, uint8_t *flags); +int8_t ws_cfg_timing_default_set(ws_timing_cfg_t *cfg); int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg); int8_t ws_cfg_timing_set(protocol_interface_info_entry_t *cur, ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg, uint8_t *flags); @@ -175,6 +177,7 @@ int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags); 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); +int8_t ws_cfg_fhss_default_set(ws_fhss_cfg_t *cfg); int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg); int8_t ws_cfg_fhss_set(protocol_interface_info_entry_t *cur, ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg, uint8_t *flags); @@ -187,4 +190,7 @@ int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg, uint8_t *flags); int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg); int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg, uint8_t *flags); +uint32_t ws_cfg_neighbour_temporary_lifetime_get(void); +void ws_cfg_neighbour_temporary_lifetime_set(uint32_t lifetime); + #endif // WS_CFG_STORAGE_H_ diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index b1d734a77a..5a242cfa4b 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -390,6 +390,24 @@ uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size) } } +static void ws_common_neighbour_address_reg_link_update(protocol_interface_info_entry_t *interface, const uint8_t *eui64) +{ + /* + * ARO registration from child can update the link timeout so we don't need to send extra NUD if ARO received + */ + mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, false, false); + + if (mac_neighbor) { + if (mac_neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + //Set Stable timeout for temporary entry here + mac_neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; + tr_info("Added new neighbor %s : index:%u", trace_array(eui64, 8), mac_neighbor->index); + } + //Refresh + mac_neighbor->lifetime = mac_neighbor->link_lifetime; + } +} + uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) { uint8_t child_count = 0; @@ -402,14 +420,7 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte //Validate Is EUI64 already allocated for any address if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, eui64)) { - /* - * ARO registration from child can update the link timeout so we don't need to send extra NUD if ARO received - */ - mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(interface), eui64, false, false); - - if (mac_neighbor) { - mac_neighbor_table_neighbor_refresh(mac_neighbor_info(interface), mac_neighbor, mac_neighbor->link_lifetime); - } + ws_common_neighbour_address_reg_link_update(interface, eui64); tr_info("Child registration from old child"); return ARO_SUCCESS; } @@ -431,7 +442,8 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); return ARO_FULL; } - ws_bootstrap_neighbor_set_stable(interface, eui64); + + ws_common_neighbour_address_reg_link_update(interface, eui64); tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); return ARO_SUCCESS; } diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 96a425c130..cb29ab6c35 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -42,6 +42,7 @@ typedef struct parent_info_s { uint16_t pan_id; /**< PAN ID */ uint8_t addr[8]; /**< address */ uint8_t link_quality; /**< LQI value measured during reception of the MPDU */ + uint8_t tx_fail; int8_t signal_dbm; /**< This extension for normal IEEE 802.15.4 Data indication */ ws_pan_information_t pan_information; ws_utt_ie_t ws_utt; diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 58f570f871..7ce70d0146 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -241,6 +241,7 @@ typedef struct ws_bs_ie { #define WS_NEIGHBOR_LINK_TIMEOUT 2200 +#define WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME 240 #define WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME 5 #define WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME 60 #define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE 520 @@ -254,7 +255,8 @@ typedef struct ws_bs_ie { #define WS_NEIGHBOR_ETX_SAMPLE_MAX 3 #define WS_NEIGHBOR_FIRST_ETX_SAMPLE_MIN_COUNT 3 //This can't be bigger than WS_NEIGHBOR_ETX_SAMPLE_MAX -#define WS_PROBE_INIT_BASE_SECONDS 8 +#define WS_SMALL_PROBE_INIT_BASE_SECONDS 4 +#define WS_NORMAL_PROBE_INIT_BASE_SECONDS 8 #define WS_NUD_RAND_PROBABILITY 1 @@ -269,6 +271,10 @@ typedef struct ws_bs_ie { #define WS_ETX_MIN_WAIT_TIME 60 +#define WS_ETX_BAD_INIT_LINK_LEVEL 3 //3 or higher attempt count will be dropped +#define WS_ETX_MAX_BAD_LINK_DROP 2 //Drop 2 bad link from init 3 + + #define WS_RPL_PARENT_CANDIDATE_MAX 5 #define WS_RPL_SELECTED_PARENT_MAX 2 @@ -321,8 +327,12 @@ typedef struct ws_bs_ie { * 3 4 1+3*1+4=20 * */ +// This configuration is used when bootstrap is ready #define WS_MAX_FRAME_RETRIES 3 #define WS_NUMBER_OF_CHANNEL_RETRIES 4 +// This configuration is used during bootstrap +#define WS_MAX_FRAME_RETRIES_BOOTSTRAP 0 +#define WS_NUMBER_OF_CHANNEL_RETRIES_BOOTSTRAP 19 #if (1 + WS_MAX_FRAME_RETRIES) * (1 + WS_NUMBER_OF_CHANNEL_RETRIES) < 20 diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 589724fda8..899b25afcd 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -174,8 +174,8 @@ extern uint8_t DEVICE_MIN_SENS; #define FRAME_COUNTER_STORE_INTERVAL 60 // Time interval (on seconds) between checking if frame counter storing is needed #define FRAME_COUNTER_STORE_FORCE_INTERVAL (3600 * 20) // Time interval (on seconds) before frame counter storing is forced (if no other storing operations triggered) #define FRAME_COUNTER_STORE_TRIGGER 5 // Delay (on seconds) before storing, when storing of frame counters is triggered -#define FRAME_COUNTER_INCREMENT 1000 // How much frame counter is incremented on start up -#define FRAME_COUNTER_STORE_THRESHOLD 800 // How much frame counter must increment before it is stored +#define FRAME_COUNTER_INCREMENT 1000000 // How much frame counter is incremented on start up +#define FRAME_COUNTER_STORE_THRESHOLD 994999 // How much frame counter must increment before it is stored /* @@ -219,7 +219,7 @@ extern uint8_t DEVICE_MIN_SENS; #define SEC_PROT_TIMER_EXPIRATIONS 2 // Number of retries // Maximum number of simultaneous security negotiations -#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL 3 +#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL 20 #define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM 20 #define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE 50 diff --git a/source/6LoWPAN/ws/ws_empty_functions.c b/source/6LoWPAN/ws/ws_empty_functions.c index 942eb00e40..990c423df8 100644 --- a/source/6LoWPAN/ws/ws_empty_functions.c +++ b/source/6LoWPAN/ws/ws_empty_functions.c @@ -422,4 +422,26 @@ int ws_device_min_sens_set( return -1; } +int ws_test_neighbour_temporary_lifetime_set(int8_t interface_id, uint32_t temporary_lifetime) +{ + (void) interface_id; + (void) temporary_lifetime; + return -1; +} + +void ws_test_skip_edfe_data_send(int8_t interface_id, bool skip) +{ + (void) interface_id; + (void) skip; +} + + +int8_t ws_test_drop_edfe_data_frames(int8_t interface_id, uint8_t number_of_dropped_frames) +{ + (void) interface_id; + (void) number_of_dropped_frames; + return -1; +} + + #endif // no HAVE_WS diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index d20f9980c9..306c90eed1 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -537,7 +537,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * ws_llc_mpx_eapol_send(base, message); } } else { - if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime < WS_NEIGHBOUR_TEMPORARY_NEIGH_MAX_LIFETIME) { //Remove temp neighbour tr_debug("Remove Temp Entry by TX confirm"); mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor); @@ -729,8 +729,6 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_ ws_neighbor_class_rsl_in_calculate(neighbor_info.ws_neighbor, data->signal_dbm); if (neighbor_info.neighbor) { - //Refresh ETX dbm - etx_lqi_dbm_update(interface->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64); if (data->Key.SecurityLevel) { //SET trusted state mac_neighbor_table_trusted_neighbor(mac_neighbor_info(interface), neighbor_info.neighbor, true); diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index 5215f2c8d9..135db220af 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -170,18 +170,29 @@ int ws_management_regulatory_domain_set( } ws_phy_cfg_t cfg; + ws_phy_cfg_t cfg_default; if (ws_cfg_phy_get(&cfg, NULL) < 0) { return -3; } + if (ws_cfg_phy_default_set(&cfg_default) < 0) { + return -3; + } + if (regulatory_domain != 255) { cfg.regulatory_domain = regulatory_domain; + } else { + cfg.regulatory_domain = cfg_default.regulatory_domain; } if (operating_mode != 255) { cfg.operating_mode = operating_mode; + } else { + cfg.operating_mode = cfg_default.operating_mode; } if (operating_class != 255) { cfg.operating_class = operating_class; + } else { + cfg.operating_class = cfg_default.operating_class; } if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) { @@ -334,7 +345,18 @@ int ws_management_channel_mask_set( return -2; } - memcpy(cfg.fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8); + ws_fhss_cfg_t cfg_default; + if (ws_cfg_fhss_default_set(&cfg_default) < 0) { + return -2; + } + + if (channel_mask) { + memcpy(cfg.fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8); + } else { + // Use the default + memcpy(cfg.fhss_channel_mask, cfg_default.fhss_channel_mask, sizeof(uint32_t) * 8); + } + if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { return -3; @@ -434,14 +456,27 @@ int ws_management_fhss_timing_configure( return -2; } + ws_fhss_cfg_t cfg_default; + if (ws_cfg_fhss_default_set(&cfg_default) < 0) { + return -2; + } + if (fhss_uc_dwell_interval > 0) { cfg.fhss_uc_dwell_interval = fhss_uc_dwell_interval; + } else if (fhss_uc_dwell_interval == 0xff) { + cfg.fhss_uc_dwell_interval = cfg_default.fhss_uc_dwell_interval; } + if (fhss_broadcast_interval > 0) { cfg.fhss_bc_interval = fhss_broadcast_interval; + } else if (fhss_broadcast_interval == 0xffff) { + cfg.fhss_bc_interval = cfg_default.fhss_bc_interval; } + if (fhss_bc_dwell_interval > 0) { cfg.fhss_bc_dwell_interval = fhss_bc_dwell_interval; + } else if (fhss_bc_dwell_interval == 0xff) { + cfg.fhss_bc_dwell_interval = cfg_default.fhss_bc_dwell_interval; } if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { @@ -469,12 +504,27 @@ int ws_management_fhss_unicast_channel_function_configure( return -2; } - if (dwell_interval > 0) { - cfg.fhss_uc_dwell_interval = dwell_interval; + ws_fhss_cfg_t cfg_default; + if (ws_cfg_fhss_default_set(&cfg_default) < 0) { + return -2; } - cfg.fhss_uc_channel_function = channel_function; - cfg.fhss_uc_fixed_channel = fixed_channel; + if (dwell_interval > 0) { + cfg.fhss_uc_dwell_interval = dwell_interval; + } else { + cfg.fhss_uc_dwell_interval = cfg_default.fhss_uc_dwell_interval; + } + if (channel_function < 0xff) { + cfg.fhss_uc_channel_function = channel_function; + } else { + cfg.fhss_uc_channel_function = cfg_default.fhss_uc_channel_function; + } + + if (fixed_channel < 0xffff) { + cfg.fhss_uc_fixed_channel = fixed_channel; + } else { + cfg.fhss_uc_fixed_channel = cfg_default.fhss_uc_fixed_channel; + } if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { return -3; @@ -556,16 +606,34 @@ int ws_management_fhss_broadcast_channel_function_configure( if (ws_cfg_fhss_get(&cfg, NULL) < 0) { return -2; } + ws_fhss_cfg_t cfg_default; + if (ws_cfg_fhss_default_set(&cfg_default) < 0) { + return -2; + } if (dwell_interval > 0) { cfg.fhss_bc_dwell_interval = dwell_interval; - } - if (broadcast_interval > 0) { - cfg.fhss_bc_interval = broadcast_interval; + } else { + cfg.fhss_bc_dwell_interval = cfg_default.fhss_bc_dwell_interval; } - cfg.fhss_bc_channel_function = channel_function; - cfg.fhss_bc_fixed_channel = fixed_channel; + if (broadcast_interval > 0) { + cfg.fhss_bc_interval = broadcast_interval; + } else { + cfg.fhss_bc_interval = cfg_default.fhss_bc_interval; + } + + if (channel_function != 0xff) { + cfg.fhss_bc_channel_function = channel_function; + } else { + cfg.fhss_bc_channel_function = cfg_default.fhss_bc_channel_function; + } + + if (fixed_channel != 0xffff) { + cfg.fhss_bc_fixed_channel = fixed_channel; + } else { + cfg.fhss_bc_fixed_channel = cfg_default.fhss_bc_fixed_channel; + } if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { return -3; @@ -652,17 +720,33 @@ int ws_management_timing_parameters_set( return -2; } + ws_timing_cfg_t cfg_default; + if (ws_cfg_timing_default_set(&cfg_default) < 0) { + return -2; + } + if (disc_trickle_imin > 0) { cfg.disc_trickle_imin = disc_trickle_imin; + } else { + cfg.disc_trickle_imin = cfg_default.disc_trickle_imin; } + if (disc_trickle_imax > 0) { cfg.disc_trickle_imax = disc_trickle_imax; + } else { + cfg.disc_trickle_imax = cfg_default.disc_trickle_imax;; } + if (disc_trickle_k > 0) { cfg.disc_trickle_k = disc_trickle_k; + } else { + cfg.disc_trickle_k = cfg_default.disc_trickle_k;; } + if (pan_timeout > 0) { cfg.pan_timeout = pan_timeout; + } else { + cfg.pan_timeout = cfg_default.pan_timeout;; } if (ws_cfg_timing_set(cur, NULL, &cfg, 0) < 0) { diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index 448127abb7..942f44379d 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -108,7 +108,7 @@ typedef struct { bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */ } pae_auth_t; -static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth); +static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth, bool force_install); static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index); static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index); static void ws_pae_auth_free(pae_auth_t *pae_auth); @@ -345,7 +345,7 @@ void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr) pae_auth->nw_info_updated(pae_auth->interface_ptr); // Inserts keys and updates GTK hash on stack - ws_pae_auth_network_keys_from_gtks_set(pae_auth); + ws_pae_auth_network_keys_from_gtks_set(pae_auth, false); // Sets active key index ws_pae_auth_network_key_index_set(pae_auth, index); @@ -362,7 +362,7 @@ void ws_pae_auth_gtks_updated(protocol_interface_info_entry_t *interface_ptr) return; } - ws_pae_auth_network_keys_from_gtks_set(pae_auth); + ws_pae_auth_network_keys_from_gtks_set(pae_auth, false); } int8_t ws_pae_auth_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index) @@ -440,7 +440,7 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int // If active GTK lifetime is larger than revocation lifetime decrements active GTK lifetime if (active_lifetime > revocation_lifetime) { - sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, active_index, current_time, active_lifetime - revocation_lifetime); + sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, active_index, current_time, active_lifetime - revocation_lifetime, true); tr_info("Access revocation start, GTK active index: %i, revoked lifetime: %"PRIu32"", active_index, revocation_lifetime); } else { // Otherwise decrements lifetime of the GTK to be installed after the active one @@ -451,7 +451,7 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int uint32_t second_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, second_index); if (second_lifetime > second_revocation_lifetime) { - sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, second_index, current_time, second_lifetime - second_revocation_lifetime); + sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, second_index, current_time, second_lifetime - second_revocation_lifetime, true); tr_info("Access revocation start, GTK second active index: %i, revoked lifetime: %"PRIu32"", second_index, second_revocation_lifetime); } // Removes other keys than active and GTK to be installed next @@ -470,7 +470,7 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int // Adds new GTK ws_pae_auth_gtk_key_insert(pae_auth); - ws_pae_auth_network_keys_from_gtks_set(pae_auth); + ws_pae_auth_network_keys_from_gtks_set(pae_auth, false); // Update keys to NVM as needed pae_auth->nw_info_updated(pae_auth->interface_ptr); @@ -535,8 +535,11 @@ int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, u } pae_auth->pan_id = pan_id; + bool force_install = false; if (strlen((char *) &pae_auth->network_name) > 0 && strcmp((char *) &pae_auth->network_name, network_name) != 0) { update_keys = true; + // Force GTK install to update the new network name to GAK + force_install = true; } strcpy((char *) &pae_auth->network_name, network_name); @@ -548,7 +551,7 @@ int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, u pae_auth->nw_keys_remove(pae_auth->interface_ptr); } - ws_pae_auth_network_keys_from_gtks_set(pae_auth); + ws_pae_auth_network_keys_from_gtks_set(pae_auth, force_install); int8_t index = sec_prot_keys_gtk_status_active_get(pae_auth->sec_keys_nw_info->gtks); if (index >= 0) { @@ -559,7 +562,7 @@ int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, u return 0; } -static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth) +static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth, bool force_install) { // Authenticator keys are always fresh sec_prot_keys_gtk_status_all_fresh_set(pae_auth->sec_keys_nw_info->gtks); @@ -571,7 +574,7 @@ static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth) } if (pae_auth->nw_key_insert) { - pae_auth->nw_key_insert(pae_auth->interface_ptr, pae_auth->sec_keys_nw_info->gtks); + pae_auth->nw_key_insert(pae_auth->interface_ptr, pae_auth->sec_keys_nw_info->gtks, force_install); } return 0; @@ -707,7 +710,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds) if (!sec_prot_keys_gtk_is_set(pae_auth->sec_keys_nw_info->gtks, i)) { continue; } - uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds); + uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds, true); if (active_index == i) { if (!pae_auth->gtk_new_inst_req_exp) { pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_cfg, timer_seconds); @@ -716,7 +719,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds) if (second_index < 0) { tr_info("GTK new install required active index: %i, time: %"PRIu32", system time: %"PRIu32"", active_index, timer_seconds, protocol_core_monotonic_time / 10); ws_pae_auth_gtk_key_insert(pae_auth); - ws_pae_auth_network_keys_from_gtks_set(pae_auth); + ws_pae_auth_network_keys_from_gtks_set(pae_auth, false); // Update keys to NVM as needed pae_auth->nw_info_updated(pae_auth->interface_ptr); } else { @@ -744,7 +747,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds) if (timer_seconds == 0) { tr_info("GTK expired index: %i, system time: %"PRIu32"", i, protocol_core_monotonic_time / 10); ws_pae_auth_gtk_clear(pae_auth, i); - ws_pae_auth_network_keys_from_gtks_set(pae_auth); + ws_pae_auth_network_keys_from_gtks_set(pae_auth, false); // Update keys to NVM as needed pae_auth->nw_info_updated(pae_auth->interface_ptr); } diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index fc1030a750..d302aeaf0f 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -207,12 +207,13 @@ typedef void ws_pae_auth_gtk_hash_set(protocol_interface_info_entry_t *interface * * \param interface_ptr interface * \param gtks group keys + * \param force_install TRUE force install keys, FALSE install keys only if GTKs has changed * * \return < 0 failure * \return >= 0 success * */ -typedef int8_t ws_pae_auth_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks); +typedef int8_t ws_pae_auth_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, bool force_install); /** * ws_pae_auth_nw_keys_remove remove network keys callback diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index e222d825da..0a7a0650d7 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -126,7 +126,7 @@ static void ws_pae_controller_nvm_frame_counter_write(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); -static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks); +static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, bool force_install); static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key); static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index); static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name); @@ -137,6 +137,7 @@ static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info static void ws_pae_controller_data_init(pae_controller_t *controller); static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller); static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters); +static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_counters, uint8_t index); static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks); 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); 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); @@ -165,7 +166,7 @@ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface // In case test keys are set uses those and does not initiate authentication if (controller->gtks_set) { if (sec_prot_keys_gtks_are_updated(&controller->gtks)) { - ws_pae_controller_nw_key_check_and_insert(controller->interface_ptr, &controller->gtks); + ws_pae_controller_nw_key_check_and_insert(controller->interface_ptr, &controller->gtks, false); sec_prot_keys_gtks_updated_reset(&controller->gtks); ws_pae_supp_gtks_set(controller->interface_ptr, &controller->gtks); } @@ -403,7 +404,7 @@ int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface return ws_pae_supp_nw_key_valid(interface_ptr, br_iid); } -static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks) +static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, bool force_install) { pae_controller_t *controller = ws_pae_controller_get(interface_ptr); if (!controller) { @@ -429,6 +430,13 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_ tr_info("NW key remove: %i", i); } + if (force_install) { + // Install always + nw_key[i].installed = false; + // Frame counters are fresh + ws_pae_controller_frame_counter_index_reset(&controller->frame_counters, i); + } + // If GTK key is not set, continues to next GTK if (!gtk) { continue; @@ -775,8 +783,14 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller) // Checks frame counters for (uint8_t index = 0; index < GTK_NUM; index++) { if (controller->frame_counters.counter[index].set) { - // Increments frame counters - controller->frame_counters.counter[index].frame_counter += FRAME_COUNTER_INCREMENT; + // If there is room on frame counter space + if (controller->frame_counters.counter[index].frame_counter < (UINT32_MAX - FRAME_COUNTER_INCREMENT * 2)) { + // Increments frame counters + controller->frame_counters.counter[index].frame_counter += FRAME_COUNTER_INCREMENT; + } else { + tr_error("Frame counter space exhausted"); + controller->frame_counters.counter[index].frame_counter = UINT32_MAX; + } controller->frame_counters.counter[index].stored_frame_counter = controller->frame_counters.counter[index].frame_counter; @@ -798,13 +812,18 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller) static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters) { for (uint8_t index = 0; index < GTK_NUM; index++) { - memset(frame_counters->counter[index].gtk, 0, GTK_LEN); - frame_counters->counter[index].frame_counter = 0; - frame_counters->counter[index].stored_frame_counter = 0; - frame_counters->counter[index].set = false; + ws_pae_controller_frame_counter_index_reset(frame_counters, index); } } +static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_counters, uint8_t index) +{ + memset(frame_counters->counter[index].gtk, 0, GTK_LEN); + frame_counters->counter[index].frame_counter = 0; + frame_counters->counter[index].stored_frame_counter = 0; + frame_counters->counter[index].set = false; +} + static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks) { if (ws_pae_controller_nvm_nw_info_read(controller->interface_ptr, &controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtks) < 0) { @@ -878,6 +897,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt ws_pae_controller_nw_info_read(controller, controller->sec_keys_nw_info.gtks); // Set active key back to fresh so that it can be used again after re-start sec_prot_keys_gtk_status_active_to_fresh_set(&controller->gtks); + sec_prot_keys_gtks_updated_reset(&controller->gtks); return 0; } diff --git a/source/6LoWPAN/ws/ws_pae_key_storage.c b/source/6LoWPAN/ws/ws_pae_key_storage.c index b50dfb0302..b168edcf10 100644 --- a/source/6LoWPAN/ws/ws_pae_key_storage.c +++ b/source/6LoWPAN/ws/ws_pae_key_storage.c @@ -360,7 +360,17 @@ int8_t ws_pae_key_storage_supp_write(const void *instance, supp_entry_t *pae_sup uint8_t *eui_64 = pae_supp->addr.eui_64; key_storage_array_t *key_storage_array; - sec_prot_keys_storage_t *key_storage = ws_pae_key_storage_get(instance, eui_64, &key_storage_array, true); + // Check if entry exists + sec_prot_keys_storage_t *key_storage = ws_pae_key_storage_get(instance, eui_64, &key_storage_array, false); + if (key_storage == NULL) { + // Do not allocate new storage if PMK and PTK are not set + if (!pae_supp->sec_keys.pmk_set && !pae_supp->sec_keys.ptk_set) { + tr_info("KeyS PMK and PTK not set, skip storing, eui64: %s", tr_array(eui_64, 8)); + return -1; + } + // Allocate new empty entry + key_storage = ws_pae_key_storage_get(instance, eui_64, &key_storage_array, true); + } // If cannot find existing or empty storage and there is room for storages tries to allocate more storage if (key_storage == NULL && key_storage_params.storages_empty > 0) { diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 9beda28756..e9d28a892f 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -355,7 +355,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt } // Modify keys - pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info->gtks); + pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info->gtks, false); return 0; } @@ -521,7 +521,7 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan (sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) && (sec_prot_keys_ptk_get(&pae_supp->entry.sec_keys) != NULL)) { tr_debug("Existing keys used, counter %i", pae_supp->nw_keys_used_cnt); - if (pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info->gtks) >= 0) { + if (pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info->gtks, false) >= 0) { tr_debug("Keys inserted"); } pae_supp->nw_keys_used_cnt++; @@ -549,11 +549,13 @@ int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, u sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys); sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys); // Delete GTKs - sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info->gtks); - sec_prot_keys_gtks_updated_set(pae_supp->sec_keys_nw_info->gtks); - ws_pae_supp_nvm_update(pae_supp); + sec_prot_keys_gtks_clear(pae_supp->sec_keys_nw_info->gtks); + // If data is changed, store to NVM + if (sec_prot_keys_are_updated(&pae_supp->entry.sec_keys) || + sec_prot_keys_gtks_are_updated(pae_supp->sec_keys_nw_info->gtks)) { + ws_pae_supp_nvm_update(pae_supp); + } } - return 0; } @@ -888,7 +890,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds) continue; } uint64_t current_time = ws_pae_current_time_get(); - sec_prot_keys_gtk_lifetime_decrement(pae_supp->sec_keys_nw_info->gtks, i, current_time, seconds); + sec_prot_keys_gtk_lifetime_decrement(pae_supp->sec_keys_nw_info->gtks, i, current_time, seconds, false); } if (pae_supp->initial_key_timer > 0) { @@ -1260,7 +1262,7 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e if ((type == IEEE_802_11_4WH || type == IEEE_802_11_GKH) && result == KMP_RESULT_OK) { if (sec_keys) { sec_prot_keys_t *keys = sec_keys; - pae_supp->nw_key_insert(pae_supp->interface_ptr, keys->gtks); + pae_supp->nw_key_insert(pae_supp->interface_ptr, keys->gtks, false); } ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_OK); diff --git a/source/6LoWPAN/ws/ws_pae_supp.h b/source/6LoWPAN/ws/ws_pae_supp.h index bed5ebc7e2..0642872896 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.h +++ b/source/6LoWPAN/ws/ws_pae_supp.h @@ -221,12 +221,13 @@ typedef const uint8_t *ws_pae_supp_auth_next_target(protocol_interface_info_entr * * \param interface_ptr interface * \param gtks group keys + * \param force_install TRUE force install keys, FALSE install keys only if GTKs has changed * * \return < 0 failure * \return >= 0 success * */ -typedef int8_t ws_pae_supp_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks); +typedef int8_t ws_pae_supp_nw_key_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, bool force_install); /** * ws_pae_supp_gtk_hash_ptr_get get pointer to GTK hash storage callback diff --git a/source/6LoWPAN/ws/ws_test_api.c b/source/6LoWPAN/ws/ws_test_api.c index 2e7cc97259..682bbf7dd1 100644 --- a/source/6LoWPAN/ws/ws_test_api.c +++ b/source/6LoWPAN/ws/ws_test_api.c @@ -164,4 +164,17 @@ int ws_test_6lowpan_fragmentation_mtu_size_set(int8_t interface_id, uint16_t mtu return 0; } +int ws_test_neighbour_temporary_lifetime_set(int8_t interface_id, uint32_t temporary_lifetime) +{ + protocol_interface_info_entry_t *cur; + + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur || !ws_info(cur)) { + return -1; + } + + ws_cfg_neighbour_temporary_lifetime_set(temporary_lifetime); + return 0; +} + #endif // HAVE_WS diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index 2a814d3fd0..38924cba93 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1794,6 +1794,9 @@ int8_t mcps_generic_edfe_frame_init(protocol_interface_rf_mac_setup_s *rf_ptr, c //Data Here mac_pre_build_frame_t *buffer; if (response->wait_response) { + if (rf_ptr->active_pd_data_request == NULL) { + return -1; + } buffer = rf_ptr->active_pd_data_request; buffer->message_builded = false; } else { diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 56463cb5ee..f6a5a18bed 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -179,6 +179,7 @@ struct rpl_instance { bool dao_in_transit: 1; /* If we have a DAO in transit */ bool requested_dao_ack: 1; /* If we requested an ACK (so we retry if no ACK, rather than assuming success) */ bool pending_neighbour_confirmation: 1; /* if we have not finished address registration state to parent */ + bool parent_was_selected: 1; uint8_t poison_count; uint8_t repair_dis_count; uint16_t repair_dis_timer; diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 7ee3a56520..babb5d0716 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -1516,6 +1516,7 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) if (preferred_parent) { // Always stop repair if we find a parent rpl_instance_set_local_repair(instance, false); + instance->parent_was_selected = true; //Validate time from last DIO uint32_t time_between_parent = protocol_core_monotonic_time - preferred_parent->dio_timestamp; @@ -1525,11 +1526,12 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance) rpl_control_transmit_dis(instance->domain, NULL, RPL_SOLINFO_PRED_INSTANCEID, instance->id, NULL, 0, preferred_parent->ll_address); } - } else if (original_preferred) { - // Only start repair if we just lost a parent + } else if (instance->parent_was_selected) { + // Only start repair if we just lost a parent or current rank goes to infinity rpl_instance_set_local_repair(instance, true); + instance->parent_was_selected = false; } else { - // !preferred_parent && !original_preferred - didn't have a parent, + // !preferred_parent && !instance->parent_was_selected - didn't have a parent, // still don't. Leave repair flag as-is (would be off on initial start // up, may be on if having problems mid-session). } diff --git a/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c index 7018d56c98..b37cdf028a 100644 --- a/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c @@ -410,7 +410,7 @@ static void radius_eap_tls_sec_prot_radius_client_deleted(sec_prot_t *prot) { radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); - tr_debug("EAP-TLS: client deleted"); + tr_info("EAP-TLS: client deleted"); data->radius_client_prot = NULL; data->radius_client_send = NULL; @@ -526,7 +526,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // On timeout if (sec_prot_result_timeout_check(&data->common)) { - tr_debug("EAP-TLS: retry EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("EAP-TLS: retry EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); if (radius_eap_tls_sec_prot_radius_eap_message_retry(prot) < 0) { tr_error("EAP-TLS: retry msg send error"); } diff --git a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c index a8dc175b7b..6b729450a0 100644 --- a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c +++ b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c @@ -79,6 +79,8 @@ typedef enum { #define RADIUS_ID_RANGE_SIZE 10 #define RADIUS_ID_RANGE_NUM (255 / RADIUS_ID_RANGE_SIZE) - 1 +#define RADIUS_ID_TIMEOUT 60 + typedef struct radius_client_sec_prot_lib_int_s radius_client_sec_prot_lib_int_t; typedef struct { @@ -120,7 +122,6 @@ typedef struct { static uint16_t radius_client_sec_prot_size(void); static int8_t radius_client_sec_prot_init(sec_prot_t *prot); static int8_t radius_client_sec_prot_shared_data_timeout(uint16_t ticks); -static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value); static int8_t radius_client_sec_prot_shared_data_delete(void); static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value); static void radius_client_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result); @@ -541,17 +542,17 @@ static uint8_t radius_client_sec_prot_identifier_allocate(sec_prot_t *prot, uint { radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); - if (!data->radius_id_range_set || value >= (data->radius_id_range * RADIUS_ID_RANGE_SIZE) + RADIUS_ID_RANGE_SIZE) { + if (!data->radius_id_range_set || value >= (data->radius_id_range * RADIUS_ID_RANGE_SIZE) + RADIUS_ID_RANGE_SIZE - 1) { for (uint8_t conn_num = 0; conn_num < RADIUS_CONN_NUMBER; conn_num++) { for (uint8_t id_range = 0; id_range < RADIUS_ID_RANGE_NUM; id_range++) { if (shared_data->radius_identifier_timer[conn_num][id_range] == 0) { // If range has been already reserved if (data->radius_id_range_set) { - // Set previous range to timeout in 5 seconds - radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 5); + // Set previous range to timeout at 1/5 of identifier timeout + radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, RADIUS_ID_TIMEOUT / 5); } // Set timeout for new range to 60 seconds - radius_identifier_timer_value_set(conn_num, id_range, 60); + radius_identifier_timer_value_set(conn_num, id_range, RADIUS_ID_TIMEOUT); data->radius_id_conn_num = conn_num; data->radius_id_range = id_range; data->radius_id_range_set = true; @@ -560,7 +561,7 @@ static uint8_t radius_client_sec_prot_identifier_allocate(sec_prot_t *prot, uint } } } else { - radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 60); + radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, RADIUS_ID_TIMEOUT); return value + 1; } @@ -572,7 +573,8 @@ static void radius_client_sec_prot_identifier_free(sec_prot_t *prot) radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); if (data->radius_id_range_set) { - radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 5); + // Timeout at 1/5 of identifier timeout + radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, RADIUS_ID_TIMEOUT / 5); } } diff --git a/source/Security/protocols/sec_prot_keys.c b/source/Security/protocols/sec_prot_keys.c index d7071e9323..ff08f74942 100644 --- a/source/Security/protocols/sec_prot_keys.c +++ b/source/Security/protocols/sec_prot_keys.c @@ -96,6 +96,16 @@ void sec_prot_keys_gtks_init(sec_prot_gtk_keys_t *gtks) gtks->updated = false; } +void sec_prot_keys_gtks_clear(sec_prot_gtk_keys_t *gtks) +{ + for (uint8_t i = 0; i < GTK_NUM; i++) { + if (sec_prot_keys_gtk_is_set(gtks, i)) { + gtks->updated = true; + } + } + memset(gtks, 0, sizeof(sec_prot_gtk_keys_t)); +} + void sec_prot_keys_gtks_delete(sec_prot_gtk_keys_t *gtks) { ns_dyn_mem_free(gtks); @@ -113,12 +123,15 @@ void sec_prot_keys_pmk_write(sec_prot_keys_t *sec_keys, uint8_t *pmk, uint32_t p void sec_prot_keys_pmk_delete(sec_prot_keys_t *sec_keys) { + if (sec_keys->pmk_key_replay_cnt != 0 || sec_keys->pmk_key_replay_cnt_set || + sec_keys->pmk_lifetime != 0 || sec_keys->pmk_set) { + sec_keys->updated = true; + } memset(sec_keys->pmk, 0, PMK_LEN); sec_keys->pmk_key_replay_cnt = 0; sec_keys->pmk_key_replay_cnt_set = false; sec_keys->pmk_lifetime = 0; sec_keys->pmk_set = false; - sec_keys->updated = true; } uint8_t *sec_prot_keys_pmk_get(sec_prot_keys_t *sec_keys) @@ -222,10 +235,12 @@ void sec_prot_keys_ptk_write(sec_prot_keys_t *sec_keys, uint8_t *ptk, uint32_t p void sec_prot_keys_ptk_delete(sec_prot_keys_t *sec_keys) { + if (sec_keys->ptk_lifetime != 0 || sec_keys->ptk_set) { + sec_keys->updated = true; + } memset(sec_keys->ptk, 0, PTK_LEN); sec_keys->ptk_lifetime = 0; sec_keys->ptk_set = false; - sec_keys->updated = true; } uint8_t *sec_prot_keys_ptk_get(sec_prot_keys_t *sec_keys) @@ -279,9 +294,11 @@ uint8_t *sec_prot_keys_ptk_eui_64_get(sec_prot_keys_t *sec_keys) void sec_prot_keys_ptk_eui_64_delete(sec_prot_keys_t *sec_keys) { + if (sec_keys->ptk_eui_64_set) { + sec_keys->updated = true; + } memset(sec_keys->ptk_eui_64, 0, 8); sec_keys->ptk_eui_64_set = false; - sec_keys->updated = true; } bool sec_prot_keys_ptk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint8_t seconds) @@ -490,7 +507,7 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index return gtks->gtk[index].lifetime; } -uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds) +uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds, bool gtk_update_enable) { if (gtks->gtk[index].lifetime > seconds) { gtks->gtk[index].lifetime -= seconds; @@ -508,7 +525,7 @@ uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t diff = expirytime - gtks->gtk[index].expirytime; } // If timestamps differ for more than 5 minutes marks field as updated (and stores to NVM) - if (diff > 300) { + if (diff > 300 && gtk_update_enable) { gtks->updated = true; } @@ -588,7 +605,8 @@ int8_t sec_prot_keys_gtk_status_active_set(sec_prot_gtk_keys_t *gtks, uint8_t in } } gtks->gtk[index].status = GTK_STATUS_ACTIVE; - gtks->updated = true; + /* Changing fresh to active does not change the gtks updated state since active + keys are set to fresh on nvm read on startup */ return 0; } diff --git a/source/Security/protocols/sec_prot_keys.h b/source/Security/protocols/sec_prot_keys.h index 5050ddeec1..0304d9eb44 100644 --- a/source/Security/protocols/sec_prot_keys.h +++ b/source/Security/protocols/sec_prot_keys.h @@ -200,6 +200,14 @@ sec_prot_gtk_keys_t *sec_prot_keys_gtks_create(void); */ void sec_prot_keys_gtks_init(sec_prot_gtk_keys_t *gtks); +/** + * sec_prot_keys_gtks_init clear GTK keys + * + * \param gtks GTK keys + * + */ +void sec_prot_keys_gtks_clear(sec_prot_gtk_keys_t *gtks); + /** * sec_prot_keys_gtks_delete frees GTK keys memory * @@ -616,11 +624,12 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index * \param index index for GTK * \param current_time current timestamp * \param seconds elapsed seconds + * \param gtk_update_enable enable GTK status to be updated * * \return new GTK lifetime * */ -uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds); +uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds, bool gtk_update_enable); /** * sec_prot_keys_gtk_exptime_from_lifetime_get converts GTK lifetime to expiry time. diff --git a/source/Security/protocols/sec_prot_lib.c b/source/Security/protocols/sec_prot_lib.c index 604644fbc2..a6ba018ae6 100644 --- a/source/Security/protocols/sec_prot_lib.c +++ b/source/Security/protocols/sec_prot_lib.c @@ -373,19 +373,23 @@ uint8_t *sec_prot_lib_message_handle(uint8_t *ptk, uint16_t *kde_len, eapol_pdu_ uint8_t *kde = ns_dyn_mem_temporary_alloc(key_data_len); *kde_len = key_data_len; - if (eapol_pdu->msg.key.key_information.encrypted_key_data) { - size_t output_len = eapol_pdu->msg.key.key_data_length; - if (nist_aes_key_wrap(0, &ptk[KEK_INDEX], 128, key_data, key_data_len, kde, &output_len) < 0 || output_len != (size_t) key_data_len - 8) { - tr_error("Decrypt failed"); - ns_dyn_mem_free(kde); - return NULL; + if (kde) { + if (eapol_pdu->msg.key.key_information.encrypted_key_data) { + size_t output_len = eapol_pdu->msg.key.key_data_length; + if (nist_aes_key_wrap(0, &ptk[KEK_INDEX], 128, key_data, key_data_len, kde, &output_len) < 0 || output_len != (size_t) key_data_len - 8) { + tr_error("Decrypt failed"); + ns_dyn_mem_free(kde); + return NULL; + } + *kde_len = output_len; + } else { + memcpy(kde, key_data, *kde_len); } - *kde_len = output_len; - } else { - memcpy(kde, key_data, *kde_len); + + return kde; } - return kde; + return NULL; } int8_t sec_prot_lib_gtk_read(uint8_t *kde, uint16_t kde_len, sec_prot_keys_t *sec_keys) diff --git a/source/Service_Libs/etx/etx.c b/source/Service_Libs/etx/etx.c index 76b7c7d203..22a86f1cca 100644 --- a/source/Service_Libs/etx/etx.c +++ b/source/Service_Libs/etx/etx.c @@ -74,6 +74,8 @@ typedef struct { uint8_t etx_min_sampling_time; uint8_t ext_storage_list_size; uint8_t min_attempts_count; + uint8_t drop_bad_max; + uint8_t bad_link_level; bool cache_sample_requested; int8_t interface_id; } ext_info_t; @@ -87,6 +89,8 @@ static ext_info_t etx_info = { .etx_cache_storage_list = NULL, .ext_storage_list_size = 0, .min_attempts_count = 0, + .drop_bad_max = 0, + .bad_link_level = 0, .max_etx_update = 0, .max_etx = 0xffff, .init_etx_sample_count = 1, @@ -133,6 +137,8 @@ static void etx_calculation(etx_storage_t *entry, uint16_t attempts, uint8_t ack entry->tmp_etx = false; entry->etx = etx; + //Clear Drop count + entry->drop_bad_count = 0; if (entry->etx_samples >= etx_info.init_etx_sample_count) { etx_cache_entry_init(etx_neigh_info->attribute_index); @@ -149,6 +155,7 @@ static void etx_cache_entry_init(uint8_t attribute_index) etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index; storage->attempts_count = 0; + storage->transition_count = 0; storage->etx_timer = etx_info.etx_min_sampling_time; storage->received_acks = 0; } @@ -162,21 +169,22 @@ static bool etx_update_possible(etx_sample_storage_t *storage, etx_storage_t *en storage->etx_timer -= time_update; } } + if (entry->etx_samples == etx_info.init_etx_sample_count && time_update == 0) { + return true; + } if (entry->etx_samples > etx_info.init_etx_sample_count) { //Slower ETX update phase - if (storage->attempts_count >= etx_info.min_attempts_count) { - - if (storage->etx_timer == 0 || storage->attempts_count == 0xffff || storage->received_acks == 0xff) { + if (storage->etx_timer == 0 || storage->attempts_count == 0xffff || storage->received_acks == 0xff) { + //When time is going zero or too much sample data + if (storage->transition_count >= etx_info.min_attempts_count) { //Got least min sample in requested time or max possible sample return true; + } else if (storage->transition_count != storage->received_acks) { + //Missing ack now ETX can be accelerated + return true; } } - return false; - } - - if (time_update == 0) { - return true; } return false; @@ -188,6 +196,7 @@ static etx_sample_storage_t *etx_cache_sample_update(uint8_t attribute_index, ui { etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index; storage->attempts_count += attempts; + storage->transition_count++; if (ack_rx) { storage->received_acks++; } @@ -196,6 +205,26 @@ static etx_sample_storage_t *etx_cache_sample_update(uint8_t attribute_index, ui } +static bool etx_drop_bad_sample(etx_storage_t *entry, uint8_t attempts, bool success) +{ + if (etx_info.bad_link_level == 0 || !success) { + //Not enabled or Failure + return false; + } + + if (attempts < etx_info.bad_link_level) { + //under configured value is accepted + return false; + } + + if (entry->drop_bad_count < etx_info.drop_bad_max) { + //Accepted only configured max value 1-2 + entry->drop_bad_count++; + return true; + } + + return false; +} /** * \brief A function to update ETX value based on transmission attempts @@ -222,6 +251,11 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ etx_neigh_info.mac64 = mac64_addr_ptr; if (entry->etx_samples < 7) { + + if (etx_drop_bad_sample(entry, attempts, success)) { + tr_debug("Drop bad etx init %u", attempts); + return; + } entry->etx_samples++; } @@ -235,10 +269,6 @@ void etx_transm_attempts_update(int8_t interface_id, uint8_t attempts, bool succ } etx_calculation(entry, storage->attempts_count, storage->received_acks, &etx_neigh_info); - - if (entry->etx_samples < 7 && !success) { - entry->etx_samples = 7; //Stop Probing to failure - } return; } @@ -409,9 +439,13 @@ uint16_t etx_local_etx_read(int8_t interface_id, uint8_t attribute_index) } if (etx_info.cache_sample_requested && entry->etx_samples < etx_info.init_etx_sample_count) { - if (!entry->etx_samples) { - return 0; + etx_sample_storage_t *storage = etx_info.etx_cache_storage_list + attribute_index; + if (storage->received_acks == 0 && storage->attempts_count) { + //No ack so return max value + return etx_info.max_etx; } + //Not ready yet + return 0xffff; } return etx_current_calc(entry->etx, entry->accumulated_failures) >> 4; @@ -668,6 +702,36 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_attempt return true; } +bool etx_allow_drop_for_poor_measurements(uint8_t bad_link_level, uint8_t max_allowed_drops) +{ + //No ini ETX allocation done yet + if (etx_info.ext_storage_list_size == 0) { + return false; + } + + if (bad_link_level == 0) { + //Disable feature + etx_info.bad_link_level = 0; + etx_info.drop_bad_max = 0; + return true; + } + + if (bad_link_level < 2) { + // 2 attepts is min value + return false; + } + + if (max_allowed_drops == 0 || max_allowed_drops > 3) { + //Accepted values is 1-3 + return false; + } + + + etx_info.bad_link_level = bad_link_level; + etx_info.drop_bad_max = max_allowed_drops; + return true; +} + void etx_max_update_set(uint16_t etx_max_update) { if (etx_max_update) { diff --git a/source/Service_Libs/etx/etx.h b/source/Service_Libs/etx/etx.h index a1c40b2694..9329d201b2 100644 --- a/source/Service_Libs/etx/etx.h +++ b/source/Service_Libs/etx/etx.h @@ -58,12 +58,14 @@ typedef struct etx_storage_s { unsigned tmp_etx: 1; unsigned linkIdr: 4; unsigned etx_samples: 3; + unsigned drop_bad_count: 2; } etx_storage_t; typedef struct etx_sample_storage_s { uint16_t attempts_count; /*!< TX attempt count */ uint8_t etx_timer; /*!< Count down from configured value 0 means that ETX Update is possible done again*/ uint8_t received_acks; /*!< Received ACK's */ + uint8_t transition_count; } etx_sample_storage_t; /** @@ -279,6 +281,15 @@ bool etx_cached_etx_parameter_set(uint8_t min_wait_time, uint8_t etx_min_attempt */ void etx_max_update_set(uint16_t etx_max_update); +/** + * \brief A function for configure limit for detect bad init ETX sample + * + * \param bad_link_level 0 No limit and >=2 Level + * \param max_allowed_drops How many init probe is accepted to drop 1-2 are possible values + * + */ +bool etx_allow_drop_for_poor_measurements(uint8_t bad_link_level, uint8_t max_allowed_drops); + /** * \brief A function for set Maxium ETX value * diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index 78cb5154d5..c3d354bd9b 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -305,12 +305,12 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay) /* Start timer with random timeout to trigger broadcast TX queue poll event. * Min random is 1/50 of the channel dwell interval. - * Max random is 1/10 of the channel dwell interval. + * Max random is 3/4 of the channel dwell interval. * Event timer resolution is 50us. */ uint32_t bc_dwell_us = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval); uint16_t bc_min_random = (bc_dwell_us / 50) / 50; - uint16_t bc_max_random = (bc_dwell_us / 10) / 50; + uint16_t bc_max_random = (bc_dwell_us - (bc_dwell_us / 4)) / 50; eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(bc_min_random, bc_max_random)); } else { fhss_structure->ws->unicast_start_time_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api); @@ -1063,7 +1063,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co fhss_structure->rx_channel = fhss_configuration->unicast_fixed_channel; } platform_exit_critical(); - tr_info("fhss Configuration set, UC channel: %d, BC channel: %d, UC CF: %d, BC CF: %d, channels: BC %d UC %d, uc dwell: %d, bc dwell: %d, bc interval: %"PRIu32", bsi:%d", + tr_info("fhss Configuration set, UC channel: %d, BC channel: %d, UC CF: %d, BC CF: %d, channels: BC %d UC %d, uc dwell: %d, bc dwell: %d, bc interval: %"PRIu32", bsi:%d, ch retries: %u", fhss_structure->ws->fhss_configuration.unicast_fixed_channel, fhss_structure->ws->fhss_configuration.broadcast_fixed_channel, fhss_structure->ws->fhss_configuration.ws_uc_channel_function, @@ -1073,7 +1073,9 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval, fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval, fhss_structure->ws->fhss_configuration.fhss_broadcast_interval, - fhss_structure->ws->fhss_configuration.bsi); + fhss_structure->ws->fhss_configuration.bsi, + fhss_structure->ws->fhss_configuration.config_parameters.number_of_channel_retries); + return 0; } diff --git a/source/libNET/src/net_dns.c b/source/libNET/src/net_dns.c index b7c7c3eec5..434bd4d6d3 100644 --- a/source/libNET/src/net_dns.c +++ b/source/libNET/src/net_dns.c @@ -150,15 +150,17 @@ int8_t net_dns_server_search_list_set(int8_t interface_id, const uint8_t address info_ptr->dns_search_list_ptr = NULL; } - if (!info_ptr->dns_search_list_ptr) { - info_ptr->dns_search_list_ptr = ns_dyn_mem_alloc(dns_search_list_len); + if (dns_search_list_len) { + if (!info_ptr->dns_search_list_ptr) { + info_ptr->dns_search_list_ptr = ns_dyn_mem_alloc(dns_search_list_len); + } + + if (!info_ptr->dns_search_list_ptr) { + return -2; + } + memcpy(info_ptr->dns_search_list_ptr, dns_search_list_ptr, dns_search_list_len); } - if (!info_ptr->dns_search_list_ptr) { - return -2; - } - - memcpy(info_ptr->dns_search_list_ptr, dns_search_list_ptr, dns_search_list_len); info_ptr->dns_search_list_len = dns_search_list_len; tr_info("DNS Search List: %s Lifetime: %lu", trace_array(info_ptr->dns_search_list_ptr, info_ptr->dns_search_list_len), (unsigned long) info_ptr->lifetime);