mirror of https://github.com/ARMmbed/mbed-os.git
Merge commit '4098b26c4477b6ed8929e71c571b8fb13195582a' into feature-wisun
* commit '4098b26c4477b6ed8929e71c571b8fb13195582a': Squashed 'features/nanostack/sal-stack-nanostack/' changes from 7e3b99c375..09d9e24f2dpull/13716/head
commit
c1c9ba5c6a
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue