From d104328f556c60ee09bb316ffc700ba8f1deca19 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 16 Apr 2020 11:43:53 +0300 Subject: [PATCH] Squashed 'features/nanostack/sal-stack-nanostack/' changes from fb7413b846..cc03296c27 cc03296c27 Merge branch 'release_internal' into release_external 59397d17c4 Fixed Wi-SUN border router restart after settings change 8295a43668 PAE authenticator TLS authentication limit based on dynamic value 2776cfef50 RPL config update not re-start whole BR again just increment version number and with new parameters. bec4d48946 Fixed FHSS testing now it follow configured channel count not a wi-sun configured Default. b9cad9d362 Remove floating point literals from Thread code 423a48f48b RPL link etx validation update 89a497a386 Merge branch 'release_internal' into release_external c8cc6601fd Merge pull request #2336 from ARMmbed/sync_with_mbedos ac5f369d70 MBEDTLS_SSL_EXPORT_KEYS added to Nanostack's tls_sec_prot_lib 6522a086ef Added missing optimizations based on mbedtls/baremetal.h config 0e8739fae3 Added new global rng, needed for MbedTLS optimisations d5db37eec8 Prepare for upcoming MbedTLS changes 4271a9dda9 Merge pull request #2335 from ARMmbed/sync_with_mbedos e2db6ffefb Fixed error of function 'mac_fcf_lenght' 28fc2a9543 Fixed error of structure 194e81beda Fixed spelling mistake of structure 00ea3fb83c Remove test files d7f7cc582a Merge branch 'release_internal' into release_external 132cd12107 Merge pull request #2333 from ARMmbed/sync_with_mbedos 550a78e544 Fix function spelling mistake in Thread 74c60242e1 Fix function spelling mistake in border_router.c 89830ecf1a Fix function spelling mistake in iphc_decompress.c 1728ae12dc Fix function spelling mistake in lowpan_context.c ed5d253fcc Fix function spelling mistake in lowpan_context.h ecbca0a2ed Fixed typo 'thead' in thread_neighbor_class.h 071911b30a Changed nanostack API network size to be a range of values 4756be4766 NEW API for Validation RX Unicast schedule channel. 0b48e5c018 Channel Mask update ,support for excluded Channels and FHSS API pdate ead1ade5a7 Start sending PAS message after EAPOL parent TX fails. 8de473b245 Implemented 802.15.4 mode setting (#2328) 975b9e670b Added missing configuration api empty functions f7db06eb1e Added configuration storage (#2283) e9561f0fe4 Removed mbedTLS internal include file fe812c3c1f Changed certificate error message wording to be less fatal 97aaf5f613 Add network property API to Nanostack (#2318) cfd1a4d271 Fixed Route cost calculation 5094614813 Added opeation mode validation for detect unsupported values. 44f85aaf4b Enabled RPL candidate list filtering and only certificate setup accept without limit. 145c7399b3 Wi-sun address registration trigger update d492575adb Modified ARO registrations timeouts from the address lifetime b898f04b5b Removed Extra version number update at revocation start. b9d14097e2 Wi-sun config message consustent filter dcebff9bb5 Use RPL parent soft filtering only after bootstrap. 523593e014 Fixed Broken new channel mask update. a3bcc2d2c8 Removed the PAN version change requirement from routers bc919d8241 Merge pull request #2315 from ARMmbed/merge_release_internal_to_master git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: cc03296c27fbe26663182d90586e2d31f140e300 --- nanostack/fhss_config.h | 5 +- nanostack/fhss_ws_extension.h | 9 + nanostack/mac_common_defines.h | 1 + nanostack/mlme.h | 1 + nanostack/ns_sha256.h | 16 +- nanostack/platform/arm_hal_phy.h | 12 +- nanostack/socket_api.h | 63 +- nanostack/ws_bbr_api.h | 85 ++ nanostack/ws_management_api.h | 295 ++++- .../Bootstraps/Generic/protocol_6lowpan.c | 88 +- source/6LoWPAN/Bootstraps/protocol_6lowpan.h | 2 + source/6LoWPAN/IPHC_Decode/iphc_decompress.c | 4 +- source/6LoWPAN/IPHC_Decode/lowpan_context.c | 4 +- source/6LoWPAN/IPHC_Decode/lowpan_context.h | 2 +- source/6LoWPAN/Thread/thread_bootstrap.c | 2 +- source/6LoWPAN/Thread/thread_common.c | 2 +- .../Thread/thread_mle_message_handler.c | 2 +- source/6LoWPAN/Thread/thread_neighbor_class.h | 2 +- .../6LoWPAN/Thread/thread_router_bootstrap.c | 2 +- source/6LoWPAN/ws/ws_bbr_api.c | 217 ++- source/6LoWPAN/ws/ws_bbr_api_internal.h | 3 + source/6LoWPAN/ws/ws_bootstrap.c | 527 ++++++-- source/6LoWPAN/ws/ws_bootstrap.h | 5 + source/6LoWPAN/ws/ws_cfg_settings.c | 1169 +++++++++++++++++ source/6LoWPAN/ws/ws_cfg_settings.h | 184 +++ source/6LoWPAN/ws/ws_common.c | 301 ++--- source/6LoWPAN/ws/ws_common.h | 47 +- source/6LoWPAN/ws/ws_common_defines.h | 53 +- source/6LoWPAN/ws/ws_config.h | 68 +- source/6LoWPAN/ws/ws_empty_functions.c | 181 +++ source/6LoWPAN/ws/ws_ie_lib.c | 89 +- source/6LoWPAN/ws/ws_llc_data_service.c | 6 + source/6LoWPAN/ws/ws_management_api.c | 686 +++++++--- source/6LoWPAN/ws/ws_neighbor_class.c | 132 +- source/6LoWPAN/ws/ws_pae_auth.c | 49 +- source/6LoWPAN/ws/ws_pae_auth.h | 28 +- source/6LoWPAN/ws/ws_pae_controller.c | 70 +- source/6LoWPAN/ws/ws_pae_controller.h | 37 +- source/6LoWPAN/ws/ws_pae_lib.c | 7 +- source/6LoWPAN/ws/ws_pae_lib.h | 2 +- source/6LoWPAN/ws/ws_pae_supp.c | 27 +- source/6LoWPAN/ws/ws_pae_supp.h | 30 +- source/6LoWPAN/ws/ws_pae_timers.c | 54 +- source/6LoWPAN/ws/ws_pae_timers.h | 35 +- source/6LoWPAN/ws/ws_test_api.c | 68 +- source/BorderRouter/border_router.c | 8 +- source/Common_Protocols/icmpv6.c | 5 +- source/Core/include/ns_error_types.h | 4 +- source/Core/include/ns_socket.h | 6 +- source/Core/ns_socket.c | 6 +- source/MAC/IEEE802_15_4/mac_defines.h | 2 + .../mac_header_helper_functions.c | 12 +- source/MAC/IEEE802_15_4/mac_mcps_sap.c | 16 +- source/MAC/IEEE802_15_4/mac_mlme.c | 61 +- source/MAC/IEEE802_15_4/mac_mlme.h | 2 +- source/MAC/IEEE802_15_4/mac_pd_sap.c | 2 +- source/MAC/IEEE802_15_4/mac_security_mib.c | 10 +- source/MAC/IEEE802_15_4/mac_security_mib.h | 2 +- source/MAC/IEEE802_15_4/sw_mac.c | 26 +- source/NWK_INTERFACE/Include/protocol.h | 1 + source/RPL/rpl_control.c | 31 +- source/RPL/rpl_control.h | 10 +- source/RPL/rpl_downward.c | 77 +- source/RPL/rpl_downward.h | 3 +- source/RPL/rpl_policy.c | 73 +- source/RPL/rpl_policy.h | 7 + source/RPL/rpl_structures.h | 1 + source/RPL/rpl_upward.c | 1 + source/Security/kmp/kmp_api.c | 4 +- source/Security/kmp/kmp_api.h | 5 +- source/Security/kmp/kmp_eapol_pdu_if.c | 1 + source/Security/kmp/kmp_socket_if.c | 1 + .../eap_tls_sec_prot/auth_eap_tls_sec_prot.c | 42 +- .../eap_tls_sec_prot/eap_tls_sec_prot_lib.c | 1 + .../eap_tls_sec_prot/supp_eap_tls_sec_prot.c | 20 +- .../eap_tls_sec_prot/supp_eap_tls_sec_prot.h | 22 - .../fwh_sec_prot/auth_fwh_sec_prot.c | 35 +- .../fwh_sec_prot/supp_fwh_sec_prot.c | 23 +- .../fwh_sec_prot/supp_fwh_sec_prot.h | 22 - .../gkh_sec_prot/auth_gkh_sec_prot.c | 33 +- .../gkh_sec_prot/supp_gkh_sec_prot.c | 1 + .../protocols/key_sec_prot/key_sec_prot.c | 1 + source/Security/protocols/sec_prot.h | 1 + source/Security/protocols/sec_prot_cfg.h | 29 + source/Security/protocols/sec_prot_keys.c | 1 + source/Security/protocols/sec_prot_lib.c | 1 + .../protocols/tls_sec_prot/tls_sec_prot.c | 2 + .../protocols/tls_sec_prot/tls_sec_prot_lib.c | 47 +- source/Service_Libs/fhss/fhss_common.h | 1 + source/Service_Libs/fhss/fhss_ws.c | 44 +- source/libNET/src/socket_api.c | 69 +- sources.mk | 1 + 92 files changed, 4358 insertions(+), 1087 deletions(-) create mode 100644 source/6LoWPAN/ws/ws_cfg_settings.c create mode 100644 source/6LoWPAN/ws/ws_cfg_settings.h create mode 100644 source/Security/protocols/sec_prot_cfg.h 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 \