diff --git a/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h b/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h index 85c4fd3d596..9c1e4a03cb2 100644 --- a/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c index eedd4ea6236..83560e9298f 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c index c0b6d5ffc58..a2f8a061581 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c @@ -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,19 +1274,12 @@ 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); - } - 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; - } } + if (entry) { + entry->tx_fail = 0; + } + return entry; } static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create) @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c index 0423ce654b2..1898b426d88 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.c @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h index 5e0e8c34c89..48592b899a5 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_cfg_settings.h @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.c index b1d734a77a2..5a242cfa4b5 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.c +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h index 96a425c1308..cb29ab6c35c 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common.h @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common_defines.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common_defines.h index c6e84d13bd9..7ce70d0146e 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_common_defines.h +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h index 589724fda8a..899b25afcd0 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c index 098f1a4b1ed..306c90eed1e 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_llc_data_service.c @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c index 5215f2c8d9c..135db220af5 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_management_api.c @@ -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; } + ws_fhss_cfg_t cfg_default; + if (ws_cfg_fhss_default_set(&cfg_default) < 0) { + return -2; + } + 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; } - cfg.fhss_uc_channel_function = channel_function; - cfg.fhss_uc_fixed_channel = fixed_channel; + 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; + } else { + cfg.fhss_bc_dwell_interval = cfg_default.fhss_bc_dwell_interval; } + if (broadcast_interval > 0) { cfg.fhss_bc_interval = broadcast_interval; + } else { + cfg.fhss_bc_interval = cfg_default.fhss_bc_interval; } - cfg.fhss_bc_channel_function = channel_function; - cfg.fhss_bc_fixed_channel = fixed_channel; + 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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c index a8752ad5ace..942f44379d6 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_auth.c @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c index cbd19d61aaf..0a7a0650d7a 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c index b50dfb03027..b168edcf101 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_key_storage.c @@ -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/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c index cca9cf79537..e9d28a892f3 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_supp.c @@ -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/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c index 7018d56c98a..b37cdf028a7 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_keys.c b/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_keys.c index d7071e93237..ff08f74942a 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_keys.c +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_keys.h b/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_keys.h index 5050ddeec12..0304d9eb444 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_keys.h +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_lib.c b/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_lib.c index 5665677dcad..a6ba018ae66 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_lib.c +++ b/features/nanostack/sal-stack-nanostack/source/Security/protocols/sec_prot_lib.c @@ -389,7 +389,7 @@ uint8_t *sec_prot_lib_message_handle(uint8_t *ptk, uint16_t *kde_len, eapol_pdu_ return kde; } - return NULL; + 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/features/nanostack/sal-stack-nanostack/source/Service_Libs/etx/etx.c b/features/nanostack/sal-stack-nanostack/source/Service_Libs/etx/etx.c index 76b7c7d2034..22a86f1cca1 100644 --- a/features/nanostack/sal-stack-nanostack/source/Service_Libs/etx/etx.c +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/Service_Libs/etx/etx.h b/features/nanostack/sal-stack-nanostack/source/Service_Libs/etx/etx.h index a1c40b2694d..9329d201b20 100644 --- a/features/nanostack/sal-stack-nanostack/source/Service_Libs/etx/etx.h +++ b/features/nanostack/sal-stack-nanostack/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/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c index 848079e69d4..c3d354bd9b4 100644 --- a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c +++ b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c @@ -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; }