From 4daaaf126d9dfbfcbe638753573139d95442da1f Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 16 Apr 2020 11:37:16 +0300 Subject: [PATCH 1/4] Squashed 'features/nanostack/coap-service/' changes from e5e0c138e6..5aa54b8e62 5aa54b8e62 Merge pull request #127 from ARMmbed/sync_with_mbedos 6fe78412d2 Follow Mbed OS coding style 2b708be451 trace group defiined for shared_rng d4c2caca41 more error handling added for ctr and hmac cace1e9c22 Added missing optimizations based on mbedtls/baremetal.h config 2cc7442ba5 Added new global rng, needed for MbedTLS optimisations f861157576 Prepare for upcoming MbedTLS changes git-subtree-dir: features/nanostack/coap-service git-subtree-split: 5aa54b8e622ec2b44bdf323cc02bd1cfc5ffd904 --- source/coap_security_handler.c | 65 +++++++++++++++++-- .../coap-service/unittest/stub/mbedtls_stub.c | 32 +++++++++ .../coap-service/unittest/stub/mbedtls_stub.h | 2 + 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/source/coap_security_handler.c b/source/coap_security_handler.c index 1fbe3ffc866..5afd2abf02e 100644 --- a/source/coap_security_handler.c +++ b/source/coap_security_handler.c @@ -30,6 +30,7 @@ #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" #include "mbedtls/ctr_drbg.h" +#include "mbedtls/hmac_drbg.h" #include "mbedtls/ssl_ciphersuites.h" #include "ns_trace.h" @@ -41,7 +42,20 @@ struct coap_security_s { mbedtls_ssl_config _conf; mbedtls_ssl_context _ssl; - mbedtls_ctr_drbg_context _ctr_drbg; +#if defined(MBEDTLS_CTR_DRBG_C) + mbedtls_ctr_drbg_context _drbg; +#define DRBG_INIT mbedtls_ctr_drbg_init +#define DRBG_RANDOM mbedtls_ctr_drbg_random +#define DRBG_FREE mbedtls_ctr_drbg_free +#elif defined(MBEDTLS_HMAC_DRBG_C) + mbedtls_hmac_drbg_context _drbg; +#define DRBG_INIT mbedtls_hmac_drbg_init +#define DRBG_RANDOM mbedtls_hmac_drbg_random +#define DRBG_FREE mbedtls_hmac_drbg_free +#else +#error "CTR or HMAC must be defined for coap_security_handler!" +#endif + mbedtls_entropy_context _entropy; bool _is_started; simple_cookie_t _cookie; @@ -68,6 +82,7 @@ struct coap_security_s { }; +#if !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) const int ECJPAKE_SUITES[] = { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, @@ -75,12 +90,15 @@ const int ECJPAKE_SUITES[] = { }; #endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) static const int PSK_SUITES[] = { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, 0 }; +#endif /* defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) */ +#endif /* !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) */ #define TRACE_GROUP "CsSh" @@ -110,7 +128,7 @@ static int coap_security_handler_init(coap_security_t *sec) mbedtls_ssl_init(&sec->_ssl); mbedtls_ssl_config_init(&sec->_conf); - mbedtls_ctr_drbg_init(&sec->_ctr_drbg); + DRBG_INIT(&sec->_drbg); mbedtls_entropy_init(&sec->_entropy); #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -128,12 +146,22 @@ static int coap_security_handler_init(coap_security_t *sec) 128, entropy_source_type) < 0) { return -1; } - - if ((mbedtls_ctr_drbg_seed(&sec->_ctr_drbg, mbedtls_entropy_func, &sec->_entropy, +#if defined(MBEDTLS_CTR_DRBG_C) + if ((mbedtls_ctr_drbg_seed(&sec->_drbg, mbedtls_entropy_func, &sec->_entropy, (const unsigned char *) pers, strlen(pers))) != 0) { return -1; } +#elif defined(MBEDTLS_HMAC_DRBG_C) + if ((mbedtls_hmac_drbg_seed(&sec->_drbg, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), + mbedtls_entropy_func, &sec->_entropy, + (const unsigned char *) pers, + strlen(pers))) != 0) { + return -1; + } +#else +#error "CTR or HMAC must be defined for coap_security_handler!" +#endif return 0; } @@ -156,7 +184,9 @@ static void coap_security_handler_reset(coap_security_t *sec) #endif mbedtls_entropy_free(&sec->_entropy); - mbedtls_ctr_drbg_free(&sec->_ctr_drbg); + + DRBG_FREE(&sec->_drbg); + mbedtls_ssl_config_free(&sec->_conf); mbedtls_ssl_free(&sec->_ssl); #if defined(MBEDTLS_PLATFORM_C) @@ -332,7 +362,9 @@ static int coap_security_handler_configure_keys(coap_security_t *sec, coap_secur if (0 != mbedtls_ssl_conf_psk(&sec->_conf, keys._priv_key, keys._priv_key_len, keys._cert, keys._cert_len)) { break; } +#if !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) mbedtls_ssl_conf_ciphersuites(&sec->_conf, PSK_SUITES); +#endif /* !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) */ ret = 0; #endif break; @@ -342,7 +374,9 @@ static int coap_security_handler_configure_keys(coap_security_t *sec, coap_secur if (mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._key, keys._key_len) != 0) { return -1; } +#if !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) mbedtls_ssl_conf_ciphersuites(&sec->_conf, ECJPAKE_SUITES); +#endif /* !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE) */ //NOTE: If thread starts supporting PSK in other modes, then this will be needed! mbedtls_ssl_conf_export_keys_cb(&sec->_conf, @@ -388,17 +422,31 @@ int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_ser mbedtls_ssl_conf_handshake_timeout(&sec->_conf, timeout_min, timeout_max); } - mbedtls_ssl_conf_rng(&sec->_conf, mbedtls_ctr_drbg_random, &sec->_ctr_drbg); +#if !defined(MBEDTLS_SSL_CONF_RNG) + mbedtls_ssl_conf_rng(&sec->_conf, DRBG_RANDOM, &sec->_drbg); +#endif if ((mbedtls_ssl_setup(&sec->_ssl, &sec->_conf)) != 0) { 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) mbedtls_ssl_set_bio(&sec->_ssl, sec, f_send, f_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, set_timer, get_timer); +#endif /* !defined(MBEDTLS_SSL_CONF_SET_TIMER) && !defined(MBEDTLS_SSL_CONF_GET_TIMER) */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) //TODO: Figure out better way!!! @@ -420,8 +468,13 @@ int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_ser &sec->_cookie); #endif +#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) */ sec->_is_started = true; diff --git a/test/coap-service/unittest/stub/mbedtls_stub.c b/test/coap-service/unittest/stub/mbedtls_stub.c index e607acd4d3f..403ae9a57a5 100644 --- a/test/coap-service/unittest/stub/mbedtls_stub.c +++ b/test/coap-service/unittest/stub/mbedtls_stub.c @@ -248,6 +248,38 @@ int mbedtls_ctr_drbg_random(void *p_rng, return mbedtls_stub.crt_expected_int; } +// from hmac_drbg.h +void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx) +{ + +} + +void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx) +{ + +} + +int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t *md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len) +{ + return mbedtls_stub.crt_expected_int; +} + +int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len) +{ + return mbedtls_stub.crt_expected_int; +} + +// from md.h +const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type) +{ + return 0; +} + //From x509_crt.h void mbedtls_x509_crt_init(mbedtls_x509_crt *a) { diff --git a/test/coap-service/unittest/stub/mbedtls_stub.h b/test/coap-service/unittest/stub/mbedtls_stub.h index 2ad72cb9398..1910f9c5f2d 100644 --- a/test/coap-service/unittest/stub/mbedtls_stub.h +++ b/test/coap-service/unittest/stub/mbedtls_stub.h @@ -24,11 +24,13 @@ #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "mbedtls/ctr_drbg.h" +#include "mbedtls/hmac_drbg.h" #include "mbedtls/x509_crt.h" #include "mbedtls/sha256.h" #include "mbedtls/entropy.h" #include "mbedtls/pk.h" #include "mbedtls/platform.h" +#include "mbedtls/md.h" #define HANDSHAKE_FINISHED_VALUE 8888 From d104328f556c60ee09bb316ffc700ba8f1deca19 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 16 Apr 2020 11:43:53 +0300 Subject: [PATCH 2/4] 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 | 297 ++--- source/6LoWPAN/ws/ws_common.h | 45 +- 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 | 654 ++++++--- 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 | 70 +- 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, 4340 insertions(+), 1069 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 a388f5643f4..9a286128acf 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 1d8e2998ee6..ac2e1b446f7 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 ebd3ccf5b8f..95515c1fd4f 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 8b584297e17..eeeb48c2e19 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 c4391fd76c6..1d9a68904a7 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 e31f9e1afb5..0b8daf32cce 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 483932b5781..07e231c8643 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 bfea2ba7a9e..8e843f5673a 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 31e2f3416ca..9a465fbc272 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 8dc22889aef..5244441741c 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 81d54494475..df32d174f6c 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 7961f10cc95..d180102e4a9 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 b07565a96c2..ee465916afd 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 6aaffc1a8ec..6a6079acfa8 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); - - // 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]; - } + ws_fhss_configure_channel_masks(cur, &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; + 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 062dc767a3b..949eac4a99d 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 00000000000..bebe6627d75 --- /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 00000000000..334489d5137 --- /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 f89fbaa7483..7bfb66df4ed 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; - - 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; + hopping_schdule->channel_plan = 0; + + 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; + 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 latency; } -uint32_t ws_common_version_timeout_get(uint8_t config) +uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur) { - 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; + 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 { - lifetime = PAN_VERSION_LARGE_NETWORK_TIMEOUT; + // huge amount of devices (now 1000) + network_size_estimate = 1000; } - return lifetime; + return network_size_estimate; } - #endif // HAVE_WS - diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 588902753ff..3aa154c0527 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,10 +140,13 @@ 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_timeout_get(uint8_t config); -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 ws_common_version_timeout_get(uint8_t config); +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 @@ -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 92f7da38eb4..d2797f8e803 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 e7afc90d982..b2a9bd18c9f 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 be07fd0126a..e03e811d634 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 a3aa0d93a65..0dfdc8b5ac1 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 9e94dbbe4cb..adef723d0cf 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 63f7322326a..cd4ce0cd80c 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; + } + + 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(cur->ws_info->network_name, network_name_ptr, 32); + + 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) { + 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_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 || 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_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; - } - 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); + cfg.operating_class = operating_class; + } + + 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 (!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; } - // 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); + + 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; + } + + 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_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; } - //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; - } - - 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; + 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; + } + + 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; } - 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_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) { - return -2; - } - - if (fhss_bc_dwell_interval && fhss_bc_dwell_interval < 15) { + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { return -2; } - 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_uc_dwell_interval > 0) { + cfg.fhss_uc_dwell_interval = fhss_uc_dwell_interval; } - 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_broadcast_interval > 0) { + cfg.fhss_bc_interval = fhss_broadcast_interval; } - 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 (fhss_bc_dwell_interval > 0) { + cfg.fhss_bc_dwell_interval = fhss_bc_dwell_interval; } - // 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); + if (ws_cfg_fhss_set(cur, NULL, &cfg, 0) < 0) { + return -3; } + 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; + return 0; +} - if (cur->ws_info->fhss_uc_channel_function != channel_function) { - cur->ws_info->fhss_uc_channel_function = channel_function; - updated_config = true; +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; } - 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; + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; } - if (dwell_interval && cur->ws_info->fhss_uc_dwell_interval != dwell_interval) { - cur->ws_info->fhss_uc_dwell_interval = dwell_interval; - updated_config = true; + *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; } - // 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); + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; } - return 0; + 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; + } + + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { + return -2; + } + + if (dwell_interval > 0) { + cfg.fhss_bc_dwell_interval = dwell_interval; + } + if (broadcast_interval > 0) { + cfg.fhss_bc_interval = broadcast_interval; + } + + 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; + } + + 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 != WS_FIXED_CHANNEL && - channel_function != WS_VENDOR_DEF_CF && - channel_function != WS_DH1CF && - channel_function != WS_TR51CF) { + if (!channel_function || !fixed_channel || !dwell_interval) { return -2; } - if (dwell_interval && dwell_interval < 15) { + ws_fhss_cfg_t cfg; + if (ws_cfg_fhss_get(&cfg, NULL) < 0) { return -2; } - if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) { - fixed_channel = 0; - tr_warn("Fixed channel not configured. Set to 0"); + *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; } - bool updated_config = false; + 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; + } - if (cur->ws_info->fhss_bc_channel_function != channel_function) { - cur->ws_info->fhss_bc_channel_function = channel_function; - updated_config = true; + ws_timing_cfg_t cfg; + if (ws_cfg_timing_get(&cfg, NULL) < 0) { + return -2; } - 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 (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 (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 (ws_cfg_timing_set(cur, NULL, &cfg, 0) < 0) { + return -3; } - if (broadcast_interval > 0 && cur->ws_info->fhss_bc_interval != broadcast_interval) { - cur->ws_info->fhss_bc_interval = broadcast_interval; - updated_config = true; + 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; } - // 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); + 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 8eda4fcc63a..7e4e7eedc02 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 01ffea56039..df50aea726f 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 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot 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 04bd157d789..5bf680f4abe 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 f5bc4dba922..cf73b0a9da3 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 eb582539767..9a16b769d1f 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 @@ -90,18 +92,20 @@ 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_init initializes PAE supplicant + * 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_supp_init(protocol_interface_info_entry_t *interface_ptr); +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 authenticator + * ws_pae_controller_init initializes PAE supplicant * * \param interface_ptr interface * @@ -109,10 +113,10 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt * \return >= 0 success * */ -int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_ptr); +int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr); /** - * ws_pae_controller_stop stop PAE controller (e.g. on interface down) + * ws_pae_controller_init initializes PAE authenticator * * \param interface_ptr interface * @@ -120,10 +124,10 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt * \return >= 0 success * */ -int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr); +int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_ptr); /** - * ws_pae_controller_delete delete PAE controller (e.g. failure to create interface) + * ws_pae_controller_stop stop PAE controller (e.g. on interface down) * * \param interface_ptr interface * @@ -131,29 +135,18 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr); * \return >= 0 success * */ -int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr); +int8_t ws_pae_controller_stop(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. + * ws_pae_controller_delete delete PAE controller (e.g. failure to create interface) * - * \param timing Timing value. + * \param interface_ptr interface * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_controller_timing_adjust(uint8_t timing); +int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr); /** * 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 455ba76f64b..4394ee1dc87 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 3ee6f10d0f3..b045fd00fd6 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 db891dc6e4a..a9e955366ea 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 458ed7bf9ea..3bfbc095c5c 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 d73dc70e21c..fd3f02e621e 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 55b80a4d524..ec792996a01 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 09a749b1bb8..f7ea71de086 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; + + 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 ws_pae_controller_key_lifetime_update(interface_id, gtk_lifetime, pmk_lifetime, ptk_lifetime); + 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; + } + + 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 ws_pae_controller_gtk_time_settings_update(interface_id, revocat_lifetime_reduct, new_activation_time, new_install_req, max_mismatch); + 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 ec1bcaa0ff5..dd12919d020 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 f0b3dc59eab..b94b55d52ab 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 c1f12cd0b0b..31d15d3f324 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 5e1c566e20c..941c7403da0 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 05961ccb5b1..e0fbffd724e 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 acc45a67880..28c2e62cfe3 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 5f8273bb6b7..65f6e05f6b9 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 6442290a48e..d7c9aa9ef87 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 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set 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 b091da2a85f..8ea8f3355ce 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 fb251c80009..2cf6a79a70d 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 1b8eda12291..09952b9b108 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 27de7e89cbe..abe65d668bc 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 86648e7f5cc..150d8ea64a0 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 a5b679eb284..67e5884227f 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 6173d0a36a1..2a1b3fbbf97 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 b17dce381e9..d555eb8124b 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 464e5c2a832..613d47eb054 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 6f7a5dbfcb5..34ca3cf6b73 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 a8c66a79b70..b2b8faa5c84 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 f8b25d86f19..5e6b7258d4e 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 13e25c492ca..ac9ca67a1f5 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 aadbc60c28e..56463cb5ee3 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 99377e6150c..7ee3a565208 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 a95802ec4df..345e9ba9fc7 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 411d982bb27..062b36b4ad5 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 2b8a6616d42..6cf5c8f064e 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 6b905d57912..79aca99ee65 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 bc61ab1ac60..e8118585ad5 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 d6ca43c18db..1513f99cb0f 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 bac7ecceb4a..c7c935242d7 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 2b1dded5e88..78ececd7bce 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 02b32b729f2..b43ca5e58f4 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 ee44df03cfe..e5a44e18b8d 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 8369625847b..2cb2284e3c1 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 b4206f69b4f..9c1b47d01df 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 ccd2890ec99..064f2bec760 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 409546c3dc2..daa07af371f 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 49d28f7d1e4..556d769f6bb 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 00000000000..fa2a88dafb9 --- /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 cdcc31de326..c420a5823f0 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 29268529d32..0987054d6bc 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 beff5f5bae7..ad07fd1ca17 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 6f236bcf1f8..de1d86b515c 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 4d10667924a..724351d0295 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 d5272250f83..1d29e70c2af 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 2cf27829c5e..105c8579aa6 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 840c51105d3..3998833c3be 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 \ From 9f2cd03bda68f2be6962b36f4b48f44f7b89978a Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 3 Apr 2020 15:33:08 +0300 Subject: [PATCH 3/4] Update S2LP 802.15.4 RF driver Update driver to version 1.0.2 --- .../source/NanostackRfPhys2lp.cpp | 111 ++++++++---------- .../stm-s2lp-rf-driver/NanostackRfPhys2lp.h | 74 ++++++------ 2 files changed, 85 insertions(+), 100 deletions(-) diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp index b65e1ebdd4a..1ed861eb165 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp @@ -49,16 +49,16 @@ using namespace rtos; #endif #ifdef TEST_GPIOS_ENABLED -#define TEST_TX_STARTED rf->TEST1 = 1; -#define TEST_TX_DONE rf->TEST1 = 0; -#define TEST_RX_STARTED rf->TEST2 = 1; -#define TEST_RX_DONE rf->TEST2 = 0; -#define TEST_ACK_TX_STARTED rf->TEST3 = 1; -#define TEST_ACK_TX_DONE rf->TEST3 = 0; -#define TEST1_ON rf->TEST4 = 1; -#define TEST1_OFF rf->TEST4 = 0; -#define TEST2_ON rf->TEST5 = 1; -#define TEST2_OFF rf->TEST5 = 0; +#define TEST_TX_STARTED test_pins->TEST1 = 1; +#define TEST_TX_DONE test_pins->TEST1 = 0; +#define TEST_RX_STARTED test_pins->TEST2 = 1; +#define TEST_RX_DONE test_pins->TEST2 = 0; +#define TEST_CSMA_STARTED test_pins->TEST3 = 1; +#define TEST_CSMA_DONE test_pins->TEST3 = 0; +#define TEST_SPARE_1_ON test_pins->TEST4 = 1; +#define TEST_SPARE_1_OFF test_pins->TEST4 = 0; +#define TEST_SPARE_2_ON test_pins->TEST5 = 1; +#define TEST_SPARE_2_OFF test_pins->TEST5 = 0; extern void (*fhss_uc_switch)(void); extern void (*fhss_bc_switch)(void); #else //TEST_GPIOS_ENABLED @@ -66,12 +66,12 @@ extern void (*fhss_bc_switch)(void); #define TEST_TX_DONE #define TEST_RX_STARTED #define TEST_RX_DONE -#define TEST_ACK_TX_STARTED -#define TEST_ACK_TX_DONE -#define TEST1_ON -#define TEST1_OFF -#define TEST2_ON -#define TEST2_OFF +#define TEST_CSMA_STARTED +#define TEST_CSMA_DONE +#define TEST_SPARE_1_ON +#define TEST_SPARE_1_OFF +#define TEST_SPARE_2_ON +#define TEST_SPARE_2_OFF #endif //TEST_GPIOS_ENABLED #define MAC_FRAME_TYPE_MASK 0x07 @@ -116,21 +116,11 @@ class RFPins { public: RFPins(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn, -#ifdef TEST_GPIOS_ENABLED - PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, -#endif //TEST_GPIOS_ENABLED PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3); UnlockedSPI spi; DigitalOut CS; DigitalOut SDN; -#ifdef TEST_GPIOS_ENABLED - DigitalOut TEST1; - DigitalOut TEST2; - DigitalOut TEST3; - DigitalOut TEST4; - DigitalOut TEST5; -#endif //TEST_GPIOS_ENABLED InterruptIn RF_S2LP_GPIO0; InterruptIn RF_S2LP_GPIO1; InterruptIn RF_S2LP_GPIO2; @@ -145,21 +135,11 @@ class RFPins { RFPins::RFPins(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn, -#ifdef TEST_GPIOS_ENABLED - PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, -#endif //TEST_GPIOS_ENABLED PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3) : spi(spi_sdi, spi_sdo, spi_sclk), CS(spi_cs), SDN(spi_sdn), -#ifdef TEST_GPIOS_ENABLED - TEST1(spi_test1), - TEST2(spi_test2), - TEST3(spi_test3), - TEST4(spi_test4), - TEST5(spi_test5), -#endif //TEST_GPIOS_ENABLED RF_S2LP_GPIO0(spi_gpio0), RF_S2LP_GPIO1(spi_gpio1), RF_S2LP_GPIO2(spi_gpio2), @@ -169,6 +149,25 @@ RFPins::RFPins(PinName spi_sdi, PinName spi_sdo, irq_thread.start(mbed::callback(this, &RFPins::rf_irq_task)); } +class TestPins_S2LP { +public: + TestPins_S2LP(PinName test_pin_1, PinName test_pin_2, PinName test_pin_3, PinName test_pin_4, PinName test_pin_5); + DigitalOut TEST1; + DigitalOut TEST2; + DigitalOut TEST3; + DigitalOut TEST4; + DigitalOut TEST5; +}; + +TestPins_S2LP::TestPins_S2LP(PinName test_pin_1, PinName test_pin_2, PinName test_pin_3, PinName test_pin_4, PinName test_pin_5) + : TEST1(test_pin_1), + TEST2(test_pin_2), + TEST3(test_pin_3), + TEST4(test_pin_4), + TEST5(test_pin_5) +{ +} + static uint8_t rf_read_register(uint8_t addr); static s2lp_states_e rf_read_state(void); static void rf_write_register(uint8_t addr, uint8_t data); @@ -183,6 +182,7 @@ static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t * static void rf_cca_timer_start(uint32_t slots); static RFPins *rf; +static TestPins_S2LP *test_pins; static phy_device_driver_s device_driver; static int8_t rf_radio_driver_id = -1; static uint8_t *tx_data_ptr; @@ -246,20 +246,20 @@ static void rf_irq_task_process_irq(); #define ACK_SENDING_TIME (uint32_t)(8000000/phy_subghz.datarate)*ACK_FRAME_LENGTH + PACKET_SENDING_EXTRA_TIME #ifdef TEST_GPIOS_ENABLED -void test1_toggle(void) +static void test1_toggle(void) { - if (rf->TEST4) { - rf->TEST4 = 0; + if (test_pins->TEST4) { + test_pins->TEST4 = 0; } else { - rf->TEST4 = 1; + test_pins->TEST4 = 1; } } -void test2_toggle(void) +static void test2_toggle(void) { - if (rf->TEST5) { - rf->TEST5 = 0; + if (test_pins->TEST5) { + test_pins->TEST5 = 0; } else { - rf->TEST5 = 1; + test_pins->TEST5 = 1; } } #endif //TEST_GPIOS_ENABLED @@ -749,19 +749,18 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_ static void rf_tx_sent_handler(void) { + TEST_TX_DONE rf_backup_timer_stop(); rf_disable_interrupt(TX_DATA_SENT); if (rf_state != RF_TX_ACK) { tx_finnish_time = rf_get_timestamp(); rf_update_tx_active_time(); - TEST_TX_DONE rf_state = RF_IDLE; rf_receive(rf_rx_channel); if (device_driver.phy_tx_done_cb) { device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); } } else { - TEST_ACK_TX_DONE rf_receive(rf_rx_channel); } } @@ -807,6 +806,7 @@ static int rf_cca_check(void) static void rf_cca_timer_interrupt(void) { + TEST_CSMA_DONE int8_t status = device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_PREPARE, 0, 0); if (status == PHY_TX_NOT_ALLOWED) { rf_flush_tx_fifo(); @@ -851,12 +851,14 @@ static void rf_cca_timer_interrupt(void) static void rf_cca_timer_stop(void) { + TEST_CSMA_DONE rf->cca_timer.detach(); } static void rf_cca_timer_start(uint32_t slots) { rf->cca_timer.attach_us(rf_cca_timer_signal, slots); + TEST_CSMA_STARTED } static void rf_backup_timer_interrupt(void) @@ -941,7 +943,7 @@ static void rf_send_ack(uint8_t seq) rf_write_packet_length(sizeof(ack_frame) + 4); tx_data_ptr = NULL; rf_start_tx(); - TEST_ACK_TX_STARTED + TEST_TX_STARTED rf_backup_timer_start(ACK_SENDING_TIME); if (device_driver.phy_rf_statistics) { device_driver.phy_rf_statistics->tx_bytes += sizeof(ack_frame); @@ -1278,6 +1280,7 @@ int8_t NanostackRfPhys2lp::rf_register() } rf = _rf; + test_pins = _test_pins; int8_t radio_id = rf_device_register(_mac_addr); if (radio_id < 0) { @@ -1300,9 +1303,6 @@ void NanostackRfPhys2lp::rf_unregister() } NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn -#ifdef TEST_GPIOS_ENABLED - ,PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5 -#endif //TEST_GPIOS_ENABLED ,PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3 #ifdef AT24MAC ,PinName i2c_sda, PinName i2c_scl @@ -1314,16 +1314,12 @@ NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName #endif //AT24MAC _mac_addr(), _rf(NULL), _mac_set(false), _spi_sdi(spi_sdi), _spi_sdo(spi_sdo), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_sdn(spi_sdn), -#ifdef TEST_GPIOS_ENABLED - _spi_test1(spi_test1), _spi_test2(spi_test2), _spi_test3(spi_test3), _spi_test4(spi_test4), _spi_test5(spi_test5), -#endif //TEST_GPIOS_ENABLED _spi_gpio0(spi_gpio0), _spi_gpio1(spi_gpio1), _spi_gpio2(spi_gpio2), _spi_gpio3(spi_gpio3) { - _rf = new RFPins(_spi_sdi, _spi_sdo, _spi_sclk, _spi_cs, _spi_sdn, + _rf = new RFPins(_spi_sdi, _spi_sdo, _spi_sclk, _spi_cs, _spi_sdn, _spi_gpio0, _spi_gpio1, _spi_gpio2, _spi_gpio3); #ifdef TEST_GPIOS_ENABLED - _spi_test1, _spi_test2, _spi_test3, _spi_test4, _spi_test5, + _test_pins = new TestPins_S2LP(TEST_PIN_TX, TEST_PIN_RX, TEST_PIN_CSMA, TEST_PIN_SPARE_1, TEST_PIN_SPARE_2); #endif //TEST_GPIOS_ENABLED - _spi_gpio0, _spi_gpio1, _spi_gpio2, _spi_gpio3); } NanostackRfPhys2lp::~NanostackRfPhys2lp() @@ -1428,9 +1424,6 @@ static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t * NanostackRfPhy &NanostackRfPhy::get_default_instance() { static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN -#ifdef TEST_GPIOS_ENABLED - ,S2LP_SPI_TEST1, S2LP_SPI_TEST2, S2LP_SPI_TEST3, S2LP_SPI_TEST4, S2LP_SPI_TEST5 -#endif //TEST_GPIOS_ENABLED ,S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3 #ifdef AT24MAC ,S2LP_I2C_SDA, S2LP_I2C_SCL diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h b/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h index 66e07011745..2b9038a84e9 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h @@ -26,98 +26,96 @@ #include "SPI.h" // Uncomment to use testing gpios attached to TX/RX processes -//#define TEST_GPIOS_ENABLED +// #define TEST_GPIOS_ENABLED #if defined(TARGET_MTB_STM_S2LP) #if !defined(S2LP_SPI_SDI) -#define S2LP_SPI_SDI PA_7 +#define S2LP_SPI_SDI PA_7 #endif #if !defined(S2LP_SPI_SDO) -#define S2LP_SPI_SDO PA_6 +#define S2LP_SPI_SDO PA_6 #endif #if !defined(S2LP_SPI_SCLK) -#define S2LP_SPI_SCLK PA_5 +#define S2LP_SPI_SCLK PA_5 #endif #if !defined(S2LP_SPI_CS) -#define S2LP_SPI_CS PC_0 +#define S2LP_SPI_CS PC_0 #endif #if !defined(S2LP_SPI_SDN) -#define S2LP_SPI_SDN PF_13 +#define S2LP_SPI_SDN PF_13 #endif #if !defined(S2LP_SPI_GPIO0) -#define S2LP_SPI_GPIO0 PA_3 +#define S2LP_SPI_GPIO0 PA_3 #endif #if !defined(S2LP_SPI_GPIO1) -#define S2LP_SPI_GPIO1 PC_3 +#define S2LP_SPI_GPIO1 PC_3 #endif #if !defined(S2LP_SPI_GPIO2) -#define S2LP_SPI_GPIO2 PF_3 +#define S2LP_SPI_GPIO2 PF_3 #endif #if !defined(S2LP_SPI_GPIO3) -#define S2LP_SPI_GPIO3 PF_10 +#define S2LP_SPI_GPIO3 PF_10 #endif #if !defined(S2LP_I2C_SDA) -#define S2LP_I2C_SDA PB_7 +#define S2LP_I2C_SDA PB_7 #endif #if !defined(S2LP_I2C_SCL) -#define S2LP_I2C_SCL PB_6 +#define S2LP_I2C_SCL PB_6 #endif #define AT24MAC #else #if !defined(S2LP_SPI_SDI) -#define S2LP_SPI_SDI D11 +#define S2LP_SPI_SDI D11 #endif #if !defined(S2LP_SPI_SDO) -#define S2LP_SPI_SDO D12 +#define S2LP_SPI_SDO D12 #endif #if !defined(S2LP_SPI_SCLK) -#define S2LP_SPI_SCLK D13 +#define S2LP_SPI_SCLK D13 #endif #if !defined(S2LP_SPI_CS) -#define S2LP_SPI_CS A1 +#define S2LP_SPI_CS A1 #endif #if !defined(S2LP_SPI_SDN) -#define S2LP_SPI_SDN D7 +#define S2LP_SPI_SDN D7 #endif -#if !defined(S2LP_SPI_TEST1) -#define S2LP_SPI_TEST1 D6 +#if !defined(TEST_PIN_TX) +#define TEST_PIN_TX D6 #endif -#if !defined(S2LP_SPI_TEST2) -#define S2LP_SPI_TEST2 D5 +#if !defined(TEST_PIN_RX) +#define TEST_PIN_RX D5 #endif -#if !defined(S2LP_SPI_TEST3) -#define S2LP_SPI_TEST3 D4 +#if !defined(TEST_PIN_CSMA) +#define TEST_PIN_CSMA D4 #endif -#if !defined(S2LP_SPI_TEST4) -#define S2LP_SPI_TEST4 D2 +#if !defined(TEST_PIN_SPARE_1) +#define TEST_PIN_SPARE_1 D2 #endif -#if !defined(S2LP_SPI_TEST5) -#define S2LP_SPI_TEST5 D8 +#if !defined(TEST_PIN_SPARE_2) +#define TEST_PIN_SPARE_2 D8 #endif #if !defined(S2LP_SPI_GPIO0) -#define S2LP_SPI_GPIO0 A0 +#define S2LP_SPI_GPIO0 A0 #endif #if !defined(S2LP_SPI_GPIO1) -#define S2LP_SPI_GPIO1 A2 +#define S2LP_SPI_GPIO1 A2 #endif #if !defined(S2LP_SPI_GPIO2) -#define S2LP_SPI_GPIO2 A3 +#define S2LP_SPI_GPIO2 A3 #endif #if !defined(S2LP_SPI_GPIO3) -#define S2LP_SPI_GPIO3 A5 +#define S2LP_SPI_GPIO3 A5 #endif #endif #include "at24mac_s2lp.h" class RFPins; +class TestPins_S2LP; class NanostackRfPhys2lp : public NanostackRfPhy { public: NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn -#ifdef TEST_GPIOS_ENABLED - ,PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5 -#endif //TEST_GPIOS_ENABLED ,PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3 #ifdef AT24MAC ,PinName i2c_sda, PinName i2c_scl @@ -135,6 +133,7 @@ class NanostackRfPhys2lp : public NanostackRfPhy { #endif //AT24MAC uint8_t _mac_addr[8]; RFPins *_rf; + TestPins_S2LP *_test_pins; bool _mac_set; const PinName _spi_sdi; @@ -142,13 +141,6 @@ class NanostackRfPhys2lp : public NanostackRfPhy { const PinName _spi_sclk; const PinName _spi_cs; const PinName _spi_sdn; -#ifdef TEST_GPIOS_ENABLED - const PinName _spi_test1; - const PinName _spi_test2; - const PinName _spi_test3; - const PinName _spi_test4; - const PinName _spi_test5; -#endif //TEST_GPIOS_ENABLED const PinName _spi_gpio0; const PinName _spi_gpio1; const PinName _spi_gpio2; From cc13a5b571aec9eb77fbfb7712fd96cf81b378f8 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 3 Apr 2020 15:23:11 +0300 Subject: [PATCH 4/4] Update Atmel 802.15.4 RF driver Update to version v3.1.0. --- .../atmel-rf-driver/NanostackRfPhyAtmel.h | 46 + .../atmel-rf-driver/source/AT86RF215Reg.h | 262 ++++ .../atmel-rf-driver/source/AT86RFReg.h | 1 + .../source/NanostackRfPhyAT86RF215.cpp | 1103 +++++++++++++++++ .../source/NanostackRfPhyAtmel.cpp | 87 +- .../atmel-rf-driver/source/rfbits.h | 73 ++ 6 files changed, 1536 insertions(+), 36 deletions(-) create mode 100644 components/802.15.4_RF/atmel-rf-driver/source/AT86RF215Reg.h create mode 100644 components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAT86RF215.cpp create mode 100644 components/802.15.4_RF/atmel-rf-driver/source/rfbits.h diff --git a/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h b/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h index a5e6baa70eb..028663f63eb 100644 --- a/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h +++ b/components/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h @@ -24,6 +24,9 @@ #include "NanostackRfPhy.h" +// Uncomment to use testing gpios attached to TX/RX processes +// #define TEST_GPIOS_ENABLED + // Arduino pin defaults for convenience #if !defined(ATMEL_SPI_MOSI) #define ATMEL_SPI_MOSI D11 @@ -52,8 +55,24 @@ #if !defined(ATMEL_I2C_SCL) #define ATMEL_I2C_SCL D15 #endif +#if !defined(TEST_PIN_TX) +#define TEST_PIN_TX D6 +#endif +#if !defined(TEST_PIN_RX) +#define TEST_PIN_RX D3 +#endif +#if !defined(TEST_PIN_CSMA) +#define TEST_PIN_CSMA D4 +#endif +#if !defined(TEST_PIN_SPARE_1) +#define TEST_PIN_SPARE_1 D2 +#endif +#if !defined(TEST_PIN_SPARE_2) +#define TEST_PIN_SPARE_2 D8 +#endif class RFBits; +class TestPins; class NanostackRfPhyAtmel : public NanostackRfPhy { public: @@ -70,6 +89,7 @@ class NanostackRfPhyAtmel : public NanostackRfPhy { AT24Mac _mac; uint8_t _mac_addr[8]; RFBits *_rf; + TestPins *_test_pins; bool _mac_set; const PinName _spi_mosi; @@ -81,5 +101,31 @@ class NanostackRfPhyAtmel : public NanostackRfPhy { const PinName _spi_irq; }; +#ifdef TEST_GPIOS_ENABLED +#define TEST_TX_STARTED test_pins->TEST1 = 1; +#define TEST_TX_DONE test_pins->TEST1 = 0; +#define TEST_RX_STARTED test_pins->TEST2 = 1; +#define TEST_RX_DONE test_pins->TEST2 = 0; +#define TEST_CSMA_STARTED test_pins->TEST3 = 1; +#define TEST_CSMA_DONE test_pins->TEST3 = 0; +#define TEST_SPARE_1_ON test_pins->TEST4 = 1; +#define TEST_SPARE_1_OFF test_pins->TEST4 = 0; +#define TEST_SPARE_2_ON test_pins->TEST5 = 1; +#define TEST_SPARE_2_OFF test_pins->TEST5 = 0; +extern void (*fhss_uc_switch)(void); +extern void (*fhss_bc_switch)(void); +#else +#define TEST_TX_STARTED +#define TEST_TX_DONE +#define TEST_RX_STARTED +#define TEST_RX_DONE +#define TEST_CSMA_STARTED +#define TEST_CSMA_DONE +#define TEST_SPARE_1_ON +#define TEST_SPARE_1_OFF +#define TEST_SPARE_2_ON +#define TEST_SPARE_2_OFF +#endif //TEST_GPIOS_ENABLED + #endif /* MBED_CONF_NANOSTACK_CONFIGURATION */ #endif /* NANOSTACK_RF_PHY_ATMEL_H_ */ diff --git a/components/802.15.4_RF/atmel-rf-driver/source/AT86RF215Reg.h b/components/802.15.4_RF/atmel-rf-driver/source/AT86RF215Reg.h new file mode 100644 index 00000000000..5463570f142 --- /dev/null +++ b/components/802.15.4_RF/atmel-rf-driver/source/AT86RF215Reg.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * 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 AT86RF215REG_H_ +#define AT86RF215REG_H_ +#ifdef __cplusplus +extern "C" { +#endif + + +/*Register addresses*/ +#define RF09_IRQS 0x00 +#define RF24_IRQS 0x01 +#define BBC0_IRQS 0x02 +#define BBC1_IRQS 0x03 +#define RF_CFG 0x06 +#define RF_IQIFC1 0x0B +#define RF_PN 0x0D +#define RF_VN 0x0E +#define RF_IRQM 0x00 +#define RF_STATE 0x02 +#define RF_CMD 0x03 +#define RF_CS 0x04 +#define RF_CCF0L 0x05 +#define RF_CCF0H 0x06 +#define RF_CNL 0x07 +#define RF_CNM 0x08 +#define RF_RXBWC 0x09 +#define RF_RXDFE 0x0A +#define RF_AGCC 0x0B +#define RF_AGCS 0x0C +#define RF_RSSI 0x0D +#define RF_EDC 0x0E +#define RF_EDV 0x10 +#define RF_TXCUTC 0x12 +#define RF_TXDFE 0x13 +#define BBC_IRQM 0x00 +#define BBC_PC 0x01 +#define BBC_RXFLL 0x04 +#define BBC_RXFLH 0x05 +#define BBC_TXFLL 0x06 +#define BBC_TXFLH 0x07 +#define BBC_FBLL 0x08 +#define BBC_FBLH 0x09 +#define BBC_OQPSKC0 0x10 +#define BBC_OQPSKC1 0x11 +#define BBC_OQPSKC2 0x12 +#define BBC_OQPSKC3 0x13 +#define BBC_OQPSKPHRTX 0x14 +#define BBC_OQPSKPHRRX 0x15 +#define BBC_AFC0 0x20 +#define BBC_AFFTM 0x22 +#define BBC_MACEA0 0x25 +#define BBC_MACPID0F0 0x2D +#define BBC_MACSHA0F0 0x2F +#define BBC_AMCS 0x40 +#define BBC_AMEDT 0x41 +#define BBC_AMAACKTL 0x43 +#define BBC_AMAACKTH 0x44 +#define BBC_FSKC0 0x60 +#define BBC_FSKC1 0x61 +#define BBC_FSKC2 0x62 +#define BBC_FSKC3 0x63 +#define BBC_FSKPLL 0x65 +#define BBC_FSKPHRTX 0x6A +#define BBC_FSKPHRRX 0x6B +#define BBC0_FBRXS 0x2000 +#define BBC0_FBTXS 0x2800 +#define BBC1_FBRXS 0x3000 +#define BBC1_FBTXS 0x3800 + +// RF_AGCC +#define AGCI (1 << 6) +#define AVGS 0x30 +#define AVGS_8_SAMPLES (0 << 4) + +// RF_AGCS +#define TGT 0xE0 +#define TGT_1 (1 << 5) + + +// RF_RXBWC +#define BW 0x0F +#define RF_BW2000KHZ_IF2000KHZ (11 << 0) +#define RF_BW1600KHZ_IF2000KHZ (10 << 0) +#define RF_BW1250KHZ_IF2000KHZ (9 << 0) +#define RF_BW1000KHZ_IF1000KHZ (8 << 0) +#define RF_BW800KHZ_IF1000KHZ (7 << 0) +#define RF_BW630KHZ_IF1000KHZ (6 << 0) +#define RF_BW500KHZ_IF500KHZ (5 << 0) +#define RF_BW400KHZ_IF500KHZ (4 << 0) +#define RF_BW320KHZ_IF500KHZ (3 << 0) +#define RF_BW250KHZ_IF250KHZ (2 << 0) +#define RF_BW200KHZ_IF250KHZ (1 << 0) +#define RF_BW160KHZ_IF250KHZ (0 << 0) +#define IFS (1 << 4) + +// RF_TXCUTC +#define PARAMP 0xC0 +#define RF_PARAMP32U (3 << 6) +#define RF_PARAMP16U (2 << 6) +#define RF_PARAMP8U (1 << 6) +#define RF_PARAMP4U (0 << 6) +#define LPFCUT 0x0F +#define RF_FLC80KHZ (0 << 0) +#define RF_FLC100KHZ (1 << 0) +#define RF_FLC125KHZ (2 << 0) +#define RF_FLC160KHZ (3 << 0) +#define RF_FLC200KHZ (4 << 0) +#define RF_FLC250KHZ (5 << 0) +#define RF_FLC315KHZ (6 << 0) +#define RF_FLC400KHZ (7 << 0) +#define RF_FLC500KHZ (8 << 0) +#define RF_FLC625KHZ (9 << 0) +#define RF_FLC800KHZ (10 << 0) +#define RF_FLC1000KHZ (11 << 0) + +// RF_TXDFE, RF_RXDFE +#define RCUT 0xE0 +#define RCUT_4 (4 << 5) +#define RCUT_2 (2 << 5) +#define RCUT_1 (1 << 5) +#define RCUT_0 (0 << 5) +#define SR 0x0F +#define SR_10 (10 << 0) +#define SR_8 (8 << 0) +#define SR_6 (6 << 0) +#define SR_5 (5 << 0) +#define SR_4 (4 << 0) +#define SR_3 (3 << 0) +#define SR_2 (2 << 0) +#define SR_1 (1 << 0) + +// BBC_FSKC0 +#define BT 0xC0 +#define BT_20 (3 << 6) +#define BT_10 (1 << 6) +#define MIDXS 0x30 +#define MIDXS_0 (0 << 4) +#define MIDX 0x0E +#define MIDX_10 (3 << 1) +#define MIDX_075 (2 << 1) +#define MIDX_05 (1 << 1) +#define MIDX_0375 (0 << 1) + +// BBC_FSKC1 +#define SRATE 0x0F +#define SRATE_400KHZ (5 << 0) +#define SRATE_300KHZ (4 << 0) +#define SRATE_200KHZ (3 << 0) +#define SRATE_150KHZ (2 << 0) +#define SRATE_100KHZ (1 << 0) +#define SRATE_50KHZ (0 << 0) + +// BBC_FSKC2 +#define RXO 0x60 +#define RXO_DIS (0 << 5) +#define FECIE (1 << 0) + +// BBC_FSKC3 +#define SFDT 0xF0 +#define PDT 0x0F +#define PDT_6 (6 << 0) + +// BBC_AFFTM +#define TYPE_2 (1 << 2) + +// BBC_AFC0 +#define PM (1 << 4) +#define AFEN3 (1 << 3) +#define AFEN2 (1 << 2) +#define AFEN1 (1 << 1) +#define AFEN0 (1 << 0) + +// BBC_OQPSKPHRTX +#define LEG (1 << 0) + +// BBC_OQPSKC0 +#define FCHIP 0x03 +#define BB_FCHIP100 (0 << 0) +#define BB_FCHIP200 (1 << 0) +#define BB_FCHIP1000 (2 << 0) +#define BB_FCHIP2000 (3 << 0) + +// BBC_OQPSKC2 +#define FCSTLEG 0x04 +#define RXM 0x03 +#define FCS_16 (1 << 2) +#define RXM_2 (2 << 0) + +// BBC_IRQS, BBC_IRQM +#define FBLI (1 << 7) +#define AGCR (1 << 6) +#define AGCH (1 << 5) +#define TXFE (1 << 4) +#define RXEM (1 << 3) +#define RXAM (1 << 2) +#define RXFE (1 << 1) +#define RXFS (1 << 0) + +//BBC_PC +#define BBEN (1 << 2) +#define PT 0x03 +#define BB_PHYOFF (0 << 0) +#define BB_MRFSK (1 << 0) +#define BB_MROFDM (2 << 0) +#define BB_MROQPSK (3 << 0) +#define FCSOK (1 << 5) +#define TXAFCS (1 << 4) +#define FCST (1 << 3) +#define FCSFE (1 << 6) + +//BBC_AMCS +#define AACKFT (1 << 7) +#define AACK (1 << 3) +#define CCAED (1 << 2) + +// RF_IQIFC1 +#define CHPM 0x70 +#define RF_MODE_BBRF (0 << 4) +#define RF_MODE_RF (1 << 4) +#define RF_MODE_BBRF09 (4 << 4) +#define RF_MODE_BBRF24 (5 << 4) + +/*RF_CFG bits*/ +#define IRQMM 0x08 +#define IRQP 0x04 + +/*RFn_IRQM bits*/ +#define TRXRDY (1 << 1) +#define EDC (1 << 2) + +/*RFn_EDC bits*/ +#define EDM 0x03 +#define RF_EDAUTO (0 << 0) +#define RF_EDSINGLE (1 << 0) +#define RF_EDCONT (2 << 0) +#define RF_EDOFF (3 << 0) + +/*Masks*/ +#define CNH 0x01 +#define EDM 0x03 +#define CHPM 0x70 + +#ifdef __cplusplus +} +#endif + +#endif /* AT86RF215REG_H_ */ diff --git a/components/802.15.4_RF/atmel-rf-driver/source/AT86RFReg.h b/components/802.15.4_RF/atmel-rf-driver/source/AT86RFReg.h index a1b9c24870b..c53d9fe9224 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/AT86RFReg.h +++ b/components/802.15.4_RF/atmel-rf-driver/source/AT86RFReg.h @@ -47,6 +47,7 @@ extern "C" { #define PART_AT86RF231 0x03 #define PART_AT86RF212 0x07 #define PART_AT86RF233 0x0B +#define PART_AT86RF215 0x34 #define VERSION_AT86RF212 0x01 #define VERSION_AT86RF212B 0x03 diff --git a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAT86RF215.cpp b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAT86RF215.cpp new file mode 100644 index 00000000000..09c31800109 --- /dev/null +++ b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAT86RF215.cpp @@ -0,0 +1,1103 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * 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 + +#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_INTERRUPTIN && defined(MBED_CONF_RTOS_PRESENT) + +#include "ns_types.h" +#include "platform/arm_hal_interrupt.h" +#include "platform/mbed_wait_api.h" +#include "nanostack/platform/arm_hal_phy.h" +#include "NanostackRfPhyAtmel.h" +#include "AT86RF215Reg.h" +#include "mbed_trace.h" +#include "common_functions.h" +#include +#include "Timeout.h" +#include "SPI.h" + +#define TRACE_GROUP "AtRF" + +#define RF_MTU_15_4_2011 127 +#define RF_MTU_15_4G_2012 2047 + +namespace { + +typedef enum { + RF_NOP = 0x00, + RF_SLEEP = 0x01, + RF_TRX_OFF = 0x02, + RF_TXPREP = 0x03, + RF_TX = 0x04, + RF_RX = 0x05, + RF_TRANSITION = 0x06, + RF_RESET = 0x07 +} rf_command_e; + +typedef enum { + COMMON = 0x00, + RF_09 = 0x01, + RF_24 = 0x02, + BBC0 = 0x03, + BBC1 = 0x04 +} rf_modules_e; + +typedef enum { + RF_IDLE, + RF_CSMA_STARTED, + RF_CSMA_WHILE_RX, + RF_TX_STARTED, + RF_RX_STARTED +} rf_states_e; + +} // anonymous namespace + +static void rf_init(void); +static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr); +static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr); +static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel); +static int8_t rf_start_csma_ca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol); +static void rf_init_registers(rf_modules_e module); +static void rf_spi_exchange(const void *tx, size_t tx_len, void *rx, size_t rx_len); +static uint8_t rf_read_rf_register(uint8_t addr, rf_modules_e module); +static void rf_write_rf_register(uint8_t addr, rf_modules_e module, uint8_t data); +static void rf_write_rf_register_field(uint8_t addr, rf_modules_e module, uint8_t field, uint8_t value); +static void rf_write_tx_packet_length(uint16_t packet_length, rf_modules_e module); +static uint16_t rf_read_rx_frame_length(rf_modules_e module); +static void rf_write_tx_buffer(uint8_t *data, uint16_t len, rf_modules_e module); +static int rf_read_rx_buffer(uint16_t length, rf_modules_e module); +static void rf_irq_rf_enable(uint8_t irq, rf_modules_e module); +static void rf_irq_rf_disable(uint8_t irq, rf_modules_e module); +static void rf_irq_bbc_enable(uint8_t irq, rf_modules_e module); +static void rf_irq_bbc_disable(uint8_t irq, rf_modules_e module); +static rf_command_e rf_read_state(rf_modules_e module); +static void rf_poll_state_change(rf_command_e state, rf_modules_e module); +static void rf_change_state(rf_command_e state, rf_modules_e module); +static void rf_receive(uint16_t rx_channel, rf_modules_e module); +static void rf_interrupt_handler(void); +static void rf_irq_task_process_irq(void); +static void rf_handle_cca_ed_done(void); +static void rf_start_tx(void); +static void rf_backup_timer_interrupt(void); +static void rf_backup_timer_stop(void); +static uint32_t rf_backup_timer_start(uint16_t bytes, uint32_t time_us); +static int rf_set_channel(uint16_t channel, rf_modules_e module); +static int rf_set_ch0_frequency(uint32_t frequency, rf_modules_e module); +static int rf_set_channel_spacing(uint32_t channel_spacing, rf_modules_e module); +static int rf_set_fsk_symbol_rate_configuration(uint32_t symbol_rate, rf_modules_e module); +static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation); +static void rf_conf_set_cca_threshold(uint8_t percent); +// Defined register read/write functions +#define rf_read_bbc_register(x, y) rf_read_rf_register(x, (rf_modules_e)(y + 2)) +#define rf_read_common_register(x) rf_read_rf_register(x, COMMON) +#define rf_write_bbc_register(x, y, z) rf_write_rf_register(x, (rf_modules_e)(y + 2), z) +#define rf_write_common_register(x, z) rf_write_rf_register(x, COMMON, z) +#define rf_write_bbc_register_field(v, x, y, z) rf_write_rf_register_field(v, (rf_modules_e)(x + 2), y, z) +#define rf_write_common_register_field(v, y, z) rf_write_rf_register_field(v, COMMON, y, z) + +static int8_t rf_radio_driver_id = -1; +static phy_device_driver_s device_driver; +static uint8_t rf_version_num = 0; +static rf_modules_e rf_module = RF_24; +static phy_802_15_4_mode_t mac_mode = IEEE_802_15_4_2011; +static uint8_t mac_tx_handle = 0; +static rf_states_e rf_state = RF_IDLE; +static bool receiver_enabled = false; +static int8_t cca_prepare_status = PHY_TX_NOT_ALLOWED; +static uint8_t rx_buffer[RF_MTU_15_4G_2012]; +static uint8_t rf_rx_channel; +static uint16_t tx_sequence = 0xffff; +static uint16_t cur_tx_packet_len = 0xffff; +static uint16_t cur_rx_packet_len = 0xffff; +static uint32_t cur_rx_stop_time = 0; +static uint32_t tx_time = 0; +static uint32_t rx_time = 0; +static uint8_t rf09_irq_mask = 0; +static uint8_t rf24_irq_mask = 0; +static uint8_t bbc0_irq_mask = 0; +static uint8_t bbc1_irq_mask = 0; + +static bool rf_update_config = false; +static int8_t cca_threshold = -80; +static bool cca_enabled = true; +static uint32_t rf_symbol_rate; + +/* Channel configurations for 2.4 and sub-GHz */ +static const phy_rf_channel_configuration_s phy_24ghz = {.channel_0_center_frequency = 2350000000U, + .channel_spacing = 5000000U, + .datarate = 250000U, + .number_of_channels = 16U, + .modulation = M_OQPSK + }; +static const phy_rf_channel_configuration_s phy_subghz = {.channel_0_center_frequency = 868300000U, + .channel_spacing = 2000000U, + .datarate = 250000U, + .number_of_channels = 11U, + .modulation = M_OQPSK + }; + +static phy_rf_channel_configuration_s phy_current_config; + +static const phy_device_channel_page_s phy_channel_pages[] = { + { CHANNEL_PAGE_0, &phy_24ghz}, + { CHANNEL_PAGE_2, &phy_subghz}, + { CHANNEL_PAGE_0, NULL} +}; + +using namespace mbed; +using namespace rtos; + +#include "rfbits.h" +static RFBits *rf; +static TestPins *test_pins; + +#define MAC_FRAME_TYPE_MASK 0x07 +#define MAC_TYPE_ACK (2) +#define MAC_DATA_PENDING 0x10 +#define FC_AR 0x20 +#define VERSION_FIELD_MASK 0x30 +#define SHIFT_VERSION_FIELD (4) + +#define SIG_RADIO 1 +#define SIG_TIMER_BACKUP 2 +#define SIG_TIMER_CCA 4 +#define SIG_TIMERS (SIG_TIMER_BACKUP|SIG_TIMER_CCA) +#define SIG_ALL (SIG_RADIO|SIG_TIMERS) + +#define ACK_FRAME_LENGTH 3 +#define PACKET_PROCESSING_TIME 5000 +#define MAX_STATE_TRANSITION_TIME_US 1000 +#define CCA_BACKUP_TIMEOUT 1000 +#define MAX_TRANSMISSION_TIME 1000000 + +#define MIN_CCA_THRESHOLD -117 +#define MAX_CCA_THRESHOLD -5 + +static uint32_t rf_get_timestamp(void) +{ + return (uint32_t)rf->tx_timer.read_us(); +} + +static void rf_lock(void) +{ + platform_enter_critical(); +} + +static void rf_unlock(void) +{ + platform_exit_critical(); +} + +static int8_t rf_device_register(const uint8_t *mac_addr) +{ + rf_init(); + device_driver.PHY_MAC = (uint8_t *)mac_addr; + device_driver.driver_description = (char *)"ATMEL_MAC"; + device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE; + device_driver.phy_channel_pages = phy_channel_pages; + device_driver.phy_MTU = RF_MTU_15_4G_2012; + device_driver.phy_header_length = 0; + device_driver.phy_tail_length = 0; + device_driver.address_write = &rf_address_write; + device_driver.extension = &rf_extension; + device_driver.state_control = &rf_interface_state_control; + device_driver.tx = &rf_start_csma_ca; + device_driver.phy_rx_cb = NULL; + device_driver.phy_tx_done_cb = NULL; + rf_radio_driver_id = arm_net_phy_register(&device_driver); + rf_update_config = true; + return rf_radio_driver_id; +} + +static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) +{ + uint8_t rf_address = 0, addr_size = 0; + switch (address_type) { + case PHY_MAC_48BIT: + break; + case PHY_MAC_64BIT: + rf_address = BBC_MACEA0; + addr_size = 8; + break; + case PHY_MAC_16BIT: + rf_address = BBC_MACSHA0F0; + addr_size = 2; + break; + case PHY_MAC_PANID: + rf_address = BBC_MACPID0F0; + addr_size = 2; + break; + } + for (uint8_t i = 0; i < addr_size; i++) { + rf_write_bbc_register(rf_address++, rf_module, address_ptr[(addr_size - 1) - i]); + } + return 0; +} + +static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr) +{ + phy_csma_params_t *csma_params; + uint32_t *timer_value; + switch (extension_type) { + case PHY_EXTENSION_SET_CHANNEL: + if (rf_state == RF_IDLE || (rf_state == RF_CSMA_STARTED && !(rf_read_rf_register(RF_EDC, rf_module) & RF_EDSINGLE))) { + rf_receive(*data_ptr, rf_module); + } else { + return -1; + } + break; + case PHY_EXTENSION_READ_RX_TIME: + common_write_32_bit(rx_time, data_ptr); + break; + case PHY_EXTENSION_GET_TIMESTAMP: + timer_value = (uint32_t *)data_ptr; + *timer_value = rf_get_timestamp(); + break; + case PHY_EXTENSION_SET_CSMA_PARAMETERS: + csma_params = (phy_csma_params_t *)data_ptr; + if (csma_params->backoff_time == 0) { + TEST_CSMA_DONE + rf->cca_timer.detach(); + if (rf_state == RF_TX_STARTED) { + rf_state = RF_IDLE; + rf_receive(rf_rx_channel, rf_module); + } + tx_time = 0; + } else { + tx_time = csma_params->backoff_time; + cca_enabled = csma_params->cca_enabled; + } + break; + case PHY_EXTENSION_GET_SYMBOLS_PER_SECOND: + timer_value = (uint32_t *)data_ptr; + *timer_value = rf_symbol_rate; + break; + case PHY_EXTENSION_DYNAMIC_RF_SUPPORTED: + *data_ptr = true; + break; + case PHY_EXTENSION_SET_RF_CONFIGURATION: + memcpy(&phy_current_config, data_ptr, sizeof(phy_rf_channel_configuration_s)); + rf_calculate_symbol_rate(phy_current_config.datarate, phy_current_config.modulation); + rf_update_config = true; + if (rf_state == RF_IDLE) { + rf_receive(rf_rx_channel, rf_module); + } + break; + case PHY_EXTENSION_SET_CCA_THRESHOLD: + rf_conf_set_cca_threshold(*data_ptr); + break; + case PHY_EXTENSION_SET_802_15_4_MODE: + mac_mode = (phy_802_15_4_mode_t) *data_ptr; // *NOPAD* + if (mac_mode == IEEE_802_15_4_2011) { + rf_module = RF_24; + } else if (mac_mode == IEEE_802_15_4G_2012) { + rf_module = RF_09; + } + break; + default: + break; + } + return 0; +} + +static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel) +{ + int8_t ret_val = 0; + switch (new_state) { + case PHY_INTERFACE_RESET: + break; + case PHY_INTERFACE_DOWN: + break; + case PHY_INTERFACE_UP: + rf_receive(rf_channel, rf_module); + break; + case PHY_INTERFACE_RX_ENERGY_STATE: + break; + case PHY_INTERFACE_SNIFFER_STATE: + break; + } + return ret_val; +} + +#ifdef TEST_GPIOS_ENABLED +static void test1_toggle(void) +{ + if (test_pins->TEST4) { + test_pins->TEST4 = 0; + } else { + test_pins->TEST4 = 1; + } +} +static void test2_toggle(void) +{ + if (test_pins->TEST5) { + test_pins->TEST5 = 0; + } else { + test_pins->TEST5 = 1; + } +} +#endif //TEST_GPIOS_ENABLED + +static void rf_init(void) +{ +#ifdef TEST_GPIOS_ENABLED + fhss_bc_switch = test1_toggle; + fhss_uc_switch = test2_toggle; +#endif //TEST_GPIOS_ENABLED + rf_lock(); + // Disable interrupts + rf_write_rf_register(RF_IRQM, RF_09, 0); + rf_write_rf_register(RF_IRQM, RF_24, 0); + // Ensure basebands enabled, I/Q IF's disabled + rf_write_rf_register_field(RF_IQIFC1, COMMON, CHPM, RF_MODE_BBRF); + rf_change_state(RF_TRX_OFF, RF_09); + rf_change_state(RF_TRX_OFF, RF_24); + memcpy(&phy_current_config, &phy_24ghz, sizeof(phy_rf_channel_configuration_s)); + rf_calculate_symbol_rate(phy_current_config.datarate, phy_current_config.modulation); + rf_init_registers(RF_24); + rf->IRQ.rise(&rf_interrupt_handler); + rf->IRQ.enable_irq(); + rf->tx_timer.start(); + rf_unlock(); +} + +static void rf_init_registers(rf_modules_e module) +{ + // O-QPSK configuration using IEEE Std 802.15.4-2011 + // FSK configuration using IEEE Std 802.15.4g-2012 + if (mac_mode == IEEE_802_15_4_2011) { + device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE; + // 16-bit FCS + rf_write_bbc_register_field(BBC_PC, module, FCST, FCST); + // Enable O-QPSK + rf_write_bbc_register_field(BBC_PC, module, PT, BB_MROQPSK); + // Chip frequency 2000kchip/s + rf_write_bbc_register_field(BBC_OQPSKC0, module, FCHIP, BB_FCHIP2000); + // FCS type legacy O-QPSK is 16-bit + rf_write_bbc_register_field(BBC_OQPSKC2, module, FCSTLEG, FCS_16); + // Listen for both MR-O-QPSK and legacy O-QPSK PHY + rf_write_bbc_register_field(BBC_OQPSKC2, module, RXM, RXM_2); + // PHY type Legacy O-QPSK + rf_write_bbc_register_field(BBC_OQPSKPHRTX, module, LEG, LEG); + // Low pass filter cut-off frequency to 1000 kHz + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC1000KHZ); + // Set TX filter to sample frequency / 2 + rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_4); + // Enable auto ack + rf_write_bbc_register_field(BBC_AMCS, module, AACK, AACK); + // Enable address filter unit 0 + rf_write_bbc_register_field(BBC_AFC0, module, AFEN0, AFEN0); + // Allow Ack frame type with address filter + rf_write_bbc_register_field(BBC_AFFTM, module, TYPE_2, TYPE_2); + } else if (mac_mode == IEEE_802_15_4G_2012) { + device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE; + // Enable FSK + rf_write_bbc_register_field(BBC_PC, module, PT, BB_MRFSK); + // Disable auto ack + rf_write_bbc_register_field(BBC_AMCS, module, AACK, 0); + // Disable address filter unit 0 + rf_write_bbc_register_field(BBC_AFC0, module, AFEN0, 0); + // Set bandwidth time product + rf_write_bbc_register_field(BBC_FSKC0, module, BT, BT_20); + // Disable interleaving + rf_write_bbc_register_field(BBC_FSKC2, module, FECIE, 0); + // Disable receiver override + rf_write_bbc_register_field(BBC_FSKC2, module, RXO, RXO_DIS); + // Set modulation index + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_bbc_register_field(BBC_FSKC0, module, MIDX, MIDX_05); + rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_0); + } else { + rf_write_bbc_register_field(BBC_FSKC0, module, MIDX, MIDX_10); + rf_write_rf_register_field(RF_TXDFE, module, RCUT, RCUT_4); + } + // Set Gain control settings + rf_write_rf_register_field(RF_AGCC, module, AVGS, AVGS_8_SAMPLES); + rf_write_rf_register_field(RF_AGCS, module, TGT, TGT_1); + // Set symbol rate and related configurations + rf_set_fsk_symbol_rate_configuration(phy_current_config.datarate, module); + // Set preamble length + uint8_t preamble_len = 24; + if (phy_current_config.datarate < 150000) { + preamble_len = 8; + } else if (phy_current_config.datarate < 300000) { + preamble_len = 12; + } + rf_write_bbc_register(BBC_FSKPLL, module, preamble_len); + rf_write_bbc_register_field(BBC_FSKC3, module, PDT, PDT_6); + } + // Disable filtering FCS + rf_write_bbc_register_field(BBC_PC, module, FCSFE, 0); + // Set channel spacing + rf_set_channel_spacing(phy_current_config.channel_spacing, module); + // Set channel 0 center frequency + rf_set_ch0_frequency(phy_current_config.channel_0_center_frequency, module); + // Set channel (must be called after frequency change) + rf_set_channel(rf_rx_channel, module); +} + +static void rf_csma_ca_timer_interrupt(void) +{ + cca_prepare_status = device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_PREPARE, 0, 0); + if (cca_prepare_status == PHY_TX_NOT_ALLOWED) { + if (rf_state == RF_CSMA_STARTED) { + rf_state = RF_IDLE; + } else if (rf_state == RF_CSMA_WHILE_RX) { + rf_state = RF_RX_STARTED; + } + TEST_CSMA_DONE + return; + } + rf_irq_rf_enable(EDC, RF_09); + rf_irq_rf_enable(EDC, rf_module); + rf_write_rf_register_field(RF_EDC, rf_module, EDM, RF_EDSINGLE); + rf_backup_timer_start(0, CCA_BACKUP_TIMEOUT); +} + +static void rf_csma_ca_timer_signal(void) +{ + rf->irq_thread_215.flags_set(SIG_TIMER_CCA); +} + +static int8_t rf_start_csma_ca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol) +{ + rf_lock(); + if (rf_state != RF_IDLE) { + rf_unlock(); + return -1; + } + rf_state = RF_CSMA_STARTED; + + // If Ack is requested, store the MAC sequence. This will be compared with received Ack. + uint8_t version = ((*(data_ptr + 1) & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD); + if ((version != MAC_FRAME_VERSION_2) && (*data_ptr & FC_AR)) { + tx_sequence = *(data_ptr + 2); + } + rf_write_tx_buffer(data_ptr, data_length, rf_module); + if (phy_current_config.modulation == M_OQPSK) { + data_length += 2; + } else if (phy_current_config.modulation == M_2FSK) { + data_length += 4; + } + rf_write_tx_packet_length(data_length, rf_module); + mac_tx_handle = tx_handle; + + if (tx_time) { + uint32_t backoff_time = tx_time - rf_get_timestamp(); + // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately + if (backoff_time <= 65000) { + rf->cca_timer.attach_us(rf_csma_ca_timer_signal, backoff_time); + TEST_CSMA_STARTED + rf_unlock(); + return 0; + } + } + // Short timeout to start CCA immediately. + rf->cca_timer.attach_us(rf_csma_ca_timer_signal, 1); + TEST_CSMA_STARTED + rf_unlock(); + return 0; +} + +static void rf_handle_cca_ed_done(void) +{ + TEST_CSMA_DONE + rf_backup_timer_stop(); + rf_irq_rf_disable(EDC, RF_09); + rf_irq_rf_disable(EDC, rf_module); + if (rf_state == RF_CSMA_WHILE_RX) { + rf_state = RF_RX_STARTED; + } + + if ((cca_enabled == true) && (rf_state == RF_RX_STARTED)) { + uint32_t backup_time = cur_rx_stop_time - rf_get_timestamp(); + if (backup_time > MAX_TRANSMISSION_TIME) { + backup_time = 0; + } + rf_backup_timer_start(0, backup_time + PACKET_PROCESSING_TIME); + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); + return; + } + if ((cca_enabled == true) && (((int8_t) rf_read_rf_register(RF_EDV, rf_module) > cca_threshold))) { + rf_state = RF_IDLE; + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); + return; + } + if (cca_prepare_status == PHY_RESTART_CSMA) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_OK, 0, 0); + if (tx_time) { + uint32_t backoff_time = tx_time - rf_get_timestamp(); + // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately + if (backoff_time > 65000) { + backoff_time = 1; + } + rf->cca_timer.attach_us(rf_csma_ca_timer_signal, backoff_time); + TEST_CSMA_STARTED + } + return; + } + rf_irq_bbc_disable(RXFE, rf_module); + rf_start_tx(); +} + +static void rf_handle_tx_done(void) +{ + rf_backup_timer_stop(); + TEST_TX_DONE + rf_irq_bbc_disable(TXFE, rf_module); + rf_state = RF_IDLE; + rf_receive(rf_rx_channel, rf_module); + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); +} + +static void rf_start_tx(void) +{ + receiver_enabled = false; + rf_change_state(RF_TXPREP, rf_module); + rf_irq_bbc_enable(TXFE, rf_module); + rf_change_state(RF_TX, rf_module); + rf_state = RF_TX_STARTED; + TEST_TX_STARTED + rf_backup_timer_start(cur_tx_packet_len, 0); +} + +static void rf_handle_ack(uint8_t seq_number, uint8_t pending) +{ + phy_link_tx_status_e phy_status; + if (tx_sequence == (uint16_t)seq_number) { + if (pending) { + phy_status = PHY_LINK_TX_DONE_PENDING; + } else { + phy_status = PHY_LINK_TX_DONE; + } + // No CCA attempts done, just waited Ack + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status, 0, 0); + // Clear TX sequence when Ack is received to avoid duplicate Acks + tx_sequence = 0xffff; + } +} + +static void rf_handle_rx_done(void) +{ + receiver_enabled = false; + TEST_RX_DONE + rf_backup_timer_stop(); + if (rf_state == RF_CSMA_WHILE_RX) { + rf_state = RF_CSMA_STARTED; + uint32_t backup_time = tx_time - rf_get_timestamp(); + // Next TX start event must occur in less than 65ms + if (backup_time > 65000) { + backup_time = 0; + } + rf_backup_timer_start(0, backup_time + CCA_BACKUP_TIMEOUT); + } else if (rf_state == RF_RX_STARTED) { + rf_state = RF_IDLE; + } + if (rf_read_bbc_register(BBC_PC, rf_module) & FCSOK) { + if (!rf_read_rx_buffer(cur_rx_packet_len, rf_module)) { + uint8_t version = ((rx_buffer[1] & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD); + if (((rx_buffer[0] & MAC_FRAME_TYPE_MASK) == MAC_TYPE_ACK) && (version < MAC_FRAME_VERSION_2)) { + rf_handle_ack(rx_buffer[2], rx_buffer[0] & MAC_DATA_PENDING); + } else { + int8_t rssi = (int8_t) rf_read_rf_register(RF_EDV, rf_module); + if (phy_current_config.modulation == M_OQPSK) { + cur_rx_packet_len -= 2; + } else if (phy_current_config.modulation == M_2FSK) { + cur_rx_packet_len -= 4; + } + device_driver.phy_rx_cb(rx_buffer, cur_rx_packet_len, 0xf0, rssi, rf_radio_driver_id); + // If auto ack used, must wait until RF returns to RF_TXPREP state + if ((version != MAC_FRAME_VERSION_2) && (rx_buffer[0] & FC_AR)) { + wait_us(100); + rf_poll_state_change(RF_TXPREP, rf_module); + } + } + } + } else { + if (device_driver.phy_rf_statistics) { + device_driver.phy_rf_statistics->crc_fails++; + } + device_driver.phy_rx_cb(NULL, 0, 0, 0, rf_radio_driver_id); + } + rf_receive(rf_rx_channel, rf_module); +} + +static void rf_handle_rx_start(void) +{ + rx_time = rf_get_timestamp(); + cur_rx_packet_len = rf_read_rx_frame_length(rf_module); + if (!cur_rx_packet_len || cur_rx_packet_len > device_driver.phy_MTU) { + return; + } + if (rf_state == RF_CSMA_STARTED) { + rf_backup_timer_stop(); + rf_state = RF_CSMA_WHILE_RX; + } else { + rf_state = RF_RX_STARTED; + } + TEST_RX_STARTED + cur_rx_stop_time = rf_backup_timer_start(cur_rx_packet_len, 0); +} + +static void rf_receive(uint16_t rx_channel, rf_modules_e module) +{ + if ((receiver_enabled == true) && (rf_update_config == false) && (rx_channel == rf_rx_channel)) { + return; + } + TEST_RX_DONE + rf_lock(); + if (rf_update_config == true) { + rf_update_config = false; + rf_change_state(RF_TRX_OFF, module); + rf_init_registers(module); + rf_change_state(RF_TXPREP, module); + } + if (rx_channel != rf_rx_channel) { + rf_change_state(RF_TXPREP, module); + rf_set_channel(rx_channel, module); + rf_rx_channel = rx_channel; + } + rf_change_state(RF_RX, module); + rf_irq_bbc_enable(RXFS, module); + rf_irq_bbc_enable(RXFE, module); + receiver_enabled = true; + rf_unlock(); + +} + +static void rf_interrupt_handler(void) +{ + rf->irq_thread_215.flags_set(SIG_RADIO); +} + +static void rf_irq_task_process_irq(void) +{ + uint8_t irq_rf09_status = 0, irq_bbc0_status = 0, irq_rf24_status = 0, irq_bbc1_status = 0; + if (rf09_irq_mask) { + irq_rf09_status = rf_read_common_register(RF09_IRQS); + irq_rf09_status &= rf09_irq_mask; + } + if (bbc0_irq_mask) { + irq_bbc0_status = rf_read_common_register(BBC0_IRQS); + irq_bbc0_status &= bbc0_irq_mask; + } + if (rf24_irq_mask) { + irq_rf24_status = rf_read_common_register(RF24_IRQS); + irq_rf24_status &= rf24_irq_mask; + } + if (bbc1_irq_mask) { + irq_bbc1_status = rf_read_common_register(BBC1_IRQS); + irq_bbc1_status &= bbc1_irq_mask; + } + if ((rf_state == RF_CSMA_STARTED) || (rf_state == RF_CSMA_WHILE_RX) || (rf_state == RF_RX_STARTED)) { + if ((irq_rf09_status & EDC) || (irq_rf24_status & EDC)) { + rf_handle_cca_ed_done(); + } + } + if (rf_state == RF_TX_STARTED) { + if ((irq_bbc0_status & TXFE) || (irq_bbc1_status & TXFE)) { + rf_handle_tx_done(); + } + } + if ((rf_state == RF_IDLE) || (rf_state == RF_CSMA_STARTED)) { + if ((irq_bbc0_status & RXFS) || (irq_bbc1_status & RXFS)) { + rf_handle_rx_start(); + } + } + if ((rf_state == RF_RX_STARTED) || (rf_state == RF_CSMA_WHILE_RX)) { + if ((irq_bbc0_status & RXFE) || (irq_bbc1_status & RXFE)) { + rf_handle_rx_done(); + } + } +} + +static void rf_write_tx_packet_length(uint16_t packet_length, rf_modules_e module) +{ + if (packet_length > device_driver.phy_MTU) { + return; + } + if ((uint8_t)(cur_tx_packet_len >> 8) != (packet_length / 256)) { + rf_write_bbc_register(BBC_TXFLH, module, packet_length / 256); + } + if ((uint8_t)cur_tx_packet_len != (packet_length % 256)) { + rf_write_bbc_register(BBC_TXFLL, module, packet_length % 256); + } + cur_tx_packet_len = packet_length; +} + +static uint16_t rf_read_rx_frame_length(rf_modules_e module) +{ + const uint8_t tx[2] = { static_cast(module + 2), static_cast(BBC_RXFLL) }; + uint8_t rx[2]; + rf->CS = 0; + rf_spi_exchange(tx, 2, NULL, 0); + rf_spi_exchange(NULL, 0, rx, 2); + rf->CS = 1; + return (uint16_t)((rx[1] << 8) | rx[0]); +} + +static void rf_write_tx_buffer(uint8_t *data, uint16_t len, rf_modules_e module) +{ + uint16_t buffer_addr = BBC0_FBTXS + (0x1000 * (module - 1)); + const uint8_t tx[2] = { static_cast(0x80 | (buffer_addr >> 8)), static_cast(buffer_addr) }; + rf->CS = 0; + rf_spi_exchange(tx, 2, NULL, 0); + rf_spi_exchange(data, len, NULL, 0); + rf->CS = 1; +} + +static int rf_read_rx_buffer(uint16_t length, rf_modules_e module) +{ + if (length > device_driver.phy_MTU) { + return -1; + } + uint8_t *ptr = rx_buffer; + uint16_t buffer_addr = BBC0_FBRXS + (0x1000 * (module - 1)); + const uint8_t tx[2] = { static_cast(buffer_addr >> 8), static_cast(buffer_addr) }; + rf->CS = 0; + rf_spi_exchange(tx, 2, NULL, 0); + rf_spi_exchange(NULL, 0, ptr, length); + rf->CS = 1; + return 0; +} + +static void rf_irq_rf_enable(uint8_t irq, rf_modules_e module) +{ + if ((module == RF_09) && !(rf09_irq_mask & irq)) { + rf_write_rf_register_field(RF_IRQM, module, irq, irq); + rf09_irq_mask |= irq; + } else if ((module == RF_24) && !(rf24_irq_mask & irq)) { + rf_write_rf_register_field(RF_IRQM, module, irq, irq); + rf24_irq_mask |= irq; + } +} + +static void rf_irq_rf_disable(uint8_t irq, rf_modules_e module) +{ + if ((module == RF_09) && (rf09_irq_mask & irq)) { + rf_write_rf_register_field(RF_IRQM, module, irq, 0); + rf09_irq_mask &= ~irq; + } else if ((module == RF_24) && (rf24_irq_mask & irq)) { + rf_write_rf_register_field(RF_IRQM, module, irq, 0); + rf24_irq_mask &= ~irq; + } +} + +static void rf_irq_bbc_enable(uint8_t irq, rf_modules_e module) +{ + if ((module == RF_09) && !(bbc0_irq_mask & irq)) { + rf_write_bbc_register_field(BBC_IRQM, module, irq, irq); + bbc0_irq_mask |= irq; + } else if ((module == RF_24) && !(bbc1_irq_mask & irq)) { + rf_write_bbc_register_field(BBC_IRQM, module, irq, irq); + bbc1_irq_mask |= irq; + } +} + +static void rf_irq_bbc_disable(uint8_t irq, rf_modules_e module) +{ + if ((module == RF_09) && (bbc0_irq_mask & irq)) { + rf_write_bbc_register_field(BBC_IRQM, module, irq, 0); + bbc0_irq_mask &= ~irq; + } else if ((module == RF_24) && (bbc1_irq_mask & irq)) { + rf_write_bbc_register_field(BBC_IRQM, module, irq, 0); + bbc1_irq_mask &= ~irq; + } +} + +static rf_command_e rf_read_state(rf_modules_e module) +{ + return (rf_command_e) rf_read_rf_register(RF_STATE, module); +} + +static void rf_poll_state_change(rf_command_e state, rf_modules_e module) +{ + uint32_t transition_start_time = rf_get_timestamp(); + while (rf_read_state(module) != state) { + if (rf_get_timestamp() > (transition_start_time + MAX_STATE_TRANSITION_TIME_US)) { + tr_err("Failed to change module %u state from %x to: %x", module, rf_read_state(module), state); + break; + } + } +} + +static void rf_change_state(rf_command_e state, rf_modules_e module) +{ + rf_write_rf_register(RF_CMD, module, state); + return rf_poll_state_change(state, module); +} + +static void rf_spi_exchange(const void *tx, size_t tx_len, void *rx, size_t rx_len) +{ + rf->spi.write(static_cast(tx), tx_len, static_cast(rx), rx_len); +} + +static uint8_t rf_read_rf_register(uint8_t addr, rf_modules_e module) +{ + const uint8_t tx[2] = { static_cast(module), static_cast(addr) }; + uint8_t rx[3]; + rf->CS = 0; + rf_spi_exchange(tx, 2, rx, 3); + rf->CS = 1; + return rx[2]; +} + +static void rf_write_rf_register(uint8_t addr, rf_modules_e module, uint8_t data) +{ + const uint8_t tx[3] = { static_cast(0x80 | module), static_cast(addr), static_cast(data) }; + uint8_t rx[2]; + rf->CS = 0; + rf_spi_exchange(tx, 3, rx, 2); + rf->CS = 1; +} + +static void rf_write_rf_register_field(uint8_t addr, rf_modules_e module, uint8_t field, uint8_t value) +{ + uint8_t reg_tmp = rf_read_rf_register(addr, module); + reg_tmp &= ~field; + reg_tmp |= value; + rf_write_rf_register(addr, module, reg_tmp); +} + +static void rf_backup_timer_interrupt(void) +{ + receiver_enabled = false; + rf_read_common_register(RF09_IRQS); + rf_read_common_register(RF24_IRQS); + rf_read_common_register(BBC0_IRQS); + rf_read_common_register(BBC1_IRQS); + rf_irq_rf_disable(EDC, RF_09); + rf_irq_rf_disable(EDC, RF_24); + if (rf_state == RF_RX_STARTED) { + if (device_driver.phy_rf_statistics) { + device_driver.phy_rf_statistics->rx_timeouts++; + } + } else { + if (device_driver.phy_rf_statistics) { + device_driver.phy_rf_statistics->tx_timeouts++; + } + } + if (rf_state == RF_TX_STARTED) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); + } + if ((rf_state == RF_CSMA_STARTED) || (rf_state == RF_CSMA_WHILE_RX)) { + TEST_CSMA_DONE + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); + } + TEST_TX_DONE + TEST_RX_DONE + rf_state = RF_IDLE; + rf_receive(rf_rx_channel, rf_module); +} + +static void rf_backup_timer_signal(void) +{ + rf->irq_thread_215.flags_set(SIG_TIMER_BACKUP); +} + +static void rf_backup_timer_stop(void) +{ + rf->cal_timer.detach(); +} + +static uint32_t rf_backup_timer_start(uint16_t bytes, uint32_t time_us) +{ + if (!time_us) { + time_us = (uint32_t)(8000000 / phy_current_config.datarate) * bytes + PACKET_PROCESSING_TIME; + } + // Using cal_timer as backup timer + rf->cal_timer.attach_us(rf_backup_timer_signal, time_us); + + return (rf_get_timestamp() + time_us); +} + +static int rf_set_channel(uint16_t channel, rf_modules_e module) +{ + rf_write_rf_register(RF_CNL, module, (uint8_t) channel); + rf_write_rf_register_field(RF_CNM, module, CNH, (uint8_t)(channel >> 8)); + return 0; +} + +static int rf_set_ch0_frequency(uint32_t frequency, rf_modules_e module) +{ + if (module == RF_24) { + frequency -= 1500000000; + } + frequency /= 25000; + rf_write_rf_register(RF_CCF0L, module, (uint8_t)frequency); + rf_write_rf_register(RF_CCF0H, module, (uint8_t)(frequency >> 8)); + return 0; +} + +static int rf_set_channel_spacing(uint32_t channel_spacing, rf_modules_e module) +{ + channel_spacing /= 25000; + rf_write_rf_register(RF_CS, module, channel_spacing); + return 0; +} + +static int rf_set_fsk_symbol_rate_configuration(uint32_t symbol_rate, rf_modules_e module) +{ + if (symbol_rate == 50000) { + rf_write_bbc_register_field(BBC_FSKC1, module, SRATE, SRATE_50KHZ); + if (rf_version_num == 1) { + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_10); + } else { + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_8); + } + rf_write_rf_register_field(RF_RXDFE, module, SR, SR_10); + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_0); + } else { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1); + } + rf_write_rf_register_field(RF_TXCUTC, module, PARAMP, RF_PARAMP32U); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC80KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW160KHZ_IF250KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, 0); + } else if (symbol_rate == 100000) { + rf_write_bbc_register_field(BBC_FSKC1, module, SRATE, SRATE_100KHZ); + if (rf_version_num == 1) { + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_5); + } else { + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_4); + } + rf_write_rf_register_field(RF_RXDFE, module, SR, SR_5); + rf_write_rf_register_field(RF_TXCUTC, module, PARAMP, RF_PARAMP16U); + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_0); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC100KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW200KHZ_IF250KHZ); + } else { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC160KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW320KHZ_IF500KHZ); + } + rf_write_rf_register_field(RF_RXBWC, module, IFS, 0); + } else if (symbol_rate == 150000) { + rf_write_bbc_register_field(BBC_FSKC1, module, SRATE, SRATE_150KHZ); + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_2); + rf_write_rf_register_field(RF_RXDFE, module, SR, SR_4); + rf_write_rf_register_field(RF_TXCUTC, module, PARAMP, RF_PARAMP16U); + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_0); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC160KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW320KHZ_IF500KHZ); + } else { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC250KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW400KHZ_IF500KHZ); + } + rf_write_rf_register_field(RF_RXBWC, module, IFS, 0); + } else if (symbol_rate == 200000) { + rf_write_bbc_register_field(BBC_FSKC1, module, SRATE, SRATE_200KHZ); + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_2); + rf_write_rf_register_field(RF_RXDFE, module, SR, SR_4); + rf_write_rf_register_field(RF_TXCUTC, module, PARAMP, RF_PARAMP16U); + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC200KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW320KHZ_IF500KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, 0); + } else { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_2); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC315KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW500KHZ_IF500KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, IFS); + } + } else if (symbol_rate == 300000) { + rf_write_bbc_register_field(BBC_FSKC1, module, SRATE, SRATE_300KHZ); + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_1); + rf_write_rf_register_field(RF_RXDFE, module, SR, SR_2); + rf_write_rf_register_field(RF_TXCUTC, module, PARAMP, RF_PARAMP8U); + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_0); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC315KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW500KHZ_IF500KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, IFS); + } else { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC500KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW630KHZ_IF1000KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, 0); + } + } else if (symbol_rate == 400000) { + rf_write_bbc_register_field(BBC_FSKC1, module, SRATE, SRATE_400KHZ); + rf_write_rf_register_field(RF_TXDFE, module, SR, SR_1); + rf_write_rf_register_field(RF_RXDFE, module, SR, SR_2); + rf_write_rf_register_field(RF_TXCUTC, module, PARAMP, RF_PARAMP8U); + if (phy_current_config.modulation_index == MODULATION_INDEX_0_5) { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_0); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC400KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW630KHZ_IF1000KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, 0); + } else { + rf_write_rf_register_field(RF_RXDFE, module, RCUT, RCUT_1); + rf_write_rf_register_field(RF_TXCUTC, module, LPFCUT, RF_FLC625KHZ); + rf_write_rf_register_field(RF_RXBWC, module, BW, RF_BW1000KHZ_IF1000KHZ); + rf_write_rf_register_field(RF_RXBWC, module, IFS, IFS); + } + } + return 0; +} + +static void rf_conf_set_cca_threshold(uint8_t percent) +{ + uint8_t step = (MAX_CCA_THRESHOLD - MIN_CCA_THRESHOLD); + cca_threshold = MIN_CCA_THRESHOLD + (step * percent) / 100; +} + +static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation) +{ + uint8_t bits_in_symbols = 4; + if (modulation == M_2FSK) { + bits_in_symbols = 1; + } + rf_symbol_rate = baudrate / bits_in_symbols; +} + +void RFBits::rf_irq_task(void) +{ + for (;;) { + uint32_t flags = ThisThread::flags_wait_any(SIG_ALL); + rf_lock(); + if (flags & SIG_RADIO) { + rf_irq_task_process_irq(); + } + if (flags & SIG_TIMER_CCA) { + rf_csma_ca_timer_interrupt(); + } + if (flags & SIG_TIMER_BACKUP) { + rf_backup_timer_interrupt(); + } + rf_unlock(); + } +} + +int RFBits::init_215_driver(RFBits *_rf, TestPins *_test_pins, const uint8_t mac[8], uint8_t *rf_part_num) +{ + rf = _rf; + test_pins = _test_pins; + irq_thread_215.start(mbed::callback(this, &RFBits::rf_irq_task)); + rf->spi.frequency(25000000); + *rf_part_num = rf_read_common_register(RF_PN); + rf_version_num = rf_read_common_register(RF_VN); + tr_info("RF version number: %x", rf_version_num); + return rf_device_register(mac); +} + +#endif // MBED_CONF_NANOSTACK_CONFIGURATION && DEVICE_SPI && DEVICE_INTERRUPTIN && defined(MBED_CONF_RTOS_PRESENT) diff --git a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp index be59a4afcd1..e747af742db 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp +++ b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp @@ -23,6 +23,7 @@ #include "NanostackRfPhyAtmel.h" #include "randLIB.h" #include "AT86RFReg.h" +#include "AT86RF215Reg.h" #include "nanostack/platform/arm_hal_phy.h" #include "mbed_trace.h" #include "mbed_toolchain.h" @@ -244,34 +245,8 @@ static void rf_if_irq_task_process_irq(); #endif // HW pins to RF chip +#include "rfbits.h" -class UnlockedSPI : public SPI { -public: - UnlockedSPI(PinName mosi, PinName miso, PinName sclk) : - SPI(mosi, miso, sclk) { } - virtual void lock() { } - virtual void unlock() { } -}; - -class RFBits { -public: - RFBits(PinName spi_mosi, PinName spi_miso, - PinName spi_sclk, PinName spi_cs, - PinName spi_rst, PinName spi_slp, PinName spi_irq); - UnlockedSPI spi; - DigitalOut CS; - DigitalOut RST; - DigitalOut SLP_TR; - InterruptIn IRQ; - Timeout ack_timer; - Timeout cal_timer; - Timeout cca_timer; -#ifdef MBED_CONF_RTOS_PRESENT - Thread irq_thread; - Mutex mutex; - void rf_if_irq_task(); -#endif -}; RFBits::RFBits(PinName spi_mosi, PinName spi_miso, PinName spi_sclk, PinName spi_cs, @@ -282,7 +257,8 @@ RFBits::RFBits(PinName spi_mosi, PinName spi_miso, SLP_TR(spi_slp), IRQ(spi_irq) #ifdef MBED_CONF_RTOS_PRESENT - , irq_thread(osPriorityRealtime, MBED_CONF_ATMEL_RF_IRQ_THREAD_STACK_SIZE, NULL, "atmel_irq_thread") + , irq_thread(osPriorityRealtime, MBED_CONF_ATMEL_RF_IRQ_THREAD_STACK_SIZE, NULL, "atmel_irq_thread"), + irq_thread_215(osPriorityRealtime, MBED_CONF_ATMEL_RF_IRQ_THREAD_STACK_SIZE, NULL, "atmel_215_irq_thread") #endif { #ifdef MBED_CONF_RTOS_PRESENT @@ -290,7 +266,17 @@ RFBits::RFBits(PinName spi_mosi, PinName spi_miso, #endif } +TestPins::TestPins(PinName test_pin_1, PinName test_pin_2, PinName test_pin_3, PinName test_pin_4, PinName test_pin_5) + : TEST1(test_pin_1), + TEST2(test_pin_2), + TEST3(test_pin_3), + TEST4(test_pin_4), + TEST5(test_pin_5) +{ +} + static RFBits *rf; +static TestPins *test_pins; static uint8_t rf_part_num = 0; /*TODO: RSSI Base value setting*/ static int8_t rf_rssi_base_val = -91; @@ -652,6 +638,10 @@ static void rf_if_write_set_tx_power_register(uint8_t value) */ static uint8_t rf_if_read_part_num(void) { + // Part number is already set + if (rf_part_num) { + return rf_part_num; + } return rf_if_read_register(PART_NUM); } @@ -664,9 +654,6 @@ static uint8_t rf_if_read_part_num(void) */ static void rf_if_write_rf_settings(void) { - /*Reset RF module*/ - rf_if_reset_radio(); - rf_part_num = rf_if_read_part_num(); rf_if_write_register(XAH_CTRL_0, 0); @@ -675,7 +662,9 @@ static void rf_if_write_rf_settings(void) rf_if_write_register(TRX_CTRL_1, TX_AUTO_CRC_ON | SPI_CMD_MODE_TRX_STATUS); rf_if_write_register(IRQ_MASK, CCA_ED_DONE | TRX_END | TRX_UR); - +#ifdef TEST_GPIOS_ENABLED + rf_if_set_bit(IRQ_MASK, RX_START, RX_START); +#endif xah_ctrl_1 = rf_if_read_register(XAH_CTRL_1); /*Read transceiver PART_NUM*/ @@ -1024,6 +1013,11 @@ static void rf_if_interrupt_handler(void) /*Read and clear interrupt flag, and pick up trx_status*/ irq_status = rf_if_read_register_with_status(IRQ_STATUS, &full_trx_status); +#ifdef TEST_GPIOS_ENABLED + if (irq_status & RX_START) { + TEST_RX_STARTED + } +#endif /*Frame end interrupt (RX and TX)*/ if (irq_status & TRX_END) { rf_trx_states_t trx_status = rf_if_trx_status_from_full(full_trx_status); @@ -1384,7 +1378,6 @@ static void rf_channel_set(uint8_t ch) rf_if_unlock(); } - /* * \brief Function initialises the radio driver and resets the radio. * @@ -1526,6 +1519,7 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h rf_tx_length = data_length; /*Start CCA timeout*/ rf_cca_timer_start(RF_CCA_BASE_BACKOFF + randLIB_get_random_in_range(0, RF_CCA_RANDOM_BACKOFF)); + TEST_CSMA_STARTED /*Store TX handle*/ mac_tx_handle = tx_handle; rf_if_unlock(); @@ -1544,6 +1538,7 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h */ static void rf_cca_abort(void) { + TEST_CSMA_DONE rf_cca_timer_stop(); rf_flags_clear(RFF_CCA); } @@ -1585,6 +1580,7 @@ static bool rf_start_tx() rf_flags_set(RFF_TX); /*RF state change: SLP_TR pulse triggers PLL_ON->BUSY_TX*/ rf_if_enable_slptr(); + TEST_TX_STARTED /*Chip permits us to write frame buffer while it is transmitting*/ /*As long as first byte of data is in within 176us of TX start, we're good */ rf_if_write_frame_buffer(rf_tx_data, rf_tx_length); @@ -1601,6 +1597,7 @@ static bool rf_start_tx() */ static void rf_receive(rf_trx_states_t trx_status) { + TEST_RX_DONE uint16_t while_counter = 0; if (rf_flags_check(RFF_ON) == 0) { rf_on(); @@ -1765,6 +1762,7 @@ static void rf_handle_ack(uint8_t seq_number, uint8_t data_pending) */ static void rf_handle_rx_end(rf_trx_states_t trx_status) { + TEST_RX_DONE /*Frame received interrupt*/ if (!rf_flags_check(RFF_RX)) { return; @@ -1827,6 +1825,7 @@ static void rf_shutdown(void) */ static void rf_handle_tx_end(rf_trx_states_t trx_status) { + TEST_TX_DONE rf_rx_mode = 0; /*If ACK is needed for this transmission*/ if ((rf_tx_data[0] & 0x20) && rf_flags_check(RFF_TX)) { @@ -1853,6 +1852,7 @@ static void rf_handle_tx_end(rf_trx_states_t trx_status) */ static void rf_handle_cca_ed_done(uint8_t full_trx_status) { + TEST_CSMA_DONE if (!rf_flags_check(RFF_CCA)) { return; } @@ -2168,11 +2168,14 @@ static uint8_t rf_scale_lqi(int8_t rssi) NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso, PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, PinName i2c_sda, PinName i2c_scl) - : _mac(i2c_sda, i2c_scl), _mac_addr(), _rf(NULL), _mac_set(false), + : _mac(i2c_sda, i2c_scl), _mac_addr(), _rf(NULL), _test_pins(NULL), _mac_set(false), _spi_mosi(spi_mosi), _spi_miso(spi_miso), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_rst(spi_rst), _spi_slp(spi_slp), _spi_irq(spi_irq) { _rf = new RFBits(_spi_mosi, _spi_miso, _spi_sclk, _spi_cs, _spi_rst, _spi_slp, _spi_irq); +#ifdef TEST_GPIOS_ENABLED + _test_pins = new TestPins(TEST_PIN_TX, TEST_PIN_RX, TEST_PIN_CSMA, TEST_PIN_SPARE_1, TEST_PIN_SPARE_2); +#endif } NanostackRfPhyAtmel::~NanostackRfPhyAtmel() @@ -2196,6 +2199,7 @@ int8_t NanostackRfPhyAtmel::rf_register() // Read the mac address if it hasn't been set by a user rf = _rf; + test_pins = _test_pins; if (!_mac_set) { int ret = _mac.read_eui64((void *)_mac_addr); if (ret < 0) { @@ -2204,9 +2208,20 @@ int8_t NanostackRfPhyAtmel::rf_register() return -1; } } - - int8_t radio_id = rf_device_register(_mac_addr); + /*Reset RF module*/ + rf_if_reset_radio(); + rf_part_num = rf_if_read_part_num(); + int8_t radio_id = -1; + if (rf_part_num != PART_AT86RF231 && rf_part_num != PART_AT86RF233 && rf_part_num != PART_AT86RF212) { + // Register RF type 215. Jumps to AT86RF215 driver. + radio_id = rf->init_215_driver(_rf, _test_pins, _mac_addr, &rf_part_num); + } else { + // Register other RF types. + radio_id = rf_device_register(_mac_addr); + } + tr_info("RF part number: %x", rf_part_num); if (radio_id < 0) { + tr_err("RF registration failed"); rf = NULL; } diff --git a/components/802.15.4_RF/atmel-rf-driver/source/rfbits.h b/components/802.15.4_RF/atmel-rf-driver/source/rfbits.h new file mode 100644 index 00000000000..94143e6a8bb --- /dev/null +++ b/components/802.15.4_RF/atmel-rf-driver/source/rfbits.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * 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 RFBITS_H_ +#define RFBITS_H_ + +#include "DigitalIn.h" +#include "DigitalOut.h" +#include "InterruptIn.h" +#include "SPI.h" +#include +#include "Timeout.h" +#include "rtos.h" + +using namespace mbed; +using namespace rtos; + +class UnlockedSPI : public SPI { +public: + UnlockedSPI(PinName mosi, PinName miso, PinName sclk) : + SPI(mosi, miso, sclk) { } + virtual void lock() { } + virtual void unlock() { } +}; + +class RFBits { +public: + RFBits(PinName spi_mosi, PinName spi_miso, + PinName spi_sclk, PinName spi_cs, + PinName spi_rst, PinName spi_slp, PinName spi_irq); + UnlockedSPI spi; + DigitalOut CS; + DigitalOut RST; + DigitalOut SLP_TR; + InterruptIn IRQ; + Timeout ack_timer; + Timeout cal_timer; + Timeout cca_timer; + Timer tx_timer; + int init_215_driver(RFBits *_rf, TestPins *_test_pins, const uint8_t mac[8], uint8_t *rf_part_num); +#ifdef MBED_CONF_RTOS_PRESENT + Thread irq_thread; + Thread irq_thread_215; + Mutex mutex; + void rf_if_irq_task(); + void rf_irq_task(); +#endif +}; + +class TestPins { +public: + TestPins(PinName test_pin_1, PinName test_pin_2, PinName test_pin_3, PinName test_pin_4, PinName test_pin_5); + DigitalOut TEST1; + DigitalOut TEST2; + DigitalOut TEST3; + DigitalOut TEST4; + DigitalOut TEST5; +}; + +#endif /* RFBITS_H_ */