diff --git a/nanostack/fhss_config.h b/nanostack/fhss_config.h index a388f5643f..9a286128ac 100644 --- a/nanostack/fhss_config.h +++ b/nanostack/fhss_config.h @@ -116,9 +116,12 @@ typedef struct fhss_ws_configuration { /** Broadcast fixed channel */ uint8_t broadcast_fixed_channel; - /** Channel mask. */ + /** Channel mask. Wi-SUN will use this for broadcast */ uint32_t channel_mask[8]; + /** Wi-SUN specific unicast channel mask */ + uint32_t unicast_channel_mask[8]; + /** Vendor defined channel function. */ fhss_vendor_defined_cf *vendor_defined_cf; diff --git a/nanostack/fhss_ws_extension.h b/nanostack/fhss_ws_extension.h index 1d8e2998ee..ac2e1b446f 100644 --- a/nanostack/fhss_ws_extension.h +++ b/nanostack/fhss_ws_extension.h @@ -30,6 +30,14 @@ extern "C" { #endif +/** + * @brief ws_channel_mask_t WS neighbour supported channel mask + */ +typedef struct ws_channel_mask { + uint16_t channel_count; /**eth_mac_api) { + // either PPP or Ethernet interface. + latency_estimate = 100; + } else if (thread_info(cur_interface)) { + // thread network + latency_estimate = 1000; + } else if (ws_info(cur_interface)) { + latency_estimate = ws_common_latency_estimate_get(cur_interface); + } else { + // 6LoWPAN ND + latency_estimate = 8000; + } + + if (latency_estimate != 0) { + *latency = latency_estimate; + return true; + } + + return false; +} + +bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand) +{ + size_t network_size; + uint32_t datarate; + protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id); + + if (!cur_interface) { + return false; + } + + *stagger_min = 1; + + if (cur_interface->eth_mac_api) { + // either PPP or Ethernet interface. + network_size = 1; + datarate = 1000000; + } else if (thread_info(cur_interface)) { + // thread network + network_size = 23; + datarate = 250000; + } else if (ws_info(cur_interface)) { + network_size = ws_common_network_size_estimate_get(cur_interface); + datarate = ws_common_datarate_get(cur_interface); + } else { + // 6LoWPAN ND + network_size = 1000; + datarate = 250000; + } + + if (data_amount == 0) { + // If no data amount given, use 1kB + data_amount = 1; + } + /**Example: + * Maximum stagger value to send 1kB on 50 devices network using datarate 50000 kb/: + * (1 * 1024 * 8 * 50) / (50000/4)) = ~ 32s + * + * devices: 50, datarate: 250kbps => stagger ~ 6s + * devices: 1000, datarate: 50kbps => stagger ~ 655s + */ + /* Do not occupy whole bandwidth, halve the theoretical datarate and reserve room for other channel usage */ + datarate = datarate / 4; + *stagger_max = (uint16_t) * stagger_min + ((data_amount * 1024 * 8 * network_size) / datarate); + + // Randomize stagger value + *stagger_rand = randLIB_get_random_in_range(*stagger_min, *stagger_max); + + return true; +} diff --git a/source/6LoWPAN/Bootstraps/protocol_6lowpan.h b/source/6LoWPAN/Bootstraps/protocol_6lowpan.h index ebd3ccf5b8..95515c1fd4 100644 --- a/source/6LoWPAN/Bootstraps/protocol_6lowpan.h +++ b/source/6LoWPAN/Bootstraps/protocol_6lowpan.h @@ -75,5 +75,7 @@ uint8_t protocol_6lowpan_beacon_join_priority_tx(int8_t interface_id); uint8_t protocol_6lowpan_beacon_compare_rx(int8_t interface_id, uint8_t join_priority, uint8_t link_quality); bool protocol_6lowpan_bootsrap_start(struct protocol_interface_info_entry *interface); bool protocol_6lowpan_bootsrap_link_set(struct protocol_interface_info_entry *interface, struct mlme_pan_descriptor_s *pan_descriptor, const uint8_t *beacon_payload, uint8_t beacon_length); +bool protocol_6lowpan_latency_estimate_get(int8_t interface_id, uint32_t *latency); +bool protocol_6lowpan_stagger_estimate_get(int8_t interface_id, uint32_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand); #endif /* PROTOCOL_6LOWPAN_H_ */ diff --git a/source/6LoWPAN/IPHC_Decode/iphc_decompress.c b/source/6LoWPAN/IPHC_Decode/iphc_decompress.c index 8b584297e1..eeeb48c2e1 100644 --- a/source/6LoWPAN/IPHC_Decode/iphc_decompress.c +++ b/source/6LoWPAN/IPHC_Decode/iphc_decompress.c @@ -249,7 +249,7 @@ static bool decompress_mc_addr(const lowpan_context_list_t *context_list, uint8_ *in_ptr = in; return true; case HC_48BIT_CONTEXT_MULTICAST: { - lowpan_context_t *ctx = lowpan_contex_get_by_id(context_list, context); + lowpan_context_t *ctx = lowpan_context_get_by_id(context_list, context); if (!ctx) { return false; } @@ -312,7 +312,7 @@ static bool decompress_addr(const lowpan_context_list_t *context_list, uint8_t * } if (mode & HC_DSTADR_COMP) { - lowpan_context_t *ctx = lowpan_contex_get_by_id(context_list, context); + lowpan_context_t *ctx = lowpan_context_get_by_id(context_list, context); if (!ctx) { return false; } diff --git a/source/6LoWPAN/IPHC_Decode/lowpan_context.c b/source/6LoWPAN/IPHC_Decode/lowpan_context.c index c4391fd76c..1d9a68904a 100644 --- a/source/6LoWPAN/IPHC_Decode/lowpan_context.c +++ b/source/6LoWPAN/IPHC_Decode/lowpan_context.c @@ -31,7 +31,7 @@ #define TRACE_GROUP "lCon" -lowpan_context_t *lowpan_contex_get_by_id(const lowpan_context_list_t *list, uint8_t id) +lowpan_context_t *lowpan_context_get_by_id(const lowpan_context_list_t *list, uint8_t id) { id &= LOWPAN_CONTEXT_CID_MASK; /* Check to see we already have info for this context */ @@ -65,7 +65,7 @@ int_fast8_t lowpan_context_update(lowpan_context_list_t *list, uint8_t cid_flags /* Check to see we already have info for this context */ - ctx = lowpan_contex_get_by_id(list, cid); + ctx = lowpan_context_get_by_id(list, cid); if (ctx) { //Remove from the list - it will be reinserted below, sorted by its //new context length. (Don't need "safe" foreach, as we break diff --git a/source/6LoWPAN/IPHC_Decode/lowpan_context.h b/source/6LoWPAN/IPHC_Decode/lowpan_context.h index e31f9e1afb..0b8daf32cc 100644 --- a/source/6LoWPAN/IPHC_Decode/lowpan_context.h +++ b/source/6LoWPAN/IPHC_Decode/lowpan_context.h @@ -88,7 +88,7 @@ void lowpan_context_timer(lowpan_context_list_t *list, uint_fast16_t ticks); * \return NULL Not supported Context ID * */ -lowpan_context_t *lowpan_contex_get_by_id(const lowpan_context_list_t *list, uint8_t id); +lowpan_context_t *lowpan_context_get_by_id(const lowpan_context_list_t *list, uint8_t id); /** * \brief Get Longest match Context entry from the list for given IPv6 address diff --git a/source/6LoWPAN/Thread/thread_bootstrap.c b/source/6LoWPAN/Thread/thread_bootstrap.c index 483932b578..07e231c864 100644 --- a/source/6LoWPAN/Thread/thread_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_bootstrap.c @@ -955,7 +955,7 @@ static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_SLEEPY_END_DEVICE; //SET Sleepy Host To RX on Idle mode for bootsrap nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0); - cur->thread_info->childUpdateReqTimer = 0.8 * cur->thread_info->host_link_timeout; + cur->thread_info->childUpdateReqTimer = 8 * cur->thread_info->host_link_timeout / 10; } else { tr_debug("Set End node Mode"); cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE; diff --git a/source/6LoWPAN/Thread/thread_common.c b/source/6LoWPAN/Thread/thread_common.c index bfea2ba7a9..8e843f5673 100644 --- a/source/6LoWPAN/Thread/thread_common.c +++ b/source/6LoWPAN/Thread/thread_common.c @@ -381,7 +381,7 @@ void thread_key_guard_timer_calculate(protocol_interface_info_entry_t *cur, link } cur->thread_info->masterSecretMaterial.keyRotation = key_rotation * 3600; // setting value is hours converting to seconds - cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = is_init ? 0 : (key_rotation * 3600 * 0.93); + cur->thread_info->masterSecretMaterial.keySwitchGuardTimer = is_init ? 0 : (key_rotation * 3600 * 93 / 100); } void thread_key_guard_timer_reset(protocol_interface_info_entry_t *cur) diff --git a/source/6LoWPAN/Thread/thread_mle_message_handler.c b/source/6LoWPAN/Thread/thread_mle_message_handler.c index 31e2f3416c..9a465fbc27 100644 --- a/source/6LoWPAN/Thread/thread_mle_message_handler.c +++ b/source/6LoWPAN/Thread/thread_mle_message_handler.c @@ -892,7 +892,7 @@ static void thread_parse_child_update_response(protocol_interface_info_entry_t * if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { if (cur->thread_info->childUpdateReqTimer < 1) { - cur->thread_info->childUpdateReqTimer = 0.8 * timeout; + cur->thread_info->childUpdateReqTimer = 8 * timeout / 10; } } //This process is ready diff --git a/source/6LoWPAN/Thread/thread_neighbor_class.h b/source/6LoWPAN/Thread/thread_neighbor_class.h index 8dc22889ae..5244441741 100644 --- a/source/6LoWPAN/Thread/thread_neighbor_class.h +++ b/source/6LoWPAN/Thread/thread_neighbor_class.h @@ -32,7 +32,7 @@ struct thread_neighbor_class_s; -/** Thead Spesific ModeFlags */ +/** Thread Spesific ModeFlags */ #define MLE_THREAD_SECURED_DATA_REQUEST 0x04 #define MLE_THREAD_REQ_FULL_DATA_SET 0x01 diff --git a/source/6LoWPAN/Thread/thread_router_bootstrap.c b/source/6LoWPAN/Thread/thread_router_bootstrap.c index 81d5449447..df32d174f6 100644 --- a/source/6LoWPAN/Thread/thread_router_bootstrap.c +++ b/source/6LoWPAN/Thread/thread_router_bootstrap.c @@ -1398,7 +1398,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le ctxId = *ptr++; if (ctxId & 0x80) { ctxId &= 0x0f; - ctx = lowpan_contex_get_by_id(&cur->lowpan_contexts, ctxId); + ctx = lowpan_context_get_by_id(&cur->lowpan_contexts, ctxId); if (ctx) { memcpy(tempIPv6Address, ctx->prefix, 8); memcpy(&tempIPv6Address[8], ptr, 8); diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 7961f10cc9..d180102e4a 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -27,6 +27,7 @@ #include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "RPL/rpl_control.h" #include "RPL/rpl_data.h" #include "Common_Protocols/icmpv6.h" @@ -61,6 +62,7 @@ static uint8_t current_instance_id = RPL_INSTANCE_ID; */ static int8_t backbone_interface_id = -1; // BBR backbone information static uint16_t configuration = 0; +static uint32_t pan_version_timer = 0; static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x72, 0x83, 0x7e}; static uint8_t static_dodag_id_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d}; @@ -80,9 +82,9 @@ static rpl_dodag_conf_t rpl_conf = { .dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE, .min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE, // DIO configuration - .dio_interval_min = WS_RPL_DIO_IMIN, - .dio_interval_doublings = WS_RPL_DIO_DOUBLING, - .dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY + .dio_interval_min = WS_RPL_DIO_IMIN_SMALL, + .dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL, + .dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL }; static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version) @@ -109,9 +111,9 @@ void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8 { if (imin == 0 || doubling == 0) { // use default values - imin = WS_RPL_DIO_IMIN; - doubling = WS_RPL_DIO_DOUBLING; - redundancy = WS_RPL_DIO_REDUNDANCY; + imin = WS_RPL_DIO_IMIN_SMALL; + doubling = WS_RPL_DIO_DOUBLING_SMALL; + redundancy = WS_RPL_DIO_REDUNDANCY_SMALL; } if (rpl_conf.dio_interval_min == imin && @@ -532,6 +534,22 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur) } } } +void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur) +{ + if (!cur) { + return; + } + tr_debug("Border router version number update"); + if (configuration & BBR_REQUIRE_DAO_REFRESH) { + // Version number is not periodically increased forcing nodes to check Border router availability using DAO + pan_version_timer = 0; + } else { + pan_version_timer = cur->ws_info->cfg->timing.pan_timeout / PAN_VERSION_CHANGE_INTERVAL; + } + cur->ws_info->pan_information.pan_version++; + // Inconsistent for border router to make information distribute faster + ws_bootstrap_configuration_trickle_reset(cur); +} void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) { @@ -574,18 +592,21 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds } // Normal BBR operation if (protocol_6lowpan_rpl_root_dodag) { - if (cur->ws_info->pan_version_timer > seconds) { - cur->ws_info->pan_version_timer -= seconds; - } else { - // PAN version number update - tr_debug("Border router version number update"); - cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config); - cur->ws_info->pan_information.pan_version++; - // Inconsistent for border router to make information distribute faster - ws_bootstrap_configuration_trickle_reset(cur); - - if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) { - ws_common_network_size_configure(cur, cur->ws_info->pan_information.pan_size); + /* + * PAN version change is one way to enable nodes to detect the border router availability + * if this is not done periodically devices need to have other means to detect border router condiftion + * + * If devices do not see version change they need to send DAO to border router before PAN timeout + * + * The update frequency should be related to PAN timeout and happen for example 4 times. + */ + if (pan_version_timer > 0) { + if (pan_version_timer > seconds) { + pan_version_timer -= seconds; + } else { + // PAN version number update + pan_version_timer = 0; + ws_bbr_pan_version_increase(cur); } } if (cur->ws_info->rpl_version_timer > seconds) { @@ -754,3 +775,163 @@ int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validatio return -1; #endif } + +int ws_bbr_rpl_parameters_set(int8_t interface_id, uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + + ws_rpl_cfg_t cfg; + if (ws_cfg_rpl_get(&cfg, NULL) < 0) { + return -1; + } + + if (dio_interval_min > 0) { + cfg.dio_interval_min = dio_interval_min; + } + if (dio_interval_doublings > 0) { + cfg.dio_interval_doublings = dio_interval_doublings; + } + if (dio_redundancy_constant != 0xff) { + cfg.dio_redundancy_constant = dio_redundancy_constant; + } + + if (ws_cfg_rpl_set(cur, NULL, &cfg, 0) < 0) { + return -2; + } + + return 0; +#else + (void) dio_interval_min; + (void) dio_interval_doublings; + (void) dio_redundancy_constant; + return -1; +#endif +} + +int ws_bbr_rpl_parameters_get(int8_t interface_id, uint8_t *dio_interval_min, uint8_t *dio_interval_doublings, uint8_t *dio_redundancy_constant) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + if (!dio_interval_min || !dio_interval_doublings || !dio_redundancy_constant) { + return -1; + } + + ws_rpl_cfg_t cfg; + if (ws_cfg_rpl_get(&cfg, NULL) < 0) { + return -2; + } + + *dio_interval_min = cfg.dio_interval_min; + *dio_interval_doublings = cfg.dio_interval_doublings; + *dio_redundancy_constant = cfg.dio_redundancy_constant; + + return 0; +#else + (void) dio_interval_min; + (void) dio_interval_doublings; + (void) dio_redundancy_constant; + return -1; +#endif +} + +int ws_bbr_rpl_parameters_validate(int8_t interface_id, uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + ws_rpl_cfg_t cfg; + if (ws_cfg_rpl_get(&cfg, NULL) < 0) { + return -2; + } + + if (dio_interval_min > 0) { + cfg.dio_interval_min = dio_interval_min; + } + if (dio_interval_doublings > 0) { + cfg.dio_interval_doublings = dio_interval_doublings; + } + if (dio_redundancy_constant != 0xff) { + cfg.dio_redundancy_constant = dio_redundancy_constant; + } + + if (ws_cfg_rpl_validate(NULL, &cfg) < 0) { + return -3; + } + + return 0; +#else + (void) dio_interval_min; + (void) dio_interval_doublings; + (void) dio_redundancy_constant; + return -1; +#endif +} + +int ws_bbr_pan_configuration_set(int8_t interface_id, uint16_t pan_id) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return -1; + } + + cfg.network_pan_id = pan_id; + + if (ws_cfg_gen_set(cur, NULL, &cfg, 0) < 0) { + return -2; + } + + return 0; +#else + (void) pan_id; + return -1; +#endif +} + +int ws_bbr_pan_configuration_get(int8_t interface_id, uint16_t *pan_id) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + if (!pan_id) { + return -1; + } + + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return -2; + } + + *pan_id = cfg.network_pan_id; + + return 0; +#else + (void) pan_id; + return -1; +#endif +} + +int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return -1; + } + + cfg.network_pan_id = pan_id; + + if (ws_cfg_gen_validate(NULL, &cfg) < 0) { + return -2; + } + + return 0; +#else + (void) pan_id; + return -1; +#endif +} diff --git a/source/6LoWPAN/ws/ws_bbr_api_internal.h b/source/6LoWPAN/ws/ws_bbr_api_internal.h index b07565a96c..ee465916af 100644 --- a/source/6LoWPAN/ws/ws_bbr_api_internal.h +++ b/source/6LoWPAN/ws/ws_bbr_api_internal.h @@ -25,6 +25,8 @@ extern uint16_t test_pan_size_override; void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); +void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur); + uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur); void ws_bbr_rpl_config(protocol_interface_info_entry_t *cur, uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase); @@ -35,6 +37,7 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur); #else #define ws_bbr_seconds_timer( cur, seconds) +#define ws_bbr_pan_version_increase(cur) #define ws_bbr_pan_size(cur) 0 #define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase) #define ws_bbr_ready_to_start(cur) true diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 6aaffc1a8e..6a6079acfa 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -17,6 +17,7 @@ #include #include "nsconfig.h" +#ifdef HAVE_WS #include "ns_types.h" #include "ns_trace.h" #include "net_interface.h" @@ -38,6 +39,7 @@ #include "RPL/rpl_protocol.h" #include "RPL/rpl_control.h" #include "RPL/rpl_data.h" +#include "RPL/rpl_policy.h" #include "Common_Protocols/icmpv6.h" #include "Common_Protocols/icmpv6_radv.h" #include "Common_Protocols/ipv6_constants.h" @@ -54,6 +56,7 @@ #include "6LoWPAN/ws/ws_neighbor_class.h" #include "6LoWPAN/ws/ws_ie_lib.h" #include "6LoWPAN/ws/ws_stats.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/lowpan_adaptation_interface.h" #include "Service_Libs/etx/etx.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" @@ -72,7 +75,7 @@ #define TRACE_GROUP "wsbs" -#ifdef HAVE_WS + static void ws_bootstrap_event_handler(arm_event_s *event); static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state); @@ -98,6 +101,8 @@ static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr); static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data); +static void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]); + 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); @@ -151,17 +156,28 @@ static void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entr mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(interface)); } +static void ws_address_reregister_trig(struct protocol_interface_info_entry *interface) +{ + if (interface->ws_info->aro_registration_timer == 0) { + interface->ws_info->aro_registration_timer = WS_NEIGHBOR_NUD_TIMEOUT; + } +} + static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_entry *interface, const struct if_address_entry *addr, if_address_callback_t reason) { /* No need for LL address registration */ - if (addr->source == ADDR_SOURCE_UNKNOWN) { + if (addr->source == ADDR_SOURCE_UNKNOWN || !interface->ws_info) { return; } if (reason == ADDR_CALLBACK_DAD_COMPLETE) { //Trig Address Registartion only when Bootstrap is ready - if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE && addr->source != ADDR_SOURCE_DHCP) { - tr_debug("Address registration %s", trace_ipv6(addr->address)); - rpl_control_register_address(interface, addr->address); + if (addr->source != ADDR_SOURCE_DHCP) { + if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE) { + tr_debug("Address registration %s", trace_ipv6(addr->address)); + ws_address_registration_update(interface, addr->address); + } + ws_address_reregister_trig(interface); + } if (addr_ipv6_scope(addr->address, interface) > IPV6_SCOPE_LINK_LOCAL) { // at least ula address available inside mesh. @@ -188,12 +204,6 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_ break; } } - } else if (reason == ADDR_CALLBACK_TIMER) { - if (addr->source != ADDR_SOURCE_DHCP) { - tr_debug("Address Re registration %s", trace_ipv6(addr->address)); - //Register - rpl_control_register_address(interface, addr->address); - } } } @@ -409,11 +419,10 @@ static fhss_ws_neighbor_timing_info_t *ws_get_neighbor_info(const fhss_api_t *ap } static void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry *cur, const fhss_ws_configuration_t *fhss_configuration) { - memcpy(cur->ws_info->hopping_schdule.channel_mask, fhss_configuration->channel_mask, sizeof(uint32_t) * 8); cur->ws_info->hopping_schdule.uc_fixed_channel = fhss_configuration->unicast_fixed_channel; cur->ws_info->hopping_schdule.bc_fixed_channel = fhss_configuration->broadcast_fixed_channel; // Read UC channel function from WS info because FHSS might be temporarily configured to fixed channel during discovery. - cur->ws_info->hopping_schdule.uc_channel_function = cur->ws_info->fhss_uc_channel_function; + cur->ws_info->hopping_schdule.uc_channel_function = cur->ws_info->cfg->fhss.fhss_uc_channel_function; cur->ws_info->hopping_schdule.bc_channel_function = fhss_configuration->ws_bc_channel_function; cur->ws_info->hopping_schdule.fhss_bc_dwell_interval = fhss_configuration->fhss_bc_dwell_interval; cur->ws_info->hopping_schdule.fhss_broadcast_interval = fhss_configuration->fhss_broadcast_interval; @@ -421,65 +430,129 @@ static void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry cur->ws_info->hopping_schdule.fhss_bsi = fhss_configuration->bsi; } +static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded_channel_data_t *excluded_data, const uint32_t *selected_channel_mask, uint16_t number_of_channels) +{ + bool active_range = false; + + //Clear Old Data + memset(excluded_data, 0, sizeof(ws_excluded_channel_data_t)); + + for (uint8_t i = 0; i < number_of_channels; i++) { + if (selected_channel_mask[0 + (i / 32)] & (1 << (i % 32))) { + if (active_range) { + //Mark range stop here + active_range = false; + } + } else { + //Mark excluded channel + //Swap Order already here + excluded_data->channel_mask[0 + (i / 32)] |= 1 << (31 - (i % 32)); + excluded_data->excluded_channel_count++; + + if (excluded_data->excluded_range_length < WS_EXCLUDED_MAX_RANGE_TO_SEND) { + if (!active_range) { + excluded_data->excluded_range_length++; + active_range = true; + //Set start channel + excluded_data->exluded_range[excluded_data->excluded_range_length - 1].range_start = i; + } else { + excluded_data->exluded_range[excluded_data->excluded_range_length - 1].range_end = i; + } + } + } + } + + excluded_data->channel_mask_bytes_inline = ((number_of_channels + 7) / 8); + + uint8_t channel_plan = 0; + if (excluded_data->excluded_range_length == 0) { + excluded_data->excuded_channel_ctrl = WS_EXC_CHAN_CTRL_NONE; + } else if (excluded_data->excluded_range_length <= WS_EXCLUDED_MAX_RANGE_TO_SEND) { + + uint8_t range_length = (excluded_data->excluded_range_length * 4) + 3; + if (range_length <= ((number_of_channels + 7) / 8) + 6) { + excluded_data->excuded_channel_ctrl = WS_EXC_CHAN_CTRL_RANGE; + } else { + excluded_data->excuded_channel_ctrl = WS_EXC_CHAN_CTRL_BITMASK; + channel_plan = 1; + } + } else { + excluded_data->excuded_channel_ctrl = WS_EXC_CHAN_CTRL_BITMASK; + channel_plan = 1; + } + tr_debug("Excluded ctrl %u, exluded channel count %u, total domain channels %u", excluded_data->excuded_channel_ctrl, excluded_data->excluded_channel_count, number_of_channels); + return channel_plan; +} + +static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration) +{ + ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); + ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); + // using bitwise AND operation for user set channel mask to remove channels not allowed in this device + for (uint8_t n = 0; n < 8; n++) { + fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n]; + } + //Update Exluded channels + cur->ws_info->hopping_schdule.channel_plan = ws_generate_exluded_channel_list_from_active_channels(&cur->ws_info->hopping_schdule.excluded_channels, fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels); +} + static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur) { fhss_api_t *fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); + fhss_ws_configuration_t fhss_configuration; + memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); if (!fhss_api) { // When FHSS doesn't exist yet, create one - fhss_ws_configuration_t fhss_configuration; - memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t)); - ws_generate_channel_list(fhss_configuration.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); + ws_fhss_configure_channel_masks(cur, &fhss_configuration); - // using bitwise AND operation for user set channel mask to remove channels not allowed in this device - for (uint8_t n = 0; n < 8; n++) { - fhss_configuration.channel_mask[n] &= cur->ws_info->fhss_channel_mask[n]; - } - - fhss_configuration.fhss_uc_dwell_interval = cur->ws_info->fhss_uc_dwell_interval; - fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; - fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_bc_channel_function; - fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->fhss_bc_dwell_interval; - fhss_configuration.fhss_broadcast_interval = cur->ws_info->fhss_bc_interval; + fhss_configuration.fhss_uc_dwell_interval = cur->ws_info->cfg->fhss.fhss_uc_dwell_interval; + fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->cfg->fhss.fhss_uc_channel_function; + 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_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr); + if (!fhss_api) { return -1; } ns_sw_mac_fhss_register(cur->mac_api, fhss_api); } else { // Read defaults from the configuration to help FHSS testing - const fhss_ws_configuration_t *fhss_configuration = ns_fhss_ws_configuration_get(fhss_api); - if (!fhss_configuration) { + const fhss_ws_configuration_t *fhss_configuration_copy = ns_fhss_ws_configuration_get(fhss_api); + if (!fhss_configuration_copy) { // no configuration set yet return 0; } - memcpy(cur->ws_info->fhss_channel_mask, fhss_configuration->channel_mask, sizeof(uint32_t) * 8); - cur->ws_info->fhss_uc_channel_function = fhss_configuration->ws_uc_channel_function; - cur->ws_info->fhss_bc_channel_function = fhss_configuration->ws_bc_channel_function; - cur->ws_info->fhss_bc_dwell_interval = fhss_configuration->fhss_bc_dwell_interval; - cur->ws_info->fhss_bc_interval = fhss_configuration->fhss_broadcast_interval; - cur->ws_info->fhss_uc_dwell_interval = fhss_configuration->fhss_uc_dwell_interval; - cur->ws_info->fhss_bc_fixed_channel = fhss_configuration->broadcast_fixed_channel; - cur->ws_info->fhss_uc_fixed_channel = fhss_configuration->unicast_fixed_channel; + fhss_configuration = *fhss_configuration_copy; + //Overwrite domain channel setup this will over write a default 35 channel + int num_of_channels = channel_list_count_channels(fhss_configuration_copy->unicast_channel_mask); + cur->ws_info->hopping_schdule.number_of_channels = (uint8_t) num_of_channels; + memcpy(cur->ws_info->cfg->fhss.fhss_channel_mask, fhss_configuration_copy->unicast_channel_mask, sizeof(uint32_t) * 8); + cur->ws_info->cfg->fhss.fhss_uc_channel_function = fhss_configuration_copy->ws_uc_channel_function; + cur->ws_info->cfg->fhss.fhss_bc_channel_function = fhss_configuration_copy->ws_bc_channel_function; + cur->ws_info->cfg->fhss.fhss_bc_dwell_interval = fhss_configuration_copy->fhss_bc_dwell_interval; + cur->ws_info->cfg->fhss.fhss_bc_interval = fhss_configuration_copy->fhss_broadcast_interval; + cur->ws_info->cfg->fhss.fhss_uc_dwell_interval = fhss_configuration_copy->fhss_uc_dwell_interval; + cur->ws_info->cfg->fhss.fhss_bc_fixed_channel = fhss_configuration_copy->broadcast_fixed_channel; + cur->ws_info->cfg->fhss.fhss_uc_fixed_channel = fhss_configuration_copy->unicast_fixed_channel; + ws_fhss_configure_channel_masks(cur, &fhss_configuration); + ns_fhss_ws_configuration_set(fhss_api, &fhss_configuration); } + return 0; } + static int8_t ws_fhss_set_defaults(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration) { - fhss_configuration->fhss_uc_dwell_interval = cur->ws_info->fhss_uc_dwell_interval; - fhss_configuration->ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; - fhss_configuration->ws_bc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_bc_channel_function; - fhss_configuration->fhss_bc_dwell_interval = cur->ws_info->fhss_bc_dwell_interval; - fhss_configuration->fhss_broadcast_interval = cur->ws_info->fhss_bc_interval; - if (cur->ws_info->fhss_uc_fixed_channel != 0xffff) { - fhss_configuration->unicast_fixed_channel = cur->ws_info->fhss_uc_fixed_channel; - } - fhss_configuration->broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel; - ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); - - // using bitwise AND operation for user set channel mask to remove channels not allowed in this device - for (uint8_t n = 0; n < 8; n++) { - fhss_configuration->channel_mask[n] &= cur->ws_info->fhss_channel_mask[n]; + fhss_configuration->fhss_uc_dwell_interval = cur->ws_info->cfg->fhss.fhss_uc_dwell_interval; + fhss_configuration->ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->cfg->fhss.fhss_uc_channel_function; + 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; + if (cur->ws_info->cfg->fhss.fhss_uc_fixed_channel != 0xffff) { + fhss_configuration->unicast_fixed_channel = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel; } + fhss_configuration->broadcast_fixed_channel = cur->ws_info->cfg->fhss.fhss_bc_fixed_channel; return 0; } static int8_t ws_fhss_border_router_configure(protocol_interface_info_entry_t *cur) @@ -492,6 +565,7 @@ static int8_t ws_fhss_border_router_configure(protocol_interface_info_entry_t *c memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); } ws_fhss_set_defaults(cur, &fhss_configuration); + ws_fhss_configure_channel_masks(cur, &fhss_configuration); ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); ws_bootstrap_llc_hopping_update(cur, &fhss_configuration); @@ -515,17 +589,19 @@ static int8_t ws_fhss_configure(protocol_interface_info_entry_t *cur, bool disco if (ns_fhss_ws_configuration_get(cur->ws_info->fhss_api)) { memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t)); + ws_fhss_set_defaults(cur, &fhss_configuration); + ws_fhss_configure_channel_masks(cur, &fhss_configuration); } // Discovery is done using fixed channel if (discovery) { fhss_configuration.ws_uc_channel_function = WS_FIXED_CHANNEL; } else { - fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->fhss_uc_channel_function; + fhss_configuration.ws_uc_channel_function = (fhss_ws_channel_functions)cur->ws_info->cfg->fhss.fhss_uc_channel_function; } fhss_configuration.ws_bc_channel_function = WS_FIXED_CHANNEL; fhss_configuration.fhss_broadcast_interval = 0; - uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); - uint8_t tmp_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); + uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); + uint8_t tmp_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); fhss_configuration.unicast_fixed_channel = tmp_uc_fixed_channel; fhss_configuration.broadcast_fixed_channel = tmp_bc_fixed_channel; ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration); @@ -577,12 +653,12 @@ static void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry fhss_configuration.ws_bc_channel_function = (fhss_ws_channel_functions)neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function; if (fhss_configuration.ws_bc_channel_function == WS_FIXED_CHANNEL) { cur->ws_info->hopping_schdule.bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel; - cur->ws_info->fhss_bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel; + cur->ws_info->cfg->fhss.fhss_bc_fixed_channel = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.fixed_channel; } fhss_configuration.bsi = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id; fhss_configuration.fhss_bc_dwell_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval; fhss_configuration.fhss_broadcast_interval = neighbor_info->ws_neighbor->fhss_data.bc_timing_info.broadcast_interval; - fhss_configuration.broadcast_fixed_channel = cur->ws_info->fhss_bc_fixed_channel; + fhss_configuration.broadcast_fixed_channel = cur->ws_info->cfg->fhss.fhss_bc_fixed_channel; neighbor_info->ws_neighbor->synch_done = true; } @@ -822,6 +898,7 @@ void ws_bootstrap_configuration_reset(protocol_interface_info_entry_t *cur) cur->ws_info->trickle_pa_running = false; cur->ws_info->trickle_pcs_running = false; cur->ws_info->trickle_pc_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; //cur->mac_security_key_usage_update_cb = ws_management_mac_security_key_update_cb; return; @@ -896,12 +973,54 @@ static parent_info_t *ws_bootstrap_candidate_parent_get_best(protocol_interface_ return ns_list_get_first(&cur->ws_info->parent_list_reserved); } +static void ws_bootstrap_decode_exclude_range_to_mask_by_range(void *mask_buffer, ws_excluded_channel_range_t *range_info, uint16_t number_of_channels) +{ + uint16_t range_start, range_stop; + uint8_t mask_index = 0; + //uint8_t channel_index = 0; + uint8_t *range_ptr = range_info->range_start; + uint32_t *mask_ptr = mask_buffer; + while (range_info->number_of_range) { + range_start = common_read_16_bit_inverse(range_ptr); + range_ptr += 2; + range_stop = common_read_16_bit_inverse(range_ptr); + range_ptr += 2; + range_info->number_of_range--; + for (uint16_t channel = 0; channel < number_of_channels; channel++) { + + if (channel && (channel % 32 == 0)) { + mask_index++; + //channel_index = 0; + } + if (channel >= range_start && channel <= range_stop) { + //mask_ptr[mask_index] |= 1 << (31 - channel_index); + mask_ptr[0 + (channel / 32)] |= 1 << (31 - (channel % 32)); + } else if (channel > range_stop) { + break; + } + } + } +} + static void ws_bootstrap_candidate_parent_store(parent_info_t *parent, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us, ws_pan_information_t *pan_information) { parent->ws_utt = *ws_utt; // Saved from unicast IE parent->ws_us = *ws_us; + //copy excluded channel here if it is inline + if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) { + memset(parent->excluded_channel_data, 0, 32); + //Decode Range to mask here + ws_bootstrap_decode_exclude_range_to_mask_by_range(parent->excluded_channel_data, &parent->ws_us.excluded_channels.range, 256); + parent->ws_us.excluded_channels.mask.channel_mask = parent->excluded_channel_data; + parent->ws_us.excluded_channels.mask.mask_len_inline = 32; + parent->ws_us.excluded_channel_ctrl = WS_EXC_CHAN_CTRL_BITMASK; + } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) { + parent->ws_us.excluded_channels.mask.channel_mask = parent->excluded_channel_data; + memcpy(parent->excluded_channel_data, ws_us->excluded_channels.mask.channel_mask, ws_us->excluded_channels.mask.mask_len_inline); + } + // Saved from Pan information, do not overwrite pan_version as it is not valid here parent->pan_information.pan_size = pan_information->pan_size; parent->pan_information.routing_cost = pan_information->routing_cost; @@ -1088,6 +1207,13 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf return; } + if (ws_us->excluded_channel_ctrl) { + //Validate that we can storage data + if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK && ws_us->excluded_channels.mask.mask_len_inline > 32) { + return; + } + } + // Check pan flags so that it is valid if (!pan_information.rpl_routing_method) { // NOT RPL routing @@ -1130,9 +1256,9 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf if (rpl_control_is_dodag_parent(cur, ll_address)) { // automatic network size adjustment learned - if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC && + if (cur->ws_info->cfg->gen.network_size == NETWORK_SIZE_AUTOMATIC && cur->ws_info->pan_information.pan_size != pan_information.pan_size) { - ws_common_network_size_configure(cur, pan_information.pan_size); + ws_cfg_network_size_configure(cur, pan_information.pan_size); } cur->ws_info->pan_information.pan_size = pan_information.pan_size; @@ -1247,8 +1373,12 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry if (cur->ws_info->configuration_learned) { tr_info("PAN Config analyse own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); if (cur->ws_info->pan_information.pan_version == pan_version) { - // Same version heard so it is consistent - trickle_consistent_heard(&cur->ws_info->trickle_pan_config); + //Check if Trgigle have been resetted in short time skip this then + if (cur->ws_info->trickle_pc_consistency_block_period == 0) { + // Same version heard so it is consistent + trickle_consistent_heard(&cur->ws_info->trickle_pan_config); + } + if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_SOFT_SYNCH); } @@ -1264,6 +1394,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry // older version heard ignoring the message return; } + cur->ws_info->trickle_pc_consistency_block_period = WS_CONFIG_CONSISTENT_FILTER_PERIOD; } } @@ -1278,7 +1409,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); // restart PAN version timer - cur->ws_info->pan_version_timeout_timer = ws_common_version_timeout_get(cur->ws_info->network_size_config); + cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; cur->ws_info->pan_information.pan_version = pan_version; ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr); @@ -1359,7 +1490,20 @@ static bool ws_channel_plan_one_compare(ws_channel_plan_one_t *rx_plan, ws_hoppi return true; } +bool ws_bootstrap_validate_channel_plan(ws_us_ie_t *ws_us, struct protocol_interface_info_entry *cur) +{ + if (ws_us->channel_plan == 0) { + if (!ws_channel_plan_zero_compare(&ws_us->plan.zero, &cur->ws_info->hopping_schdule)) { + return false; + } + } else if (ws_us->channel_plan == 1) { + if (!ws_channel_plan_one_compare(&ws_us->plan.one, &cur->ws_info->hopping_schdule)) { + return false; + } + } + return true; +} static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type) @@ -1375,7 +1519,7 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c case WS_FT_PAN_ADVERT_SOL: case WS_FT_PAN_CONF_SOL: //Check Network Name - if (!ws_bootstrap_network_name_matches(ie_ext, cur->ws_info->network_name)) { + if (!ws_bootstrap_network_name_matches(ie_ext, cur->ws_info->cfg->gen.network_name)) { // Not in our network return; } @@ -1399,21 +1543,10 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c return; } - //Compare Unicast channel Plan - if (ws_us.channel_plan != cur->ws_info->hopping_schdule.channel_plan) { + if (!ws_bootstrap_validate_channel_plan(&ws_us, cur)) { return; } - if (ws_us.channel_plan == 0) { - if (!ws_channel_plan_zero_compare(&ws_us.plan.zero, &cur->ws_info->hopping_schdule)) { - return; - } - } else if (ws_us.channel_plan == 1) { - if (!ws_channel_plan_one_compare(&ws_us.plan.one, &cur->ws_info->hopping_schdule)) { - return; - } - } - //Handle Message's switch (message_type) { case WS_FT_PAN_ADVERT: @@ -1507,13 +1640,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent //Read current timestamp uint32_t time_from_last_unicast_shedule = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor); - uint32_t min_timeout; - if (interface->ws_info->network_size_config == NETWORK_SIZE_LARGE) { - min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE; - } else { - min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; - } - if (time_from_last_unicast_shedule > min_timeout) { + if (time_from_last_unicast_shedule > interface->ws_info->cfg->timing.temp_link_min_timeout) { //Accept only Enough Old Device if (!neighbor_entry_ptr) { //Accept first compare @@ -1615,12 +1742,19 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, if (time_from_start > WS_NEIGHBOR_NUD_TIMEOUT) { - if (ipv6_neighbour_has_registered_by_eui64(&cur->ipv6_neighbour_cache, entry_ptr->mac64)) { - // This is our child with valid ARO registration Change link timeout to future we check at 2 minute intervals - entry_ptr->lifetime = entry_ptr->lifetime + 120; - if (entry_ptr->lifetime > entry_ptr->link_lifetime) { - entry_ptr->lifetime = entry_ptr->link_lifetime; - } + /* For parents ARO registration is sent in link timeout times + * For candidate parents NUD is needed + * For children NUD is sent only at very close to end + */ + if (ipv6_neighbour_has_registered_by_eui64(&cur->ipv6_neighbour_cache, entry_ptr->mac64) && + (time_from_start < WS_NEIGHBOR_NUD_TIMEOUT * 1.8)) { + /* This is our child with valid ARO registration send NUD if we are close to delete + * + * if ARO was received link is considered active so this is only in case of very long ARO registration times + * + * 1.8 means with link timeout of 30 minutes that NUD is sent 6 minutes before timeout + * + */ return false; } @@ -1766,6 +1900,11 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) goto init_fail; } + if (ws_cfg_settings_interface_set(cur) < 0) { + ret_val = -4; + goto init_fail; + } + if (ws_bootstrap_tasklet_init(cur) != 0) { ret_val = -4; goto init_fail; @@ -1786,6 +1925,10 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) ret_val = -4; goto init_fail; } + if (ws_pae_controller_configure(cur, &cur->ws_info->cfg->sec_timer, &cur->ws_info->cfg->sec_prot) < 0) { + ret_val = -4; + goto init_fail; + } //Init EAPOL PDU handler and register it to MPX if (ws_eapol_pdu_init(cur) < 0) { @@ -1817,19 +1960,13 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) // Set the default parameters for MPL cur->mpl_proactive_forwarding = true; - cur->mpl_data_trickle_params.Imin = MPL_MS_TO_TICKS(DATA_MESSAGE_IMIN); - cur->mpl_data_trickle_params.Imax = MPL_MS_TO_TICKS(DATA_MESSAGE_IMAX); - cur->mpl_data_trickle_params.TimerExpirations = DATA_MESSAGE_TIMER_EXPIRATIONS; - cur->mpl_data_trickle_params.k = 8; - // Specification is ruling out the compression mode, but we are now doing it. cur->mpl_seed = true; cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_IPV6_SRC_FOR_DOMAIN; - cur->mpl_seed_set_entry_lifetime = MPL_SEED_SET_ENTRY_TIMEOUT; cur->mpl_control_trickle_params.TimerExpirations = 0; - mpl_domain_create(cur, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL); + cur->mpl_domain = mpl_domain_create(cur, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL); addr_add_group(cur, ADDR_REALM_LOCAL_ALL_NODES); addr_add_group(cur, ADDR_REALM_LOCAL_ALL_ROUTERS); @@ -1858,9 +1995,26 @@ int ws_bootstrap_restart(int8_t interface_id) return 0; } +int ws_bootstrap_restart_delayed(int8_t interface_id) +{ + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur || !cur->ws_info) { + return -1; + } + ws_bootstrap_state_change(cur, ER_WAIT_RESTART); + cur->bootsrap_state_machine_cnt = 3; + return 0; +} + int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_channel_configuration_s rf_configs) { mlme_set_t set_request; + // Set MAC mode + phy_802_15_4_mode_t mac_mode = IEEE_802_15_4G_2012; + set_request.attr = mac802_15_4Mode; + set_request.value_pointer = &mac_mode; + set_request.value_size = sizeof(phy_802_15_4_mode_t); + cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request); // Set RF configuration set_request.attr = macRfConfiguration; set_request.value_pointer = &rf_configs; @@ -1898,6 +2052,19 @@ int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t return 0; } +static int ws_bootstrap_set_domain_rf_config(protocol_interface_info_entry_t *cur) +{ + phy_rf_channel_configuration_s rf_configs; + rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000; + rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing); + rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); + rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); + rf_configs.modulation = M_2FSK; + rf_configs.number_of_channels = cur->ws_info->hopping_schdule.number_of_channels; + ws_bootstrap_set_rf_config(cur, rf_configs); + return 0; +} + static void ws_bootstrap_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, bool coordinator) { mlme_start_t start_req; @@ -1928,7 +2095,7 @@ static void ws_bootstrap_fhss_activate(protocol_interface_info_entry_t *cur) mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true); cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE; ws_bootstrap_mac_security_enable(cur); - ws_bootstrap_mac_activate(cur, cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->network_pan_id, true); + ws_bootstrap_mac_activate(cur, cur->ws_info->cfg->fhss.fhss_uc_fixed_channel, cur->ws_info->network_pan_id, true); return; } @@ -1986,10 +2153,33 @@ static void ws_set_fhss_hop(protocol_interface_info_entry_t *cur) tr_debug("own hop: %u, own rank: %u, rank inc: %u", own_hop, own_rank, rank_inc); } -static void ws_address_registration_update(protocol_interface_info_entry_t *interface) +static void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]) +{ + rpl_control_register_address(interface, addr); + // Timer is used only to track full registrations + + if (addr != NULL && interface->ws_info->aro_registration_timer) { + // Single address update and timer is running + return; + } + + if (interface->ws_info->aro_registration_timer == 0) { + // Timer expired and check if we have valid address to register + ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) { + if (!addr_is_ipv6_link_local(address->address)) { + // We have still valid addresses let the timer run for next period + tr_info("ARO registration timer start"); + interface->ws_info->aro_registration_timer = WS_NEIGHBOR_NUD_TIMEOUT; + return; + } + } + } +} + +static void ws_address_parent_update(protocol_interface_info_entry_t *interface) { - rpl_control_register_address(interface, NULL); tr_info("RPL parent update ... register ARO"); + ws_address_registration_update(interface, NULL); } static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) @@ -2014,9 +2204,13 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) // Set both own port and border router port to 10253 ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT); // Set network information to PAE - ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name); + ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name); // Network key is valid ws_pae_controller_nw_key_valid(cur); + + // After successful DAO ACK connection to border router is verified + cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; + } ws_set_fhss_hop(cur); @@ -2031,7 +2225,7 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) */ } else if (event == RPL_EVENT_DAO_PARENT_ADD) { - ws_address_registration_update(cur); + ws_address_parent_update(cur); } cur->ws_info->rpl_state = event; tr_info("RPL event %d", event); @@ -2046,7 +2240,7 @@ static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[ if (register_status) { protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); if (cur) { - rpl_control_register_address(cur, prefix); + ws_address_reregister_trig(cur); } } else { //Delete dhcpv6 client @@ -2114,13 +2308,18 @@ static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t static bool ws_rpl_candidate_soft_filtering(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) { + //If bootstrap active we not need any candidate filtering + if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) && (ws_info(cur)->cfg->gen.network_size == NETWORK_SIZE_CERTIFICATE)) { + return true; + } + //Already many candidates - if (rpl_control_candidate_list_size(cur, instance) > cur->ws_info->rpl_parent_candidate_max) { + if (rpl_control_candidate_list_size(cur, instance) > cur->ws_info->cfg->rpl.rpl_parent_candidate_max) { return false; } //Already enough selected candidates - if (rpl_control_selected_parent_count(cur, instance) >= cur->ws_info->rpl_selected_parent_max) { + if (rpl_control_selected_parent_count(cur, instance) >= cur->ws_info->cfg->rpl.rpl_selected_parent_max) { return false; } @@ -2267,12 +2466,20 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) rpl_control_process_routes(protocol_6lowpan_rpl_domain, false); // Wi-SUN assumes that no default route needed rpl_control_request_parent_link_confirmation(true); rpl_control_set_dio_multicast_min_config_advertisment_count(WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT); + rpl_control_set_address_registration_timeout((WS_NEIGHBOR_LINK_TIMEOUT / 60) + 1); rpl_control_set_dao_retry_count(WS_MAX_DAO_RETRIES); rpl_control_set_initial_dao_ack_wait(WS_MAX_DAO_INITIAL_TIMEOUT); rpl_control_set_mrhof_parent_set_size(WS_MAX_PARENT_SET_COUNT); if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { rpl_control_set_memory_limits(WS_NODE_RPL_SOFT_MEM_LIMIT, WS_NODE_RPL_HARD_MEM_LIMIT); } + // Set RPL Link ETX Validation Threshold to 2.5 - 33.0 + // This setup will set ETX 0x800 to report ICMP error 18% probability + // When ETX start go over 0x280 forward dropping probability start increase linear to 100% at 0x2100 + rpl_policy_forward_link_etx_threshold_set(0x280, 0x2100); + + // Set the minimum target refresh to sen DAO registrations before pan timeout + rpl_control_set_minimum_dao_target_refresh(WS_RPL_DAO_MAX_TIMOUT); cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event } @@ -2280,7 +2487,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) static void ws_bootstrap_network_start(protocol_interface_info_entry_t *cur) { //Set Network names, Pan information configure, hopping schedule & GTKHash - ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->network_name, strlen(cur->ws_info->network_name)); + ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->cfg->gen.network_name, strlen(cur->ws_info->cfg->gen.network_name)); ws_llc_set_pan_information_pointer(cur, &cur->ws_info->pan_information); } @@ -2289,11 +2496,12 @@ static void ws_bootstrap_network_discovery_configure(protocol_interface_info_ent // Reset information to defaults cur->ws_info->network_pan_id = 0xffff; - ws_common_regulatory_domain_config(cur); + ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule); + ws_bootstrap_set_domain_rf_config(cur); ws_fhss_configure(cur, true); //Set Network names, Pan information configure, hopping schedule & GTKHash - ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->network_name, strlen(cur->ws_info->network_name)); + ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->cfg->gen.network_name, strlen(cur->ws_info->cfg->gen.network_name)); } @@ -2302,12 +2510,14 @@ static void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur) cur->ws_info->trickle_pa_running = true; trickle_start(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); cur->ws_info->trickle_pc_running = true; + cur->ws_info->trickle_pc_consistency_block_period = 0; trickle_start(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); } static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur) { - cur->ws_info->pan_version_timer = 1; + (void)cur; + ws_bbr_pan_version_increase(cur); } // Start network scan @@ -2319,7 +2529,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); cur->nwk_nd_re_scan_count = 0; cur->ws_info->configuration_learned = false; - cur->ws_info->pan_version_timeout_timer = 0; + cur->ws_info->pan_timeout_timer = 0; // Clear learned neighbours ws_bootstrap_neighbor_list_clean(cur); @@ -2369,7 +2579,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) static void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur) { // Set PAN ID and network name to controller - ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name); + ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name); ws_pae_controller_authenticate(cur); } @@ -2431,6 +2641,12 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_ ws_bootstrap_candidate_parent_free(cur, target_eui_64); // Go back for network scanning ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN); + + // Start PAS interval between imin - imax. + cur->ws_info->trickle_pas_running = true; + trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); + + // Parent selection is made before imin/2 so if there is parent candidates solicit is not sent cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, cur->ws_info->trickle_params_pan_discovery.Imin >> 1); tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); } else { @@ -2467,10 +2683,15 @@ static void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur) // routers wait until RPL root is contacted ws_bootstrap_state_change(cur, ER_RPL_SCAN); //For Large network and medium shuold do passive scan - if (cur->ws_info->network_size_config == NETWORK_SIZE_LARGE || cur->ws_info->network_size_config == NETWORK_SIZE_MEDIUM) { + if (cur->ws_info->cfg->gen.network_size > NETWORK_SIZE_SMALL) { // Set timeout for check to 30 -60 seconds cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_INITIAL_TIMEOUT / 2, WS_RPL_DIS_INITIAL_TIMEOUT); } + /* While in Join State 4, if a non Border Router determines it has been unable to communicate with the PAN Border + * Router for an interval of PAN_TIMEOUT, a node MUST assume failure of the PAN Border Router and MUST + * Transition to Join State 1 + */ + cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; } /* @@ -2505,9 +2726,9 @@ void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *c static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asynch_request_t *async_req) { memset(&async_req->channel_list, 0, sizeof(channel_list_s)); - if (cur->ws_info->fhss_uc_channel_function == WS_FIXED_CHANNEL) { + if (cur->ws_info->cfg->fhss.fhss_uc_channel_function == WS_FIXED_CHANNEL) { //SET 1 Channel only - uint16_t channel_number = cur->ws_info->fhss_uc_fixed_channel; + uint16_t channel_number = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel; async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32)); } else { ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); @@ -2581,6 +2802,10 @@ static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entr //Scale to 128 based ETX (local read retur 0x100 - 0xffff etx = etx >> 1; } + // Make the 0xffff as maximum value + if (ws_neighbor->routing_cost + etx > 0xffff) { + return 0xffff; + } return ws_neighbor->routing_cost + etx; } @@ -2685,27 +2910,41 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; cur->mac_parameters->mac_default_key_index = 0; + // Clear parent blacklist + blacklist_clear(); + // All trickle timers stopped to allow entry from any state cur->ws_info->trickle_pa_running = false; cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { tr_info("Border router start network"); + if (!ws_bbr_ready_to_start(cur)) { // Wi-SUN not started yet we wait for Border router permission ws_bootstrap_state_change(cur, ER_WAIT_RESTART); cur->nwk_nd_re_scan_count = randLIB_get_random_in_range(40, 100); return; } + // Clear Old information from stack + + ws_nud_table_reset(cur); + ws_bootstrap_neighbor_list_clean(cur); + ws_bootstrap_ip_stack_reset(cur); ws_pae_controller_auth_init(cur); // Randomize fixed channels. Only used if channel plan is fixed. - cur->ws_info->fhss_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); - cur->ws_info->fhss_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); - cur->ws_info->network_pan_id = randLIB_get_random_in_range(0, 0xfffd); + cur->ws_info->cfg->fhss.fhss_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); + cur->ws_info->cfg->fhss.fhss_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels); + if (cur->ws_info->cfg->gen.network_pan_id == 0xffff) { + cur->ws_info->network_pan_id = randLIB_get_random_in_range(0, 0xfffd); + } else { + cur->ws_info->network_pan_id = cur->ws_info->cfg->gen.network_pan_id; + } cur->ws_info->pan_information.pan_size = 0; cur->ws_info->pan_information.pan_version = randLIB_get_random_in_range(0, 0xffff); cur->ws_info->pan_information.routing_cost = 0; @@ -2715,12 +2954,13 @@ static void ws_bootstrap_event_handler(arm_event_s *event) uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur); ws_llc_set_gtkhash(cur, gtkhash); - cur->ws_info->pan_version_timer = ws_common_version_lifetime_get(cur->ws_info->network_size_config); + ws_bbr_pan_version_increase(cur); // Set default parameters for FHSS when starting a discovery + ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule); ws_fhss_border_router_configure(cur); + ws_bootstrap_set_domain_rf_config(cur); ws_bootstrap_fhss_activate(cur); - ws_bootstrap_event_operation_start(cur); uint8_t ll_addr[16]; addr_interface_get_ll_address(cur, ll_addr, 1); @@ -2735,10 +2975,12 @@ static void ws_bootstrap_event_handler(arm_event_s *event) ws_eapol_auth_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, ll_addr, PAE_AUTH_SOCKET_PORT); // Set PAN ID and network name to controller - ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->network_name); + ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name); // 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); + + ws_bootstrap_event_operation_start(cur); break; } ws_pae_controller_supp_init(cur); @@ -2757,6 +2999,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; // Build list of possible neighbours and learn first broadcast schedule @@ -2769,6 +3012,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; // Activate RPL // Activate IPv6 stack ws_bootstrap_ip_stack_activate(cur); @@ -2788,6 +3032,7 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; // Indicate PAE controller that bootstrap is ready ws_pae_controller_bootstrap_done(cur); @@ -2947,6 +3192,7 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur) cur->ws_info->trickle_pc_running = false; cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + cur->ws_info->trickle_pc_consistency_block_period = 0; ws_fhss_configure(cur, false); ws_bootstrap_start_authentication(cur); break; @@ -3007,27 +3253,58 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t tr_info("Send PAN advertisement"); ws_bootstrap_pan_advert(cur); } - if (cur->ws_info->trickle_pc_running && - trickle_timer(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery, ticks)) { - // send PAN Configuration - tr_info("Send PAN configuration"); - ws_bootstrap_pan_config(cur); + if (cur->ws_info->trickle_pc_running) { + + if (cur->ws_info->trickle_pc_consistency_block_period) { + if (ticks >= cur->ws_info->trickle_pc_consistency_block_period) { + cur->ws_info->trickle_pc_consistency_block_period = 0; + } else { + cur->ws_info->trickle_pc_consistency_block_period -= ticks; + } + } + + if (trickle_timer(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery, ticks)) { + // send PAN Configuration + tr_info("Send PAN configuration"); + ws_bootstrap_pan_config(cur); + } } } void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) { - if (cur->ws_info->pan_version_timeout_timer) { + /* Border router keep alive check + */ + if (cur->ws_info->pan_timeout_timer) { // PAN version timer running - if (cur->ws_info->pan_version_timeout_timer > seconds) { - cur->ws_info->pan_version_timeout_timer -= seconds; + if (cur->ws_info->pan_timeout_timer > seconds) { + cur->ws_info->pan_timeout_timer -= seconds; + if (cur->ws_info->pan_timeout_timer < cur->ws_info->cfg->timing.pan_timeout / 10) { + /* pan timeout is closing need to verify that DAO is tested before the pan times out. + This will give some extra time for RPL to find better parents. + Border router liveliness can be checked from version number change or from successful DAO registrations + in this case there has not been any version number changes during this PAN lifetime. + */ + rpl_control_dao_timeout(cur->rpl_domain, 20); + } } else { // Border router has timed out + cur->ws_info->pan_timeout_timer = 0; tr_warn("Border router has timed out"); ws_bootstrap_event_discovery_start(cur); } } + if (cur->ws_info->aro_registration_timer) { + if (cur->ws_info->aro_registration_timer > seconds) { + cur->ws_info->aro_registration_timer -= seconds; + } else { + // Update all addressess. This function will update the timer value if needed + cur->ws_info->aro_registration_timer = 0; + ws_address_registration_update(cur, NULL); + } + } + } void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) @@ -3050,7 +3327,7 @@ void ws_secondary_parent_update(protocol_interface_info_entry_t *interface) if (interface->ws_info) { ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) { if (!addr_is_ipv6_link_local(address->address)) { - ws_address_registration_update(interface); + ws_address_parent_update(interface); } } } diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index 062dc767a3..949eac4a99 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -30,6 +30,7 @@ typedef enum { #ifdef HAVE_WS struct llc_neighbour_req; +struct ws_us_ie; int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode); @@ -37,6 +38,8 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur); int ws_bootstrap_restart(int8_t interface_id); +int ws_bootstrap_restart_delayed(int8_t interface_id); + int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_channel_configuration_s rf_configs); int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address); @@ -76,6 +79,8 @@ bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur); void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, struct llc_neighbour_req *neighbor_info); +bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_interface_info_entry *cur); + #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) diff --git a/source/6LoWPAN/ws/ws_cfg_settings.c b/source/6LoWPAN/ws/ws_cfg_settings.c new file mode 100644 index 0000000000..bebe6627d7 --- /dev/null +++ b/source/6LoWPAN/ws/ws_cfg_settings.c @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "nsconfig.h" +#include "ns_types.h" +#include "ns_list.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "net_interface.h" +#include "eventOS_event.h" +#include "NWK_INTERFACE/Include/protocol.h" +#include "6LoWPAN/ws/ws_common.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" +#include "6LoWPAN/ws/ws_bbr_api_internal.h" +#include "6LoWPAN/ws/ws_bootstrap.h" +#include "6LoWPAN/ws/ws_pae_controller.h" +#include "ws_management_api.h" +#include "MPL/mpl.h" + +#define TRACE_GROUP "cstr" + +#ifdef HAVE_WS + +#define CFG_SETTINGS_OK 0 +#define CFG_SETTINGS_CHANGED 1 + +#define CFG_FLAGS_DISABLE_VAL_SET 0x01 +#define CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET 0x02 +#define CFG_FLAGS_FORCE_INTERNAL_CONFIG 0x04 +#define CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE 0x08 + +#define TRICKLE_IMIN_60_SECS 60 +#define TRICKLE_IMIN_30_SECS 30 +#define TRICKLE_IMIN_15_SECS 15 + +typedef struct ws_cfg_nw_size_s { + ws_timing_cfg_t timing; /**< Timing configuration */ + ws_rpl_cfg_t rpl; /**< RPL configuration */ + ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */ +} ws_cfg_nw_size_t; + +typedef int8_t (*ws_cfg_default_set)(void *cfg); +typedef int8_t (*ws_cfg_validate)(void *cfg, void *new_cfg); +typedef int8_t (*ws_cfg_set)(protocol_interface_info_entry_t *cur, void *cfg, void *new_cfg, uint8_t *flags); + +typedef struct { + ws_cfg_default_set default_set; + ws_cfg_validate validate; + ws_cfg_set set; + uint16_t setting_offset; +} ws_cfg_cb_t; + +typedef union { + ws_gen_cfg_t gen; + ws_phy_cfg_t phy; + ws_timing_cfg_t timing; + ws_rpl_cfg_t rpl; + ws_fhss_cfg_t fhss; + ws_mpl_cfg_t mpl; + ws_sec_timer_cfg_t sec_timer; + ws_sec_prot_cfg_t sec_prot; +} ws_cfgs_t; + +static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate valid_cb, ws_cfgs_t *external_cfg, uint8_t *cfg_flags, uint8_t *flags); + +static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg); +static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg); +static void ws_cfg_network_size_config_set_large(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_rpl_default_set(ws_rpl_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); + +#define CFG_CB(default_cb, validate_cb, set_cb, offset) \ + { \ + .default_set = (ws_cfg_default_set) default_cb, \ + .validate = (ws_cfg_validate) validate_cb, \ + .set = (ws_cfg_set) set_cb, \ + .setting_offset = offset, \ + } + +// Create validate and set callback table +static const ws_cfg_cb_t cfg_cb[] = { + // Network size configuration must be done first + CFG_CB(ws_cfg_network_size_default_set, ws_cfg_network_size_validate, ws_cfg_network_size_set, offsetof(ws_cfg_t, gen)), + CFG_CB(ws_cfg_gen_default_set, ws_cfg_gen_validate, ws_cfg_gen_set, offsetof(ws_cfg_t, gen)), + CFG_CB(ws_cfg_phy_default_set, ws_cfg_phy_validate, ws_cfg_phy_set, offsetof(ws_cfg_t, phy)), + CFG_CB(ws_cfg_timing_default_set, ws_cfg_timing_validate, ws_cfg_timing_set, offsetof(ws_cfg_t, timing)), + CFG_CB(ws_cfg_rpl_default_set, ws_cfg_rpl_validate, ws_cfg_rpl_set, offsetof(ws_cfg_t, rpl)), + CFG_CB(ws_cfg_mpl_default_set, ws_cfg_mpl_validate, ws_cfg_mpl_set, offsetof(ws_cfg_t, mpl)), + CFG_CB(ws_cfg_fhss_default_set, ws_cfg_fhss_validate, ws_cfg_fhss_set, offsetof(ws_cfg_t, fhss)), + CFG_CB(ws_cfg_sec_timer_default_set, ws_cfg_sec_timer_validate, ws_cfg_sec_timer_set, offsetof(ws_cfg_t, sec_timer)), + CFG_CB(ws_cfg_sec_prot_default_set, ws_cfg_sec_prot_validate, ws_cfg_sec_prot_set, offsetof(ws_cfg_t, sec_prot)), +}; + +#define CFG_CB_NUM (sizeof(cfg_cb) / sizeof(ws_cfg_cb_t)) + +// Wisun configuration storage +ws_cfg_t ws_cfg; + +// If automatic network size mode; external configuration shown to towards users of external APIs +ws_cfg_nw_size_t *nw_size_external_cfg = NULL; + +static int8_t ws_cfg_to_get(ws_cfgs_t **cfg, ws_cfgs_t *new_cfg, ws_cfg_validate valid_cb, ws_cfgs_t *ws_cfg_ptr, uint8_t *cfg_flags, uint8_t *flags) +{ + // In case target configuration is not set, uses ws_cfg storage + if (*cfg == NULL) { + // In case external configuration is not same as internal + if (nw_size_external_cfg && (!flags || !(*flags & CFG_FLAGS_FORCE_INTERNAL_CONFIG))) { + if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.timing) { + *cfg = (ws_cfgs_t *) &nw_size_external_cfg->timing; + } else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.rpl) { + *cfg = (ws_cfgs_t *) &nw_size_external_cfg->rpl; + } else if (ws_cfg_ptr == (ws_cfgs_t *) &ws_cfg.sec_prot) { + *cfg = (ws_cfgs_t *) &nw_size_external_cfg->sec_prot; + } else { + *cfg = ws_cfg_ptr; + } + } else { + *cfg = ws_cfg_ptr; + } + + if (valid_cb) { + int8_t ret = valid_cb(*cfg, new_cfg); + // On failure and if nothing is changed, returns + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + } + } + + if (!cfg_flags) { + return CFG_SETTINGS_CHANGED; + } + *cfg_flags = 0; + if (flags) { + *cfg_flags |= *flags; + } + if (nw_size_external_cfg && !(*cfg_flags & CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET)) { + *cfg_flags |= CFG_FLAGS_DISABLE_VAL_SET; + } + + return CFG_SETTINGS_CHANGED; +} + +#ifdef FEA_TRACE_SUPPORT +static void ws_cfg_trace(ws_cfgs_t *cfg, ws_cfgs_t *new_cfg, uint8_t size, char *name) +{ + uint8_t *start = 0; + uint8_t *end = 0; + + tr_debug("config set: %s, changed fields:", name); + + bool print_index = true; + for (uint8_t i = 0; i < size; i++) { + if (((uint8_t *) cfg)[i] != ((uint8_t *) new_cfg)[i]) { + if (print_index) { + start = &((uint8_t *) new_cfg)[i]; + print_index = false; + } + end = &((uint8_t *) new_cfg)[i]; + } else { + if (start && end) { + tr_debug("i: %p v: %s ", (void *)(start - ((uint8_t *) new_cfg)), trace_array(start, end - start + 1)); + } + start = NULL; + end = NULL; + print_index = true; + } + } + + if (start && end) { + tr_debug("i: %p v: %s ", (void *)(start - ((uint8_t *) new_cfg)), trace_array(start, end - start + 1)); + } +} +#else +#define ws_cfg_trace(cfg, new_cfg, size, name) +#endif + +static int8_t ws_cfg_network_size_default_set(ws_gen_cfg_t *cfg) +{ + cfg->network_size = NETWORK_SIZE_MEDIUM; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags) +{ + ws_gen_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, 0); + + if (cfg->network_size != new_cfg->network_size) { + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +typedef void (*ws_cfg_network_size_config_set_size)(ws_cfg_nw_size_t *cfg); + +int8_t ws_cfg_network_size_set(protocol_interface_info_entry_t *cur, ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg, uint8_t *flags) +{ + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_network_size_validate, (ws_cfgs_t *) &ws_cfg.gen, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + uint8_t old_network_size = cfg->network_size; + + // If network size configuration has not changed, returns + if (cfg->network_size == new_cfg->network_size) { + return CFG_SETTINGS_OK; + } + + cfg->network_size = new_cfg->network_size; + + ws_cfg_nw_size_t nw_size_cfg; + ws_cfg_timing_get(&nw_size_cfg.timing, NULL); + ws_cfg_rpl_get(&nw_size_cfg.rpl, NULL); + ws_cfg_sec_prot_get(&nw_size_cfg.sec_prot, NULL); + + ws_cfg_network_size_config_set_size set_function = NULL; + + if (cfg->network_size == NETWORK_SIZE_CERTIFICATE) { + set_function = ws_cfg_network_size_config_set_certificate; + } else if (cfg->network_size <= NETWORK_SIZE_SMALL || cfg->network_size == NETWORK_SIZE_AUTOMATIC) { + set_function = ws_cfg_network_size_config_set_small; + } else if (cfg->network_size <= NETWORK_SIZE_MEDIUM) { + set_function = ws_cfg_network_size_config_set_medium; + } else { + set_function = ws_cfg_network_size_config_set_large; + } + + // Overrides the values on the new configuration + if (set_function != NULL) { + set_function(&nw_size_cfg); + } + + /* If no longer in an automatic network size mode, frees automatic configuration, + so that new configuration is set */ + if (nw_size_external_cfg && old_network_size == NETWORK_SIZE_AUTOMATIC) { + ns_dyn_mem_free(nw_size_external_cfg); + nw_size_external_cfg = NULL; + } + + uint8_t set_flags = 0; + if (cfg->network_size == NETWORK_SIZE_AUTOMATIC) { + set_flags = CFG_FLAGS_DISABLE_VAL_SET; + } + /* Sets values if changed or network size has been previously automatic (to make sure + the settings are in sync */ + if (ws_cfg_timing_validate(&ws_cfg.timing, &nw_size_cfg.timing) == CFG_SETTINGS_CHANGED || + old_network_size == NETWORK_SIZE_AUTOMATIC) { + ws_cfg_timing_set(cur, &ws_cfg.timing, &nw_size_cfg.timing, &set_flags); + } + if (ws_cfg_rpl_validate(&ws_cfg.rpl, &nw_size_cfg.rpl) == CFG_SETTINGS_CHANGED || + old_network_size == NETWORK_SIZE_AUTOMATIC) { + ws_cfg_rpl_set(cur, &ws_cfg.rpl, &nw_size_cfg.rpl, &set_flags); + } + if (ws_cfg_sec_prot_validate(&ws_cfg.sec_prot, &nw_size_cfg.sec_prot) == CFG_SETTINGS_CHANGED || + old_network_size == NETWORK_SIZE_AUTOMATIC) { + ws_cfg_sec_prot_set(cur, &ws_cfg.sec_prot, &nw_size_cfg.sec_prot, &set_flags); + } + + // If is in an automatic network size mode, updates automatic configuration + if (cfg->network_size == NETWORK_SIZE_AUTOMATIC && cur) { + ws_cfg_network_size_configure(cur, cur->ws_info->pan_information.pan_size); + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size) +{ + // Read settings that are affected by network size + ws_cfg_nw_size_t new_nw_size_cfg; + uint8_t flags = CFG_FLAGS_OVERRIDE_DISABLE_VAL_SET | CFG_FLAGS_FORCE_INTERNAL_CONFIG; + ws_cfg_timing_get(&new_nw_size_cfg.timing, &flags); + ws_cfg_rpl_get(&new_nw_size_cfg.rpl, &flags); + ws_cfg_sec_prot_get(&new_nw_size_cfg.sec_prot, &flags); + + if (!nw_size_external_cfg) { + nw_size_external_cfg = ns_dyn_mem_alloc(sizeof(ws_cfg_nw_size_t)); + if (!nw_size_external_cfg) { + return -1; + } + memcpy(nw_size_external_cfg, &new_nw_size_cfg, sizeof(ws_cfg_nw_size_t)); + } + + // Small + if (network_size < 100) { + // Automatic + ws_cfg_network_size_config_set_small(&new_nw_size_cfg); + } else if (network_size < 300) { + // Medium + ws_cfg_network_size_config_set_medium(&new_nw_size_cfg); + } else { + // Large + ws_cfg_network_size_config_set_large(&new_nw_size_cfg); + } + + ws_cfg_timing_set(cur, NULL, &new_nw_size_cfg.timing, &flags); + ws_cfg_rpl_set(cur, NULL, &new_nw_size_cfg.rpl, &flags); + ws_cfg_sec_prot_set(cur, NULL, &new_nw_size_cfg.sec_prot, &flags); + + return CFG_SETTINGS_OK; +} + +static void ws_cfg_network_size_config_set_small(ws_cfg_nw_size_t *cfg) +{ + // Configure the Wi-SUN timing trickle parameter + cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds + cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds + cfg->timing.disc_trickle_k = 1; + cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT; + cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; + + // RPL configuration + cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds + cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128 + cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled + cfg->rpl.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; + cfg->rpl.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->rpl.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; + cfg->rpl.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX; + + // EAPOL configuration + cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; + cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; + cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; + cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; + cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_SMALL; +} + +static void ws_cfg_network_size_config_set_medium(ws_cfg_nw_size_t *cfg) +{ + // Configure the Wi-SUN timing trickle parameters + cfg->timing.disc_trickle_imin = TRICKLE_IMIN_30_SECS; // 30 seconds + cfg->timing.disc_trickle_imax = TRICKLE_IMIN_30_SECS << 5; // 960 seconds; 16 minutes + cfg->timing.disc_trickle_k = 1; + cfg->timing.pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT; + cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; + + // RPL configuration + cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_MEDIUM; // 15; 32s + cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_MEDIUM; // 2; 1024s + cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_MEDIUM; // 10 + cfg->rpl.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; + cfg->rpl.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->rpl.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; + cfg->rpl.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX; + + // EAPOL configuration + cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; + cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; + cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; + cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; + cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_MEDIUM; +} + +static void ws_cfg_network_size_config_set_large(ws_cfg_nw_size_t *cfg) +{ + // Configure the Wi-SUN timing trickle parameters + cfg->timing.disc_trickle_imin = TRICKLE_IMIN_60_SECS; // 60 seconds + cfg->timing.disc_trickle_imax = TRICKLE_IMIN_60_SECS << 4; // 960 seconds; 16 minutes + cfg->timing.disc_trickle_k = 1; + cfg->timing.pan_timeout = PAN_VERSION_LARGE_NETWORK_TIMEOUT; + cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE; + + // RPL configuration + cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_LARGE; // 19; 524s, 9min + cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_LARGE; // 1; 1024s, 17min + cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_LARGE; // 10 + cfg->rpl.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; + cfg->rpl.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->rpl.rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; + cfg->rpl.rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX; + + // EAPOL configuration + cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_LARGE_IMIN; + cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_LARGE_IMAX; + cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; + cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_LARGE; + cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_LARGE; +} + +static void ws_cfg_network_size_config_set_certificate(ws_cfg_nw_size_t *cfg) +{ + // Configure the Wi-SUN timing trickle parameters + cfg->timing.disc_trickle_imin = TRICKLE_IMIN_15_SECS; // 15 seconds + cfg->timing.disc_trickle_imax = TRICKLE_IMIN_15_SECS << 2; // 60 seconds + cfg->timing.disc_trickle_k = 1; + cfg->timing.pan_timeout = PAN_VERSION_SMALL_NETWORK_TIMEOUT; + cfg->timing.temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; + + // RPL configuration (small) + cfg->rpl.dio_interval_min = WS_RPL_DIO_IMIN_SMALL; // 15; 32s seconds + cfg->rpl.dio_interval_doublings = WS_RPL_DIO_DOUBLING_SMALL; // 2; 128 + cfg->rpl.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL; // Disabled + cfg->rpl.dag_max_rank_increase = WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE; + cfg->rpl.min_hop_rank_increase = WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE; + cfg->rpl.rpl_parent_candidate_max = WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX; + cfg->rpl.rpl_selected_parent_max = WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX; + + // EAPOL configuration + cfg->sec_prot.sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; + cfg->sec_prot.sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; + cfg->sec_prot.sec_prot_trickle_timer_exp = SEC_PROT_TIMER_EXPIRATIONS; + cfg->sec_prot.sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; + cfg->sec_prot.sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_SMALL; +} + +static int8_t ws_cfg_gen_default_set(ws_gen_cfg_t *cfg) +{ + memset(cfg->network_name, 0, sizeof(cfg->network_name)); + cfg->network_pan_id = 0xffff; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_gen_get(ws_gen_cfg_t *cfg, uint8_t *flags) +{ + ws_gen_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_gen_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.gen, 0, 0); + + if (strlen(new_cfg->network_name) > 32) { + return CFG_SETTINGS_ERROR_GEN_CONF; + } + + // Regulator domain, operating mode or class has changed + if (strcmp(cfg->network_name, new_cfg->network_name) != 0 || + cfg->network_pan_id != new_cfg->network_pan_id) { + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +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) +{ + (void) cur; + (void) flags; + + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_gen_validate, (ws_cfgs_t *) &ws_cfg.gen, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_gen_cfg_t), "gen"); + + if (&cfg->network_name != &new_cfg->network_name) { + strncpy(cfg->network_name, new_cfg->network_name, 32); + } + cfg->network_pan_id = new_cfg->network_pan_id; + + if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) { + ws_bootstrap_restart_delayed(cur->id); + } + + return CFG_SETTINGS_OK; +} + +static int8_t ws_cfg_phy_default_set(ws_phy_cfg_t *cfg) +{ + // FHSS configuration + cfg->regulatory_domain = REG_DOMAIN_EU; + cfg->operating_mode = OPERATING_MODE_3; + cfg->operating_class = 2; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_phy_get(ws_phy_cfg_t *cfg, uint8_t *flags) +{ + ws_phy_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.phy, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_phy_validate(ws_phy_cfg_t *cfg, ws_phy_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.phy, 0, 0); + + // Regulator domain, operating mode or class has changed + if (cfg->regulatory_domain != new_cfg->regulatory_domain || + cfg->operating_mode != new_cfg->operating_mode || + cfg->operating_class != new_cfg->operating_class) { + + ws_hopping_schedule_t hopping_schdule = { + .regulatory_domain = new_cfg->regulatory_domain, + .operating_mode = new_cfg->operating_mode, + .operating_class = new_cfg->operating_class + }; + + // Check that new settings are valid + if (ws_common_regulatory_domain_config(NULL, &hopping_schdule) < 0) { + // Invalid regulatory domain set + return CFG_SETTINGS_ERROR_PHY_CONF; + } + + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +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) +{ + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_phy_validate, (ws_cfgs_t *) &ws_cfg.phy, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + // Check settings and configure interface + if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + cur->ws_info->hopping_schdule.regulatory_domain = new_cfg->regulatory_domain; + cur->ws_info->hopping_schdule.operating_mode = new_cfg->operating_mode; + cur->ws_info->hopping_schdule.operating_class = new_cfg->operating_class; + + if (ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule) < 0) { + return CFG_SETTINGS_ERROR_PHY_CONF; + } + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_phy_cfg_t), "phy"); + + *cfg = *new_cfg; + + if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) { + ws_bootstrap_restart_delayed(cur->id); + } + + return CFG_SETTINGS_OK; +} + +static 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_30_SECS; // 30 seconds + cfg->disc_trickle_imax = TRICKLE_IMIN_30_SECS << 5; // 960 seconds; 16 minutes + cfg->disc_trickle_k = 1; + cfg->pan_timeout = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT; + cfg->temp_link_min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_timing_get(ws_timing_cfg_t *cfg, uint8_t *flags) +{ + ws_timing_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.timing, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_timing_validate(ws_timing_cfg_t *cfg, ws_timing_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.timing, 0, 0); + + if (cfg->disc_trickle_imin != new_cfg->disc_trickle_imin || + cfg->disc_trickle_imax != new_cfg->disc_trickle_imax || + cfg->disc_trickle_k != new_cfg->disc_trickle_k || + cfg->pan_timeout != new_cfg->pan_timeout || + cfg->temp_link_min_timeout != new_cfg->temp_link_min_timeout) { + + // Discovery Imin 1 to 255 + if (new_cfg->disc_trickle_imin < 1 || new_cfg->disc_trickle_imin > 255) { + return CFG_SETTINGS_ERROR_TIMING_CONF; + } + // Discovery Imax, 1 to 8 doublings of imin + if (new_cfg->disc_trickle_imax < new_cfg->disc_trickle_imin * 2 || + new_cfg->disc_trickle_imax > new_cfg->disc_trickle_imin * 256) { + return CFG_SETTINGS_ERROR_TIMING_CONF; + } + // Discovery k parameter defined to be 1 + if (cfg->disc_trickle_k != 1) { + return CFG_SETTINGS_ERROR_TIMING_CONF; + } + + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +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) +{ + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_timing_validate, (ws_cfgs_t *) &ws_cfg.timing, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + cur->ws_info->trickle_params_pan_discovery.Imin = new_cfg->disc_trickle_imin * 10; + cur->ws_info->trickle_params_pan_discovery.Imax = new_cfg->disc_trickle_imax * 10; + cur->ws_info->trickle_params_pan_discovery.k = new_cfg->disc_trickle_k; + cur->ws_info->trickle_params_pan_discovery.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE; + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_timing_cfg_t), "timing"); + + *cfg = *new_cfg; + + return CFG_SETTINGS_OK; +} + +static int8_t ws_cfg_rpl_default_set(ws_rpl_cfg_t *cfg) +{ + // Something in between + // imin: 15 (32s) + // doublings:5 (960s) + // redundancy; 10 + //ws_bbr_rpl_config(cur, 15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); + + cfg->dio_interval_min = 15; // 32s + cfg->dio_interval_doublings = 5; // 1024s + cfg->dio_redundancy_constant = 10; + cfg->dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE; + cfg->min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE; + cfg->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; + cfg->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_rpl_get(ws_rpl_cfg_t *cfg, uint8_t *flags) +{ + ws_rpl_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.rpl, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_rpl_validate(ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.rpl, 0, 0); + + if (cfg->dio_interval_min != new_cfg->dio_interval_min || + cfg->dio_interval_doublings != new_cfg->dio_interval_doublings || + cfg->dio_redundancy_constant != new_cfg->dio_redundancy_constant || + cfg->dag_max_rank_increase != new_cfg->dag_max_rank_increase || + cfg->min_hop_rank_increase != new_cfg->min_hop_rank_increase || + cfg->rpl_parent_candidate_max != new_cfg->rpl_parent_candidate_max || + cfg->rpl_selected_parent_max != new_cfg->rpl_selected_parent_max) { + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_rpl_set(protocol_interface_info_entry_t *cur, ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg, uint8_t *flags) +{ + (void) cur; + (void) flags; + + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_rpl_validate, (ws_cfgs_t *) &ws_cfg.rpl, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + if (!(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + // cur is optional, default values are for Wi-SUN small network parameters, + ws_bbr_rpl_config(cur, new_cfg->dio_interval_min, new_cfg->dio_interval_doublings, + new_cfg->dio_redundancy_constant, new_cfg->dag_max_rank_increase, + new_cfg->min_hop_rank_increase); + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_rpl_cfg_t), "rpl"); + + *cfg = *new_cfg; + + return CFG_SETTINGS_OK; +} + +static int8_t ws_cfg_mpl_default_set(ws_mpl_cfg_t *cfg) +{ + // MPL configuration + cfg->mpl_trickle_imin = DATA_MESSAGE_IMIN; + cfg->mpl_trickle_imax = DATA_MESSAGE_IMAX; + cfg->mpl_trickle_k = DATA_MESSAGE_K; + cfg->mpl_trickle_timer_exp = DATA_MESSAGE_TIMER_EXPIRATIONS; + cfg->seed_set_entry_lifetime = MPL_SEED_SET_ENTRY_TIMEOUT; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_mpl_get(ws_mpl_cfg_t *cfg, uint8_t *flags) +{ + ws_mpl_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.mpl, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_mpl_validate(ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.mpl, 0, 0); + + // MPL configuration has changed + if (cfg->mpl_trickle_imin != new_cfg->mpl_trickle_imin || + cfg->mpl_trickle_imax != new_cfg->mpl_trickle_imax || + cfg->mpl_trickle_k != new_cfg->mpl_trickle_k || + cfg->mpl_trickle_timer_exp != new_cfg->mpl_trickle_timer_exp || + cfg->seed_set_entry_lifetime != new_cfg->seed_set_entry_lifetime) { + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_mpl_set(protocol_interface_info_entry_t *cur, ws_mpl_cfg_t *cfg, ws_mpl_cfg_t *new_cfg, uint8_t *flags) +{ + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_mpl_validate, (ws_cfgs_t *) &ws_cfg.mpl, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + cur->mpl_data_trickle_params.Imin = MPL_MS_TO_TICKS(new_cfg->mpl_trickle_imin * 1000); + cur->mpl_data_trickle_params.Imax = MPL_MS_TO_TICKS(new_cfg->mpl_trickle_imax * 1000); + cur->mpl_data_trickle_params.k = new_cfg->mpl_trickle_k; + cur->mpl_data_trickle_params.TimerExpirations = new_cfg->mpl_trickle_timer_exp; + cur->mpl_seed_set_entry_lifetime = new_cfg->seed_set_entry_lifetime; + + if (cur->mpl_domain) { + // Update MPL settings + mpl_domain_change_timing(cur->mpl_domain, &cur->mpl_data_trickle_params, cur->mpl_seed_set_entry_lifetime); + } + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_mpl_cfg_t), "mpl"); + + *cfg = *new_cfg; + + return CFG_SETTINGS_OK; +} + +static 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; + cfg->fhss_bc_fixed_channel = 0xffff; + cfg->fhss_uc_dwell_interval = WS_FHSS_UC_DWELL_INTERVAL; + cfg->fhss_bc_interval = WS_FHSS_BC_INTERVAL; + cfg->fhss_bc_dwell_interval = WS_FHSS_BC_DWELL_INTERVAL; + cfg->fhss_uc_channel_function = WS_DH1CF; + cfg->fhss_bc_channel_function = WS_DH1CF; + + for (uint8_t n = 0; n < 8; n++) { + cfg->fhss_channel_mask[n] = 0xffffffff; + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_fhss_get(ws_fhss_cfg_t *cfg, uint8_t *flags) +{ + ws_fhss_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.fhss, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_fhss_validate(ws_fhss_cfg_t *cfg, ws_fhss_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.fhss, 0, 0); + + if (memcmp(cfg->fhss_channel_mask, new_cfg->fhss_channel_mask, sizeof(uint32_t) * 8) != 0 || + cfg->fhss_uc_dwell_interval != new_cfg->fhss_uc_dwell_interval || + cfg->fhss_bc_dwell_interval != new_cfg->fhss_bc_dwell_interval || + cfg->fhss_bc_interval != new_cfg->fhss_bc_interval || + cfg->fhss_uc_channel_function != new_cfg->fhss_uc_channel_function || + cfg->fhss_bc_channel_function != new_cfg->fhss_bc_channel_function || + cfg->fhss_uc_fixed_channel != new_cfg->fhss_uc_fixed_channel || + cfg->fhss_bc_fixed_channel != new_cfg->fhss_bc_fixed_channel) { + + if (new_cfg->fhss_uc_dwell_interval < 15) { + return CFG_SETTINGS_ERROR_FHSS_CONF; + } + + if (new_cfg->fhss_bc_dwell_interval < 15) { + return CFG_SETTINGS_ERROR_FHSS_CONF; + } + + if (cfg->fhss_uc_channel_function != WS_FIXED_CHANNEL && + cfg->fhss_uc_channel_function != WS_VENDOR_DEF_CF && + cfg->fhss_uc_channel_function != WS_DH1CF && + cfg->fhss_uc_channel_function != WS_TR51CF) { + return CFG_SETTINGS_ERROR_FHSS_CONF; + } + + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +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) +{ + (void) cur; + + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_fhss_validate, (ws_cfgs_t *) &ws_cfg.fhss, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_fhss_cfg_t), "fhss"); + + *cfg = *new_cfg; + + if (cfg->fhss_uc_channel_function == WS_FIXED_CHANNEL && cfg->fhss_uc_fixed_channel == 0xffff) { + cfg->fhss_uc_fixed_channel = 0; + tr_warn("UC fixed channel not configured. Set to 0"); + } + + if (cfg->fhss_uc_channel_function != WS_FIXED_CHANNEL) { + cfg->fhss_uc_fixed_channel = 0xffff; + } + + if (cfg->fhss_bc_channel_function == WS_FIXED_CHANNEL && cfg->fhss_bc_fixed_channel == 0xffff) { + cfg->fhss_bc_fixed_channel = 0; + tr_warn("BC fixed channel not configured. Set to 0"); + } + + if (cfg->fhss_bc_channel_function != WS_FIXED_CHANNEL) { + cfg->fhss_bc_fixed_channel = 0xffff; + } + + if (cur && !(cfg_flags & CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE)) { + ws_bootstrap_restart_delayed(cur->id); + } + + return CFG_SETTINGS_OK; +} + +static int8_t ws_cfg_sec_timer_default_set(ws_sec_timer_cfg_t *cfg) +{ + cfg->gtk_expire_offset = DEFAULT_GTK_EXPIRE_OFFSET; + cfg->pmk_lifetime = DEFAULT_PMK_LIFETIME; + cfg->ptk_lifetime = DEFAULT_PTK_LIFETIME; + cfg->gtk_new_act_time = DEFAULT_GTK_NEW_ACTIVATION_TIME; + cfg->revocat_lifetime_reduct = DEFAULT_REVOCATION_LIFETIME_REDUCTION; + cfg->gtk_request_imin = DEFAULT_GTK_REQUEST_IMIN; + cfg->gtk_request_imax = DEFAULT_GTK_REQUEST_IMAX; + cfg->gtk_max_mismatch = DEFAULT_GTK_MAX_MISMATCH; + cfg->gtk_new_install_req = DEFAULT_GTK_NEW_INSTALL_REQUIRED; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg, uint8_t *flags) +{ + ws_sec_timer_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.sec_timer, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.sec_timer, 0, 0); + + if (cfg->gtk_expire_offset != new_cfg->gtk_expire_offset || + cfg->pmk_lifetime != new_cfg->pmk_lifetime || + cfg->ptk_lifetime != new_cfg->ptk_lifetime || + cfg->gtk_new_act_time != new_cfg->gtk_new_act_time || + cfg->revocat_lifetime_reduct != new_cfg->revocat_lifetime_reduct || + cfg->gtk_request_imin != new_cfg->gtk_request_imin || + cfg->gtk_request_imax != new_cfg->gtk_request_imax || + cfg->gtk_max_mismatch != new_cfg->gtk_max_mismatch || + cfg->gtk_new_install_req != new_cfg->gtk_new_install_req) { + + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg, uint8_t *flags) +{ + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_sec_timer_validate, (ws_cfgs_t *) &ws_cfg.sec_timer, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + ws_pae_controller_configure(cur, new_cfg, NULL); + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_sec_timer_cfg_t), "sec_timer"); + + *cfg = *new_cfg; + + return CFG_SETTINGS_OK; +} + +static int8_t ws_cfg_sec_prot_default_set(ws_sec_prot_cfg_t *cfg) +{ + cfg->sec_prot_trickle_imin = SEC_PROT_SMALL_IMIN; + cfg->sec_prot_trickle_imax = SEC_PROT_SMALL_IMAX; + cfg->sec_prot_trickle_timer_exp = 2; + cfg->sec_prot_retry_timeout = SEC_PROT_RETRY_TIMEOUT_SMALL; + cfg->sec_max_ongoing_authentication = MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_MEDIUM; + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg, uint8_t *flags) +{ + ws_sec_prot_cfg_t *get_cfg = NULL; + ws_cfg_to_get((ws_cfgs_t **) &get_cfg, NULL, NULL, (ws_cfgs_t *) &ws_cfg.sec_prot, 0, flags); + *cfg = *get_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg) +{ + ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, NULL, (ws_cfgs_t *) &ws_cfg.sec_prot, 0, 0); + + if (cfg->sec_prot_trickle_imin != new_cfg->sec_prot_trickle_imin || + cfg->sec_prot_trickle_imax != new_cfg->sec_prot_trickle_imax || + cfg->sec_prot_trickle_timer_exp != new_cfg->sec_prot_trickle_timer_exp || + cfg->sec_prot_retry_timeout != new_cfg->sec_prot_retry_timeout || + cfg->sec_max_ongoing_authentication != new_cfg->sec_max_ongoing_authentication) { + + return CFG_SETTINGS_CHANGED; + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg, uint8_t *flags) +{ + uint8_t cfg_flags; + int8_t ret = ws_cfg_to_get((ws_cfgs_t **) &cfg, (ws_cfgs_t *) new_cfg, (ws_cfg_validate) ws_cfg_sec_prot_validate, (ws_cfgs_t *) &ws_cfg.sec_prot, &cfg_flags, flags); + if (ret != CFG_SETTINGS_CHANGED) { + return ret; + } + + if (cur && !(cfg_flags & CFG_FLAGS_DISABLE_VAL_SET)) { + ws_pae_controller_configure(cur, NULL, new_cfg); + } + + if (cfg == new_cfg) { + return CFG_SETTINGS_OK; + } + + ws_cfg_trace((ws_cfgs_t *) cfg, (ws_cfgs_t *) new_cfg, sizeof(ws_sec_prot_cfg_t), "sec_prot"); + + *cfg = *new_cfg; + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_settings_init(void) +{ + ws_cfg_settings_default_set(); + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_settings_default_set(void) +{ + int8_t ret_value = 0; + + // Set default configuration values + for (uint8_t index = 0; index < CFG_CB_NUM; index++) { + if (cfg_cb[index].default_set) { + if (cfg_cb[index].default_set( + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset) < 0) { + ret_value = CFG_SETTINGS_OTHER_ERROR; + } + } + } + + // Set new configuration values + for (uint8_t index = 0; index < CFG_CB_NUM; index++) { + uint8_t flags = 0; + if (cfg_cb[index].set(NULL, + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + &flags) < 0) { + tr_info("FATAL CONFIG FAILURE"); + ret_value = CFG_SETTINGS_OTHER_ERROR; + } + } + + return ret_value; +} + +int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur) +{ + int8_t ret_value = 0; + + cur->ws_info->cfg = &ws_cfg; + + // Set new configuration values + for (uint8_t index = 0; index < CFG_CB_NUM; index++) { + uint8_t flags = CFG_FLAGS_BOOTSTRAP_RESTART_DISABLE; + // Validation + if (cfg_cb[index].set) { + if (cfg_cb[index].set(cur, + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + &flags) < 0) { + tr_info("FATAL CONFIG FAILURE"); + ret_value = CFG_SETTINGS_OTHER_ERROR; + } + } + } + + return ret_value; +} + +int8_t ws_cfg_settings_get(protocol_interface_info_entry_t *cur, ws_cfg_t *cfg) +{ + (void) cur; + + *cfg = ws_cfg; + + ws_cfg_timing_get(&cfg->timing, NULL); + ws_cfg_rpl_get(&cfg->rpl, NULL); + ws_cfg_sec_prot_get(&cfg->sec_prot, NULL); + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_settings_validate(protocol_interface_info_entry_t *cur, struct ws_cfg_s *new_cfg) +{ + (void) cur; + + // Validate new configuration values + for (uint8_t index = 0; index < CFG_CB_NUM; index++) { + if (cfg_cb[index].validate) { + int8_t ret = cfg_cb[index].validate( + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + ((uint8_t *)new_cfg) + cfg_cb[index].setting_offset); + if (ret < 0) { + // Validation failed + return ret; + } + } + } + + return CFG_SETTINGS_OK; +} + +int8_t ws_cfg_settings_set(protocol_interface_info_entry_t *cur, ws_cfg_t *new_cfg) +{ + int8_t ret_value = CFG_SETTINGS_OK; + + bool call_cfg_set[CFG_CB_NUM]; + + // Validate new configuration values + for (uint8_t index = 0; index < CFG_CB_NUM; index++) { + if (cfg_cb[index].validate) { + int8_t ret = cfg_cb[index].validate( + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + ((uint8_t *)new_cfg) + cfg_cb[index].setting_offset); + + if (ret < 0) { + // Validation failed + return ret; + } else if (ret == CFG_SETTINGS_CHANGED) { + call_cfg_set[index] = true; + } else { + call_cfg_set[index] = false; + } + } else { + // If validation not needed, set right away + call_cfg_set[index] = true; + } + } + + // Set new configuration values + for (uint8_t index = 0; index < CFG_CB_NUM; index++) { + uint8_t flags = 0; + // Validation + if (call_cfg_set[index]) { + if (cfg_cb[index].set(cur, + ((uint8_t *)&ws_cfg) + cfg_cb[index].setting_offset, + ((uint8_t *)new_cfg) + cfg_cb[index].setting_offset, &flags) < 0) { + tr_info("FATAL CONFIG FAILURE"); + ret_value = CFG_SETTINGS_OTHER_ERROR; + } + } + } + + return ret_value; +} + +#endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_cfg_settings.h b/source/6LoWPAN/ws/ws_cfg_settings.h new file mode 100644 index 0000000000..334489d513 --- /dev/null +++ b/source/6LoWPAN/ws/ws_cfg_settings.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WS_CFG_STORAGE_H_ +#define WS_CFG_STORAGE_H_ + +/** + * \brief Struct ws_gen_cfg_t General configuration + */ +typedef struct ws_gen_cfg_s { + /* Changing the network size resets the configuration settings depending on it to + default values */ + uint8_t network_size; /**< Network size selection; default medium (= 8) */ + char network_name[33]; /**< Network name; max 32 octets + terminating 0 */ + uint16_t network_pan_id; /**< PAN identifier; PAN_ID; default 0xffff */ +} ws_gen_cfg_t; + +/** + * \brief Struct ws_phy_cfg_t Physical layer configuration + */ +typedef struct ws_phy_cfg_s { + uint8_t regulatory_domain; /**< PHY regulatory domain; default "KR" 0x09 */ + uint8_t operating_class; /**< PHY operating class; default 1 */ + uint8_t operating_mode; /**< PHY operating mode; default "1b" symbol rate 50, modulation index 1 */ +} ws_phy_cfg_t; + +/** + * \brief Struct ws_timing_cfg_t Timing configuration + */ +typedef struct ws_timing_cfg_s { + uint16_t disc_trickle_imin; /**< Discovery trickle Imin; DISC_IMIN; seconds; range 1-255; default 30 */ + uint16_t disc_trickle_imax; /**< Discovery trickle Imax; DISC_IMAX; seconds; range (2-2^8)*Imin‬; default 960 */ + uint8_t disc_trickle_k; /**< Discovery trickle k; DISC_K; default 1 */ + uint16_t pan_timeout; /**< PAN timeout; PAN_TIMEOUT; seconds; range 60-15300; default 3840 */ + uint16_t temp_link_min_timeout; /**< Temporary neighbor link minimum timeout; seconds; default 260 */ +} ws_timing_cfg_t; + +/** + * \brief Struct ws_rpl_cfg_t RPL configuration + */ +typedef struct ws_rpl_cfg_s { + uint8_t dio_interval_min; /**> DIO interval min; DEFAULT_DIO_INTERVAL_MIN; 2^value in milliseconds; range 1-255; default */ + uint8_t dio_interval_doublings; /**> DIO interval doublings; DEFAULT_DIO_INTERVAL_DOUBLINGS; range 1-8; default */ + uint8_t dio_redundancy_constant; /**> DIO redundancy constant; DEFAULT_DIO_REDUNDANCY_CONSTANT; range 0-10; default */ + uint16_t dag_max_rank_increase; + uint16_t min_hop_rank_increase; + uint16_t rpl_parent_candidate_max; /**< RPL parent candidate maximum value; default 5 */ + uint16_t rpl_selected_parent_max; /**< RPL selected parent maximum value; default 2 */ +} ws_rpl_cfg_t; + +/** + * \brief Struct ws_fhss_cfg_t Frequency hopping configuration + */ +typedef struct ws_fhss_cfg_s { + uint8_t fhss_uc_dwell_interval; /**< FHSS unicast dwell interval; range 15-250 milliseconds; default 255 */ + uint8_t fhss_bc_dwell_interval; /**< FHSS broadcast dwell interval; range 15-250 milliseconds; default 255 */ + uint32_t fhss_bc_interval; /**< FHSS broadcast interval; duration between broadcast dwell intervals. range: 0-16777216 milliseconds; default 1020 */ + uint8_t fhss_uc_channel_function; /**< FHSS WS unicast channel function; default 2 direct hash channel function */ + uint8_t fhss_bc_channel_function; /**< FHSS WS broadcast channel function; default 2 direct hash channel function */ + uint16_t fhss_uc_fixed_channel; /**< FHSS unicast fixed channel; default 0xffff */ + uint16_t fhss_bc_fixed_channel; /**< FHSS broadcast fixed channel; default 0xffff */ + uint32_t fhss_channel_mask[8]; /**< FHSS channel mask; default; 0xffffffff * 8 */ +} ws_fhss_cfg_t; + +/** + * \brief Struct ws_mpl_cfg_t Multicast configuration + */ +typedef struct ws_mpl_cfg_s { + uint16_t mpl_trickle_imin; /**< MPL trickle parameters Imin; DATA_MESSAGE_IMIN; seconds; range 1-255; default 10 */ + uint16_t mpl_trickle_imax; /**< MPL trickle parameters Imax; DATA_MESSAGE_IMAX; seconds; range (2-2^8)*Imin‬; default 10 */ + uint8_t mpl_trickle_k; /**< MPL trickle parameters k; default 8 */ + uint8_t mpl_trickle_timer_exp; /**< MPL trickle parameters timer expirations; default 3 */ + uint16_t seed_set_entry_lifetime; /**< MPL minimum seed set lifetime; seconds; default 960 */ +} ws_mpl_cfg_t; + +/** + * \brief Struct ws_sec_timer_cfg_t Security timers configuration + */ +typedef struct ws_sec_timer_cfg_s { + uint32_t gtk_expire_offset; /**< GTK lifetime; GTK_EXPIRE_OFFSET; minutes; default 43200 */ + uint32_t pmk_lifetime; /**< PMK lifetime; minutes; default 172800 */ + uint32_t ptk_lifetime; /**< PTK lifetime; minutes; default 86400 */ + uint16_t gtk_new_act_time; /**< GTK_NEW_ACTIVATION_TIME (1/X of expire offset); default 720 */ + uint16_t revocat_lifetime_reduct; /**< REVOCATION_LIFETIME_REDUCTION (reduction of lifetime); default 30 */ + uint16_t gtk_request_imin; /**< GTK_REQUEST_IMIN; minutes; range 1-255; default 4 */ + uint16_t gtk_request_imax; /**< GTK_REQUEST_IMAX; minutes; range (2-2^8)*Imin; default 64 */ + uint16_t gtk_max_mismatch; /**< GTK_MAX_MISMATCH; minutes; default 64 */ + uint8_t gtk_new_install_req; /**< GTK_NEW_INSTALL_REQUIRED; percent of GTK lifetime; range 1-100; default 80 */ +} ws_sec_timer_cfg_t; + +/** + * \brief Struct ws_sec_prot_cfg_t Security protocols configuration + */ +typedef struct ws_sec_prot_cfg_s { + uint16_t sec_prot_retry_timeout; /**< Security protocol retry timeout; seconds; default 330 */ + uint16_t sec_prot_trickle_imin; /**< Security protocol trickle parameters Imin; seconds; default 30 */ + uint16_t sec_prot_trickle_imax; /**< Security protocol trickle parameters Imax; seconds; default 90 */ + uint8_t sec_prot_trickle_timer_exp; /**< Security protocol trickle timer expirations; default 2 */ + uint16_t sec_max_ongoing_authentication; /**< Pae authenticator max Accept ongoing authentication count */ +} ws_sec_prot_cfg_t; + +/** + * \brief Struct ws_nw_size_cfg_t Network size configuration + */ +typedef struct ws_cfg_s { + ws_gen_cfg_t gen; /**< General configuration */ + ws_phy_cfg_t phy; /**< Physical layer configuration */ + ws_timing_cfg_t timing; /**< Timing configuration */ + ws_rpl_cfg_t rpl; /**< RPL configuration */ + ws_fhss_cfg_t fhss; /**< Frequency hopping configuration */ + ws_mpl_cfg_t mpl; /**< Multicast configuration */ + ws_sec_timer_cfg_t sec_timer; /**< Security timers configuration */ + ws_sec_prot_cfg_t sec_prot; /**< Security protocols configuration */ +} ws_cfg_t; + +/** Configuration setting errors. */ +#define CFG_SETTINGS_PARAMETER_ERROR -1 /**< Function parameter error */ +#define CFG_SETTINGS_OTHER_ERROR -2 /**< Other error */ +#define CFG_SETTINGS_ERROR_NW_SIZE_CONF -10 /**< Network size configuration error */ +#define CFG_SETTINGS_ERROR_GEN_CONF -11 /**< General configuration error */ +#define CFG_SETTINGS_ERROR_PHY_CONF -12 /**< Physical layer configuration error */ +#define CFG_SETTINGS_ERROR_TIMING_CONF -13 /**< Timing configuration error */ +#define CFG_SETTINGS_ERROR_RPL_CONF -14 /**< RPL configuration error */ +#define CFG_SETTINGS_ERROR_FHSS_CONF -15 /**< Frequency hopping configuration error */ +#define CFG_SETTINGS_ERROR_MPL_CONF -16 /**< Multicast configuration error */ +#define CFG_SETTINGS_ERROR_SEC_TIMER_CONF -17 /**< Security timers configuration error */ +#define CFG_SETTINGS_ERROR_SEC_PROT_CONF -18 /**< Security protocols configuration error */ + +int8_t ws_cfg_settings_init(void); +int8_t ws_cfg_settings_default_set(void); +int8_t ws_cfg_settings_interface_set(protocol_interface_info_entry_t *cur); +int8_t ws_cfg_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size); + +int8_t ws_cfg_network_size_get(ws_gen_cfg_t *cfg, uint8_t *flags); +int8_t ws_cfg_network_size_validate(ws_gen_cfg_t *cfg, ws_gen_cfg_t *new_cfg); +int8_t ws_cfg_network_size_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_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_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_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); + +int8_t ws_cfg_rpl_get(ws_rpl_cfg_t *cfg, uint8_t *flags); +int8_t ws_cfg_rpl_validate(ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg); +int8_t ws_cfg_rpl_set(protocol_interface_info_entry_t *cur, ws_rpl_cfg_t *cfg, ws_rpl_cfg_t *new_cfg, uint8_t *flags); + +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_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); + +int8_t ws_cfg_sec_timer_get(ws_sec_timer_cfg_t *cfg, uint8_t *flags); +int8_t ws_cfg_sec_timer_validate(ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg); +int8_t ws_cfg_sec_timer_set(protocol_interface_info_entry_t *cur, ws_sec_timer_cfg_t *cfg, ws_sec_timer_cfg_t *new_cfg, uint8_t *flags); + +int8_t ws_cfg_sec_prot_get(ws_sec_prot_cfg_t *cfg, uint8_t *flags); +int8_t ws_cfg_sec_prot_validate(ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg); +int8_t ws_cfg_sec_prot_set(protocol_interface_info_entry_t *cur, ws_sec_prot_cfg_t *cfg, ws_sec_prot_cfg_t *new_cfg, uint8_t *flags); + +#endif // WS_CFG_STORAGE_H_ diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index f89fbaa748..7bfb66df4e 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -29,6 +29,7 @@ #include "6LoWPAN/ws/ws_bootstrap.h" #include "6LoWPAN/ws/ws_bbr_api_internal.h" #include "6LoWPAN/ws/ws_pae_controller.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "Service_Libs/etx/etx.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "Service_Libs/blacklist/blacklist.h" @@ -44,30 +45,7 @@ // This provides a range of -174 (0) to +80 (254) dBm uint8_t DEVICE_MIN_SENS = 174 - 93; -#define TRICKLE_IMIN_60_SECS (60 * 10) -#define TRICKLE_IMIN_30_SECS (30 * 10) -#define TRICKLE_IMIN_15_SECS (15 * 10) -static const trickle_params_t trickle_params_pan_discovery_large = { - .Imin = TRICKLE_IMIN_60_SECS, /* 60 second; ticks are 1s */ - .Imax = TRICKLE_IMIN_60_SECS << 4, /* 960 seconds 16 min*/ - .k = 1, /* 1 */ - .TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE -}; - -static const trickle_params_t trickle_params_pan_discovery_medium = { - .Imin = TRICKLE_IMIN_30_SECS, /* 30 second; ticks are 1s */ - .Imax = TRICKLE_IMIN_30_SECS << 5, /* 960 seconds 16 min*/ - .k = 1, /* 1 */ - .TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE -}; - -static const trickle_params_t trickle_params_pan_discovery_small = { - .Imin = TRICKLE_IMIN_15_SECS, /* 15 second; ticks are 1s */ - .Imax = TRICKLE_IMIN_15_SECS << 2, /* 60 seconds 1 min*/ - .k = 1, /* 1 */ - .TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE -}; uint16_t test_max_child_count_override = 0xffff; @@ -81,7 +59,7 @@ int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_chann return 0; } -static uint32_t ws_decode_channel_spacing(uint8_t channel_spacing) +uint32_t ws_decode_channel_spacing(uint8_t channel_spacing) { if (CHANNEL_SPACING_100 == channel_spacing) { return 100000; @@ -97,7 +75,7 @@ static uint32_t ws_decode_channel_spacing(uint8_t channel_spacing) return 0; } -static uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode) +uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode) { if ((OPERATING_MODE_1a == operating_mode) || (OPERATING_MODE_1b == operating_mode)) { return 50000; @@ -113,7 +91,7 @@ static uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode) return 0; } -static phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode) +phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode) { if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) { return MODULATION_INDEX_1_0; @@ -122,105 +100,95 @@ static phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8 } } -static int ws_set_domain_rf_config(protocol_interface_info_entry_t *cur) +int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule) { - phy_rf_channel_configuration_s rf_configs; - rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000; - rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing); - rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); - rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); - rf_configs.modulation = M_2FSK; - rf_configs.number_of_channels = cur->ws_info->hopping_schdule.number_of_channels; - ws_bootstrap_set_rf_config(cur, rf_configs); - return 0; -} + (void)cur; + if (ws_get_datarate_using_operating_mode(hopping_schdule->operating_mode) == 0) { + //Unsupported operation mode + return -1; + } -int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur) -{ - cur->ws_info->hopping_schdule.channel_plan = 0; + hopping_schdule->channel_plan = 0; - if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_KR) { - if (cur->ws_info->hopping_schdule.operating_class == 1) { - cur->ws_info->hopping_schdule.ch0_freq = 9171; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; - } else if (cur->ws_info->hopping_schdule.operating_class == 2) { - cur->ws_info->hopping_schdule.ch0_freq = 9173; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400; + if (hopping_schdule->regulatory_domain == REG_DOMAIN_KR) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9171; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9173; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; } else { return -1; } - } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_EU) { - if (cur->ws_info->hopping_schdule.operating_class == 1) { - cur->ws_info->hopping_schdule.ch0_freq = 8631; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100; - } else if (cur->ws_info->hopping_schdule.operating_class == 2) { - cur->ws_info->hopping_schdule.ch0_freq = 8631; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; - } else if (cur->ws_info->hopping_schdule.operating_class == 3) { - cur->ws_info->hopping_schdule.ch0_freq = 8701; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100; - } else if (cur->ws_info->hopping_schdule.operating_class == 4) { - cur->ws_info->hopping_schdule.ch0_freq = 8702; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_EU) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 8631; + hopping_schdule->channel_spacing = CHANNEL_SPACING_100; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 8631; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 8701; + hopping_schdule->channel_spacing = CHANNEL_SPACING_100; + } else if (hopping_schdule->operating_class == 4) { + hopping_schdule->ch0_freq = 8702; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; } else { return -1; } - } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_IN) { - if (cur->ws_info->hopping_schdule.operating_class == 1) { - cur->ws_info->hopping_schdule.ch0_freq = 8651; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100; - } else if (cur->ws_info->hopping_schdule.operating_class == 2) { - cur->ws_info->hopping_schdule.ch0_freq = 8651; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_IN) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 8651; + hopping_schdule->channel_spacing = CHANNEL_SPACING_100; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 8651; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; } else { return -1; } - } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_NA) { - if (cur->ws_info->hopping_schdule.operating_class == 1) { - cur->ws_info->hopping_schdule.ch0_freq = 9022; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; - } else if (cur->ws_info->hopping_schdule.operating_class == 2) { - cur->ws_info->hopping_schdule.ch0_freq = 9024; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400; - } else if (cur->ws_info->hopping_schdule.operating_class == 3) { - cur->ws_info->hopping_schdule.ch0_freq = 9026; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_600; + } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_NA) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 9026; + hopping_schdule->channel_spacing = CHANNEL_SPACING_600; } else { return -1; } - } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_JP) { - if (cur->ws_info->hopping_schdule.operating_class == 1) { - cur->ws_info->hopping_schdule.ch0_freq = 9206; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; - } else if (cur->ws_info->hopping_schdule.operating_class == 2) { - cur->ws_info->hopping_schdule.ch0_freq = 9209; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400; - } else if (cur->ws_info->hopping_schdule.operating_class == 3) { - cur->ws_info->hopping_schdule.ch0_freq = 9208; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_600; + } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_JP) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9206; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9209; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 9208; + hopping_schdule->channel_spacing = CHANNEL_SPACING_600; } else { return -1; } - } else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_WW) { - if (cur->ws_info->hopping_schdule.operating_class == 1) { - cur->ws_info->hopping_schdule.ch0_freq = 24002; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200; - } else if (cur->ws_info->hopping_schdule.operating_class == 2) { - cur->ws_info->hopping_schdule.ch0_freq = 24004; - cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_WW) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 24002; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 24004; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; } else { return -1; } } else { return -1; } - cur->ws_info->hopping_schdule.number_of_channels = (uint8_t)ws_common_channel_number_calc(cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); - if (!cur->ws_info->hopping_schdule.number_of_channels) { + hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class); + if (!hopping_schdule->number_of_channels) { return -1; } - // Note: doesn't work for Brazil region - ws_generate_channel_list(cur->ws_info->hopping_schdule.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain); - ws_set_domain_rf_config(cur); return 0; } @@ -292,10 +260,13 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur) ns_list_init(&cur->ws_info->parent_list_free); ns_list_init(&cur->ws_info->parent_list_reserved); + cur->ws_info->network_pan_id = 0xffff; cur->ws_info->pan_information.use_parent_bs = true; cur->ws_info->pan_information.rpl_routing_method = true; cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0; + cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; + cur->ws_info->hopping_schdule.regulatory_domain = REG_DOMAIN_EU; cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3; cur->ws_info->hopping_schdule.operating_class = 2; @@ -303,70 +274,12 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur) cur->ws_info->hopping_schdule.clock_drift = 255; // Timing accuracy is given from 0 to 2.55msec with 10usec resolution cur->ws_info->hopping_schdule.timing_accurancy = 100; - ws_common_regulatory_domain_config(cur); - cur->ws_info->network_size_config = NETWORK_SIZE_MEDIUM; - cur->ws_info->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; - cur->ws_info->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX; - ws_common_network_size_configure(cur, 200); // defaults to medium network size - - // Set defaults for the device. user can modify these. - cur->ws_info->fhss_uc_fixed_channel = 0xffff; - cur->ws_info->fhss_bc_fixed_channel = 0xffff; - cur->ws_info->fhss_uc_dwell_interval = WS_FHSS_UC_DWELL_INTERVAL; - cur->ws_info->fhss_bc_interval = WS_FHSS_BC_INTERVAL; - cur->ws_info->fhss_bc_dwell_interval = WS_FHSS_BC_DWELL_INTERVAL; - cur->ws_info->fhss_uc_channel_function = WS_DH1CF; - cur->ws_info->fhss_bc_channel_function = WS_DH1CF; - + ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule); cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; - for (uint8_t n = 0; n < 8; n++) { - cur->ws_info->fhss_channel_mask[n] = 0xffffffff; - } return 0; } -void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size) -{ - // TODO Modify NUD timings based on network size - // TODO Modify EAPOLL timings - - if (network_size < 100) { - // Configure the Wi-SUN discovery trickle parameters - cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_small; - // default values are for Wi-SUN small network parameters - // imin: 14 (16s) - // doublings:3 (128s) - // redundancy; 0 Disabled - if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) { - ws_bbr_rpl_config(cur, 14, 3, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); - } else if (cur->ws_info->network_size_config == NETWORK_SIZE_CERTIFICATE) { - ws_bbr_rpl_config(cur, 0, 0, 0, WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE, WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE); - } else { - ws_bbr_rpl_config(cur, 0, 0, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); - } - ws_pae_controller_timing_adjust(1); // Fast and reactive network - } else if (network_size < 300) { - // Configure the Wi-SUN discovery trickle parameters - cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_medium; - // Something in between - // imin: 15 (32s) - // doublings:5 (960s) - // redundancy; 10 - ws_bbr_rpl_config(cur, 15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); - ws_pae_controller_timing_adjust(9); // medium limited network - } else { - // Configure the Wi-SUN discovery trickle parameters - cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_large; - // Wi-SUN Large network parameters - // imin: 19 (524s, 9 min) - // doublings:1 (1048s, 17 min) - // redundancy; 10 May need some tuning still - ws_bbr_rpl_config(cur, 19, 1, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE); - ws_pae_controller_timing_adjust(24); // Very slow and high latency network - } - return; -} void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) { @@ -418,6 +331,14 @@ 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); + } tr_info("Child registration from old child"); return ARO_SUCCESS; } @@ -456,35 +377,53 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con return true; } -uint32_t ws_common_version_lifetime_get(uint8_t config) +uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur) { - uint32_t lifetime; - if (config == NETWORK_SIZE_SMALL || config == NETWORK_SIZE_CERTIFICATE) { - lifetime = PAN_VERSION_SMALL_NETWORK_LIFETIME; - } else if (config == NETWORK_SIZE_MEDIUM) { - lifetime = PAN_VERSION_MEDIUM_NETWORK_LIFETIME; - } else { - lifetime = PAN_VERSION_LARGE_NETWORK_LIFETIME; + uint32_t latency = 0; + uint8_t network_size = cur->ws_info->cfg->gen.network_size; + + if (network_size == NETWORK_SIZE_AUTOMATIC) { + network_size = cur->ws_info->pan_information.pan_size / 100; } - return lifetime; - -} - -uint32_t ws_common_version_timeout_get(uint8_t config) -{ - uint32_t lifetime; - if (config == NETWORK_SIZE_SMALL || config == NETWORK_SIZE_CERTIFICATE) { - lifetime = PAN_VERSION_SMALL_NETWORK_TIMEOUT; - } else if (config == NETWORK_SIZE_MEDIUM) { - lifetime = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT; - } else { - lifetime = PAN_VERSION_LARGE_NETWORK_TIMEOUT; + if (network_size <= NETWORK_SIZE_SMALL) { + // handles also NETWORK_SIZE_CERTIFICATE + latency = 8000; + } else if (network_size <= NETWORK_SIZE_MEDIUM) { + latency = 16000; + } else { + latency = 32000; } - return lifetime; + return latency; } +uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur) +{ + return ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode); +} + +uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur) +{ + uint32_t network_size_estimate = 0; + uint8_t network_size = cur->ws_info->cfg->gen.network_size; + + if (network_size == NETWORK_SIZE_AUTOMATIC) { + network_size = cur->ws_info->pan_information.pan_size / 100; + } + + if (network_size <= NETWORK_SIZE_SMALL) { + // tens of devices (now 30), handles also NETWORK_SIZE_CERTIFICATE + network_size_estimate = 30; + } else if (network_size <= NETWORK_SIZE_MEDIUM) { + // hundreds of devices (now 300) + network_size_estimate = 300; + } else { + // huge amount of devices (now 1000) + network_size_estimate = 1000; + } + + return network_size_estimate; +} #endif // HAVE_WS - diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 588902753f..3aa154c052 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -35,6 +35,8 @@ extern uint16_t test_max_child_count_override; struct ws_pan_information_s; struct ws_neighbor_class_s; +struct ws_excluded_channel_data_s; +struct ws_cfg_s; typedef struct parent_info_s { uint16_t pan_id; /**< PAN ID */ @@ -46,6 +48,7 @@ typedef struct parent_info_s { ws_us_ie_t ws_us; uint32_t timestamp; /**< Timestamp when packet was received */ uint32_t age; /**< Age of entry in 100ms ticks */ + uint8_t excluded_channel_data[32]; //Channel mask Max length and it accept 8 different range ns_list_link_t link; } parent_info_t; @@ -72,45 +75,33 @@ typedef struct { typedef NS_LIST_HEAD(ws_nud_table_entry_t, link) ws_nud_table_list_t; typedef struct ws_info_s { - char network_name[33]; // Network name max 32 octets + terminating 0. - uint16_t network_pan_id; - trickle_t trickle_pan_config_solicit; trickle_t trickle_pan_config; trickle_t trickle_pan_advertisement_solicit; trickle_t trickle_pan_advertisement; trickle_params_t trickle_params_pan_discovery; - uint8_t network_size_config; // configuration for network size selection of application. - uint16_t rpl_parent_candidate_max; - uint16_t rpl_selected_parent_max; uint8_t rpl_state; // state from rpl_event_t uint8_t pas_requests; // Amount of PAN solicits sent parent_info_t parent_info[WS_PARENT_LIST_SIZE]; parent_info_list_t parent_list_free; parent_info_list_t parent_list_reserved; + uint16_t aro_registration_timer; /**< Aro registration timer */ uint16_t rpl_version_timer; /**< RPL version update timeout */ - uint32_t pan_version_timer; /**< border router version update timeout */ - uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */ + uint32_t pan_timeout_timer; /**< routers will fallback to previous state after this */ uint32_t pan_config_sol_max_timeout; uint8_t gtkhash[32]; + uint16_t network_pan_id; bool configuration_learned: 1; bool trickle_pas_running: 1; bool trickle_pa_running: 1; bool trickle_pcs_running: 1; bool trickle_pc_running: 1; + uint16_t trickle_pc_consistency_block_period; ws_pending_key_index_t pending_key_index_info; - // default fhss parameters for this device - uint8_t fhss_uc_dwell_interval; - uint8_t fhss_bc_dwell_interval; - uint32_t fhss_bc_interval; - uint8_t fhss_uc_channel_function; - uint8_t fhss_bc_channel_function; - uint16_t fhss_uc_fixed_channel; - uint16_t fhss_bc_fixed_channel; - uint32_t fhss_channel_mask[8]; ws_nud_table_entry_t nud_table_entrys[ACTIVE_NUD_PROCESS_MAX]; ws_nud_table_list_t active_nud_process; ws_nud_table_list_t free_nud_entries; + struct ws_cfg_s *cfg; /**< Wi-SUN configuration */ struct ws_pan_information_s pan_information; ws_hopping_schedule_t hopping_schdule; struct ws_statistics *stored_stats_ptr; @@ -123,14 +114,18 @@ typedef struct ws_info_s { int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain); -int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur); +uint32_t ws_decode_channel_spacing(uint8_t channel_spacing); + +uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode); + +phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode); + +int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule); uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class); int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur); -void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size); - void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); @@ -145,11 +140,14 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *cur, bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, const uint8_t *eui64); - -uint32_t ws_common_version_lifetime_get(uint8_t config); - uint32_t ws_common_version_timeout_get(uint8_t config); +uint32_t ws_common_latency_estimate_get(protocol_interface_info_entry_t *cur); + +uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur); + +uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur); + #define ws_info(cur) ((cur)->ws_info) #else #define ws_info(cur) ((ws_info_t *) NULL) @@ -160,6 +158,9 @@ uint32_t ws_common_version_timeout_get(uint8_t config); #define ws_common_fast_timer(cur, ticks) ((void) 0) #define ws_common_allow_child_registration(cur, eui64) (2) #define ws_common_negative_aro_mark(interface, eui64)(false) +#define ws_common_latency_estimate_get(cur) 0 +#define ws_common_datarate_get(cur) 0 +#define ws_common_network_size_estimate_get(cur) 0 #endif //HAVE_WS #endif //WS_COMMON_H_ diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index 92f7da38eb..d2797f8e80 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -51,6 +51,12 @@ #define WS_FT_ACK 5 /**< Enhanced ACK */ #define WS_FT_EAPOL 6 /**< EAPOL message inside MPX */ +/* WS exluded channel Control */ +#define WS_EXC_CHAN_CTRL_NONE 0 /**< No excluded channels */ +#define WS_EXC_CHAN_CTRL_RANGE 1 /**< Excluded channels are in 1 or multiple channel range */ +#define WS_EXC_CHAN_CTRL_BITMASK 2 /**< Excluded channels are marked to bitmask which length based on configured channels */ + +#define WS_EXCLUDED_MAX_RANGE_TO_SEND 3 /** * @brief ws_pan_information_t PAN information @@ -64,6 +70,26 @@ typedef struct ws_pan_information_s { unsigned version: 3; /**< Pan version support. */ } ws_pan_information_t; +/** + * @brief ws_excluded_channel_range_data_t Excludd Chanel range information + */ +typedef struct ws_excluded_channel_range_data_s { + uint16_t range_start; + uint16_t range_end; +} ws_excluded_channel_range_data_t; + +/** + * @brief ws_excluded_channel_data_t Excludd Chanel information + */ +typedef struct ws_excluded_channel_data_s { + unsigned excuded_channel_ctrl: 2; + unsigned excluded_range_length: 3; + ws_excluded_channel_range_data_t exluded_range[WS_EXCLUDED_MAX_RANGE_TO_SEND]; + uint16_t excluded_channel_count; + uint8_t channel_mask_bytes_inline; + uint32_t channel_mask[8]; +} ws_excluded_channel_data_t; + /** * @brief ws_hopping_schedule_t Chanel hopping schedule information */ @@ -84,8 +110,8 @@ typedef struct ws_hopping_schedule_s { uint16_t bc_fixed_channel; uint16_t fhss_bsi; uint32_t fhss_broadcast_interval; - uint32_t channel_mask[8]; uint_fast24_t ch0_freq; // Default should be derived from regulatory domain + ws_excluded_channel_data_t excluded_channels; } ws_hopping_schedule_t; /** @@ -137,6 +163,22 @@ typedef struct ws_channel_function_three { uint8_t *channel_list; } ws_channel_function_three_t; +/** + * @brief ws_excluded_channel_range_t WS excluded channel range + */ +typedef struct ws_excluded_channel_range { + uint8_t number_of_range; + uint8_t *range_start; +} ws_excluded_channel_range_t; + +/** + * @brief ws_excluded_channel_mask_t WS excluded channel mask + */ +typedef struct ws_excluded_channel_mask { + uint8_t *channel_mask; + uint8_t mask_len_inline; +} ws_excluded_channel_mask_t; + /** * @brief ws_us_ie_t WS US-IE read */ @@ -155,6 +197,10 @@ typedef struct ws_us_ie { ws_channel_function_zero_t zero; ws_channel_function_three_t three; } function; + union { + ws_excluded_channel_range_t range; + ws_excluded_channel_mask_t mask; + } excluded_channels; } ws_us_ie_t; /** @@ -249,6 +295,11 @@ typedef struct ws_bs_ie { */ #define WS_TACK_MAX_MS 5 +/* + * Config new version consistent filter period in 100ms periods + */ +#define WS_CONFIG_CONSISTENT_FILTER_PERIOD 100 + // With FHSS we need to check CCA twice on TX channel #define WS_NUMBER_OF_CSMA_PERIODS 2 // Interval between two CCA checks diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index e7afc90d98..b2a9bd18c9 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -27,9 +27,21 @@ * */ -#define WS_RPL_DIO_IMIN 15 -#define WS_RPL_DIO_DOUBLING 2 -#define WS_RPL_DIO_REDUNDANCY 0 +#define WS_RPL_DIO_IMIN_SMALL 15 +#define WS_RPL_DIO_DOUBLING_SMALL 2 +#define WS_RPL_DIO_REDUNDANCY_SMALL 0 + +#define WS_RPL_DIO_IMIN_MEDIUM 15 +#define WS_RPL_DIO_DOUBLING_MEDIUM 5 +#define WS_RPL_DIO_REDUNDANCY_MEDIUM 10 + +#define WS_RPL_DIO_IMIN_LARGE 19 +#define WS_RPL_DIO_DOUBLING_LARGE 1 +#define WS_RPL_DIO_REDUNDANCY_LARGE 10 // May need some tuning still + +#define WS_RPL_DIO_IMIN_AUTOMATIC 14 +#define WS_RPL_DIO_DOUBLING_AUTOMATIC 3 +#define WS_RPL_DIO_REDUNDANCY_AUTOMATIC 0 #define WS_RPL_MIN_HOP_RANK_INCREASE 196 #define WS_RPL_MAX_HOP_RANK_INCREASE 2048 @@ -37,14 +49,17 @@ #define WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE 128 #define WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE 0 +/* + * RPL DAO timeout maximum value. This will force DAO timeout to happen before this time + */ +#define WS_RPL_DAO_MAX_TIMOUT (3600*2) + /* Border router version change interval * - * Minimum interval at which a Border Router shall increment its PAN Version value. + * Amount of version increases border router makes during PAN_TIMEOUT time */ -#define PAN_VERSION_SMALL_NETWORK_LIFETIME 4*60 -#define PAN_VERSION_MEDIUM_NETWORK_LIFETIME 15*60 -#define PAN_VERSION_LARGE_NETWORK_LIFETIME 30*60 //30min +#define PAN_VERSION_CHANGE_INTERVAL 3 // RPL version number update intervall // after restart version numbers are increased faster and then slowed down when network is stable @@ -101,10 +116,11 @@ extern uint8_t DEVICE_MIN_SENS; * IMIN = 10 seconds, IMAX = 3 doublings */ -#define DATA_MESSAGE_IMIN (10 * 1000) +#define DATA_MESSAGE_IMIN 10 #define DATA_MESSAGE_TIMER_EXPIRATIONS 3 -#define DATA_MESSAGE_IMAX (80 * 1000) -#define MPL_SEED_SET_ENTRY_TIMEOUT (DATA_MESSAGE_IMAX * 24 * 4 / 1000) // 10 seconds per hop making this 240 seconds +#define DATA_MESSAGE_IMAX 80 +#define DATA_MESSAGE_K 8 +#define MPL_SEED_SET_ENTRY_TIMEOUT (DATA_MESSAGE_IMAX * 24 * 4) // 10 seconds per hop making this 240 seconds /* DHCP client timeout configuration values * @@ -170,4 +186,36 @@ extern uint8_t DEVICE_MIN_SENS; */ #define WISUN_1_0_ERRATA_FIX +/* + * Security protocol message retry configuration parameters + */ +#define SEC_PROT_SMALL_IMIN 30 // Retries done in 30 seconds +#define SEC_PROT_SMALL_IMAX 90 // Largest value 90 seconds +#define SEC_PROT_RETRY_TIMEOUT_SMALL 330 // Retry timeout for small network additional 30 seconds for authenticator delay + +#define SEC_PROT_LARGE_IMIN 60 // Retries done in 60 seconds +#define SEC_PROT_LARGE_IMAX 240 // Largest value 240 seconds +#define SEC_PROT_RETRY_TIMEOUT_LARGE 750 // Retry timeout for large network additional 30 seconds for authenticator delay + +#define SEC_PROT_TIMER_EXPIRATIONS 2 // Number of retries + +// Maximum number of simultaneous EAP-TLS negotiations +#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_SMALL 3 +#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_MEDIUM 20 +#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS_LARGE 50 + +/* + * Security protocol timer configuration parameters + */ +#define MINUTES_IN_DAY 24 * 60 +#define DEFAULT_GTK_EXPIRE_OFFSET 43200 // 30 days +#define DEFAULT_PMK_LIFETIME 4 * 30 * MINUTES_IN_DAY // 4 months +#define DEFAULT_PTK_LIFETIME 2 * 30 * MINUTES_IN_DAY // 2 months +#define DEFAULT_GTK_NEW_ACTIVATION_TIME 720 // default 1/720 * 30 days --> 60 minutes +#define DEFAULT_REVOCATION_LIFETIME_REDUCTION 30 // default 1/30 * 30 days --> 1 day +#define DEFAULT_GTK_REQUEST_IMIN 4 // 4 minutes +#define DEFAULT_GTK_REQUEST_IMAX 64 // 64 minutes +#define DEFAULT_GTK_MAX_MISMATCH 64 // 64 minutes +#define DEFAULT_GTK_NEW_INSTALL_REQUIRED 80 // 80 percent of GTK lifetime --> 24 days + #endif /* WS_CONFIG_H_ */ diff --git a/source/6LoWPAN/ws/ws_empty_functions.c b/source/6LoWPAN/ws/ws_empty_functions.c index be07fd0126..e03e811d63 100644 --- a/source/6LoWPAN/ws/ws_empty_functions.c +++ b/source/6LoWPAN/ws/ws_empty_functions.c @@ -49,6 +49,24 @@ int ws_management_network_name_set( return -1; } +int ws_management_network_name_get( + int8_t interface_id, + char *network_name_ptr) +{ + (void)interface_id; + (void)network_name_ptr; + return -1; +} + +int ws_management_network_name_validate( + int8_t interface_id, + char *network_name_ptr) +{ + (void)interface_id; + (void)network_name_ptr; + return -1; +} + int ws_management_regulatory_domain_set( int8_t interface_id, uint8_t regulatory_domain, @@ -62,6 +80,32 @@ int ws_management_regulatory_domain_set( return -1; } +int ws_management_regulatory_domain_get( + int8_t interface_id, + uint8_t *regulatory_domain, + uint8_t *operating_class, + uint8_t *operating_mode) +{ + (void)interface_id; + (void)regulatory_domain; + (void)operating_class; + (void)operating_mode; + return -1; +} + +int ws_management_regulatory_domain_validate( + int8_t interface_id, + uint8_t regulatory_domain, + uint8_t operating_class, + uint8_t operating_mode) +{ + (void)interface_id; + (void)regulatory_domain; + (void)operating_class; + (void)operating_mode; + return -1; +} + int ws_management_network_size_set( int8_t interface_id, uint8_t network_size) @@ -71,6 +115,24 @@ int ws_management_network_size_set( return -1; } +int ws_management_network_size_get( + int8_t interface_id, + uint8_t *network_size) +{ + (void)interface_id; + (void)network_size; + return -1; +} + +int ws_management_network_size_validate( + int8_t interface_id, + uint8_t network_size) +{ + (void)interface_id; + (void)network_size; + return -1; +} + int ws_management_channel_mask_set( int8_t interface_id, uint32_t channel_mask[8]) @@ -80,6 +142,24 @@ int ws_management_channel_mask_set( return -1; } +int ws_management_channel_mask_get( + int8_t interface_id, + uint32_t *channel_mask) +{ + (void)interface_id; + (void)channel_mask; + return -1; +} + +int ws_management_channel_mask_validate( + int8_t interface_id, + uint32_t channel_mask[8]) +{ + (void)interface_id; + (void)channel_mask; + return -1; +} + int ws_management_channel_plan_set( int8_t interface_id, uint8_t channel_plan, @@ -125,6 +205,32 @@ int ws_management_fhss_unicast_channel_function_configure( return -1; } +int ws_management_fhss_unicast_channel_function_get( + int8_t interface_id, + uint8_t *channel_function, + uint16_t *fixed_channel, + uint8_t *dwell_interval) +{ + (void)interface_id; + (void)channel_function; + (void)fixed_channel; + (void)dwell_interval; + return -1; +} + +int ws_management_fhss_unicast_channel_function_validate( + int8_t interface_id, + uint8_t channel_function, + uint16_t fixed_channel, + uint8_t dwell_interval) +{ + (void)interface_id; + (void)channel_function; + (void)fixed_channel; + (void)dwell_interval; + return -1; +} + int ws_management_fhss_broadcast_channel_function_configure( int8_t interface_id, uint8_t channel_function, @@ -140,6 +246,81 @@ int ws_management_fhss_broadcast_channel_function_configure( return -1; } +int ws_management_fhss_broadcast_channel_function_get( + int8_t interface_id, + uint8_t *channel_function, + uint16_t *fixed_channel, + uint8_t *dwell_interval, + uint32_t *broadcast_interval) +{ + (void)interface_id; + (void)channel_function; + (void)fixed_channel; + (void)dwell_interval; + (void)broadcast_interval; + return -1; +} + +int ws_management_fhss_broadcast_channel_function_validate( + int8_t interface_id, + uint8_t channel_function, + uint16_t fixed_channel, + uint8_t dwell_interval, + uint32_t broadcast_interval) +{ + (void)interface_id; + (void)channel_function; + (void)fixed_channel; + (void)dwell_interval; + (void)broadcast_interval; + return -1; +} + +int ws_management_timing_parameters_set( + int8_t interface_id, + uint16_t disc_trickle_imin, + uint16_t disc_trickle_imax, + uint8_t disc_trickle_k, + uint16_t pan_timeout) +{ + (void)interface_id; + (void)disc_trickle_imin; + (void)disc_trickle_imax; + (void)disc_trickle_k; + (void)pan_timeout; + return -1; +} + +int ws_management_timing_parameters_get( + int8_t interface_id, + uint16_t *disc_trickle_imin, + uint16_t *disc_trickle_imax, + uint8_t *disc_trickle_k, + uint16_t *pan_timeout) +{ + (void)interface_id; + (void)disc_trickle_imin; + (void)disc_trickle_imax; + (void)disc_trickle_k; + (void)pan_timeout; + return -1; +} + +int ws_management_timing_parameters_validate( + int8_t interface_id, + uint16_t disc_trickle_imin, + uint16_t disc_trickle_imax, + uint8_t disc_trickle_k, + uint16_t pan_timeout) +{ + (void)interface_id; + (void)disc_trickle_imin; + (void)disc_trickle_imax; + (void)disc_trickle_k; + (void)pan_timeout; + return -1; +} + /* ### test api ### */ int ws_test_pan_size_set(int8_t interface_id, uint16_t pan_size) { diff --git a/source/6LoWPAN/ws/ws_ie_lib.c b/source/6LoWPAN/ws/ws_ie_lib.c index a3aa0d93a6..0dfdc8b5ac 100644 --- a/source/6LoWPAN/ws/ws_ie_lib.c +++ b/source/6LoWPAN/ws/ws_ie_lib.c @@ -82,7 +82,13 @@ uint16_t ws_wp_nested_hopping_schedule_length(struct ws_hopping_schedule_s *hopp length += ws_channel_function_length(channel_function, 1); - //Todo Derive some how exluded channel control + if (unicast_schedule && hopping_schedule->excluded_channels.excuded_channel_ctrl) { + if (hopping_schedule->excluded_channels.excuded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) { + length += (hopping_schedule->excluded_channels.excluded_range_length * 4) + 1; + } else { + length += hopping_schedule->excluded_channels.channel_mask_bytes_inline; + } + } return length; } @@ -161,10 +167,11 @@ uint8_t *ws_wp_nested_hopping_schedule_write(uint8_t *ptr, struct ws_hopping_sch channel_info_base = (hopping_schedule->channel_plan); if (unicast_schedule) { channel_info_base |= (hopping_schedule->uc_channel_function << 3); + //Set Excluded Channel control part + channel_info_base |= (hopping_schedule->excluded_channels.excuded_channel_ctrl << 6); } else { channel_info_base |= (hopping_schedule->bc_channel_function << 3); } - //Todo define excluded channel ctrl *ptr++ = channel_info_base; @@ -176,9 +183,9 @@ uint8_t *ws_wp_nested_hopping_schedule_write(uint8_t *ptr, struct ws_hopping_sch break; case 1: //CHo, Channel spasing and number of channel's inline - ptr = common_write_24_bit(hopping_schedule->fhss_uc_dwell_interval, ptr); - *ptr++ = ((hopping_schedule->channel_spacing << 4) & 0xf0); - ptr = common_write_16_bit(hopping_schedule->number_of_channels, ptr); + ptr = common_write_24_bit_inverse(hopping_schedule->ch0_freq * 100, ptr); + *ptr++ = hopping_schedule->channel_spacing; + ptr = common_write_16_bit_inverse(hopping_schedule->number_of_channels, ptr); break; default: break; @@ -210,6 +217,44 @@ uint8_t *ws_wp_nested_hopping_schedule_write(uint8_t *ptr, struct ws_hopping_sch break; } + + if (unicast_schedule && hopping_schedule->excluded_channels.excuded_channel_ctrl) { + if (hopping_schedule->excluded_channels.excuded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) { + uint8_t range_length = hopping_schedule->excluded_channels.excluded_range_length; + ws_excluded_channel_range_data_t *range_ptr = hopping_schedule->excluded_channels.exluded_range; + *ptr++ = range_length; + while (range_length) { + ptr = common_write_16_bit_inverse(range_ptr->range_start, ptr); + ptr = common_write_16_bit_inverse(range_ptr->range_end, ptr); + range_length--; + range_ptr++; + } + } else if (hopping_schedule->excluded_channels.excuded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) { + //Set Mask + uint16_t channel_mask_length = hopping_schedule->excluded_channels.channel_mask_bytes_inline * 8; + + for (uint8_t i = 0; i < 8; i++) { + uint32_t mask_value = hopping_schedule->excluded_channels.channel_mask[i]; + if (channel_mask_length >= 32) { + ptr = common_write_32_bit(mask_value, ptr); + channel_mask_length -= 32; + } else { + //Write MSB Bits from mask 24-8 top bits + uint8_t move_mask = 0; + while (channel_mask_length) { + *ptr++ = (uint8_t)(mask_value >> (24 - move_mask)); + channel_mask_length -= 8; + move_mask += 8; + } + } + + if (channel_mask_length == 0) { + break; + } + } + } + } + return ptr; } @@ -330,8 +375,9 @@ static uint8_t *ws_channel_plan_zero_read(uint8_t *ptr, ws_channel_plan_zero_t * static uint8_t *ws_channel_plan_one_read(uint8_t *ptr, ws_channel_plan_one_t *plan) { plan->ch0 = common_read_24_bit_inverse(ptr); + plan->ch0 /= 100; ptr += 3; - plan->channel_spacing = (*ptr++ & 0xf0) >> 4; + plan->channel_spacing = *ptr++; plan->number_of_channel = common_read_16_bit_inverse(ptr); ptr += 2; return ptr; @@ -358,6 +404,7 @@ bool ws_wp_nested_us_read(uint8_t *data, uint16_t length, struct ws_us_ie *us_ie if (mac_ie_nested_discover(data, length, &nested_payload_ie) < 4) { return false; } + data = nested_payload_ie.content_ptr; us_ie->dwell_interval = *data++; us_ie->clock_drift = *data++; @@ -419,6 +466,36 @@ bool ws_wp_nested_us_read(uint8_t *data, uint16_t length, struct ws_us_ie *us_ie } + switch (us_ie->excluded_channel_ctrl) { + case WS_EXC_CHAN_CTRL_NONE: + + break; + case WS_EXC_CHAN_CTRL_RANGE: + us_ie->excluded_channels.range.number_of_range = *data; + if (nested_payload_ie.length < (us_ie->excluded_channels.range.number_of_range * 4) + 1) { + return false; + } + //Set Range start after validation + us_ie->excluded_channels.range.range_start = data + 1; + break; + + case WS_EXC_CHAN_CTRL_BITMASK: + if (us_ie->channel_plan == 1) { + us_ie->excluded_channels.mask.mask_len_inline = ((us_ie->plan.one.number_of_channel + 7) / 8); + if (us_ie->excluded_channels.mask.mask_len_inline != nested_payload_ie.length) { + //Channel mask length is not correct + return false; + } + } else { + us_ie->excluded_channels.mask.mask_len_inline = nested_payload_ie.length; + } + + us_ie->excluded_channels.mask.channel_mask = data; + break; + default: + return false; + } + return true; } bool ws_wp_nested_bs_read(uint8_t *data, uint16_t length, struct ws_bs_ie *bs_ie) diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index 9e94dbbe4c..adef723d0c 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -547,6 +547,12 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t bs_ie_inline = ws_wp_nested_bs_read(ws_wp_nested.content_ptr, ws_wp_nested.length, &ws_bs_ie); } + //Validate Unicast shedule Channel Plan + if (us_ie_inline && !ws_bootstrap_validate_channel_plan(&us_ie, interface)) { + //Channel plan configuration mismatch + return; + } + llc_neighbour_req_t neighbor_info; bool multicast; bool request_new_entry; diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index 63f7322326..cd4ce0cd80 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -21,11 +21,12 @@ #include "ns_trace.h" #include #include +#include "fhss_config.h" +#include "ws_management_api.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" - -#include "ws_management_api.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #define TRACE_GROUP "wsmg" @@ -40,19 +41,37 @@ int ws_management_node_init( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } if (!network_name_ptr || !fhss_timer_ptr) { return -2; } - cur->ws_info->hopping_schdule.regulatory_domain = regulatory_domain; - if (ws_common_regulatory_domain_config(cur) < 0) { - // Invalid regulatory domain set + + ws_phy_cfg_t phy_cfg; + if (ws_cfg_phy_get(&phy_cfg, NULL) < 0) { return -3; } - strncpy(cur->ws_info->network_name, network_name_ptr, 32); + + phy_cfg.regulatory_domain = regulatory_domain; + + if (ws_cfg_phy_set(cur, NULL, &phy_cfg, 0) < 0) { + return -4; + } + + ws_gen_cfg_t gen_cfg; + if (ws_cfg_gen_get(&gen_cfg, NULL) < 0) { + return -3; + } + + strncpy(gen_cfg.network_name, network_name_ptr, 32); + + if (ws_cfg_gen_set(cur, NULL, &gen_cfg, 0) < 0) { + return -4; + } + cur->ws_info->fhss_timer_ptr = fhss_timer_ptr; + return 0; } @@ -62,65 +81,162 @@ int ws_management_network_name_set( { protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - if (!network_name_ptr || strlen(network_name_ptr) == 0 || strlen(network_name_ptr) > 32) { + if (!network_name_ptr) { return -2; } - if (strcmp(cur->ws_info->network_name, network_name_ptr) == 0) { - // Network name is the same no further actions required. - return 0; + + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return -3; } - strncpy(cur->ws_info->network_name, network_name_ptr, 32); - // if settings change reset_restart for the settings needed - if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { - // bootstrap active need to restart - ws_bootstrap_restart(interface_id); + + strncpy(cfg.network_name, network_name_ptr, 32); + + if (ws_cfg_gen_set(cur, NULL, &cfg, 0) < 0) { + return -4; } return 0; } + +int ws_management_network_name_get( + int8_t interface_id, + char *network_name_ptr) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!network_name_ptr) { + return -2; + } + + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return -3; + } + + memcpy(network_name_ptr, cfg.network_name, 32); + + return 0; +} + +int ws_management_network_name_validate( + int8_t interface_id, + char *network_name_ptr) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!network_name_ptr) { + return -2; + } + + ws_gen_cfg_t cfg; + if (ws_cfg_gen_get(&cfg, NULL) < 0) { + return -3; + } + + strncpy(cfg.network_name, network_name_ptr, 32); + + if (ws_cfg_gen_validate(NULL, &cfg) < 0) { + return -4; + } + + return 0; +} + int ws_management_regulatory_domain_set( int8_t interface_id, uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode) { - uint8_t regulatory_domain_saved; - uint8_t operating_class_saved; - uint8_t operating_mode_saved; protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - regulatory_domain_saved = cur->ws_info->hopping_schdule.regulatory_domain; - operating_class_saved = cur->ws_info->hopping_schdule.operating_mode; - operating_mode_saved = cur->ws_info->hopping_schdule.operating_class; + + ws_phy_cfg_t cfg; + if (ws_cfg_phy_get(&cfg, NULL) < 0) { + return -3; + } + if (regulatory_domain != 255) { - cur->ws_info->hopping_schdule.regulatory_domain = regulatory_domain; + cfg.regulatory_domain = regulatory_domain; } if (operating_mode != 255) { - cur->ws_info->hopping_schdule.operating_mode = operating_mode; + cfg.operating_mode = operating_mode; } if (operating_class != 255) { - cur->ws_info->hopping_schdule.operating_class = operating_class; + cfg.operating_class = operating_class; } - if (ws_common_regulatory_domain_config(cur) != 0) { - // Restore old config on failure - //tr_error("unsupported regulatory domain: %d class: %d, mode: %d", regulatory_domain, operating_class, operating_mode); - cur->ws_info->hopping_schdule.regulatory_domain = regulatory_domain_saved; - cur->ws_info->hopping_schdule.operating_mode = operating_mode_saved; - cur->ws_info->hopping_schdule.operating_class = operating_class_saved; - ws_common_regulatory_domain_config(cur); + + if (ws_cfg_phy_set(cur, NULL, &cfg, 0) < 0) { + return -4; + } + + return 0; +} + +int ws_management_regulatory_domain_get( + int8_t interface_id, + uint8_t *regulatory_domain, + uint8_t *operating_class, + uint8_t *operating_mode) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - // if settings change reset_restart for the settings needed - if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) { - // bootstrap active need to restart - ws_bootstrap_restart(interface_id); + if (!regulatory_domain || !operating_class || !operating_mode) { + return -2; + } + + ws_phy_cfg_t cfg; + if (ws_cfg_phy_get(&cfg, NULL) < 0) { + return -3; + } + + *regulatory_domain = cfg.regulatory_domain; + *operating_class = cfg.operating_class; + *operating_mode = cfg.operating_mode; + + return 0; +} + +int ws_management_regulatory_domain_validate( + int8_t interface_id, + uint8_t regulatory_domain, + uint8_t operating_class, + uint8_t operating_mode) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_phy_cfg_t cfg; + if (ws_cfg_phy_get(&cfg, NULL) < 0) { + return -3; + } + + cfg.regulatory_domain = regulatory_domain; + cfg.operating_class = operating_class; + cfg.operating_mode = operating_mode; + + if (ws_cfg_phy_validate(NULL, &cfg) < 0) { + return -4; } return 0; @@ -133,38 +249,68 @@ int ws_management_network_size_set( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - //Store old setup if new is not accepted - uint8_t old_setup = ws_info(cur)->network_size_config; - ws_info(cur)->network_size_config = network_size; - uint16_t rpl_parent_candidate_max; - uint16_t rpl_selected_parent_max; - - if (network_size == NETWORK_SIZE_CERTIFICATE) { - rpl_parent_candidate_max = WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX; - rpl_selected_parent_max = WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX; - } else { - rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX; - rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX; + ws_gen_cfg_t cfg; + if (ws_cfg_network_size_get(&cfg, NULL) < 0) { + return -3; } - if (network_size == NETWORK_SIZE_LARGE) { - ws_common_network_size_configure(cur, 5000); - } else if (network_size == NETWORK_SIZE_MEDIUM) { - ws_common_network_size_configure(cur, 200); - } else if (network_size == NETWORK_SIZE_SMALL) { - ws_common_network_size_configure(cur, 10); - } else if (network_size == NETWORK_SIZE_CERTIFICATE) { - ws_common_network_size_configure(cur, 0); - } else { - ws_info(cur)->network_size_config = old_setup; + cfg.network_size = network_size; + + if (ws_cfg_network_size_set(cur, NULL, &cfg, 0) < 0) { + return -3; + } + + return 0; +} + +int ws_management_network_size_get( + int8_t interface_id, + uint8_t *network_size) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!network_size) { return -2; } - cur->ws_info->rpl_parent_candidate_max = rpl_parent_candidate_max; - cur->ws_info->rpl_selected_parent_max = rpl_selected_parent_max; + + ws_gen_cfg_t cfg; + if (ws_cfg_network_size_get(&cfg, NULL) < 0) { + return -3; + } + + *network_size = cfg.network_size; + + return 0; +} + +int ws_management_network_size_validate( + int8_t interface_id, + uint8_t network_size) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_gen_cfg_t cfg; + if (ws_cfg_network_size_get(&cfg, NULL) < 0) { + return -3; + } + + cfg.network_size = network_size; + + if (ws_cfg_network_size_validate(NULL, &cfg) < 0) { + return -4; + } + return 0; } @@ -175,10 +321,68 @@ int ws_management_channel_mask_set( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - memcpy(cur->ws_info->fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8); + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + memcpy(cfg.fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8); + + if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { + return -3; + } + + return 0; +} + +int ws_management_channel_mask_get( + int8_t interface_id, + uint32_t *channel_mask) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!channel_mask) { + return -2; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + memcpy(channel_mask, cfg.fhss_channel_mask, sizeof(uint32_t) * 8); + + return 0; +} + +int ws_management_channel_mask_validate( + int8_t interface_id, + uint32_t channel_mask[8]) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + memcpy(cfg.fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8); + + if (ws_cfg_fhss_validate(NULL, &cfg) < 0) { + return -4; + } + return 0; } @@ -194,7 +398,7 @@ int ws_management_channel_plan_set( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } cur->ws_info->hopping_schdule.channel_plan = channel_plan; @@ -217,38 +421,29 @@ int ws_management_fhss_timing_configure( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - if (fhss_uc_dwell_interval && fhss_uc_dwell_interval < 15) { + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { return -2; } - if (fhss_bc_dwell_interval && fhss_bc_dwell_interval < 15) { - return -2; + if (fhss_uc_dwell_interval > 0) { + cfg.fhss_uc_dwell_interval = fhss_uc_dwell_interval; + } + if (fhss_broadcast_interval > 0) { + cfg.fhss_bc_interval = fhss_broadcast_interval; + } + if (fhss_bc_dwell_interval > 0) { + cfg.fhss_bc_dwell_interval = fhss_bc_dwell_interval; } - bool updated_configure = false; - - if (fhss_uc_dwell_interval > 0 && cur->ws_info->fhss_uc_dwell_interval != fhss_uc_dwell_interval) { - cur->ws_info->fhss_uc_dwell_interval = fhss_uc_dwell_interval; - updated_configure = true; - } - if (fhss_broadcast_interval > 0 && cur->ws_info->fhss_bc_interval != fhss_broadcast_interval) { - cur->ws_info->fhss_bc_interval = fhss_broadcast_interval; - updated_configure = true; - } - if (fhss_bc_dwell_interval > 0 && cur->ws_info->fhss_bc_dwell_interval != fhss_bc_dwell_interval) { - cur->ws_info->fhss_bc_dwell_interval = fhss_bc_dwell_interval; - updated_configure = true; + if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { + return -3; } - // if settings change reset_restart for the settings needed - if (updated_configure && (cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { - // bootstrap active need to restart - ws_bootstrap_restart(interface_id); - } return 0; } @@ -261,53 +456,82 @@ int ws_management_fhss_unicast_channel_function_configure( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - if (channel_function != WS_FIXED_CHANNEL && - channel_function != WS_VENDOR_DEF_CF && - channel_function != WS_DH1CF && - channel_function != WS_TR51CF) { + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { return -2; } - if (dwell_interval && dwell_interval < 15) { - return -2; + if (dwell_interval > 0) { + cfg.fhss_uc_dwell_interval = dwell_interval; } - if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) { - fixed_channel = 0; - tr_warn("Fixed channel not configured. Set to 0"); + cfg.fhss_uc_channel_function = channel_function; + cfg.fhss_uc_fixed_channel = fixed_channel; + + if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { + return -3; } - bool updated_config = false; - - if (cur->ws_info->fhss_uc_channel_function != channel_function) { - cur->ws_info->fhss_uc_channel_function = channel_function; - updated_config = true; - } - - if (cur->ws_info->fhss_uc_channel_function == WS_FIXED_CHANNEL) { - if (cur->ws_info->fhss_uc_fixed_channel != fixed_channel) { - cur->ws_info->fhss_uc_fixed_channel = fixed_channel; - updated_config = true; - } - } else { - cur->ws_info->fhss_uc_fixed_channel = 0xffff; - } - - if (dwell_interval && cur->ws_info->fhss_uc_dwell_interval != dwell_interval) { - cur->ws_info->fhss_uc_dwell_interval = dwell_interval; - updated_config = true; - } - - // if settings change reset_restart for the settings needed - if (updated_config && (cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { - // bootstrap active need to restart - ws_bootstrap_restart(interface_id); - } return 0; +} +int ws_management_fhss_unicast_channel_function_get( + int8_t interface_id, + uint8_t *channel_function, + uint16_t *fixed_channel, + uint8_t *dwell_interval) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!channel_function || !fixed_channel || !dwell_interval) { + return -2; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + *dwell_interval = cfg.fhss_uc_dwell_interval; + *channel_function = cfg.fhss_uc_channel_function; + *fixed_channel = cfg.fhss_uc_fixed_channel; + + return 0; +} + +int ws_management_fhss_unicast_channel_function_validate( + int8_t interface_id, + uint8_t channel_function, + uint16_t fixed_channel, + uint8_t dwell_interval) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + cfg.fhss_uc_dwell_interval = dwell_interval; + cfg.fhss_uc_channel_function = channel_function; + cfg.fhss_uc_fixed_channel = fixed_channel; + + if (ws_cfg_fhss_validate(NULL, &cfg) < 0) { + return -4; + } + + return 0; } int ws_management_fhss_broadcast_channel_function_configure( @@ -320,57 +544,187 @@ int ws_management_fhss_broadcast_channel_function_configure( protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur || !ws_info(cur)) { + if (interface_id >= 0 && (!cur || !ws_info(cur))) { return -1; } - if (channel_function != WS_FIXED_CHANNEL && - channel_function != WS_VENDOR_DEF_CF && - channel_function != WS_DH1CF && - channel_function != WS_TR51CF) { + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { return -2; } - if (dwell_interval && dwell_interval < 15) { - return -2; + if (dwell_interval > 0) { + cfg.fhss_bc_dwell_interval = dwell_interval; + } + if (broadcast_interval > 0) { + cfg.fhss_bc_interval = broadcast_interval; } - if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) { - fixed_channel = 0; - tr_warn("Fixed channel not configured. Set to 0"); + cfg.fhss_bc_channel_function = channel_function; + cfg.fhss_bc_fixed_channel = fixed_channel; + + if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { + return -3; } - bool updated_config = false; - - if (cur->ws_info->fhss_bc_channel_function != channel_function) { - cur->ws_info->fhss_bc_channel_function = channel_function; - updated_config = true; - } - - if (cur->ws_info->fhss_bc_channel_function == WS_FIXED_CHANNEL) { - if (cur->ws_info->fhss_bc_fixed_channel != fixed_channel) { - cur->ws_info->fhss_bc_fixed_channel = fixed_channel; - updated_config = true; - } - } else { - cur->ws_info->fhss_bc_fixed_channel = 0xffff; - } - - if (dwell_interval > 0 && cur->ws_info->fhss_bc_dwell_interval != dwell_interval) { - cur->ws_info->fhss_bc_dwell_interval = dwell_interval; - updated_config = true; - } - - if (broadcast_interval > 0 && cur->ws_info->fhss_bc_interval != broadcast_interval) { - cur->ws_info->fhss_bc_interval = broadcast_interval; - updated_config = true; - } - - // if settings change reset_restart for the settings needed - if (updated_config && (cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { - // bootstrap active need to restart - ws_bootstrap_restart(interface_id); - } return 0; - } + +int ws_management_fhss_broadcast_channel_function_get( + int8_t interface_id, + uint8_t *channel_function, + uint16_t *fixed_channel, + uint8_t *dwell_interval, + uint32_t *broadcast_interval) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!channel_function || !fixed_channel || !dwell_interval) { + return -2; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + *dwell_interval = cfg.fhss_bc_dwell_interval; + *broadcast_interval = cfg.fhss_bc_interval; + *channel_function = cfg.fhss_bc_channel_function; + *fixed_channel = cfg.fhss_bc_fixed_channel; + + return 0; +} + +int ws_management_fhss_broadcast_channel_function_validate( + int8_t interface_id, + uint8_t channel_function, + uint16_t fixed_channel, + uint8_t dwell_interval, + uint32_t broadcast_interval) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + cfg.fhss_bc_dwell_interval = dwell_interval; + cfg.fhss_bc_interval = broadcast_interval; + cfg.fhss_bc_channel_function = channel_function; + cfg.fhss_bc_fixed_channel = fixed_channel; + + if (ws_cfg_fhss_validate(NULL, &cfg) < 0) { + return -4; + } + + return 0; +} + +int ws_management_timing_parameters_set( + int8_t interface_id, + uint16_t disc_trickle_imin, + uint16_t disc_trickle_imax, + uint8_t disc_trickle_k, + uint16_t pan_timeout) +{ + protocol_interface_info_entry_t *cur; + + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_timing_cfg_t cfg; + if (ws_cfg_timing_get(&cfg, NULL) < 0) { + return -2; + } + + if (disc_trickle_imin > 0) { + cfg.disc_trickle_imin = disc_trickle_imin; + } + if (disc_trickle_imax > 0) { + cfg.disc_trickle_imax = disc_trickle_imax; + } + if (disc_trickle_k > 0) { + cfg.disc_trickle_k = disc_trickle_k; + } + if (pan_timeout > 0) { + cfg.pan_timeout = pan_timeout; + } + + if (ws_cfg_timing_set(cur, NULL, &cfg, 0) < 0) { + return -3; + } + + return 0; +} + +int ws_management_timing_parameters_get( + int8_t interface_id, + uint16_t *disc_trickle_imin, + uint16_t *disc_trickle_imax, + uint8_t *disc_trickle_k, + uint16_t *pan_timeout) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + if (!disc_trickle_imin || !disc_trickle_imax || !disc_trickle_k || !pan_timeout) { + return -2; + } + + ws_timing_cfg_t cfg; + if (ws_cfg_timing_get(&cfg, NULL) < 0) { + return -2; + } + + *disc_trickle_imin = cfg.disc_trickle_imin; + *disc_trickle_imax = cfg.disc_trickle_imax; + *disc_trickle_k = cfg.disc_trickle_k; + *pan_timeout = cfg.pan_timeout; + + return 0; +} + +int ws_management_timing_parameters_validate( + int8_t interface_id, + uint16_t disc_trickle_imin, + uint16_t disc_trickle_imax, + uint8_t disc_trickle_k, + uint16_t pan_timeout) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (interface_id >= 0 && (!cur || !ws_info(cur))) { + return -1; + } + + ws_timing_cfg_t cfg; + if (ws_cfg_timing_get(&cfg, NULL) < 0) { + return -2; + } + + cfg.disc_trickle_imin = disc_trickle_imin; + cfg.disc_trickle_imax = disc_trickle_imax; + cfg.disc_trickle_k = disc_trickle_k; + cfg.pan_timeout = pan_timeout; + + if (ws_cfg_timing_validate(NULL, &cfg) < 0) { + return -4; + } + + return 0; +} + #endif // HAVE_WS diff --git a/source/6LoWPAN/ws/ws_neighbor_class.c b/source/6LoWPAN/ws/ws_neighbor_class.c index 8eda4fcc63..7e4e7eedc0 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.c +++ b/source/6LoWPAN/ws/ws_neighbor_class.c @@ -21,6 +21,7 @@ #include "ns_list.h" #include "ns_trace.h" #include "nsdynmemLIB.h" +#include "common_functions.h" #include "fhss_config.h" #include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_neighbor_class.h" @@ -94,6 +95,121 @@ void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi; } +static void ws_neighbour_channel_list_enable_all(ws_channel_mask_t *channel_info, uint16_t number_of_channels) +{ + uint32_t mask; + channel_info->channel_count = number_of_channels; + for (uint8_t n = 0; n < 8; n++) { + if (number_of_channels >= 32) { + mask = 0xffffffff; + number_of_channels -= 32; + } else if (number_of_channels) { + mask = 0; + //Start bit enable to MSB + for (uint16_t i = 0; i < (number_of_channels % 32); i++) { + mask |= 1 << i; + } + number_of_channels = 0; + } else { + mask = 0; + } + channel_info->channel_mask[n] = mask; + } +} + +static void ws_neighbour_excluded_mask_by_range(ws_channel_mask_t *channel_info, ws_excluded_channel_range_t *range_info, uint16_t number_of_channels) +{ + uint16_t range_start, range_stop; + uint8_t mask_index = 0; + uint32_t compare_mask_bit; + uint8_t *range_ptr = range_info->range_start; + while (range_info->number_of_range) { + range_start = common_read_16_bit_inverse(range_ptr); + range_ptr += 2; + range_stop = common_read_16_bit_inverse(range_ptr); + range_ptr += 2; + range_info->number_of_range--; + for (uint16_t channel = 0; channel < number_of_channels; channel++) { + + if (channel >= range_start && channel <= range_stop) { + //Cut channel + compare_mask_bit = 1 << (channel % 32); + mask_index = 0 + (channel / 32); + + if (channel_info->channel_mask[mask_index] & compare_mask_bit) { + channel_info->channel_mask[mask_index] ^= compare_mask_bit; + channel_info->channel_count--; + } + } else if (channel > range_stop) { + break; + } + } + } +} + +static uint32_t ws_reserve_order_32_bit(uint32_t value) +{ + uint32_t ret_val = 0; + for (uint8_t i = 0; i < 32; i++) { + if ((value & (1 << i))) { + ret_val |= 1 << ((32 - 1) - i); + } + } + return ret_val; +} + +static void ws_neighbour_excluded_mask_by_mask(ws_channel_mask_t *channel_info, ws_excluded_channel_mask_t *mask_info, uint16_t number_of_channels) +{ + if (mask_info->mask_len_inline == 0) { + return; + } + + uint16_t channel_at_mask; + uint8_t mask_index = 0; + uint32_t channel_compare_mask, compare_mask_bit; + uint8_t *mask_ptr = mask_info->channel_mask; + + channel_at_mask = mask_info->mask_len_inline * 8; + + for (uint16_t channel = 0; channel < number_of_channels; channel += 32) { + if (channel) { + mask_index++; + mask_ptr += 4; + } + + //Read allaways 32-bit + if (channel_at_mask >= 32) { + channel_compare_mask = common_read_32_bit(mask_ptr); + channel_at_mask -= 32; + } else { + //Read Rest bytes seprately + channel_compare_mask = 0; + uint8_t move_mask = 0; + //Convert 8-24bit to 32-bit + while (channel_at_mask) { + channel_compare_mask |= (uint32_t)(*mask_ptr++ << (24 - move_mask)); + channel_at_mask -= 8; + move_mask += 8; + } + } + //Reserve bit order for compare + channel_compare_mask = ws_reserve_order_32_bit(channel_compare_mask); + //Compare now 32-bit mask's bits one by one + for (uint8_t i = 0; i < 32; i++) { + //Start from MSB + compare_mask_bit = 1 << (i); + if ((channel_compare_mask & compare_mask_bit) && (channel_info->channel_mask[mask_index] & compare_mask_bit)) { + channel_info->channel_mask[mask_index] ^= compare_mask_bit; + channel_info->channel_count--; + } + } + //Stop compare if all bits in line are compared + if (channel_at_mask == 0) { + break; + } + } +} + void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us) { ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function = ws_us->channel_function; @@ -105,9 +221,21 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t * ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class); } else if (ws_us->channel_plan == 1) { ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel; - } else { - ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 0; } + + //Handle excluded channel and generate activate channel list + if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) { + ws_neighbour_channel_list_enable_all(&ws_neighbor->fhss_data.uc_channel_list, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); + ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); + } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) { + ws_neighbour_channel_list_enable_all(&ws_neighbor->fhss_data.uc_channel_list, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); + ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); + } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) { + if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) { + ws_neighbour_channel_list_enable_all(&ws_neighbor->fhss_data.uc_channel_list, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); + } + } + } ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval = ws_us->dwell_interval; } diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index 01ffea5603..df50aea726 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -23,12 +23,14 @@ #include "ns_trace.h" #include "nsdynmemLIB.h" #include "fhss_config.h" +#include "ws_management_api.h" #include "eventOS_event.h" #include "eventOS_scheduler.h" #include "eventOS_event_timer.h" #include "ns_address.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/kmp/kmp_socket_if.h" @@ -39,6 +41,7 @@ #include "Security/protocols/tls_sec_prot/tls_sec_prot.h" #include "Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h" #include "Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_pae_controller.h" #include "6LoWPAN/ws/ws_pae_timers.h" #include "6LoWPAN/ws/ws_pae_auth.h" @@ -56,8 +59,6 @@ // Wait for for supplicant to indicate activity (e.g. to send a message) #define WAIT_FOR_AUTHENTICATION_TICKS 5 * 60 * 10 // 5 minutes -// Maximum number of simultaneous EAP-TLS negotiations -#define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS 3 /* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how long to wait for previous negotiation to complete */ @@ -86,7 +87,8 @@ typedef struct { sec_prot_gtk_keys_t *gtks; /**< GTKs */ sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */ const sec_prot_certs_t *certs; /**< Certificates */ - timer_settings_t *timer_settings; /**< Timer settings */ + sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */ + sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */ uint16_t supp_max_number; /**< Max number of stored supplicants */ uint16_t slow_timer_seconds; /**< Slow timer seconds */ bool timer_running : 1; /**< Timer is running */ @@ -117,13 +119,13 @@ static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e typ static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys); static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry); static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry); -static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry); +static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *cfg); static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp); static int8_t tasklet_id = -1; static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link); -int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, timer_settings_t *timer_settings) +int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg) { if (!interface_ptr || !gtks || !certs) { return -1; @@ -150,7 +152,8 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot pae_auth->gtks = gtks; pae_auth->next_gtks = next_gtks; pae_auth->certs = certs; - pae_auth->timer_settings = timer_settings; + pae_auth->sec_timer_cfg = sec_timer_cfg; + pae_auth->sec_prot_cfg = sec_prot_cfg; pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER; pae_auth->slow_timer_seconds = 0; @@ -215,14 +218,6 @@ error: return -1; } -int8_t ws_pae_auth_timing_adjust(uint8_t timing) -{ - auth_gkh_sec_prot_timing_adjust(timing); - auth_fwh_sec_prot_timing_adjust(timing); - auth_eap_tls_sec_prot_timing_adjust(timing); - return 0; -} - int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port) { if (!interface_ptr || !remote_addr) { @@ -387,7 +382,7 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int // As default removes other keys than active int8_t not_removed_index = active_index; - uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->timer_settings); + uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->sec_timer_cfg); uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, active_index); @@ -608,7 +603,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds) uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, i, seconds); 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->timer_settings, timer_seconds); + pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_timer_cfg, timer_seconds); if (pae_auth->gtk_new_inst_req_exp) { int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); if (second_index < 0) { @@ -622,7 +617,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds) } if (!pae_auth->gtk_new_act_time_exp) { - pae_auth->gtk_new_act_time_exp = ws_pae_timers_gtk_new_activation_time(pae_auth->timer_settings, timer_seconds); + pae_auth->gtk_new_act_time_exp = ws_pae_timers_gtk_new_activation_time(pae_auth->sec_timer_cfg, timer_seconds); if (pae_auth->gtk_new_act_time_exp) { int8_t new_active_index = ws_pae_auth_new_gtk_activate(pae_auth); tr_info("GTK new activation time active index: %i, time: %"PRIu32", new index: %i, system time: %"PRIu32"", active_index, timer_seconds, new_active_index, protocol_core_monotonic_time / 10); @@ -644,8 +639,8 @@ void ws_pae_auth_slow_timer(uint16_t seconds) pae_auth->slow_timer_seconds += seconds; if (pae_auth->slow_timer_seconds > 60) { - ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, pae_auth->timer_settings, pae_auth->slow_timer_seconds); - ws_pae_lib_supp_list_slow_timer_update(&pae_auth->inactive_supp_list, pae_auth->timer_settings, pae_auth->slow_timer_seconds); + ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, pae_auth->sec_timer_cfg, pae_auth->slow_timer_seconds); + ws_pae_lib_supp_list_slow_timer_update(&pae_auth->inactive_supp_list, pae_auth->sec_timer_cfg, pae_auth->slow_timer_seconds); pae_auth->slow_timer_seconds = 0; } } @@ -675,7 +670,7 @@ static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth) } // Gets latest installed key lifetime and adds GTK expire offset to it - uint32_t lifetime = pae_auth->timer_settings->gtk_expire_offset; + uint32_t lifetime = pae_auth->sec_timer_cfg->gtk_expire_offset; int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); if (last_index >= 0) { lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, last_index); @@ -838,7 +833,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_ } // Create a new KMP for initial eapol-key - kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY); + kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY, pae_auth->sec_prot_cfg); if (!kmp) { return 0; @@ -944,7 +939,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup supplicant. Otherwise supplicant must re-send initial EAPOL-Key to try again using its trickle schedule */ uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, IEEE_802_1X_MKA); - if (ongoing_eap_tls_cnt >= MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS) { + if (ongoing_eap_tls_cnt >= pae_auth->sec_prot_cfg->sec_max_ongoing_authentication) { supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT; tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(supp_entry->addr.eui_64, 8)); return; @@ -952,7 +947,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup } // Create new instance - kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry); + kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry, pae_auth->sec_prot_cfg); if (!new_kmp) { return; } @@ -965,7 +960,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup return; } // Create TLS instance */ - if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry) == NULL) { + if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry, pae_auth->sec_prot_cfg) == NULL) { ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp); return; } @@ -1009,7 +1004,7 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry * has been, trigger 4WH to update also the PTK. This prevents writing multiple * GTK keys to same index using same PTK. */ - if (pae_auth->timer_settings->gtk_expire_offset > SHORT_GTK_LIFETIME && + if (pae_auth->sec_timer_cfg->gtk_expire_offset > SHORT_GTK_LIFETIME && sec_prot_keys_ptk_installed_gtk_hash_mismatch_check(sec_keys, gtk_index)) { // start 4WH towards supplicant next_type = IEEE_802_11_4WH; @@ -1033,10 +1028,10 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry } -static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry) +static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *cfg) { // Create KMP instance for new authentication - kmp_api_t *kmp = kmp_api_create(service, type); + kmp_api_t *kmp = kmp_api_create(service, type, cfg); if (!kmp) { return NULL; diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index 04bd157d78..5bf680f4ab 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -47,34 +47,14 @@ * \param next_gtks next group keys to be used * \param cert_chain certificate chain * \param timer_settings timer settings + * \param sec_timer_cfg timer configuration + * \param sec_prot_cfg protocol configuration * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, timer_settings_t *timer_settings); - -/** - * ws_pae_auth_timing_adjust Adjust retries and timings of the security protocols - * - * Timing value is a generic number between 0 to 32 that goes from fast and - * reactive network to low bandwidth and long latency. - * - * example value definitions: - * 0-8 very fast network - * 9-16 medium network - * 16-24 slow network - * 25-32 extremely slow network - * - * There is no need to have lots variations in every layer if protocol is not very active in any case. - * - * \param timing Timing value. - * - * \return < 0 failure - * \return >= 0 success - * - */ -int8_t ws_pae_auth_timing_adjust(uint8_t timing); +int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg); /** * ws_pae_auth_addresses_set set relay addresses @@ -231,7 +211,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #else -#define ws_pae_auth_init(interface_ptr, gtks, next_gtks, certs, timer_settings) 1 +#define ws_pae_auth_init(interface_ptr, gtks, next_gtks, certs, sec_timer_cfg, sec_prot_cfg) 1 #define ws_pae_auth_timing_adjust(timing) #define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1 #define ws_pae_auth_delete NULL diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index f5bc4dba92..cf73b0a9da 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -23,9 +23,12 @@ #include "nsdynmemLIB.h" #include "fhss_config.h" #include "ns_address.h" +#include "ws_management_api.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_pae_controller.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/protocols/sec_prot_certs.h" #include "Security/protocols/sec_prot_keys.h" #include "6LoWPAN/ws/ws_pae_timers.h" @@ -67,7 +70,8 @@ typedef struct { char *network_name; /**< Network name for GAK generation */ uint16_t frame_cnt_store_timer; /**< Timer for storing frame counter value */ frame_counters_t frame_counters; /**< Frame counters */ - timer_settings_t timer_settings; /**< Timer settings */ + sec_timer_cfg_t sec_timer_cfg; /**< Timer configuration (configuration set values) */ + sec_prot_cfg_t sec_prot_cfg; /**< Configuration */ protocol_interface_info_entry_t *interface_ptr; /**< List link entry */ ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */ ws_pae_controller_nw_key_set *nw_key_set; /**< Key set callback */ @@ -576,6 +580,8 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr) controller->nw_frame_counter_set = NULL; controller->pan_ver_increment = NULL; controller->pae_nvm_buffer = pae_nvm_buffer; + memset(&controller->sec_timer_cfg, 0, sizeof(ws_sec_timer_cfg_t)); + memset(&controller->sec_prot_cfg, 0, sizeof(sec_prot_cfg_t)); ws_pae_controller_data_init(controller); @@ -584,6 +590,30 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr) return 0; } +int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg) +{ + pae_controller_t *controller = ws_pae_controller_get(interface_ptr); + if (controller == NULL) { + return 0; + } + + if (sec_prot_cfg) { + controller->sec_prot_cfg.sec_prot_trickle_params.Imin = sec_prot_cfg->sec_prot_trickle_imin * 10; + controller->sec_prot_cfg.sec_prot_trickle_params.Imax = sec_prot_cfg->sec_prot_trickle_imax * 10; + controller->sec_prot_cfg.sec_prot_trickle_params.k = 0; + controller->sec_prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp; + controller->sec_prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10; + controller->sec_prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication; + } + + if (sec_timer_cfg) { + ws_pae_timers_settings_init(&controller->sec_timer_cfg, sec_timer_cfg); + } + + return 0; +} + + static void ws_pae_controller_data_init(pae_controller_t *controller) { memset(controller->target_eui_64, 0, 8); @@ -616,7 +646,6 @@ static void ws_pae_controller_data_init(pae_controller_t *controller) sec_prot_keys_gtks_init(&controller->next_gtks); sec_prot_certs_init(&controller->certs); sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled); - ws_pae_timers_settings_init(&controller->timer_settings); } static void ws_pae_controller_frame_counter_read(pae_controller_t *controller) @@ -667,7 +696,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt return -1; } - if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->timer_settings) < 0) { + if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg) < 0) { return -1; } @@ -693,7 +722,7 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt return -1; } - if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->next_gtks, &controller->certs, &controller->timer_settings) < 0) { + if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->next_gtks, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg) < 0) { return -1; } @@ -752,13 +781,6 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr) return 0; } -int8_t ws_pae_controller_timing_adjust(uint8_t timing) -{ - ws_pae_supp_timing_adjust(timing); - ws_pae_auth_timing_adjust(timing); - return 0; -} - int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *new_chain) { if (!new_chain) { @@ -998,7 +1020,7 @@ int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM]) for (uint8_t i = 0; i < GTK_NUM; i++) { if (gtk[i]) { uint32_t lifetime = sec_prot_keys_gtk_install_order_last_lifetime_get(&controller->gtks); - lifetime += controller->timer_settings.gtk_expire_offset; + lifetime += controller->sec_timer_cfg.gtk_expire_offset; if (sec_prot_keys_gtk_set(&controller->gtks, i, gtk[i], lifetime) >= 0) { controller->gtks_set = true; tr_info("GTK set index: %i, lifetime %"PRIu32", system time: %"PRIu32"", i, lifetime, protocol_core_monotonic_time / 10); @@ -1053,30 +1075,6 @@ int8_t ws_pae_controller_active_key_update(int8_t interface_id, uint8_t index) return 0; } -int8_t ws_pae_controller_key_lifetime_update(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime) -{ - pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); - if (!controller) { - return -1; - } - - ws_pae_timers_lifetime_set(&controller->timer_settings, gtk_lifetime, pmk_lifetime, ptk_lifetime); - - return 0; -} - -int8_t ws_pae_controller_gtk_time_settings_update(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch) -{ - pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); - if (!controller) { - return -1; - } - - ws_pae_timers_gtk_time_settings_set(&controller->timer_settings, revocat_lifetime_reduct, new_activation_time, new_install_req, max_mismatch); - - return 0; -} - int8_t ws_pae_controller_node_keys_remove(int8_t interface_id, uint8_t *eui_64) { #ifndef HAVE_PAE_AUTH diff --git a/source/6LoWPAN/ws/ws_pae_controller.h b/source/6LoWPAN/ws/ws_pae_controller.h index eb58253976..9a16b769d1 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.h +++ b/source/6LoWPAN/ws/ws_pae_controller.h @@ -28,6 +28,8 @@ typedef enum { } auth_result_e; struct nvm_tlv_entry; +struct ws_sec_timer_cfg_s; +struct ws_sec_prot_cfg_s; /** * ws_pae_controller_set_target sets EAPOL target for PAE supplicant @@ -89,6 +91,19 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in */ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr); +/** + * ws_pae_controller_config_set sets PAE controller configuration + * + * \param interface_ptr interface + * \param sec_timer_cfg timer configuration or NULL if not set + * \param sec_prot_cfg protocol configuration or NULL if not set + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_ptr, struct ws_sec_timer_cfg_s *sec_timer_cfg, struct ws_sec_prot_cfg_s *sec_prot_cfg); + /** * ws_pae_controller_init initializes PAE supplicant * @@ -133,28 +148,6 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr); */ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr); -/** - * ws_pae_controller_timing_adjust Adjust retries and timings of the security protocols - * - * Timing value is a generic number between 0 to 32 that goes from fast and - * reactive network to low bandwidth and long latency. - * - * example value definitions: - * 0-8 very fast network - * 9-16 medium network - * 16-24 slow network - * 25-32 extremely slow network - * - * There is no need to have lots variations in every layer if protocol is not very active in any case. - * - * \param timing Timing value. - * - * \return < 0 failure - * \return >= 0 success - * - */ -int8_t ws_pae_controller_timing_adjust(uint8_t timing); - /** * ws_pae_controller_certificate_chain_set set certificate chain * diff --git a/source/6LoWPAN/ws/ws_pae_lib.c b/source/6LoWPAN/ws/ws_pae_lib.c index 455ba76f64..4394ee1dc8 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.c +++ b/source/6LoWPAN/ws/ws_pae_lib.c @@ -22,13 +22,16 @@ #include "ns_trace.h" #include "nsdynmemLIB.h" #include "fhss_config.h" +#include "ws_management_api.h" #include "NWK_INTERFACE/Include/protocol.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_pae_timers.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/protocols/sec_prot_certs.h" #include "Security/protocols/sec_prot_keys.h" -#include "6LoWPAN/ws/ws_pae_timers.h" #include "6LoWPAN/ws/ws_pae_lib.h" #ifdef HAVE_WS @@ -228,7 +231,7 @@ bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_ return timer_running; } -void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settings_t *timer_settings, uint16_t seconds) +void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, sec_timer_cfg_t *timer_settings, uint16_t seconds) { ns_list_foreach(supp_entry_t, entry, supp_list) { if (sec_prot_keys_pmk_lifetime_decrement(&entry->sec_keys, timer_settings->pmk_lifetime, seconds)) { diff --git a/source/6LoWPAN/ws/ws_pae_lib.h b/source/6LoWPAN/ws/ws_pae_lib.h index 3ee6f10d0f..b045fd00fd 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.h +++ b/source/6LoWPAN/ws/ws_pae_lib.h @@ -233,7 +233,7 @@ bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_ * \param seconds seconds * */ -void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settings_t *timer_settings, uint16_t seconds); +void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, sec_timer_cfg_t *timer_settings, uint16_t seconds); /** * ws_pae_lib_supp_list_timer_update updates supplicant timers diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index db891dc6e4..a9e955366e 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -23,6 +23,7 @@ #include "ns_trace.h" #include "nsdynmemLIB.h" #include "fhss_config.h" +#include "ws_management_api.h" #include "eventOS_event.h" #include "eventOS_scheduler.h" #include "eventOS_event_timer.h" @@ -32,6 +33,7 @@ #include "RPL/rpl_control.h" #include "RPL/rpl_data.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/protocols/sec_prot_certs.h" @@ -41,6 +43,7 @@ #include "Security/protocols/tls_sec_prot/tls_sec_prot.h" #include "Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h" #include "Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_pae_controller.h" #include "6LoWPAN/ws/ws_pae_timers.h" #include "6LoWPAN/ws/ws_pae_supp.h" @@ -101,7 +104,8 @@ typedef struct { sec_prot_gtk_keys_t gtks; /**< GTKs */ uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap */ sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */ - timer_settings_t *timer_settings; /**< Timer settings */ + sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */ + sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */ uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */ uint8_t initial_key_retry_cnt; /**< initial EAPOL-Key retry counter */ bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */ @@ -370,7 +374,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt // Starts supplicant timer ws_pae_supp_timer_start(pae_supp); - tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->timer_settings->gtk_request_imin, pae_supp->timer_settings->gtk_request_imax, pae_supp->timer_settings->gtk_max_mismatch, pae_supp->auth_trickle_timer.t); + tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->sec_timer_cfg->gtk_request_imin, pae_supp->sec_timer_cfg->gtk_request_imax, pae_supp->sec_timer_cfg->gtk_max_mismatch, pae_supp->auth_trickle_timer.t); } } @@ -618,7 +622,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ pae_supp->gtk_hash_ptr_get = gtk_hash_ptr_get; } -int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, timer_settings_t *timer_settings) +int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg) { if (!interface_ptr) { return -1; @@ -641,8 +645,9 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se pae_supp->initial_key_timer = 0; pae_supp->initial_key_retry_timer = 0; pae_supp->nw_keys_used_cnt = 0; - pae_supp->timer_settings = timer_settings; pae_supp->initial_key_retry_cnt = INITIAL_KEY_RETRY_COUNT; + pae_supp->sec_timer_cfg = sec_timer_cfg; + pae_supp->sec_prot_cfg = sec_prot_cfg; pae_supp->auth_trickle_running = false; pae_supp->auth_requested = false; pae_supp->timer_running = false; @@ -744,14 +749,6 @@ int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr) return 0; } -int8_t ws_pae_supp_timing_adjust(uint8_t timing) -{ - timing_value = timing; - supp_fwh_sec_prot_timing_adjust(timing); - supp_eap_sec_prot_timing_adjust(timing); - return 0; -} - static void ws_pae_supp_free(pae_supp_t *pae_supp) { if (!pae_supp) { @@ -998,8 +995,8 @@ static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pa static void ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp_t *pae_supp, uint8_t timer_expirations) { // Starts trickle for the key update - pae_supp->auth_trickle_params.Imin = pae_supp->timer_settings->gtk_request_imin; - pae_supp->auth_trickle_params.Imax = pae_supp->timer_settings->gtk_request_imax; + pae_supp->auth_trickle_params.Imin = pae_supp->sec_timer_cfg->gtk_request_imin; + pae_supp->auth_trickle_params.Imax = pae_supp->sec_timer_cfg->gtk_request_imax; pae_supp->auth_trickle_params.k = 0; pae_supp->auth_trickle_params.TimerExpirations = timer_expirations; @@ -1216,7 +1213,7 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_ static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp) { // Create new instance - kmp_api_t *kmp = kmp_api_create(service, type); + kmp_api_t *kmp = kmp_api_create(service, type, pae_supp->sec_prot_cfg); if (!kmp) { return NULL; } diff --git a/source/6LoWPAN/ws/ws_pae_supp.h b/source/6LoWPAN/ws/ws_pae_supp.h index 458ed7bf9e..3bfbc095c5 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.h +++ b/source/6LoWPAN/ws/ws_pae_supp.h @@ -38,13 +38,14 @@ * * \param interface_ptr interface * \param cert_chain certificate chain - * \param timer_settings timer settings + * \param sec_timer_cfg timer configuration + * \param sec_prot_cfg protocol configuration * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, timer_settings_t *timer_settings); +int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg); /** * ws_pae_supp_delete deletes PAE supplicant @@ -57,29 +58,6 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se */ int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr); - -/** - * ws_pae_supp_timing_adjust Adjust retries and timings of the 4WH protocol - * - * Timing value is a generic number between 0 to 32 that goes from fast and - * reactive network to low bandwidth and long latency. - * - * example value definitions: - * 0-8 very fast network - * 9-16 medium network - * 16-24 slow network - * 25-32 extremely slow network - * - * There is no need to have lots variations in every layer if protocol is not very active in any case. - * - * \param timing Timing value. - * - * \return < 0 failure - * \return >= 0 success - * - */ -int8_t ws_pae_supp_timing_adjust(uint8_t timing); - /** * ws_pae_supp_fast_timer PAE supplicant fast timer call * @@ -259,7 +237,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #else -#define ws_pae_supp_init(interface_ptr, certs, timer_settings) 1 +#define ws_pae_supp_init(interface_ptr, certs, sec_timer_cfg, sec_prot_cfg) 1 #define ws_pae_supp_delete NULL #define ws_pae_supp_timing_adjust(timing) 1 #define ws_pae_supp_cb_register(interface_ptr, completed, nw_key_insert, nw_key_index_set) diff --git a/source/6LoWPAN/ws/ws_pae_timers.c b/source/6LoWPAN/ws/ws_pae_timers.c index d73dc70e21..fd3f02e621 100644 --- a/source/6LoWPAN/ws/ws_pae_timers.c +++ b/source/6LoWPAN/ws/ws_pae_timers.c @@ -22,44 +22,43 @@ #include "ns_trace.h" #include "nsdynmemLIB.h" #include "fhss_config.h" +#include "ws_management_api.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_pae_timers.h" #ifdef HAVE_WS #define TRACE_GROUP "wspt" -#define SECONDS_IN_DAY 24 * 60 * 60 -#define SECONDS_IN_MONTH 30 * SECONDS_IN_DAY #define SECONDS_IN_MINUTE 60 -#define DEFAULT_GTK_EXPIRE_OFFSET 43200 // 30 days -#define DEFAULT_PMK_LIFETIME 4 // 4 months -#define DEFAULT_PTK_LIFETIME 2 // 2 months -#define DEFAULT_GTK_NEW_ACTIVATION_TIME 720 // default 1/720 * 30 days --> 60 minutes -#define DEFAULT_REVOCATION_LIFETIME_REDUCTION 30 // default 1/30 * 30 days --> 1 day #define DEFAULT_GTK_REQUEST_IMIN 4 // 4 minutes #define DEFAULT_GTK_REQUEST_IMAX 64 // 64 minutes -#define DEFAULT_GTK_MAX_MISMATCH 64 // 64 minutes -#define DEFAULT_GTK_NEW_INSTALL_REQUIRED 80 // 80 percent of GTK lifetime --> 24 days -static void ws_pae_timers_calculate(timer_settings_t *timer_settings); +static void ws_pae_timers_calculate(sec_timer_cfg_t *timer_settings); -void ws_pae_timers_settings_init(timer_settings_t *timer_settings) +void ws_pae_timers_settings_init(sec_timer_cfg_t *timer_settings, ws_sec_timer_cfg_t *new_timer_settings) { - timer_settings->gtk_expire_offset = DEFAULT_GTK_EXPIRE_OFFSET * SECONDS_IN_MINUTE; - timer_settings->pmk_lifetime = DEFAULT_PMK_LIFETIME * SECONDS_IN_MONTH; - timer_settings->ptk_lifetime = DEFAULT_PTK_LIFETIME * SECONDS_IN_MONTH; - timer_settings->gtk_new_act_time = DEFAULT_GTK_NEW_ACTIVATION_TIME; - timer_settings->revocat_lifetime_reduct = DEFAULT_REVOCATION_LIFETIME_REDUCTION; - timer_settings->gtk_request_imin = DEFAULT_GTK_REQUEST_IMIN * SECONDS_IN_MINUTE; - timer_settings->gtk_request_imax = DEFAULT_GTK_REQUEST_IMAX * SECONDS_IN_MINUTE; - timer_settings->gtk_max_mismatch = DEFAULT_GTK_MAX_MISMATCH * SECONDS_IN_MINUTE; - timer_settings->gtk_new_install_req = DEFAULT_GTK_NEW_INSTALL_REQUIRED; + if (timer_settings == NULL || new_timer_settings == NULL) { + return; + } + + timer_settings->gtk_expire_offset = new_timer_settings->gtk_expire_offset * SECONDS_IN_MINUTE; + timer_settings->pmk_lifetime = new_timer_settings->pmk_lifetime * SECONDS_IN_MINUTE; + timer_settings->ptk_lifetime = new_timer_settings->ptk_lifetime * SECONDS_IN_MINUTE; + timer_settings->gtk_new_act_time = new_timer_settings->gtk_new_act_time; + timer_settings->revocat_lifetime_reduct = new_timer_settings->revocat_lifetime_reduct; + timer_settings->gtk_request_imin = new_timer_settings->gtk_request_imin * SECONDS_IN_MINUTE; + timer_settings->gtk_request_imax = new_timer_settings->gtk_request_imax * SECONDS_IN_MINUTE; + timer_settings->gtk_max_mismatch = new_timer_settings->gtk_max_mismatch * SECONDS_IN_MINUTE; + timer_settings->gtk_new_install_req = new_timer_settings->gtk_new_install_req; + + ws_pae_timers_calculate(timer_settings); } -void ws_pae_timers_lifetime_set(timer_settings_t *timer_settings, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime) +void ws_pae_timers_lifetime_set(sec_timer_cfg_t *timer_settings, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime) { if (gtk_lifetime) { timer_settings->gtk_expire_offset = gtk_lifetime * 60; @@ -73,7 +72,7 @@ void ws_pae_timers_lifetime_set(timer_settings_t *timer_settings, uint32_t gtk_l ws_pae_timers_calculate(timer_settings); } -void ws_pae_timers_gtk_time_settings_set(timer_settings_t *timer_settings, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch) +void ws_pae_timers_gtk_time_settings_set(sec_timer_cfg_t *timer_settings, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch) { if (revocat_lifetime_reduct) { timer_settings->revocat_lifetime_reduct = revocat_lifetime_reduct; @@ -90,7 +89,7 @@ void ws_pae_timers_gtk_time_settings_set(timer_settings_t *timer_settings, uint8 ws_pae_timers_calculate(timer_settings); } -static void ws_pae_timers_calculate(timer_settings_t *timer_settings) +static void ws_pae_timers_calculate(sec_timer_cfg_t *timer_settings) { // Calculate GTK_NEW_INSTALL_REQUIRED < 100 * (1 - 1 / REVOCATION_LIFETIME_REDUCTION) uint8_t calc_gtk_new_install_req = 100 - (100 / timer_settings->revocat_lifetime_reduct); @@ -106,9 +105,6 @@ static void ws_pae_timers_calculate(timer_settings_t *timer_settings) } // Verify that GTK request Imin and Imax are sensible when compared to revocation lifetime - timer_settings->gtk_request_imin = DEFAULT_GTK_REQUEST_IMIN * SECONDS_IN_MINUTE; - timer_settings->gtk_request_imax = DEFAULT_GTK_REQUEST_IMAX * SECONDS_IN_MINUTE; - uint32_t gtk_revocation_lifetime = timer_settings->gtk_expire_offset / timer_settings->revocat_lifetime_reduct; uint32_t new_activation_time = timer_settings->gtk_expire_offset / timer_settings->gtk_new_act_time; @@ -147,7 +143,7 @@ static void ws_pae_timers_calculate(timer_settings_t *timer_settings) } } -bool ws_pae_timers_gtk_new_install_required(timer_settings_t *timer_settings, uint32_t seconds) +bool ws_pae_timers_gtk_new_install_required(sec_timer_cfg_t *timer_settings, uint32_t seconds) { uint32_t gtk_new_install_req_seconds = timer_settings->gtk_expire_offset - timer_settings->gtk_new_install_req * timer_settings->gtk_expire_offset / 100; @@ -158,7 +154,7 @@ bool ws_pae_timers_gtk_new_install_required(timer_settings_t *timer_settings, ui } } -bool ws_pae_timers_gtk_new_activation_time(timer_settings_t *timer_settings, uint32_t seconds) +bool ws_pae_timers_gtk_new_activation_time(sec_timer_cfg_t *timer_settings, uint32_t seconds) { uint32_t gtk_gtk_new_activation_time_seconds = timer_settings->gtk_expire_offset / timer_settings->gtk_new_act_time; @@ -169,7 +165,7 @@ bool ws_pae_timers_gtk_new_activation_time(timer_settings_t *timer_settings, uin } } -uint32_t ws_pae_timers_gtk_revocation_lifetime_get(timer_settings_t *timer_settings) +uint32_t ws_pae_timers_gtk_revocation_lifetime_get(sec_timer_cfg_t *timer_settings) { return timer_settings->gtk_expire_offset / timer_settings->revocat_lifetime_reduct; } diff --git a/source/6LoWPAN/ws/ws_pae_timers.h b/source/6LoWPAN/ws/ws_pae_timers.h index 55b80a4d52..ec792996a0 100644 --- a/source/6LoWPAN/ws/ws_pae_timers.h +++ b/source/6LoWPAN/ws/ws_pae_timers.h @@ -18,25 +18,26 @@ #ifndef WS_PAE_TIMERS_H_ #define WS_PAE_TIMERS_H_ -typedef struct { - uint32_t gtk_expire_offset; // GTK lifetime; GTK_EXPIRE_OFFSET (seconds) - uint32_t pmk_lifetime; // PMK lifetime (seconds) - uint32_t ptk_lifetime; // PTK lifetime (seconds) - uint16_t gtk_new_act_time; // GTK_NEW_ACTIVATION_TIME (1/X of expire offset) - uint16_t revocat_lifetime_reduct; // REVOCATION_LIFETIME_REDUCTION (reduction of lifetime) - uint16_t gtk_request_imin; // GTK_REQUEST_IMIN (seconds) - uint16_t gtk_request_imax; // GTK_REQUEST_IMAX (seconds) - uint16_t gtk_max_mismatch; // GTK_MAX_MISMATCH (seconds) - uint8_t gtk_new_install_req; // GTK_NEW_INSTALL_REQUIRED (percent of GTK lifetime) -} timer_settings_t; +typedef struct sec_timer_cfg_s { + uint32_t gtk_expire_offset; /* GTK lifetime; GTK_EXPIRE_OFFSET (seconds) */ + uint32_t pmk_lifetime; /* PMK lifetime (seconds) */ + uint32_t ptk_lifetime; /* PTK lifetime (seconds) */ + uint16_t gtk_new_act_time; /* GTK_NEW_ACTIVATION_TIME (1/X of expire offset) */ + uint16_t revocat_lifetime_reduct; /* REVOCATION_LIFETIME_REDUCTION (reduction of lifetime) */ + uint16_t gtk_request_imin; /* GTK_REQUEST_IMIN (seconds) */ + uint16_t gtk_request_imax; /* GTK_REQUEST_IMAX (seconds) */ + uint16_t gtk_max_mismatch; /* GTK_MAX_MISMATCH (seconds) */ + uint8_t gtk_new_install_req; /* GTK_NEW_INSTALL_REQUIRED (percent of GTK lifetime) */ +} sec_timer_cfg_t; /** * ws_pae_timers_settings_init initializes timer settings structure * * \param timer_settings timer settings + * \param new_timer_settings new timer settings * */ -void ws_pae_timers_settings_init(timer_settings_t *timer_settings); +void ws_pae_timers_settings_init(sec_timer_cfg_t *timer_settings, ws_sec_timer_cfg_t *new_timer_settings); /** * ws_pae_timers_lifetime_set sets GTK, PTK and PTK lifetimes @@ -47,7 +48,7 @@ void ws_pae_timers_settings_init(timer_settings_t *timer_settings); * \param ptk_lifetime PTK lifetime * */ -void ws_pae_timers_lifetime_set(timer_settings_t *timer_settings, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime); +void ws_pae_timers_lifetime_set(sec_timer_cfg_t *timer_settings, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime); /** * ws_pae_timers_gtk_time_settings_set sets GTK, PTK and PTK lifetimes @@ -59,7 +60,7 @@ void ws_pae_timers_lifetime_set(timer_settings_t *timer_settings, uint32_t gtk_l * \param max_mismatch max mismatch * */ -void ws_pae_timers_gtk_time_settings_set(timer_settings_t *timer_settings, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch); +void ws_pae_timers_gtk_time_settings_set(sec_timer_cfg_t *timer_settings, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch); /** * ws_pae_timers_gtk_new_install_required GTK new install required check @@ -71,7 +72,7 @@ void ws_pae_timers_gtk_time_settings_set(timer_settings_t *timer_settings, uint8 * \return false GTK install not required * */ -bool ws_pae_timers_gtk_new_install_required(timer_settings_t *timer_settings, uint32_t seconds); +bool ws_pae_timers_gtk_new_install_required(sec_timer_cfg_t *timer_settings, uint32_t seconds); /** * ws_pae_timers_gtk_new_activation_time GTK new activation time @@ -83,7 +84,7 @@ bool ws_pae_timers_gtk_new_install_required(timer_settings_t *timer_settings, ui * \return false GTK new activation time not expired * */ -bool ws_pae_timers_gtk_new_activation_time(timer_settings_t *timer_settings, uint32_t seconds); +bool ws_pae_timers_gtk_new_activation_time(sec_timer_cfg_t *timer_settings, uint32_t seconds); /** * ws_pae_timers_gtk_revocation_lifetime_get GTK revocation lifetime get @@ -93,6 +94,6 @@ bool ws_pae_timers_gtk_new_activation_time(timer_settings_t *timer_settings, uin * \return GTK revocation lifetime * */ -uint32_t ws_pae_timers_gtk_revocation_lifetime_get(timer_settings_t *timer_settings); +uint32_t ws_pae_timers_gtk_revocation_lifetime_get(sec_timer_cfg_t *timer_settings); #endif /* WS_PAE_TIMERS_H_ */ diff --git a/source/6LoWPAN/ws/ws_test_api.c b/source/6LoWPAN/ws/ws_test_api.c index 09a749b1bb..f7ea71de08 100644 --- a/source/6LoWPAN/ws/ws_test_api.c +++ b/source/6LoWPAN/ws/ws_test_api.c @@ -21,11 +21,14 @@ #include #include #include +#include "fhss_config.h" +#include "ws_management_api.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bbr_api_internal.h" #include "6LoWPAN/ws/ws_pae_controller.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" #include "randLIB.h" #include "ns_trace.h" @@ -74,24 +77,67 @@ int ws_test_active_key_set(int8_t interface_id, uint8_t index) int ws_test_key_lifetime_set(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime) { - (void) interface_id; - (void) gtk_lifetime; - (void) pmk_lifetime; - (void) ptk_lifetime; + protocol_interface_info_entry_t *cur; - return ws_pae_controller_key_lifetime_update(interface_id, gtk_lifetime, pmk_lifetime, ptk_lifetime); + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur || !ws_info(cur)) { + return -1; + } + + ws_sec_timer_cfg_t cfg; + if (ws_cfg_sec_timer_get(&cfg, NULL) < 0) { + return -2; + } + + if (gtk_lifetime > 0) { + cfg.gtk_expire_offset = gtk_lifetime; + } + if (pmk_lifetime > 0) { + cfg.pmk_lifetime = pmk_lifetime; + } + if (ptk_lifetime > 0) { + cfg.ptk_lifetime = ptk_lifetime; + } + + if (ws_cfg_sec_timer_set(cur, NULL, &cfg, NULL) < 0) { + return -3; + } + + return 0; } int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch) { - (void) interface_id; - (void) revocat_lifetime_reduct; - (void) new_activation_time; - (void) new_install_req; - (void) max_mismatch; + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur || !ws_info(cur)) { + return -1; + } - return ws_pae_controller_gtk_time_settings_update(interface_id, revocat_lifetime_reduct, new_activation_time, new_install_req, max_mismatch); + ws_sec_timer_cfg_t cfg; + if (ws_cfg_sec_timer_get(&cfg, NULL) < 0) { + return -2; + } + + if (revocat_lifetime_reduct > 0) { + cfg.revocat_lifetime_reduct = revocat_lifetime_reduct; + } + if (new_activation_time > 0) { + cfg.gtk_new_act_time = new_activation_time; + } + if (new_install_req > 0) { + cfg.gtk_new_install_req = new_install_req; + } + if (max_mismatch > 0) { + cfg.gtk_max_mismatch = max_mismatch; + } + + if (ws_cfg_sec_timer_set(cur, NULL, &cfg, NULL) < 0) { + return -3; + } + + return 0; } int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4]) diff --git a/source/BorderRouter/border_router.c b/source/BorderRouter/border_router.c index ec1bcaa0ff..dd12919d02 100644 --- a/source/BorderRouter/border_router.c +++ b/source/BorderRouter/border_router.c @@ -201,7 +201,7 @@ int8_t arm_nwk_6lowpan_border_router_context_update(int8_t interface_id, uint8_t if (cur->border_router_setup->nd_nwk) { nd_router_setup_t *routerSetup = cur->border_router_setup->nd_border_router_configure; - if (!lowpan_contex_get_by_id(&routerSetup->context_list, (c_id_flags & LOWPAN_CONTEXT_CID_MASK))) { + if (!lowpan_context_get_by_id(&routerSetup->context_list, (c_id_flags & LOWPAN_CONTEXT_CID_MASK))) { if (ns_list_count(&routerSetup->context_list) >= ND_MAX_PROXY_CONTEXT_COUNT) { return -1; } @@ -245,7 +245,7 @@ int8_t arm_nwk_6lowpan_border_router_nd_context_load(int8_t interface_id, uint8_ contex_data += 2; //Now Pointer Indicate to prefix //Check first is current ID at list - if (!lowpan_contex_get_by_id(&nd_router_setup->context_list, (c_id & LOWPAN_CONTEXT_CID_MASK))) { + if (!lowpan_context_get_by_id(&nd_router_setup->context_list, (c_id & LOWPAN_CONTEXT_CID_MASK))) { if (ns_list_count(&nd_router_setup->context_list) >= ND_MAX_PROXY_CONTEXT_COUNT) { tr_debug("All Contexts are allocated"); return -1; @@ -305,7 +305,7 @@ int8_t arm_nwk_6lowpan_border_router_context_remove_by_id(int8_t interface_id, u nd_router_configuration = cur_interface->border_router_setup->nd_border_router_configure; - entry = lowpan_contex_get_by_id(&nd_router_configuration->context_list, c_id); + entry = lowpan_context_get_by_id(&nd_router_configuration->context_list, c_id); if (entry) { ns_list_remove(&nd_router_configuration->context_list, entry); ns_dyn_mem_free(entry); @@ -333,7 +333,7 @@ int8_t arm_nwk_6lowpan_border_router_context_parameter_update(int8_t interface_i nd_router_configuration = cur_interface->border_router_setup->nd_border_router_configure; - entry = lowpan_contex_get_by_id(&nd_router_configuration->context_list, c_id); + entry = lowpan_context_get_by_id(&nd_router_configuration->context_list, c_id); if (entry) { uint8_t cid_flag = entry->cid; entry->compression = compress_mode; diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index f0b3dc59ea..b94b55d52a 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -1377,6 +1377,7 @@ void ack_remove_neighbour_cb(struct buffer *buffer_ptr, uint8_t status) static void icmpv6_aro_cb(buffer_t *buf, uint8_t status) { + (void)status; uint8_t ll_address[16]; if (buf->dst_sa.addr_type == ADDR_IPV6) { /*Full IPv6 address*/ @@ -1387,8 +1388,8 @@ static void icmpv6_aro_cb(buffer_t *buf, uint8_t status) memcpy(ll_address + 8, &buf->dst_sa.address[2], 8); ll_address[8] ^= 2; } - rpl_control_address_register_done(buf->interface, ll_address, status); - if (status != SOCKET_TX_DONE) { + if (rpl_control_address_register_done(buf->interface, ll_address, status)) { + // When RPL returns true neighbor should be blacklisted ws_common_aro_failure(buf->interface, ll_address); } } diff --git a/source/Core/include/ns_error_types.h b/source/Core/include/ns_error_types.h index c1f12cd0b0..31d15d3f32 100644 --- a/source/Core/include/ns_error_types.h +++ b/source/Core/include/ns_error_types.h @@ -22,11 +22,11 @@ * \enum error_t * \brief System generic error. */ -typedef enum error_t { +typedef enum { eOK = 0, /*!< no error */ eFALSE = 1, /*!< no result */ eBUSY = 2, /*!< resource busy */ eSYSTEM /*!< error code readable in sys_error */ -} error_t; +} socket_error_t; #endif /* NS_ERROR_TYPES_H_ */ diff --git a/source/Core/include/ns_socket.h b/source/Core/include/ns_socket.h index 5e1c566e20..941c7403da 100644 --- a/source/Core/include/ns_socket.h +++ b/source/Core/include/ns_socket.h @@ -190,7 +190,7 @@ extern void socket_init(void); extern int8_t socket_event_handler_id_get(void); extern bool socket_data_queued_event_push(socket_t *socket); extern void socket_event_push(uint8_t sock_event, socket_t *socket, int8_t interface_id, void *session_ptr, uint16_t length); -extern error_t socket_create(socket_family_t family, socket_type_t type, uint8_t protocol, int8_t *sid, uint16_t port, void (*passed_fptr)(void *), bool buffer_type); +extern socket_error_t socket_create(socket_family_t family, socket_type_t type, uint8_t protocol, int8_t *sid, uint16_t port, void (*passed_fptr)(void *), bool buffer_type); extern socket_t *socket_new_incoming_connection(socket_t *listen_socket); void socket_connection_abandoned(socket_t *socket, int8_t interface_id, uint8_t reason); void socket_connection_complete(socket_t *socket, int8_t interface_id); @@ -201,8 +201,8 @@ extern void socket_id_detach(int8_t sid); extern buffer_t *socket_buffer_read(socket_t *socket); extern socket_t *socket_lookup(socket_family_t family, uint8_t protocol, const sockaddr_t *local_addr, const sockaddr_t *remote_addr); extern socket_t *socket_lookup_ipv6(uint8_t protocol, const sockaddr_t *local_addr, const sockaddr_t *remote_addr, bool allow_wildcards); -extern error_t socket_port_validate(uint16_t port, uint8_t protocol); -extern error_t socket_up(buffer_t *buf); +extern socket_error_t socket_port_validate(uint16_t port, uint8_t protocol); +extern socket_error_t socket_up(buffer_t *buf); extern bool socket_message_validate_iov(const struct ns_msghdr *msg, uint16_t *length_out); extern int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr *msg, int flags); extern socket_t *socket_pointer_get(int8_t socket); diff --git a/source/Core/ns_socket.c b/source/Core/ns_socket.c index 05961ccb5b..e0fbffd724 100644 --- a/source/Core/ns_socket.c +++ b/source/Core/ns_socket.c @@ -342,7 +342,7 @@ static void socket_free(socket_t *socket) ns_dyn_mem_free(socket); } -error_t socket_port_validate(uint16_t port, uint8_t protocol) +socket_error_t socket_port_validate(uint16_t port, uint8_t protocol) { ns_list_foreach(socket_t, socket, &socket_list) { if (!socket_is_ipv6(socket)) { @@ -497,7 +497,7 @@ socket_t *socket_dereference(socket_t *socket_ptr) * \return eFALSE no free sockets * \return eBUSY port reserved */ -error_t socket_create(socket_family_t family, socket_type_t type, uint8_t protocol, int8_t *sid, uint16_t port, void (*passed_fptr)(void *), bool buffer_type) +socket_error_t socket_create(socket_family_t family, socket_type_t type, uint8_t protocol, int8_t *sid, uint16_t port, void (*passed_fptr)(void *), bool buffer_type) { if (sid) { *sid = -1; @@ -850,7 +850,7 @@ socket_t *socket_lookup(socket_family_t family, uint8_t protocol, const sockaddr * \return eFALSE no socket found * \return eBUSY socket full */ -error_t socket_up(buffer_t *buf) +socket_error_t socket_up(buffer_t *buf) { socket_t *socket = buf->socket; diff --git a/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index acc45a6788..28c2e62cfe 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -225,6 +225,8 @@ typedef struct protocol_interface_rf_mac_setup { uint8_t aUnitBackoffPeriod; uint8_t number_of_csma_ca_periods; /**< Number of CSMA-CA periods */ uint16_t multi_cca_interval; /**< Length of the additional CSMA-CA period(s) in microseconds */ + uint16_t phy_mtu_size; + phy_802_15_4_mode_t current_mac_mode; /* Indirect queue parameters */ struct mac_pre_build_frame *indirect_pd_data_request_queue; struct mac_pre_build_frame enhanced_ack_buffer; diff --git a/source/MAC/IEEE802_15_4/mac_header_helper_functions.c b/source/MAC/IEEE802_15_4/mac_header_helper_functions.c index 5f8273bb6b..65f6e05f6b 100644 --- a/source/MAC/IEEE802_15_4/mac_header_helper_functions.c +++ b/source/MAC/IEEE802_15_4/mac_header_helper_functions.c @@ -32,7 +32,7 @@ static uint8_t *mcps_mac_security_aux_header_start_pointer_get(const mac_pre_par static uint8_t *mac_header_information_elements_write(const mac_pre_build_frame_t *buffer, uint8_t *ptr); -static uint8_t mac_fcf_lenght(const mac_fcf_sequence_t *header) +static uint8_t mac_fcf_length(const mac_fcf_sequence_t *header) { uint8_t length; if (header->frameVersion == MAC_FRAME_VERSION_2015) { @@ -298,7 +298,7 @@ static uint8_t *mac_header_write_fcf_dsn(const mac_fcf_sequence_t *header, uint8 uint16_t mac_header_off_set_to_aux_header(const mac_fcf_sequence_t *fcf) { //Skip first FCF & address field - uint16_t offset = mac_fcf_lenght(fcf);//Skip FCF + DSN + uint16_t offset = mac_fcf_length(fcf);//Skip FCF + DSN offset += mac_dst_address_length_with_panid(fcf); offset += mac_address_length(fcf->SrcAddrMode); if (fcf->SrcPanPresents) { @@ -351,7 +351,7 @@ static bool mac_header_pan_full_compressed(const mac_fcf_sequence_t *header) static uint16_t mac_header_read_src_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr) { - ptr += mac_fcf_lenght(header);//Skip FCF + DSN + ptr += mac_fcf_length(header);//Skip FCF + DSN ptr += mac_dst_address_length_with_panid(header); //Skip Dst panID & Address @@ -360,7 +360,7 @@ static uint16_t mac_header_read_src_pan(const mac_fcf_sequence_t *header, const static uint16_t mac_header_read_dst_pan(const mac_fcf_sequence_t *header, const uint8_t *ptr) { - ptr += mac_fcf_lenght(header);//Skip FCF + DSN + ptr += mac_fcf_length(header);//Skip FCF + DSN return common_read_16_bit_inverse(ptr); } @@ -403,7 +403,7 @@ void mac_header_get_src_address(const mac_fcf_sequence_t *header, const uint8_t return; } - ptr += mac_fcf_lenght(header);//Skip FCF + DSN + ptr += mac_fcf_length(header);//Skip FCF + DSN ptr += mac_dst_address_length_with_panid(header); @@ -430,7 +430,7 @@ void mac_header_get_dst_address(const mac_fcf_sequence_t *header, const uint8_t } uint8_t address_len, address_index, i; - ptr += mac_fcf_lenght(header);//Skip FCF + DSN + ptr += mac_fcf_length(header);//Skip FCF + DSN address_len = mac_address_length(header->DstAddrMode); diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index 6442290a48..d7c9aa9ef8 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -228,8 +228,8 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set goto verify_status; } - if ((data_req->msduLength + ie_header_length + ie_payload_length) > rf_mac_setup->dev_driver->phy_driver->phy_MTU - MAC_DATA_PACKET_MIN_HEADER_LENGTH) { - tr_debug("packet %u, %u", data_req->msduLength, rf_mac_setup->dev_driver->phy_driver->phy_MTU); + if ((data_req->msduLength + ie_header_length + ie_payload_length) > rf_mac_setup->phy_mtu_size - MAC_DATA_PACKET_MIN_HEADER_LENGTH) { + tr_debug("packet %u, %u", data_req->msduLength, rf_mac_setup->phy_mtu_size); status = MLME_FRAME_TOO_LONG; goto verify_status; } @@ -358,7 +358,7 @@ verify_status: static int8_t mac_virtual_data_req_handler(protocol_interface_rf_mac_setup_s *rf_mac_setup, const uint8_t *data_ptr, uint16_t data_length) { - if (!rf_mac_setup->macUpState || data_length > rf_mac_setup->dev_driver->phy_driver->phy_MTU) { + if (!rf_mac_setup->macUpState || data_length > rf_mac_setup->phy_mtu_size) { return -1; } @@ -1576,7 +1576,7 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt uint16_t mac_payload_length = frame_length; if (mac_payload_length > MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE && - dev_driver->phy_MTU == MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) { + rf_ptr->phy_mtu_size == MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) { /* IEEE 802.15.4-2003 only allowed unsecured payloads up to 102 bytes * (always leaving room for maximum MAC overhead). * IEEE 802.15.4-2006 allows bigger if MAC header is small enough, but @@ -1596,8 +1596,8 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt //Add MHR length to total length frame_length += buffer->mac_header_length_with_security + buffer->security_mic_len; - if ((frame_length) > dev_driver->phy_MTU - 2) { - tr_debug("Too Long %u, %u pa %u header %u mic %u", frame_length, mac_payload_length, buffer->mac_header_length_with_security, buffer->security_mic_len, dev_driver->phy_MTU); + if ((frame_length) > rf_ptr->phy_mtu_size - 2) { + tr_debug("Too Long %u, %u pa %u header %u mic %u", frame_length, mac_payload_length, buffer->mac_header_length_with_security, buffer->security_mic_len, rf_ptr->phy_mtu_size); buffer->status = MLME_FRAME_TOO_LONG; //decrement security counter if (key_desc) { @@ -1745,8 +1745,8 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in //Add MHR length to total length frame_length += buffer->mac_header_length_with_security + buffer->security_mic_len; uint16_t ack_mtu_size; - if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_MTU) { - ack_mtu_size = dev_driver->phy_MTU; + if (ENHANCED_ACK_MAX_LENGTH > rf_ptr->phy_mtu_size) { + ack_mtu_size = rf_ptr->phy_mtu_size; } else { ack_mtu_size = ENHANCED_ACK_MAX_LENGTH; } diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index b091da2a85..8ea8f3355c 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -69,6 +69,7 @@ static void mac_mlme_timer_cb(int8_t timer_id, uint16_t slots); static void mac_mlme_start_confirm_handler(protocol_interface_rf_mac_setup_s *rf_ptr, const mlme_start_conf_t *conf); static void mac_mlme_scan_confirm_handler(protocol_interface_rf_mac_setup_s *rf_ptr, const mlme_scan_conf_t *conf); static int mac_mlme_set_symbol_rate(protocol_interface_rf_mac_setup_s *rf_mac_setup); +static int mac_mlme_allocate_tx_buffers(protocol_interface_rf_mac_setup_s *rf_mac_setup, arm_device_driver_list_s *dev_driver, uint16_t mtu_size); static void mac_mlme_energy_scan_start(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t channel) { @@ -767,6 +768,29 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8); } return 0; + case mac802_15_4Mode: + pu8 = (uint8_t *) set_req->value_pointer; + if (rf_mac_setup->current_mac_mode == *pu8) { + return -1; + } + rf_mac_setup->current_mac_mode = *pu8; + rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_802_15_4_MODE, pu8); + uint16_t new_mtu_size = MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE; + if (*pu8 == IEEE_802_15_4G_2012) { + new_mtu_size = MAC_IEEE_802_15_4G_MAX_PHY_PACKET_SIZE; + } + mac_api_t *mac_api = get_sw_mac_api(rf_mac_setup); + if (rf_mac_setup->dev_driver->phy_driver->phy_MTU > new_mtu_size) { + mac_api->phyMTU = rf_mac_setup->phy_mtu_size = new_mtu_size; + } else { + mac_api->phyMTU = rf_mac_setup->phy_mtu_size = rf_mac_setup->dev_driver->phy_driver->phy_MTU; + } + if (mac_mlme_allocate_tx_buffers(rf_mac_setup, rf_mac_setup->dev_driver, rf_mac_setup->phy_mtu_size)) { + tr_err("Failed to reallocate TX buffers"); + return -1; + } + tr_debug("Set MAC mode to %s, MTU size: %u", *pu8 == IEEE_802_15_4G_2012 ? "IEEE 802.15.4G-2012" : "IEEE 802.15.4-2011", rf_mac_setup->phy_mtu_size); + return 0; case macTXPower: pu8 = (uint8_t *) set_req->value_pointer; rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_TX_POWER, pu8); @@ -1067,9 +1091,29 @@ static int mac_mlme_set_symbol_rate(protocol_interface_rf_mac_setup_s *rf_mac_se return -1; } -protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, arm_device_driver_list_s *dev_driver, mac_description_storage_size_t *storage_sizes) +static int mac_mlme_allocate_tx_buffers(protocol_interface_rf_mac_setup_s *rf_mac_setup, arm_device_driver_list_s *dev_driver, uint16_t mtu_size) { + ns_dyn_mem_free(rf_mac_setup->dev_driver_tx_buffer.buf); + ns_dyn_mem_free(rf_mac_setup->mac_beacon_payload); uint16_t total_length = 0; + //Allocate tx buffer by given MTU + header + tail + total_length = mtu_size; + total_length += (dev_driver->phy_driver->phy_header_length + dev_driver->phy_driver->phy_tail_length); + rf_mac_setup->dev_driver_tx_buffer.buf = ns_dyn_mem_alloc(total_length); + if (!rf_mac_setup->dev_driver_tx_buffer.buf) { + return -1; + } + //allocate Beacon Payload buffer + rf_mac_setup->max_beacon_payload_length = mtu_size - MAC_IEEE_802_15_4_MAX_BEACON_OVERHEAD; + rf_mac_setup->mac_beacon_payload = ns_dyn_mem_alloc(rf_mac_setup->max_beacon_payload_length); + if (!rf_mac_setup->mac_beacon_payload) { + return -1; + } + return 0; +} + +protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, arm_device_driver_list_s *dev_driver, mac_description_storage_size_t *storage_sizes, uint16_t mtu_size) +{ //allocate security if (!dev_driver || !mac64 || !dev_driver->phy_driver || !storage_sizes) { return NULL; @@ -1102,20 +1146,9 @@ protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, a mac_mlme_data_base_deallocate(entry); return NULL; } + entry->phy_mtu_size = mtu_size; - //Allocate tx buffer by given MTU + header + tail - total_length = dev_driver->phy_driver->phy_MTU; - total_length += (dev_driver->phy_driver->phy_header_length + dev_driver->phy_driver->phy_tail_length); - entry->dev_driver_tx_buffer.buf = ns_dyn_mem_alloc(total_length); - if (!entry->dev_driver_tx_buffer.buf) { - mac_mlme_data_base_deallocate(entry); - return NULL; - } - - //allocate Beacon Payload buffer - entry->max_beacon_payload_length = dev_driver->phy_driver->phy_MTU - MAC_IEEE_802_15_4_MAX_BEACON_OVERHEAD; - entry->mac_beacon_payload = ns_dyn_mem_alloc(entry->max_beacon_payload_length); - if (!entry->mac_beacon_payload) { + if (mac_mlme_allocate_tx_buffers(entry, dev_driver, mtu_size)) { mac_mlme_data_base_deallocate(entry); return NULL; } diff --git a/source/MAC/IEEE802_15_4/mac_mlme.h b/source/MAC/IEEE802_15_4/mac_mlme.h index fb251c8000..2cf6a79a70 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.h +++ b/source/MAC/IEEE802_15_4/mac_mlme.h @@ -106,7 +106,7 @@ void mac_mlme_event_cb(void *mac_ptr); void mac_mlme_set_active_state(struct protocol_interface_rf_mac_setup *entry, bool new_state); -struct protocol_interface_rf_mac_setup *mac_mlme_data_base_allocate(uint8_t *mac64, struct arm_device_driver_list *dev_driver, struct mac_description_storage_size_s *storage_sizes); +struct protocol_interface_rf_mac_setup *mac_mlme_data_base_allocate(uint8_t *mac64, struct arm_device_driver_list *dev_driver, struct mac_description_storage_size_s *storage_sizes, uint16_t mtu_size); void mac_mlme_data_base_deallocate(struct protocol_interface_rf_mac_setup *rf_mac); uint8_t mac_mlme_set_new_sqn(struct protocol_interface_rf_mac_setup *rf_setup); diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index 1b8eda1229..09952b9b10 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -111,7 +111,7 @@ uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup) backoff_in_us += ((rf_mac_setup->multi_cca_interval * (rf_mac_setup->number_of_csma_ca_periods - 1)) - backoff_in_us); } if (rf_mac_setup->mac_tx_retry) { - backoff_in_us += rf_mac_setup->fhss_api->get_retry_period(rf_mac_setup->fhss_api, rf_mac_setup->active_pd_data_request->DstAddr, rf_mac_setup->dev_driver->phy_driver->phy_MTU); + backoff_in_us += rf_mac_setup->fhss_api->get_retry_period(rf_mac_setup->fhss_api, rf_mac_setup->active_pd_data_request->DstAddr, rf_mac_setup->phy_mtu_size); } } return backoff_in_us; diff --git a/source/MAC/IEEE802_15_4/mac_security_mib.c b/source/MAC/IEEE802_15_4/mac_security_mib.c index 27de7e89cb..abe65d668b 100644 --- a/source/MAC/IEEE802_15_4/mac_security_mib.c +++ b/source/MAC/IEEE802_15_4/mac_security_mib.c @@ -90,7 +90,7 @@ static int mac_sec_mib_frame_counter_key_buffer_allocate(protocol_interface_rf_m mlme_key_descriptor_t *key_descriptor_list = rf_mac_setup->key_description_table; uint32_t *frame_counter_pointer = rf_mac_setup->key_device_frame_counter_list_buffer; for (uint8_t i = 0; i < rf_mac_setup->key_description_table_size; i++) { - key_descriptor_list->KeyDeviceFrameCouterList = frame_counter_pointer; + key_descriptor_list->KeyDeviceFrameCounterList = frame_counter_pointer; key_descriptor_list->KeyFrameCounterPerKey = true; key_descriptor_list->KeyFrameCounter = 0; //Update Pointers @@ -105,7 +105,7 @@ static void mac_sec_mib_frame_counter_key_buffer_free(protocol_interface_rf_mac_ { mlme_key_descriptor_t *key_descriptor_list = rf_mac_setup->key_description_table; for (uint8_t i = 0; i < rf_mac_setup->key_description_table_size; i++) { - key_descriptor_list->KeyDeviceFrameCouterList = NULL; + key_descriptor_list->KeyDeviceFrameCounterList = NULL; key_descriptor_list->KeyFrameCounterPerKey = false; //Update Pointers key_descriptor_list++; @@ -368,7 +368,7 @@ int8_t mac_sec_mib_key_description_set(uint8_t atribute_index, mlme_key_descript key_ptr->KeyFrameCounter = 0; if (key_ptr->KeyDeviceListEntries == 0) { //Clear all frame counters from old possible user's - uint32_t *counter_ptr = key_ptr->KeyDeviceFrameCouterList; + uint32_t *counter_ptr = key_ptr->KeyDeviceFrameCounterList; for (int i = 0; i < rf_mac_setup->device_description_table_size; i++) { *counter_ptr++ = 0; } @@ -613,7 +613,7 @@ void mac_sec_mib_key_outgoing_frame_counter_decrement(struct protocol_interface_ void mac_sec_mib_key_device_frame_counter_set(mlme_key_descriptor_t *key_descpription_table, mlme_device_descriptor_t *device_info, uint32_t frame_counter, uint8_t attribute_index) { if (key_descpription_table->KeyFrameCounterPerKey) { - uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCouterList + attribute_index; + uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCounterList + attribute_index; *counter_ptr = frame_counter; } else { device_info->FrameCounter = frame_counter; @@ -623,7 +623,7 @@ void mac_sec_mib_key_device_frame_counter_set(mlme_key_descriptor_t *key_descpri uint32_t mac_mib_key_device_frame_counter_get(mlme_key_descriptor_t *key_descpription_table, mlme_device_descriptor_t *device_info, uint8_t attribute_index) { if (key_descpription_table->KeyFrameCounterPerKey) { - uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCouterList + attribute_index; + uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCounterList + attribute_index; return *counter_ptr; } return device_info->FrameCounter; diff --git a/source/MAC/IEEE802_15_4/mac_security_mib.h b/source/MAC/IEEE802_15_4/mac_security_mib.h index 86648e7f5c..150d8ea64a 100644 --- a/source/MAC/IEEE802_15_4/mac_security_mib.h +++ b/source/MAC/IEEE802_15_4/mac_security_mib.h @@ -27,7 +27,7 @@ typedef struct mlme_key_descriptor_s { mlme_key_id_lookup_descriptor_t *KeyIdLookupList; mlme_key_device_descriptor_t *KeyDeviceList; mlme_key_usage_descriptor_t *KeyUsageList; - uint32_t *KeyDeviceFrameCouterList; + uint32_t *KeyDeviceFrameCounterList; uint32_t KeyFrameCounter; uint8_t Key[16]; uint8_t KeyDeviceListSize; diff --git a/source/MAC/IEEE802_15_4/sw_mac.c b/source/MAC/IEEE802_15_4/sw_mac.c index a5b679eb28..67e5884227 100644 --- a/source/MAC/IEEE802_15_4/sw_mac.c +++ b/source/MAC/IEEE802_15_4/sw_mac.c @@ -31,6 +31,9 @@ #include "mac_fhss_callbacks.h" #include "eventOS_callback_timer.h" #include "common_functions.h" +#include "ns_trace.h" + +#define TRACE_GROUP "swm" //TODO: create linked list of created MACs @@ -96,13 +99,28 @@ mac_api_t *ns_sw_mac_create(int8_t rf_driver_id, mac_description_storage_size_t memset(this, 0, sizeof(mac_api_t)); this->parent_id = -1; mac_store.dev_driver = driver; - mac_store.setup = mac_mlme_data_base_allocate(mac_store.dev_driver->phy_driver->PHY_MAC, mac_store.dev_driver, storage_sizes); + + // Set default MTU size to 127 unless it is too much for PHY driver + if (driver->phy_driver->phy_MTU > MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) { + this->phyMTU = MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE; + } else { + this->phyMTU = driver->phy_driver->phy_MTU; + } + + mac_store.setup = mac_mlme_data_base_allocate(mac_store.dev_driver->phy_driver->PHY_MAC, mac_store.dev_driver, storage_sizes, this->phyMTU); if (!mac_store.setup) { ns_dyn_mem_free(this); return NULL; } + // Set MAC mode to PHY driver + mac_store.setup->current_mac_mode = IEEE_802_15_4_2011; + if (mac_store.setup->dev_driver->phy_driver->extension) { + mac_store.setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_802_15_4_MODE, (uint8_t *) &mac_store.setup->current_mac_mode); + } + tr_debug("Set MAC mode to %s, MTU size: %u", "IEEE 802.15.4-2011", mac_store.setup->phy_mtu_size); + arm_net_phy_init(driver->phy_driver, &sw_mac_net_phy_rx, &sw_mac_net_phy_tx_done); arm_net_virtual_config_rx_cb_set(driver->phy_driver, &sw_mac_net_phy_config_parser); arm_net_virtual_confirmation_rx_cb_set(driver->phy_driver, &mac_mlme_virtual_confirmation_handle); @@ -116,10 +134,8 @@ mac_api_t *ns_sw_mac_create(int8_t rf_driver_id, mac_description_storage_size_t this->mac64_get = &macext_mac64_address_get; this->mac64_set = &macext_mac64_address_set; this->mac_storage_sizes_get = &sw_mac_storage_decription_sizes_get; - this->phyMTU = driver->phy_driver->phy_MTU; mac_store.mac_api = this; - mac_store.virtual_driver = NULL; return this; } @@ -279,8 +295,8 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication ns_dyn_mem_free(mac_store.setup->dev_driver_tx_buffer.enhanced_ack_buf); uint16_t total_length; - if (ENHANCED_ACK_MAX_LENGTH > dev_driver->phy_driver->phy_MTU) { - total_length = dev_driver->phy_driver->phy_MTU; + if (ENHANCED_ACK_MAX_LENGTH > mac_store.setup->phy_mtu_size) { + total_length = mac_store.setup->phy_mtu_size; } else { total_length = ENHANCED_ACK_MAX_LENGTH; } diff --git a/source/NWK_INTERFACE/Include/protocol.h b/source/NWK_INTERFACE/Include/protocol.h index 6173d0a36a..2a1b3fbbf9 100644 --- a/source/NWK_INTERFACE/Include/protocol.h +++ b/source/NWK_INTERFACE/Include/protocol.h @@ -375,6 +375,7 @@ struct protocol_interface_info_entry { trickle_params_t mpl_control_trickle_params; uint16_t mpl_seed_set_entry_lifetime; uint8_t mpl_seed_id[16]; + struct mpl_domain *mpl_domain; #endif if_6lowpan_dad_entry_t if_6lowpan_dad_process; lowpan_context_list_t lowpan_contexts; diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index b17dce381e..d555eb8124 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -181,11 +181,19 @@ void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_cou rpl_policy_set_dio_multicast_config_advertisment_min_count(min_count); } +void rpl_control_set_address_registration_timeout(uint16_t timeout_in_minutes) +{ + rpl_policy_set_address_registration_timeout(timeout_in_minutes); +} + void rpl_control_set_dao_retry_count(uint8_t count) { rpl_policy_set_dao_retry_count(count); } - +void rpl_control_set_minimum_dao_target_refresh(uint16_t seconds) +{ + rpl_policy_set_minimum_dao_target_refresh(seconds); +} void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms) { rpl_policy_set_initial_dao_ack_wait(timeout_in_ms); @@ -198,6 +206,9 @@ void rpl_control_set_mrhof_parent_set_size(uint16_t parent_set_size) /* Send address registration to either specified address, or to non-registered address */ void rpl_control_register_address(protocol_interface_info_entry_t *interface, const uint8_t addr[16]) { + if (!interface->rpl_domain) { + return; + } if (!rpl_policy_parent_confirmation_requested()) { return; } @@ -206,21 +217,23 @@ void rpl_control_register_address(protocol_interface_info_entry_t *interface, co } } -void rpl_control_address_register_done(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16], uint8_t status) +bool rpl_control_address_register_done(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16], uint8_t status) { + bool blacklist_neighbour = false; if (!interface->rpl_domain) { - return; + return false; } if (!rpl_policy_parent_confirmation_requested()) { - return; + return false; } ns_list_foreach(struct rpl_instance, instance, &interface->rpl_domain->instances) { rpl_neighbour_t *neighbour = rpl_lookup_neighbour_by_ll_address(instance, ll_addr, interface->id); if (neighbour) { - rpl_instance_address_registration_done(interface, instance, neighbour, status); + blacklist_neighbour = blacklist_neighbour || rpl_instance_address_registration_done(interface, instance, neighbour, status); } } + return blacklist_neighbour; } bool rpl_control_is_dodag_parent(protocol_interface_info_entry_t *interface, const uint8_t ll_addr[16]) @@ -673,6 +686,14 @@ void rpl_control_force_leaf(rpl_domain_t *domain, bool leaf) } } } + +void rpl_control_dao_timeout(rpl_domain_t *domain, uint16_t seconds) +{ + ns_list_foreach(rpl_instance_t, instance, &domain->instances) { + rpl_instance_dao_timeout(instance, seconds); + } +} + void rpl_control_process_routes(rpl_domain_t *domain, bool process_routes) { domain->process_routes = process_routes; diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index 464e5c2a83..613d47eb05 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -145,6 +145,9 @@ void rpl_control_process_routes(rpl_domain_t *domain, bool process_routes); /* Manually send poison on all existing instances a few times */ void rpl_control_poison(rpl_domain_t *domain, uint8_t poison_count); +/* force DAO to verify connections before given time*/ +void rpl_control_dao_timeout(rpl_domain_t *domain, uint16_t seconds); + /* APIs to create domains and map them to interfaces */ rpl_domain_t *rpl_control_create_domain(void); void rpl_control_delete_domain(rpl_domain_t *domain); @@ -170,11 +173,13 @@ bool rpl_control_find_worst_neighbor(struct protocol_interface_info_entry *inter /* Parent link confirmation API extension */ void rpl_control_request_parent_link_confirmation(bool requested); void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count); +void rpl_control_set_address_registration_timeout(uint16_t timeout_in_minutes); void rpl_control_set_dao_retry_count(uint8_t count); +void rpl_control_set_minimum_dao_target_refresh(uint16_t seconds); void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms); void rpl_control_set_mrhof_parent_set_size(uint16_t parent_set_size); void rpl_control_register_address(struct protocol_interface_info_entry *interface, const uint8_t addr[16]); -void rpl_control_address_register_done(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t status); +bool rpl_control_address_register_done(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t status); /* Configure and return the routing lookup predicate for a specified RPL instance ID */ ipv6_route_predicate_fn_t *rpl_control_get_route_predicate(rpl_domain_t *domain, uint8_t instance_id, const uint8_t src[16], const uint8_t dst[16]); @@ -198,10 +203,9 @@ uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain); #define rpl_control_remove_domain_from_interface(cur) ((void) 0) #define rpl_control_free_domain_instances_from_interface(cur) ((void) 0) #define rpl_control_register_address(interface, addr) ((void) 0) -#define rpl_control_address_register_done(interface, ll_addr, status) ((void) 0) +#define rpl_control_address_register_done(interface, ll_addr, status) (false) #define rpl_policy_mrhof_parent_set_size_get(domain) (0) #define rpl_control_set_mrhof_parent_set_size(parent_set_size) - #endif /* HAVE_RPL */ #endif /* RPL_CONTROL_H_ */ diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 6f7a5dbfcb..34ca3cf6b7 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -109,8 +109,6 @@ static void rpl_downward_topo_sort_invalidate(rpl_instance_t *instance); #define DEFAULT_DAO_DELAY 10 /* *100ms ticks = 1s */ -//#define MINIMUM_DAO_TARGET_REFRESH (5*60) /* seconds */ - /* Bit of the PC mask */ #define PCBIT(n) (UINT8_C(0x80) >> (n)) @@ -184,7 +182,7 @@ static bool rpl_instance_parent_selection_ready(rpl_instance_t *instance) { rpl_neighbour_t *neighbour = ns_list_get_first(&instance->candidate_neighbours); if (neighbour && neighbour->dodag_parent && neighbour->dao_path_control) { - //We have a Primary parent with Dao patha control + //We have a Primary parent with Dao path control return true; } return false; @@ -1603,11 +1601,10 @@ void rpl_instance_dao_acked(rpl_instance_t *instance, const uint8_t src[16], int } else { t = 0xFFFFFFFF; } -#ifdef MINIMUM_DAO_TARGET_REFRESH - if (t > MINIMUM_DAO_TARGET_REFRESH) { - t = randLIB_randomise_base(MINIMUM_DAO_TARGET_REFRESH, 0x7333, 0x8CCD); /* +/- 10% */ + if (rpl_policy_minimum_dao_target_refresh() && t > rpl_policy_minimum_dao_target_refresh()) { + // set the minimum target refresh time ranging from 25% to 10% below the value + t = randLIB_randomise_base(rpl_policy_minimum_dao_target_refresh(), 0x6000, 0x7333); } -#endif target->info.non_root.refresh_timer = t; tr_debug("set rfr to %"PRIu32, t); } @@ -1639,6 +1636,21 @@ void rpl_instance_dao_request(struct rpl_instance *instance, struct rpl_neighbou rpl_instance_dao_trigger(instance, 0); } +void rpl_instance_dao_timeout(struct rpl_instance *instance, uint16_t seconds) +{ + // Forces DAO timeout to happen before given time distributed in given time + ns_list_foreach(rpl_dao_target_t, target, &instance->dao_targets) { + if (!target->published || target->info.non_root.refresh_timer == 0) { + continue; + } + if (target->info.non_root.refresh_timer < seconds) { + continue; + } + // Shorten the timeout + target->info.non_root.refresh_timer = randLIB_get_random_in_range(1, seconds); + } +} + void rpl_downward_dao_slow_timer(rpl_instance_t *instance, uint16_t seconds) { @@ -1771,8 +1783,11 @@ static bool rpl_instance_push_address_registration(protocol_interface_info_entry aro.status = ARO_SUCCESS; aro.present = true; - aro.lifetime = (addr->valid_lifetime / 60) + 1; memcpy(aro.eui64, interface->mac, 8); + aro.lifetime = rpl_policy_address_registration_timeout(); + if (!aro.lifetime) { + aro.lifetime = (addr->valid_lifetime / 60) + 1; + } buffer_t *buf = icmpv6_build_ns(interface, neighbour->ll_address, addr->address, true, false, &aro); if (!buf) { @@ -1807,6 +1822,13 @@ static void rpl_instance_address_registration_cancel(rpl_instance_t *instance) instance->dao_retry_timer = 0; } +static void rpl_instance_address_registration_retry(rpl_dao_target_t *dao_target) +{ + dao_target->active_confirmation_state = true; // Active timer is set true so the response_wait_time runs out + dao_target->trig_confirmation_state = true; + dao_target->response_wait_time = 20; // Wait 20 seconds before retry +} + void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint16_t seconds) { if (!instance->pending_neighbour_confirmation) { @@ -1861,7 +1883,6 @@ void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint return; } - if (rpl_instance_push_address_registration(interface, neighbour, address)) { instance->wait_response = neighbour; dao_target->response_wait_time = 5; @@ -1869,33 +1890,41 @@ void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint } -void rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status) +bool rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status) { - if (!instance->pending_neighbour_confirmation) { - return; + return false; } rpl_dao_target_t *dao_target = rpl_instance_get_active_target_confirmation(instance); if (!dao_target || instance->wait_response != neighbour) { - return; + return false; } tr_debug("Address %s register to %s", trace_ipv6(dao_target->prefix), trace_ipv6(neighbour->ll_address)); - if (status == SOCKET_TX_DONE) { - /* State_timer is 1/10 s. Set renewal to 75-85% of lifetime */ - if_address_entry_t *address = rpl_interface_addr_get(interface, dao_target->prefix); - if (address && address->source != ADDR_SOURCE_DHCP) { - address->state_timer = (address->preferred_lifetime * randLIB_get_random_in_range(75, 85) / 10); + if (status != SOCKET_TX_DONE) { + if (neighbour->addr_reg_failures > 0) { + // Neighbor should be blacklisted after this. + tr_error("Address registration failed delete neighbor"); + rpl_instance_address_registration_cancel(instance); + rpl_delete_neighbour(instance, neighbour); + return true; } - neighbour->confirmed = true; - dao_target->response_wait_time = 6; - } else { - tr_error("Address registration failed"); - rpl_delete_neighbour(instance, neighbour); - rpl_instance_address_registration_cancel(instance); + tr_warn("Address registration ACK fail retry selection"); + neighbour->addr_reg_failures++; + rpl_instance_address_registration_retry(dao_target); + return false; } + /* State_timer is 1/10 s. Set renewal to 75-85% of lifetime */ + if_address_entry_t *address = rpl_interface_addr_get(interface, dao_target->prefix); + if (address && address->source != ADDR_SOURCE_DHCP) { + address->state_timer = (address->preferred_lifetime * randLIB_get_random_in_range(75, 85) / 10); + } + neighbour->addr_reg_failures = 0; + neighbour->confirmed = true; + dao_target->response_wait_time = 6; + return false; } #endif /* HAVE_RPL */ diff --git a/source/RPL/rpl_downward.h b/source/RPL/rpl_downward.h index a8c66a79b7..b2b8faa5c8 100644 --- a/source/RPL/rpl_downward.h +++ b/source/RPL/rpl_downward.h @@ -38,11 +38,12 @@ void rpl_instance_delete_published_dao_target(struct rpl_instance *instance, con struct rpl_dao_target *rpl_instance_match_dao_target(struct rpl_instance *instance, const uint8_t *prefix, uint8_t prefix_len); void rpl_instance_dao_request(struct rpl_instance *instance, struct rpl_neighbour *neighbour); +void rpl_instance_dao_timeout(struct rpl_instance *instance, uint16_t seconds); void rpl_instance_dao_trigger(struct rpl_instance *instance, uint16_t delay); void rpl_instance_dao_acked(struct rpl_instance *instance, const uint8_t src[16], int8_t interface_id, uint8_t dao_sequence, uint8_t status); void rpl_instance_parent_address_reg_timer_update(struct rpl_instance *instance, uint16_t seconds); void rpl_instance_send_address_registration(rpl_instance_t *instance, const uint8_t addr[16]); -void rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status); +bool rpl_instance_address_registration_done(protocol_interface_info_entry_t *interface, rpl_instance_t *instance, rpl_neighbour_t *neighbour, uint8_t status); struct rpl_dao_target *rpl_instance_get_active_target_confirmation(struct rpl_instance *instance); #ifdef HAVE_RPL_DAO_HANDLING diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index f8b25d86f1..5e6b7258d4 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -21,7 +21,7 @@ #include "ns_types.h" #include "ns_trace.h" - +#include "randLIB.h" #include "net_interface.h" #include "Core/include/ns_address_internal.h" @@ -34,12 +34,19 @@ #define TRACE_GROUP "RPLy" +typedef enum { + RPL_POLICY_FORWARD, + RPL_POLICY_DROP +} rpl_forward_policy_t; + static bool rpl_policy_parent_confirmation_req = false; static int8_t rpl_policy_dao_retry_count_conf = 0; static int16_t rpl_policy_dao_initial_timeout_conf = 20; // Default is 2 seconds 100ms ticks static uint16_t rpl_policy_dio_validity_period_hysteresis = 0x0180; //Fixed Point 1.5 static uint8_t rpl_policy_multicast_config_min_advertisment_count = 0; static uint8_t rpl_policy_mrhof_parent_set_size_conf = 3; // default parent set size +static uint16_t rpl_policy_minimum_dao_target_refresh_conf = 0; // by default follow the configuration +static uint16_t rpl_policy_address_registration_timeout_value = 0; // Address registration timeouts in minutes 0 use address lifetime /* TODO - application API to control when to join new instances / DODAGs * @@ -115,6 +122,16 @@ void rpl_policy_set_initial_dao_ack_wait(uint16_t timeout_in_ms) rpl_policy_dao_initial_timeout_conf = timeout_in_ms; } +void rpl_policy_set_minimum_dao_target_refresh(uint16_t seconds) +{ + rpl_policy_minimum_dao_target_refresh_conf = seconds; +} + +uint16_t rpl_policy_minimum_dao_target_refresh(void) +{ + return rpl_policy_minimum_dao_target_refresh_conf; +} + uint16_t rpl_policy_initial_dao_ack_wait(const rpl_domain_t *domain, uint8_t mop) { (void)mop; @@ -144,6 +161,46 @@ int8_t rpl_policy_dao_retry_count() return rpl_policy_dao_retry_count_conf; } +//Default Optimistic value is ETX < 2.5 +static uint16_t rpl_policy_etx_full_forward = 0x280; +//Total Drop limit default is 8.0 etx +static uint16_t rpl_policy_etx_full_drop = 0x800; + +//Scale 100 % to bigger are to get more random resolution +#define MAX_DROP_COMPARE (100 * 256) + +int rpl_policy_forward_link_etx_threshold_set(uint16_t etx_full_forward, uint16_t etx_full_drop) +{ + if (etx_full_forward > etx_full_drop) { + return -1; + } + + rpl_policy_etx_full_forward = etx_full_forward; + rpl_policy_etx_full_drop = etx_full_drop; + + return 0; +} + +static rpl_forward_policy_t rpl_policy_link_forward_policy(uint16_t link_etx) +{ + if (link_etx >= rpl_policy_etx_full_drop) { + return RPL_POLICY_DROP; + } + + if (link_etx <= rpl_policy_etx_full_forward) { + return RPL_POLICY_FORWARD; + } + + // The multiplication could overflow 16-bit, even though the final result will be 16-bit + uint16_t drop_prob = (uint32_t) MAX_DROP_COMPARE * (link_etx - rpl_policy_etx_full_forward) / (rpl_policy_etx_full_drop - rpl_policy_etx_full_forward); + + if (randLIB_get_random_in_range(0, 25599) < drop_prob) { + return RPL_POLICY_DROP; + } + + return RPL_POLICY_FORWARD; +} + /* Given the next-hop address from a source routing header, which interface, * if any, should we assume that next hop is on? */ @@ -162,7 +219,9 @@ int8_t rpl_policy_srh_next_hop_interface(rpl_domain_t *domain, int8_t if_id, con } uint16_t etx = ipv6_map_ip_to_ll_and_call_ll_addr_handler(NULL, if_id, n, next_hop, etx_read); - if (etx > ETX_SRH_THRESHOLD) { + + //Validate Link ETX and play poker game if ETX is over optimistic value + if (rpl_policy_link_forward_policy(etx) == RPL_POLICY_DROP) { tr_warn("Rejecting SRH to %s: etx = %x", trace_ipv6(next_hop), etx); goto reject; } @@ -381,6 +440,16 @@ void rpl_policy_set_dio_multicast_config_advertisment_min_count(uint8_t min_coun rpl_policy_multicast_config_min_advertisment_count = min_count; } +uint16_t rpl_policy_address_registration_timeout() +{ + return rpl_policy_address_registration_timeout_value; +} + +void rpl_policy_set_address_registration_timeout(uint16_t timeout_in_minutes) +{ + rpl_policy_address_registration_timeout_value = timeout_in_minutes; +} + #ifdef RPL_STRUCTURES_H_ #error "rpl_structures.h should not be included by rpl_policy.c" diff --git a/source/RPL/rpl_policy.h b/source/RPL/rpl_policy.h index 13e25c492c..ac9ca67a1f 100644 --- a/source/RPL/rpl_policy.h +++ b/source/RPL/rpl_policy.h @@ -29,9 +29,14 @@ bool rpl_policy_request_dao_acks(const rpl_domain_t *domain, uint8_t mop); uint16_t rpl_policy_initial_dao_ack_wait(const rpl_domain_t *domain, uint8_t mop); void rpl_policy_set_initial_dao_ack_wait(uint16_t timeout_in_ms); +void rpl_policy_set_minimum_dao_target_refresh(uint16_t seconds); +uint16_t rpl_policy_minimum_dao_target_refresh(void); + void rpl_policy_set_dao_retry_count(uint8_t count); int8_t rpl_policy_dao_retry_count(); +int rpl_policy_forward_link_etx_threshold_set(uint16_t etx_full_forward, uint16_t etx_full_drop); + int8_t rpl_policy_srh_next_hop_interface(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop); uint16_t rpl_policy_modify_downward_cost_to_root_neighbour(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop, uint16_t cost); @@ -68,5 +73,7 @@ bool rpl_policy_parent_confirmation_requested(void); void rpl_policy_set_parent_confirmation_request(bool confirmation_requested); uint8_t rpl_policy_dio_multicast_config_advertisment_min_count(void); void rpl_policy_set_dio_multicast_config_advertisment_min_count(uint8_t min_count); +uint16_t rpl_policy_address_registration_timeout(); +void rpl_policy_set_address_registration_timeout(uint16_t timeout_in_minutes); #endif /* RPL_POLICY_H_ */ diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index aadbc60c28..56463cb5ee 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -52,6 +52,7 @@ struct rpl_neighbour { unsigned dodag_pref: 4; // Preference indication for DODAG parents (0=best) uint8_t dao_path_control; // Path control bit assignments for DAO parent uint8_t old_dao_path_control; + uint8_t addr_reg_failures; // Address registration failure count (missing ACK) int8_t interface_id; uint8_t g_mop_prf; uint8_t dtsn; diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 99377e6150..7ee3a56520 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -444,6 +444,7 @@ rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *version, const uint8_ neighbour->dtsn = dtsn; neighbour->dao_path_control = 0; neighbour->confirmed = 0; + neighbour->addr_reg_failures = 0; /* Need to limit number of neighbours here - chucking worst neighbour */ diff --git a/source/Security/kmp/kmp_api.c b/source/Security/kmp/kmp_api.c index a95802ec4d..345e9ba9fc 100644 --- a/source/Security/kmp/kmp_api.c +++ b/source/Security/kmp/kmp_api.c @@ -25,6 +25,7 @@ #include "Common_Protocols/ipv6_constants.h" #include "socket_api.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/kmp/kmp_socket_if.h" @@ -98,7 +99,7 @@ static void kmp_sec_prot_receive_disable(sec_prot_t *prot); #define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot)); -kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type) +kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *cfg) { if (!service) { return 0; @@ -150,6 +151,7 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type) kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get; kmp->sec_prot.type_get = kmp_sec_prot_by_type_get; kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable; + kmp->sec_prot.cfg = cfg; if (sec_prot->init(&kmp->sec_prot) < 0) { ns_dyn_mem_free(kmp); diff --git a/source/Security/kmp/kmp_api.h b/source/Security/kmp/kmp_api.h index 411d982bb2..062b36b4ad 100644 --- a/source/Security/kmp/kmp_api.h +++ b/source/Security/kmp/kmp_api.h @@ -61,6 +61,8 @@ typedef struct sec_prot_s sec_prot_t; typedef struct kmp_api_s kmp_api_t; typedef struct kmp_service_s kmp_service_t; +struct ws_cfg_settings_s; + /** * kmp_api_create_request KMP-CREATE.request * @@ -123,11 +125,12 @@ typedef void kmp_api_finished(kmp_api_t *kmp); * * \param service KMP service * \param type KMP type + * \param cfg configuration * * \return KMP instance or NULL * */ -kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type); +kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *cfg); /** * kmp_api_start start KMP api diff --git a/source/Security/kmp/kmp_eapol_pdu_if.c b/source/Security/kmp/kmp_eapol_pdu_if.c index 2b8a6616d4..6cf5c8f064 100644 --- a/source/Security/kmp/kmp_eapol_pdu_if.c +++ b/source/Security/kmp/kmp_eapol_pdu_if.c @@ -23,6 +23,7 @@ #include "nsdynmemLIB.h" #include "6LoWPAN/ws/ws_config.h" #include "NWK_INTERFACE/Include/protocol.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/kmp/kmp_eapol_pdu_if.h" diff --git a/source/Security/kmp/kmp_socket_if.c b/source/Security/kmp/kmp_socket_if.c index 6b905d5791..79aca99ee6 100644 --- a/source/Security/kmp/kmp_socket_if.c +++ b/source/Security/kmp/kmp_socket_if.c @@ -29,6 +29,7 @@ #include "Common_Protocols/ipv6_constants.h" #include "socket_api.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/kmp/kmp_socket_if.h" diff --git a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c index bc61ab1ac6..e8118585ad 100644 --- a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c @@ -24,6 +24,8 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" @@ -77,22 +79,6 @@ typedef struct { bool send_pending: 1; /**< TLS data is not yet send to network */ } eap_tls_sec_prot_int_t; -/*Small network setup*/ -#define EAP_TLS_SMALL_IMIN 300 // retries done in 30 seconds -#define EAP_TLS_SMALL_IMAX 900 // Largest value 90 seconds - -/* Large network setup*/ -#define EAP_TLS_LARGE_IMIN 600 // retries done in 60 seconds -#define EAP_TLS_LARGE_IMAX 2400 // Largest value 240 seconds - - -static trickle_params_t eap_tls_trickle_params = { - .Imin = EAP_TLS_SMALL_IMIN, /* ticks are 100ms */ - .Imax = EAP_TLS_SMALL_IMAX, /* ticks are 100ms */ - .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 2 -}; - static uint16_t auth_eap_tls_sec_prot_size(void); static int8_t auth_eap_tls_sec_prot_init(sec_prot_t *prot); @@ -126,19 +112,6 @@ int8_t auth_eap_tls_sec_prot_register(kmp_service_t *service) return 0; } -int8_t auth_eap_tls_sec_prot_timing_adjust(uint8_t timing) -{ - - if (timing < 16) { - eap_tls_trickle_params.Imin = EAP_TLS_SMALL_IMIN; - eap_tls_trickle_params.Imax = EAP_TLS_SMALL_IMAX; - } else { - eap_tls_trickle_params.Imin = EAP_TLS_LARGE_IMIN; - eap_tls_trickle_params.Imax = EAP_TLS_LARGE_IMAX; - } - return 0; -} - static uint16_t auth_eap_tls_sec_prot_size(void) { return sizeof(eap_tls_sec_prot_int_t); @@ -216,7 +189,7 @@ static int8_t auth_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_ // Call state machine prot->state_machine(prot); // Resets trickle timer to give time for supplicant to answer - sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); data->init_key_cnt++; } // Filters repeated initial EAPOL-key messages @@ -323,7 +296,8 @@ static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks data->burst_filt_timer = 0; } - sec_prot_timer_timeout_handle(prot, &data->common, &eap_tls_trickle_params, ticks); + sec_prot_timer_timeout_handle(prot, &data->common, + &prot->cfg->sec_prot_trickle_params, ticks); } static void auth_eap_tls_sec_prot_tls_create_indication(sec_prot_t *tls_prot) @@ -447,7 +421,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot) auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE); // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_ID); break; @@ -471,7 +445,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot) auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START); // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_START); break; @@ -553,7 +527,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot) auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING); // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); } else { // TLS done, indicate success to peer if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_OVER) { diff --git a/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c b/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c index d6ca43c18d..1513f99cb0 100644 --- a/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c +++ b/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c @@ -25,6 +25,7 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" diff --git a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c index bac7ecceb4..c7c935242d 100644 --- a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c @@ -24,6 +24,7 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" @@ -75,8 +76,6 @@ typedef struct { #define EAP_TLS_RETRY_TIMEOUT_SMALL 330*10 // retry timeout for small network additional 30 seconds for authenticator delay #define EAP_TLS_RETRY_TIMEOUT_LARGE 750*10 // retry timeout for large network additional 30 seconds for authenticator delay -static uint16_t retry_timeout = EAP_TLS_RETRY_TIMEOUT_SMALL; - static uint16_t supp_eap_tls_sec_prot_size(void); static int8_t supp_eap_tls_sec_prot_init(sec_prot_t *prot); @@ -110,17 +109,6 @@ int8_t supp_eap_tls_sec_prot_register(kmp_service_t *service) return 0; } -int8_t supp_eap_sec_prot_timing_adjust(uint8_t timing) -{ - if (timing < 16) { - retry_timeout = EAP_TLS_RETRY_TIMEOUT_SMALL; - } else { - retry_timeout = EAP_TLS_RETRY_TIMEOUT_LARGE; - } - return 0; -} - - static uint16_t supp_eap_tls_sec_prot_size(void) { return sizeof(eap_tls_sec_prot_int_t); @@ -416,7 +404,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) } // Set retry timeout based on network size - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; // Store sequence ID supp_eap_tls_sec_prot_seq_id_update(prot); @@ -461,7 +449,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) supp_eap_tls_sec_prot_seq_id_update(prot); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST); - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; // Initialize TLS protocol if (supp_eap_tls_sec_prot_init_tls(prot) < 0) { @@ -495,7 +483,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // Store sequence ID if (supp_eap_tls_sec_prot_seq_id_update(prot)) { // When receiving a new sequence number, adds more time for re-send if no response - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; } // All fragments received for a message diff --git a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h index 2b1dded5e8..78ececd7bc 100644 --- a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h +++ b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h @@ -33,27 +33,5 @@ */ int8_t supp_eap_tls_sec_prot_register(kmp_service_t *service); -/** - * supp_eap_sec_prot_timing_adjust Adjust retries and timings of the 4WH protocol - * - * Timing value is a generic number between 0 to 32 that goes from fast and - * reactive network to low bandwidth and long latency. - * - * example value definitions: - * 0-8 very fast network - * 9-16 medium network - * 16-24 slow network - * 25-32 extremely slow network - * - * There is no need to have lots variations in every layer if protocol is not very active in any case. - * - * \param timing Timing value. - * - * \return < 0 failure - * \return >= 0 success - * - */ -int8_t supp_eap_sec_prot_timing_adjust(uint8_t timing); - #endif /* SUPP_EAP_TLS_SEC_PROT_H_ */ diff --git a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c index 02b32b729f..b43ca5e58f 100644 --- a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c +++ b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c @@ -24,6 +24,8 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" @@ -68,21 +70,6 @@ typedef struct { uint16_t recv_size; /**< received pdu size */ } fwh_sec_prot_int_t; -/*Small network setup*/ -#define FWH_SMALL_IMIN 300 // retries done in 30 seconds -#define FWH_SMALL_IMAX 900 // Largest value 90 seconds - -/* Large network setup*/ -#define FWH_LARGE_IMIN 600 // retries done in 60 seconds -#define FWH_LARGE_IMAX 2400 // Largest value 240 seconds - -static trickle_params_t fwh_trickle_params = { - .Imin = FWH_SMALL_IMIN, /* ticks are 100ms */ - .Imax = FWH_SMALL_IMAX, /* ticks are 100ms */ - .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 2 -}; - static uint16_t auth_fwh_sec_prot_size(void); static int8_t auth_fwh_sec_prot_init(sec_prot_t *prot); @@ -113,18 +100,6 @@ int8_t auth_fwh_sec_prot_register(kmp_service_t *service) return 0; } -int8_t auth_fwh_sec_prot_timing_adjust(uint8_t timing) -{ - if (timing < 16) { - fwh_trickle_params.Imin = FWH_SMALL_IMIN; - fwh_trickle_params.Imax = FWH_SMALL_IMAX; - } else { - fwh_trickle_params.Imin = FWH_LARGE_IMIN; - fwh_trickle_params.Imax = FWH_LARGE_IMAX; - } - return 0; -} - static uint16_t auth_fwh_sec_prot_size(void) { return sizeof(fwh_sec_prot_int_t); @@ -331,7 +306,7 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_ static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) { fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot); - sec_prot_timer_timeout_handle(prot, &data->common, &fwh_trickle_params, ticks); + sec_prot_timer_timeout_handle(prot, &data->common, &prot->cfg->sec_prot_trickle_params, ticks); } static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot) @@ -368,7 +343,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot) auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1); // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &fwh_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_2); break; @@ -396,7 +371,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot) auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3); // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &fwh_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_4); } diff --git a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c index ee44df03cf..e5a44e18b8 100644 --- a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c +++ b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c @@ -24,6 +24,7 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" @@ -82,11 +83,6 @@ typedef struct { bool recv_replay_cnt_set : 1; /**< received replay counter set */ } fwh_sec_prot_int_t; -#define FWH_RETRY_TIMEOUT_SMALL 300*10 // retry timeout for small network -#define FWH_RETRY_TIMEOUT_LARGE 720*10 // retry timeout for large network - -static uint16_t retry_timeout = FWH_RETRY_TIMEOUT_SMALL; - static uint16_t supp_fwh_sec_prot_size(void); static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot); @@ -124,15 +120,6 @@ int8_t supp_fwh_sec_prot_register(kmp_service_t *service) return 0; } -int8_t supp_fwh_sec_prot_timing_adjust(uint8_t timing) -{ - if (timing < 16) { - retry_timeout = FWH_RETRY_TIMEOUT_SMALL; - } else { - retry_timeout = FWH_RETRY_TIMEOUT_LARGE; - } - return 0; -} static uint16_t supp_fwh_sec_prot_size(void) { @@ -152,7 +139,7 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot) sec_prot_init(&data->common); sec_prot_state_set(prot, &data->common, FWH_STATE_INIT); - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; data->msg3_received = false; data->msg3_retry_wait = false; data->recv_replay_cnt = 0; @@ -350,7 +337,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) if (sec_prot_result_ok_check(&data->common)) { // Send 4WH message 2 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2); - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3); } else { // Ready to be deleted @@ -378,7 +365,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) // Send 4WH message 2 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2); - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; return; } else if (data->recv_msg != FWH_MESSAGE_3) { return; @@ -405,7 +392,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) // Sends 4WH Message 4 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4); - data->common.ticks = retry_timeout; + data->common.ticks = prot->cfg->sec_prot_retry_timeout; sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH); break; diff --git a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h index 8369625847..2cb2284e3c 100644 --- a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h +++ b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h @@ -34,26 +34,4 @@ */ int8_t supp_fwh_sec_prot_register(kmp_service_t *service); -/** - * supp_fwh_sec_prot_timing_adjust Adjust retries and timings of the 4WH protocol - * - * Timing value is a generic number between 0 to 32 that goes from fast and - * reactive network to low bandwidth and long latency. - * - * example value definitions: - * 0-8 very fast network - * 9-16 medium network - * 16-24 slow network - * 25-32 extremely slow network - * - * There is no need to have lots variations in every layer if protocol is not very active in any case. - * - * \param timing Timing value. - * - * \return < 0 failure - * \return >= 0 success - * - */ -int8_t supp_fwh_sec_prot_timing_adjust(uint8_t timing); - #endif /* SUPP_FWH_SEC_PROT_H_ */ diff --git a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c index b4206f69b4..9c1b47d01d 100644 --- a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c +++ b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c @@ -24,6 +24,8 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_cfg_settings.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" @@ -60,21 +62,6 @@ typedef struct { uint16_t recv_size; /**< Received pdu size */ } gkh_sec_prot_int_t; -/*Small network setup*/ -#define GKH_SMALL_IMIN 300 // retries done in 30 seconds -#define GKH_SMALL_IMAX 900 // Largest value 90 seconds - -/* Large network setup*/ -#define GKH_LARGE_IMIN 600 // retries done in 60 seconds -#define GKH_LARGE_IMAX 2400 // Largest value 240 seconds - -static trickle_params_t gkh_trickle_params = { - .Imin = GKH_SMALL_IMIN, /* ticks are 100ms */ - .Imax = GKH_SMALL_IMAX, /* ticks are 100ms */ - .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 2 -}; - static uint16_t auth_gkh_sec_prot_size(void); static int8_t auth_gkh_sec_prot_init(sec_prot_t *prot); @@ -103,18 +90,6 @@ int8_t auth_gkh_sec_prot_register(kmp_service_t *service) return 0; } -int8_t auth_gkh_sec_prot_timing_adjust(uint8_t timing) -{ - if (timing < 16) { - gkh_trickle_params.Imin = GKH_SMALL_IMIN; - gkh_trickle_params.Imax = GKH_SMALL_IMAX; - } else { - gkh_trickle_params.Imin = GKH_LARGE_IMIN; - gkh_trickle_params.Imax = GKH_LARGE_IMAX; - } - return 0; -} - static uint16_t auth_gkh_sec_prot_size(void) { return sizeof(gkh_sec_prot_int_t); @@ -283,7 +258,7 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_ static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) { gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); - sec_prot_timer_timeout_handle(prot, &data->common, &gkh_trickle_params, ticks); + sec_prot_timer_timeout_handle(prot, &data->common, &prot->cfg->sec_prot_trickle_params, ticks); } static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot) @@ -312,7 +287,7 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot) auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1); // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &gkh_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->cfg->sec_prot_trickle_params); sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_2); diff --git a/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c b/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c index ccd2890ec9..064f2bec76 100644 --- a/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c +++ b/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c @@ -24,6 +24,7 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" diff --git a/source/Security/protocols/key_sec_prot/key_sec_prot.c b/source/Security/protocols/key_sec_prot/key_sec_prot.c index 409546c3dc..daa07af371 100644 --- a/source/Security/protocols/key_sec_prot/key_sec_prot.c +++ b/source/Security/protocols/key_sec_prot/key_sec_prot.c @@ -24,6 +24,7 @@ #include "fhss_config.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" diff --git a/source/Security/protocols/sec_prot.h b/source/Security/protocols/sec_prot.h index 49d28f7d1e..556d769f6b 100644 --- a/source/Security/protocols/sec_prot.h +++ b/source/Security/protocols/sec_prot.h @@ -268,6 +268,7 @@ struct sec_prot_s { sec_prot_receive_disable *receive_disable; /**< Disable receiving of messages */ sec_prot_keys_t *sec_keys; /**< Security keys storage pointer */ + sec_prot_cfg_t *cfg; /**< Configuration pointer */ uint8_t header_size; /**< Header size */ sec_prot_int_data_t *data; /**< Protocol internal data */ }; diff --git a/source/Security/protocols/sec_prot_cfg.h b/source/Security/protocols/sec_prot_cfg.h new file mode 100644 index 0000000000..fa2a88dafb --- /dev/null +++ b/source/Security/protocols/sec_prot_cfg.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SEC_PROT_CFG_H_ +#define SEC_PROT_CFG_H_ + +/* Security protocol configuration settings */ + +typedef struct sec_prot_cfg_s { + trickle_params_t sec_prot_trickle_params; + uint16_t sec_prot_retry_timeout; + uint16_t sec_max_ongoing_authentication; +} sec_prot_cfg_t; + +#endif /* SEC_PROT_CONF_H_ */ diff --git a/source/Security/protocols/sec_prot_keys.c b/source/Security/protocols/sec_prot_keys.c index cdcc31de32..c420a5823f 100644 --- a/source/Security/protocols/sec_prot_keys.c +++ b/source/Security/protocols/sec_prot_keys.c @@ -25,6 +25,7 @@ #include "Common_Protocols/ipv6_constants.h" #include "socket_api.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" diff --git a/source/Security/protocols/sec_prot_lib.c b/source/Security/protocols/sec_prot_lib.c index 29268529d3..0987054d6b 100644 --- a/source/Security/protocols/sec_prot_lib.c +++ b/source/Security/protocols/sec_prot_lib.c @@ -26,6 +26,7 @@ #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" #include "Service_Libs/Trickle/trickle.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" diff --git a/source/Security/protocols/tls_sec_prot/tls_sec_prot.c b/source/Security/protocols/tls_sec_prot/tls_sec_prot.c index beff5f5bae..ad07fd1ca1 100644 --- a/source/Security/protocols/tls_sec_prot/tls_sec_prot.c +++ b/source/Security/protocols/tls_sec_prot/tls_sec_prot.c @@ -22,8 +22,10 @@ #include "ns_trace.h" #include "nsdynmemLIB.h" #include "fhss_config.h" +#include "Service_Libs/Trickle/trickle.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/kmp/kmp_addr.h" #include "Security/kmp/kmp_api.h" #include "Security/PANA/pana_eap_header.h" diff --git a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c index 6f236bcf1f..de1d86b515 100644 --- a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c +++ b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c @@ -24,7 +24,7 @@ #include MBEDTLS_CONFIG_FILE #endif -#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_SSL_EXPORT_KEYS) /* EXPORT_KEYS not supported by mbedtls baremetal yet */ #define WS_MBEDTLS_SECURITY_ENABLED #endif @@ -35,10 +35,14 @@ #include "ns_trace.h" #include "nsdynmemLIB.h" #include "common_functions.h" +#include "Service_Libs/Trickle/trickle.h" +#include "Security/protocols/sec_prot_cfg.h" #include "Security/protocols/sec_prot_certs.h" #include "Security/protocols/tls_sec_prot/tls_sec_prot_lib.h" +#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_SSL_EXPORT_KEYS) /* EXPORT_KEYS not supported by mbedtls baremetal yet */ #ifdef WS_MBEDTLS_SECURITY_ENABLED +#endif #include "mbedtls/sha256.h" #include "mbedtls/error.h" @@ -51,8 +55,6 @@ #include "mbedtls/debug.h" #include "mbedtls/oid.h" -#include "mbedtls/ssl_internal.h" - #define TRACE_GROUP "tlsl" #define TLS_HANDSHAKE_TIMEOUT_MIN 25000 @@ -327,8 +329,10 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p return -1; } +#if !defined(MBEDTLS_SSL_CONF_RNG) // Configure random number generator mbedtls_ssl_conf_rng(&sec->conf, mbedtls_ctr_drbg_random, &sec->ctr_drbg); +#endif #ifdef MBEDTLS_ECP_RESTARTABLE // Set ECC calculation maximum operations (affects only client) @@ -340,9 +344,22 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p return -1; } + // Defines MBEDTLS_SSL_CONF_RECV/SEND/RECV_TIMEOUT define global functions which should be the same for all + // callers of mbedtls_ssl_set_bio_ctx and there should be only one ssl context. If these rules don't apply, + // these defines can't be used. +#if !defined(MBEDTLS_SSL_CONF_RECV) && !defined(MBEDTLS_SSL_CONF_SEND) && !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT) // Set calbacks mbedtls_ssl_set_bio(&sec->ssl, sec, tls_sec_prot_lib_ssl_send, tls_sec_prot_lib_ssl_recv, NULL); +#else + mbedtls_ssl_set_bio_ctx(&sec->ssl, sec); +#endif /* !defined(MBEDTLS_SSL_CONF_RECV) && !defined(MBEDTLS_SSL_CONF_SEND) && !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT) */ + +// Defines MBEDTLS_SSL_CONF_SET_TIMER/GET_TIMER define global functions which should be the same for all +// callers of mbedtls_ssl_set_timer_cb and there should be only one ssl context. If these rules don't apply, +// these defines can't be used. +#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && !defined(MBEDTLS_SSL_CONF_GET_TIMER) mbedtls_ssl_set_timer_cb(&sec->ssl, sec, tls_sec_prot_lib_ssl_set_timer, tls_sec_prot_lib_ssl_get_timer); +#endif /* !defined(MBEDTLS_SSL_CONF_SET_TIMER) && !defined(MBEDTLS_SSL_CONF_GET_TIMER) */ // Configure certificates, keys and certificate revocation list if (tls_sec_prot_lib_configure_certificates(sec, certs) != 0) { @@ -350,6 +367,7 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p return -1; } +#if !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) // Configure ciphersuites static const int sec_suites[] = { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, @@ -358,6 +376,7 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p 0 }; mbedtls_ssl_conf_ciphersuites(&sec->conf, sec_suites); +#endif /* !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) */ #ifdef TLS_SEC_PROT_LIB_TLS_DEBUG mbedtls_ssl_conf_dbg(&sec->conf, tls_sec_prot_lib_debug, sec); @@ -367,19 +386,23 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p // Export keys callback mbedtls_ssl_conf_export_keys_ext_cb(&sec->conf, tls_sec_prot_lib_ssl_export_keys, sec); +#if !defined(MBEDTLS_SSL_CONF_MIN_MINOR_VER) || !defined(MBEDTLS_SSL_CONF_MIN_MAJOR_VER) mbedtls_ssl_conf_min_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3); +#endif /* !defined(MBEDTLS_SSL_CONF_MIN_MINOR_VER) || !defined(MBEDTLS_SSL_CONF_MIN_MAJOR_VER) */ + +#if !defined(MBEDTLS_SSL_CONF_MAX_MINOR_VER) || !defined(MBEDTLS_SSL_CONF_MAX_MAJOR_VER) mbedtls_ssl_conf_max_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3); +#endif /* !defined(MBEDTLS_SSL_CONF_MAX_MINOR_VER) || !defined(MBEDTLS_SSL_CONF_MAX_MAJOR_VER) */ // Set certificate verify callback mbedtls_ssl_set_verify(&sec->ssl, tls_sec_prot_lib_x509_crt_verify, sec); -#ifdef MBEDTLS_ECP_RESTARTABLE - if (is_server_is_set) { - // Temporary to enable non blocking ECC */ - sec->ssl.handshake->ecrs_enabled = 1; - } -#endif - + /* Currently assuming we are running fast enough HW that ECC calculations are not blocking any normal operation. + * + * If there is a problem with ECC calculations and those are taking too long in border router + * MBEDTLS_ECP_RESTARTABLE feature needs to be enabled and public API is needed to allow it in border router + * enabling should be done here. + */ return 0; } @@ -550,7 +573,7 @@ static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(tls_security_t *sec, m // For both IDevID and LDevId both subject alternative name or extended key usage must be valid if (tls_sec_prot_lib_subject_alternative_name_validate(crt) < 0 || tls_sec_prot_lib_extended_key_usage_validate(crt) < 0) { - tr_error("invalid cert"); + tr_info("no wisun fields on cert"); if (sec->ext_cert_valid) { *flags |= MBEDTLS_X509_BADCERT_OTHER; return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; @@ -570,7 +593,7 @@ static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_ if (sane_res >= 0 || ext_key_res >= 0) { // Then both subject alternative name and extended key usage must be valid if (sane_res < 0 || ext_key_res < 0) { - tr_error("invalid cert"); + tr_info("no wisun fields on cert"); if (sec->ext_cert_valid) { *flags |= MBEDTLS_X509_BADCERT_OTHER; return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; diff --git a/source/Service_Libs/fhss/fhss_common.h b/source/Service_Libs/fhss/fhss_common.h index 4d10667924..724351d029 100644 --- a/source/Service_Libs/fhss/fhss_common.h +++ b/source/Service_Libs/fhss/fhss_common.h @@ -40,6 +40,7 @@ struct fhss_structure { int8_t fhss_event_timer; uint8_t active_fhss_events; uint16_t number_of_channels; + uint16_t number_of_uc_channels; uint16_t optimal_packet_length; fhss_states fhss_state; uint32_t fhss_timeout; diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index d5272250f8..1d29e70c2a 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -122,6 +122,8 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati return NULL; } int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); + int uc_channel_count = channel_list_count_channels(fhss_configuration->unicast_channel_mask); + if (channel_count <= 0) { // There must be at least one configured channel in channel list return NULL; @@ -145,7 +147,15 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); fhss_struct->ws->fhss_configuration = *fhss_configuration; + if (uc_channel_count == 0) { + //If Unicast channel is empty use Domain mask + for (uint8_t i = 0; i < 8; i++) { + fhss_struct->ws->fhss_configuration.unicast_channel_mask[i] = fhss_configuration->channel_mask[i]; + } + uc_channel_count = channel_count; + } fhss_struct->number_of_channels = channel_count; + fhss_struct->number_of_uc_channels = uc_channel_count; fhss_struct->optimal_packet_length = OPTIMAL_PACKET_LENGTH; fhss_ws_set_hop_count(fhss_struct, 0xff); fhss_struct->rx_channel = fhss_configuration->unicast_fixed_channel; @@ -371,7 +381,7 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_ uint8_t dwell_time = fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval; uint16_t cur_slot = fhss_structure->ws->uc_slot; if (cur_slot == 0) { - cur_slot = fhss_structure->number_of_channels; + cur_slot = fhss_structure->number_of_uc_channels; } cur_slot--; uint32_t remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval))); @@ -383,8 +393,8 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_ uint64_t ms_since_seq_start = (cur_slot * dwell_time) + (dwell_time - remaining_time_ms) + time_to_tx; uint32_t seq_length = 0x10000; if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_TR51CF) { - ms_since_seq_start %= (dwell_time * fhss_structure->number_of_channels); - seq_length = fhss_structure->number_of_channels; + ms_since_seq_start %= (dwell_time * fhss_structure->number_of_uc_channels); + seq_length = fhss_structure->number_of_uc_channels; } return own_floor((float)(ms_since_seq_start * DEF_2E24) / (seq_length * dwell_time)); } @@ -467,16 +477,16 @@ static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure) if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_FIXED_CHANNEL) { return; } else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_TR51CF) { - next_channel = fhss_structure->rx_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_channels, NULL); - if (++fhss_structure->ws->uc_slot == fhss_structure->number_of_channels) { + next_channel = fhss_structure->rx_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_uc_channels, NULL); + if (++fhss_structure->ws->uc_slot == fhss_structure->number_of_uc_channels) { fhss_structure->ws->uc_slot = 0; } } else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_DH1CF) { - next_channel = fhss_structure->rx_channel = dh1cf_get_uc_channel_index(fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_channels); + next_channel = fhss_structure->rx_channel = dh1cf_get_uc_channel_index(fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_uc_channels); fhss_structure->ws->uc_slot++; } else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_VENDOR_DEF_CF) { if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) { - next_channel = fhss_structure->rx_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, mac_address, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels); + next_channel = fhss_structure->rx_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, mac_address, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_uc_channels); } } // Do not switch unicast channel when broadcast channel is active. @@ -521,16 +531,17 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a fhss_stats_update(fhss_structure, STATS_FHSS_UNKNOWN_NEIGHBOR, 1); return -2; } - // TODO: WS bootstrap has to store neighbors number of channels + if (neighbor_timing_info->uc_timing_info.unicast_number_of_channels == 0) { - neighbor_timing_info->uc_timing_info.unicast_number_of_channels = fhss_structure->number_of_channels; + return -1; } + uint16_t destination_slot = fhss_ws_calculate_destination_slot(neighbor_timing_info, tx_time); int32_t tx_channel = neighbor_timing_info->uc_timing_info.fixed_channel; if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_TR51CF) { tx_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, destination_slot, destination_address, neighbor_timing_info->uc_timing_info.unicast_number_of_channels, NULL); } else if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_DH1CF) { - tx_channel = dh1cf_get_uc_channel_index(destination_slot, destination_address, neighbor_timing_info->uc_timing_info.unicast_number_of_channels); + tx_channel = dh1cf_get_uc_channel_index(destination_slot, destination_address, neighbor_timing_info->uc_channel_list.channel_count); } else if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_VENDOR_DEF_CF) { if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) { tx_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, destination_address, fhss_structure->ws->fhss_configuration.bsi, neighbor_timing_info->uc_timing_info.unicast_number_of_channels); @@ -951,6 +962,7 @@ int fhss_ws_remove_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_configuration_t *fhss_configuration) { int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); + int channel_count_uc = channel_list_count_channels(fhss_configuration->unicast_channel_mask); if (channel_count <= 0) { return -1; } @@ -968,17 +980,27 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co fhss_structure->ws->unicast_timer_running = true; } fhss_structure->ws->fhss_configuration = *fhss_configuration; + if (channel_count_uc == 0) { + //If Unicast channel is empty use Domain mask + for (uint8_t i = 0; i < 8; i++) { + fhss_structure->ws->fhss_configuration.unicast_channel_mask[i] = fhss_configuration->channel_mask[i]; + } + channel_count_uc = channel_count; + } + fhss_structure->number_of_channels = channel_count; + fhss_structure->number_of_uc_channels = channel_count_uc; if (fhss_configuration->ws_uc_channel_function == WS_FIXED_CHANNEL) { 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: %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", 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, fhss_structure->ws->fhss_configuration.ws_bc_channel_function, fhss_structure->number_of_channels, + fhss_structure->number_of_uc_channels, 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, diff --git a/source/libNET/src/socket_api.c b/source/libNET/src/socket_api.c index 2cf27829c5..105c8579aa 100644 --- a/source/libNET/src/socket_api.c +++ b/source/libNET/src/socket_api.c @@ -39,10 +39,14 @@ #include "Common_Protocols/ipv6_flow.h" #include "Common_Protocols/tcp.h" #include "Common_Protocols/udp.h" +#include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "common_functions.h" #define TRACE_GROUP "sckA" +/* Data already written to space provided */ +#define GETSOCKOPT_DATA_READY 1 + const uint8_t ns_in6addr_any[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int8_t socket_open(uint8_t protocol, uint16_t identifier, void (*passed_fptr)(void *)) @@ -1010,12 +1014,35 @@ int8_t socket_setsockopt(int8_t socket, uint8_t level, uint8_t opt_name, const v } } +static bool socket_latency_get(const uint8_t dest_addr[static 16], uint32_t *latency) +{ + ipv6_route_t *route = ipv6_route_choose_next_hop(dest_addr, -1, NULL); + if (!route) { + return false; + } + + return protocol_6lowpan_latency_estimate_get(route->info.interface_id, latency); +} + +static bool socket_stagger_value_get(const uint8_t dest_addr[static 16], uint32_t data_amount, uint16_t *stagger_min, uint16_t *stagger_max, uint16_t *stagger_rand) +{ + ipv6_route_t *route = ipv6_route_choose_next_hop(dest_addr, -1, NULL); + if (!route) { + // No route found, return 0 + return false; + } + + return protocol_6lowpan_stagger_estimate_get(route->info.interface_id, data_amount, stagger_min, stagger_max, stagger_rand); +} + static union { int8_t s8; uint16_t u16; int16_t s16; uint32_t u32; int32_t s32; + uint64_t u64; + int64_t s64; bool boolean; } opt_temp; @@ -1130,7 +1157,41 @@ static int8_t ipv6_getsockopt(const socket_t *socket_ptr, uint8_t opt_name, cons *value = &opt_temp.boolean; *len = sizeof(bool); break; + case SOCKET_LATENCY: { + ns_ipv6_latency_t *ns_ipv6_latency = (ns_ipv6_latency_t *)*value; + if (*len < sizeof(ns_ipv6_latency_t)) { + return -1; + } + if (socket_latency_get(ns_ipv6_latency->dest_addr, &ns_ipv6_latency->latency)) { + *len = sizeof(ns_ipv6_latency_t); + return GETSOCKOPT_DATA_READY; + } + return -3; + /* break; */ + } + case SOCKET_STAGGER: { + ns_ipv6_stagger_t *ns_ipv6_stagger = (ns_ipv6_stagger_t *)*value; + uint16_t stagger_min, stagger_max, stagger_rand; + bool retval; + + if (*len < sizeof(ns_ipv6_stagger_t)) { + return -1; + } + retval = socket_stagger_value_get(ns_ipv6_stagger->dest_addr, + ns_ipv6_stagger->data_amount, + &stagger_min, &stagger_max, &stagger_rand); + if (retval) { + ns_ipv6_stagger->stagger_min = stagger_min; + ns_ipv6_stagger->stagger_max = stagger_max; + ns_ipv6_stagger->stagger_rand = stagger_rand; + *len = sizeof(ns_ipv6_stagger_t); + return GETSOCKOPT_DATA_READY; + } + + return -3; + /* break; */ + } default: return -2; } @@ -1145,12 +1206,15 @@ int8_t socket_getsockopt(int8_t socket, uint8_t level, uint8_t opt_name, void *o return -1; } - const void *value; - uint16_t len; + const void *value = opt_value; + uint16_t len = *opt_len; if (level == SOCKET_IPPROTO_IPV6 && socket_is_ipv6(socket_ptr)) { int8_t ret = ipv6_getsockopt(socket_ptr, opt_name, &value, &len); if (ret != 0) { + if (ret == GETSOCKOPT_DATA_READY) { + ret = 0; + } return ret; } } else if (level == SOCKET_SOL_SOCKET) { @@ -1198,4 +1262,3 @@ ns_cmsghdr_t *NS_CMSG_NXTHDR(const ns_msghdr_t *msgh, const ns_cmsghdr_t *cmsg) } return (ns_cmsghdr_t *) start_of_next_header; } - diff --git a/sources.mk b/sources.mk index 840c51105d..3998833c3b 100644 --- a/sources.mk +++ b/sources.mk @@ -40,6 +40,7 @@ SRCS += \ source/6LoWPAN/ws/ws_eapol_relay_lib.c \ source/6LoWPAN/ws/ws_eapol_pdu.c \ source/6LoWPAN/ws/ws_stats.c \ + source/6LoWPAN/ws/ws_cfg_settings.c \ source/BorderRouter/border_router.c \ source/Common_Protocols/icmpv6.c \ source/Common_Protocols/icmpv6_prefix.c \