From 4098b26c4477b6ed8929e71c571b8fb13195582a Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 5 Oct 2020 13:59:09 +0300 Subject: [PATCH] Squashed 'features/nanostack/sal-stack-nanostack/' changes from 7e3b99c375..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) git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: 09d9e24f2d3e97cd38139e5df3d9e79d2ee65f4e --- nanostack/ws_bbr_api.h | 1 + source/6LoWPAN/ws/ws_bbr_api.c | 15 +- source/6LoWPAN/ws/ws_bootstrap.c | 128 ++++++++++++------ source/6LoWPAN/ws/ws_cfg_settings.c | 9 +- source/6LoWPAN/ws/ws_cfg_settings.h | 3 + source/6LoWPAN/ws/ws_common.c | 30 ++-- source/6LoWPAN/ws/ws_common.h | 1 + source/6LoWPAN/ws/ws_common_defines.h | 11 +- source/6LoWPAN/ws/ws_config.h | 6 +- source/6LoWPAN/ws/ws_llc_data_service.c | 2 - source/6LoWPAN/ws/ws_management_api.c | 104 ++++++++++++-- source/6LoWPAN/ws/ws_pae_auth.c | 6 +- source/6LoWPAN/ws/ws_pae_controller.c | 11 +- source/6LoWPAN/ws/ws_pae_key_storage.c | 12 +- source/6LoWPAN/ws/ws_pae_supp.c | 12 +- .../radius_eap_tls_sec_prot.c | 4 +- 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 | 6 +- 22 files changed, 411 insertions(+), 118 deletions(-) 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 c0b6d5ffc5..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*/ @@ -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); } @@ -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; @@ -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 0423ce654b..1898b426d8 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/source/6LoWPAN/ws/ws_cfg_settings.c @@ -87,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); @@ -601,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; @@ -681,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 @@ -901,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; diff --git a/source/6LoWPAN/ws/ws_cfg_settings.h b/source/6LoWPAN/ws/ws_cfg_settings.h index 5e0e8c34c8..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); 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 c6e84d13bd..7ce70d0146 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -255,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 @@ -270,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 @@ -322,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_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index 098f1a4b1e..306c90eed1 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -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 a8752ad5ac..942f44379d 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -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 @@ -710,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); diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index cbd19d61aa..0a7a0650d7 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -783,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; @@ -891,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 cca9cf7953..e9d28a892f 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -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) { 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/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 848079e69d..c3d354bd9b 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -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; }