From 00253cb11629fab6f753682d89faa2ce7b4a213a Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 8 Dec 2021 13:39:38 +0200 Subject: [PATCH] Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 225a4af94f..154db5425e 154db5425e Merge branch 'release_internal' into release_external dca258c3f0 Updated unit test 89df990e6d Set EAPOL relay state function to LLC as a callback 47d8f42bf5 Removed extra call to supplicant delete callback 00ebfd905f Added new configuration options for Border router 421f6a8191 Move RPL code to the 6lr state machine e1e43b8ac2 Corrected pae controller BR EUI-64 flagging aaefdaebab Refactored pae controller (#2707) b82e0ee19a Update copyright text in CMakeLists.txt files (#2706) 5791a22d37 Renamed bootstrap files and separated pae controller callback functions (#2703) 4e3ec07caf MAC beacon payload max MTU allocation limited to for support MTU size 127. a997ab6653 Iotthd 4698 (#2702) e64b057bff Adjusted security protocols timeouts (#2701) cb3db6419f Return invalid values from old API if new configuration is used 6872401f8d RPL address registration update 90a434d318 RPL DAO lifetime update e39f6432eb Forward RPL configuration unmodified 58da4d6c93 Sync Cmake updates from Mbed OS (#2697) 4c229b46c9 Adjust Wi-SUN host/router config - HAVE_RPL (#2696) 40bd2320ba Update release v15.0.0 details to CHANGELOG (#2694) git-subtree-dir: connectivity/nanostack/sal-stack-nanostack git-subtree-split: 154db5425eb9f0df82ee081cb05e7d80cda11415 --- CMakeLists.txt | 33 + nanostack/net_interface.h | 2 + nanostack/socket_api.h | 1 + nanostack/ws_bbr_api.h | 69 +- source/6LoWPAN/CMakeLists.txt | 114 ++ source/6LoWPAN/ND/nd_router_object.c | 12 +- source/6LoWPAN/adaptation_interface.c | 3 + source/6LoWPAN/ws/ws_bbr_api.c | 89 + source/6LoWPAN/ws/ws_bootstrap.c | 916 +--------- source/6LoWPAN/ws/ws_bootstrap.h | 32 +- source/6LoWPAN/ws/ws_bootstrap_6lbr.c | 127 +- source/6LoWPAN/ws/ws_bootstrap_6lbr.h | 2 + ...{ws_bootstrap_lfn.c => ws_bootstrap_6ln.c} | 117 +- source/6LoWPAN/ws/ws_bootstrap_6ln.h | 51 + source/6LoWPAN/ws/ws_bootstrap_6lr.c | 1477 +++++++++++++++++ source/6LoWPAN/ws/ws_bootstrap_6lr.h | 52 + source/6LoWPAN/ws/ws_bootstrap_ffn.c | 1192 ++++--------- source/6LoWPAN/ws/ws_bootstrap_ffn.h | 25 +- source/6LoWPAN/ws/ws_bootstrap_lfn.h | 43 - source/6LoWPAN/ws/ws_cfg_settings.c | 7 + source/6LoWPAN/ws/ws_common.c | 15 +- source/6LoWPAN/ws/ws_config.h | 12 +- source/6LoWPAN/ws/ws_llc.h | 20 +- source/6LoWPAN/ws/ws_llc_data_service.c | 13 +- source/6LoWPAN/ws/ws_management_api.c | 23 +- source/6LoWPAN/ws/ws_pae_auth.h | 2 +- source/6LoWPAN/ws/ws_pae_controller.c | 122 +- source/6LoWPAN/ws/ws_pae_controller.h | 76 +- source/6LoWPAN/ws/ws_pae_key_storage.c | 2 + source/6LoWPAN/ws/ws_pae_key_storage.h | 20 + source/6LoWPAN/ws/ws_pae_lib.c | 3 - source/6LoWPAN/ws/ws_pae_supp.c | 1 + source/6LoWPAN/ws/ws_pae_supp.h | 5 +- source/6LoWPAN/ws/ws_test_api.c | 2 +- source/BorderRouter/CMakeLists.txt | 12 + source/Common_Protocols/CMakeLists.txt | 21 + source/Common_Protocols/icmpv6_radv.c | 1 + source/Core/CMakeLists.txt | 17 + source/Core/ns_socket.c | 4 + source/DHCPv6_Server/CMakeLists.txt | 12 + source/DHCPv6_client/CMakeLists.txt | 12 + source/MAC/CMakeLists.txt | 34 + source/MAC/IEEE802_15_4/mac_mlme.c | 25 +- source/MLE/CMakeLists.txt | 13 + source/MPL/CMakeLists.txt | 12 + source/NWK_INTERFACE/CMakeLists.txt | 16 + source/NWK_INTERFACE/Include/protocol.h | 4 - source/RPL/CMakeLists.txt | 19 + source/RPL/rpl_control.c | 43 +- source/RPL/rpl_control.h | 57 +- source/RPL/rpl_downward.c | 81 +- source/RPL/rpl_policy.c | 4 +- source/RPL/rpl_policy.h | 2 +- source/RPL/rpl_structures.h | 2 +- source/RPL/rpl_upward.c | 8 +- source/RPL/rpl_upward.h | 4 +- source/Security/CMakeLists.txt | 69 + .../eap_tls_sec_prot/auth_eap_tls_sec_prot.c | 2 +- .../radius_eap_tls_sec_prot.c | 6 +- .../eap_tls_sec_prot/supp_eap_tls_sec_prot.c | 6 +- .../fwh_sec_prot/auth_fwh_sec_prot.c | 4 +- .../fwh_sec_prot/supp_fwh_sec_prot.c | 12 +- .../gkh_sec_prot/auth_gkh_sec_prot.c | 2 +- .../gkh_sec_prot/supp_gkh_sec_prot.c | 2 +- .../protocols/key_sec_prot/key_sec_prot.c | 4 +- .../radius_sec_prot/radius_client_sec_prot.c | 4 +- source/Security/protocols/sec_prot_lib.c | 4 +- source/Security/protocols/sec_prot_lib.h | 6 +- .../protocols/tls_sec_prot/tls_sec_prot.c | 8 +- source/Service_Libs/CMakeLists.txt | 107 ++ source/configs/CMakeLists.txt | 8 + source/configs/base/cfg_ws_full.h | 20 + source/configs/base/cfg_ws_host.h | 4 +- source/configs/base/cfg_ws_router.h | 1 + source/configs/cfg_generic.h | 4 +- source/configs/cfg_ws_full.h | 20 + source/configs/cfg_ws_host.h | 1 + source/configs/cfg_ws_router.h | 3 +- source/ipv6_stack/CMakeLists.txt | 13 + source/libDHCPv6/CMakeLists.txt | 15 + source/libNET/CMakeLists.txt | 25 + source/libNET/src/net_load_balance.c | 2 +- sources.mk | 3 +- 83 files changed, 3385 insertions(+), 2053 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 source/6LoWPAN/CMakeLists.txt rename source/6LoWPAN/ws/{ws_bootstrap_lfn.c => ws_bootstrap_6ln.c} (57%) create mode 100644 source/6LoWPAN/ws/ws_bootstrap_6ln.h create mode 100644 source/6LoWPAN/ws/ws_bootstrap_6lr.c create mode 100644 source/6LoWPAN/ws/ws_bootstrap_6lr.h delete mode 100644 source/6LoWPAN/ws/ws_bootstrap_lfn.h create mode 100644 source/BorderRouter/CMakeLists.txt create mode 100644 source/Common_Protocols/CMakeLists.txt create mode 100644 source/Core/CMakeLists.txt create mode 100644 source/DHCPv6_Server/CMakeLists.txt create mode 100644 source/DHCPv6_client/CMakeLists.txt create mode 100644 source/MAC/CMakeLists.txt create mode 100644 source/MLE/CMakeLists.txt create mode 100644 source/MPL/CMakeLists.txt create mode 100644 source/NWK_INTERFACE/CMakeLists.txt create mode 100644 source/RPL/CMakeLists.txt create mode 100644 source/Security/CMakeLists.txt create mode 100644 source/Service_Libs/CMakeLists.txt create mode 100644 source/configs/CMakeLists.txt create mode 100644 source/configs/base/cfg_ws_full.h create mode 100644 source/configs/cfg_ws_full.h create mode 100644 source/ipv6_stack/CMakeLists.txt create mode 100644 source/libDHCPv6/CMakeLists.txt create mode 100644 source/libNET/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..2cab979e90 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(source/6LoWPAN) +add_subdirectory(source/BorderRouter) +add_subdirectory(source/Common_Protocols) +add_subdirectory(source/Core) +add_subdirectory(source/DHCPv6_Server) +add_subdirectory(source/DHCPv6_client) +add_subdirectory(source/MAC) +add_subdirectory(source/MLE) +add_subdirectory(source/MPL) +add_subdirectory(source/NWK_INTERFACE) +add_subdirectory(source/RPL) +add_subdirectory(source/Security) +add_subdirectory(source/Service_Libs) +add_subdirectory(source/configs) +add_subdirectory(source/ipv6_stack) +add_subdirectory(source/libDHCPv6) +add_subdirectory(source/libNET) + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./nanostack + ./nanostack/platform + ./source +) + +target_link_libraries(mbed-nanostack + INTERFACE + mbed-nanostack-coap_service +) diff --git a/nanostack/net_interface.h b/nanostack/net_interface.h index eb87675af5..6be75ae8fe 100644 --- a/nanostack/net_interface.h +++ b/nanostack/net_interface.h @@ -99,6 +99,8 @@ typedef enum arm_library_event_type_e { #define SOCKET_NO_RAM (10 << 4) /** TCP connection problem indication (RFC 1122 R1) */ #define SOCKET_CONNECTION_PROBLEM (11 << 4) +/** Socket is busy or Radio is returning CCA failure */ +#define SOCKET_BUSY (12 << 4) #define SOCKET_BIND_DONE SOCKET_CONNECT_DONE /**< Backward compatibility */ #define SOCKET_BIND_FAIL SOCKET_CONNECT_FAIL /**< Backward compatibility */ diff --git a/nanostack/socket_api.h b/nanostack/socket_api.h index 7cf8b57748..fe19acd75e 100644 --- a/nanostack/socket_api.h +++ b/nanostack/socket_api.h @@ -115,6 +115,7 @@ extern "C" { * | | | TCP: some data acknowledged (d_len = data remaining in send queue) | * | SOCKET_NO_RAM | 0xA0 | No RAM available. | * | SOCKET_CONNECTION_PROBLEM | 0xB0 | TCP connection is retrying. | + * | SOCKET_BUSY | 0xC0 | Socket is busy or Radio channel is returning CCA failure. | * * * \section socket-tcp How to use TCP sockets: diff --git a/nanostack/ws_bbr_api.h b/nanostack/ws_bbr_api.h index 00e8623c65..2450de8546 100644 --- a/nanostack/ws_bbr_api.h +++ b/nanostack/ws_bbr_api.h @@ -88,6 +88,22 @@ typedef struct bbr_timezone_configuration { * "bit xxxxxxxxxxxxxxxS" 0 = false 1 = true Daylight saving time status*/ uint16_t status; } bbr_timezone_configuration_t; + + +/** + * \brief Border router configuration. + */ +typedef struct bbr_configuration_s { + uint32_t dhcp_address_lifetime; /**< DHCP address lifetime in seconds minimum 2 hours and maximum few days*/ + uint32_t rpl_default_lifetime; /**< RPL default lifetime value from 30 minutes to 16 hours*/ + uint16_t dag_max_rank_increase; /**< DIO Max rank increase. Range 0-2048 */ + uint16_t min_hop_rank_increase; /**< DIO Min hop rank increase. range 32-256 */ + uint16_t options; /**< Border router configuration options */ + uint8_t dio_interval_min; /**< DIO interval min. range 1-255 */ + uint8_t dio_interval_doublings; /**< DIO interval doublings. range 1-8 */ + uint8_t dio_redundancy_constant; /**< DIO redundancy constant. Range 0-10 */ +} bbr_configuration_t; + /** * Start backbone border router service. * @@ -270,7 +286,52 @@ int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit); int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validation); /** - * Sets RPL parameters + * Sets Border router configuration + * + * Sets the configuration to the border router. Use ws_configuration_get to get + * the settings and modify wanted parameters. + * + * Minor validation is done to parameters, but full validation must be done + * at application level + * + * \param interface_id Network interface ID. + * \param configuration_ptr Configuration structure. + * + * \return 0, Configuration parameters set. + * \return <0 Parameter set failed. + */ +int ws_bbr_configuration_set(int8_t interface_id, bbr_configuration_t *configuration_ptr); + +/** + * Get Border router configuration + * + * Gets the current configuration to the border router. + * + * \param interface_id Network interface ID. + * \param configuration_ptr Configuration structure. + * + * \return 0, Configuration parameters set. + * \return <0 Parameter set failed. + */ +int ws_bbr_configuration_get(int8_t interface_id, bbr_configuration_t *configuration_ptr); + +/** + * validate Border router configuration + * + * Minor validation is done to parameters. + * Full validation must be done at application level. + * + * \param interface_id Network interface ID. + * \param configuration_ptr Configuration structure. + * + * \return 0, Configuration parameters set. + * \return <0 Parameter set failed. + */ +int ws_bbr_configuration_validate(int8_t interface_id, bbr_configuration_t *configuration_ptr); + +/** + * Sets RPL parameters (DEPRECATED) + * Use ws_bbr_configuration_set instead. * * Sets RPL DIO trickle parameters. * @@ -285,7 +346,8 @@ int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validatio 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); /** - * Gets RPL parameters + * Gets RPL parameters (DEPRECATED) + * Use ws_bbr_configuration_get instead. * * Gets RPL DIO trickle parameters. * @@ -300,7 +362,8 @@ int ws_bbr_rpl_parameters_set(int8_t interface_id, uint8_t dio_interval_min, uin 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); /** - * Validate RPL parameters + * Validate RPL parameters (DEPRECATED) + * Use ws_bbr_configuration_validate instead. * * Validates RPL DIO trickle parameters. * diff --git a/source/6LoWPAN/CMakeLists.txt b/source/6LoWPAN/CMakeLists.txt new file mode 100644 index 0000000000..ef3b50ce2c --- /dev/null +++ b/source/6LoWPAN/CMakeLists.txt @@ -0,0 +1,114 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./Bootstraps + ./Fragmentation + ./IPHC_Decode + ./MAC + ./Mesh + ./ND + ./NVM + ./Thread + ./ws +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + adaptation_interface.c + + Bootstraps/Generic/network_lib.c + Bootstraps/Generic/protocol_6lowpan.c + Bootstraps/Generic/protocol_6lowpan_bootstrap.c + Bootstraps/Generic/protocol_6lowpan_interface.c + + Fragmentation/cipv6_fragmenter.c + + IPHC_Decode/6lowpan_iphc.c + IPHC_Decode/iphc_compress.c + IPHC_Decode/iphc_decompress.c + IPHC_Decode/lowpan_context.c + + MAC/beacon_handler.c + MAC/mac_data_poll.c + MAC/mac_helper.c + MAC/mac_ie_lib.c + MAC/mac_pairwise_key.c + MAC/mac_response_handler.c + + Mesh/mesh.c + + ND/nd_router_object.c + + NVM/nwk_nvm.c + + Thread/thread_bbr_api.c + Thread/thread_bbr_commercial.c + Thread/thread_beacon.c + Thread/thread_bootstrap.c + Thread/thread_border_router_api.c + Thread/thread_ccm.c + Thread/thread_commissioning_api.c + Thread/thread_commissioning_if.c + Thread/thread_common.c + Thread/thread_dhcpv6_server.c + Thread/thread_diagnostic.c + Thread/thread_discovery.c + Thread/thread_host_bootstrap.c + Thread/thread_joiner_application.c + Thread/thread_leader_service.c + Thread/thread_lowpower_api.c + Thread/thread_lowpower_private_api.c + Thread/thread_management_api.c + Thread/thread_management_client.c + Thread/thread_management_if.c + Thread/thread_management_server.c + Thread/thread_mdns.c + Thread/thread_meshcop_lib.c + Thread/thread_mle_message_handler.c + Thread/thread_nd.c + Thread/thread_neighbor_class.c + Thread/thread_net_config_api.c + Thread/thread_network_data_lib.c + Thread/thread_network_data_storage.c + Thread/thread_network_synch.c + Thread/thread_nvm_store.c + Thread/thread_resolution_client.c + Thread/thread_resolution_server.c + Thread/thread_router_bootstrap.c + Thread/thread_routing.c + Thread/thread_test_api.c + + ws/ws_bbr_api.c + ws/ws_bootstrap.c + ws/ws_bootstrap_6lbr.c + ws/ws_bootstrap_6ln.c + ws/ws_bootstrap_6lr.c + ws/ws_bootstrap_ffn.c + ws/ws_cfg_settings.c + ws/ws_common.c + ws/ws_eapol_auth_relay.c + ws/ws_eapol_pdu.c + ws/ws_eapol_relay.c + ws/ws_eapol_relay_lib.c + ws/ws_empty_functions.c + ws/ws_ie_lib.c + ws/ws_llc_data_service.c + ws/ws_management_api.c + ws/ws_mpx_header.c + ws/ws_neighbor_class.c + ws/ws_pae_auth.c + ws/ws_pae_controller.c + ws/ws_pae_key_storage.c + ws/ws_pae_lib.c + ws/ws_pae_nvm_data.c + ws/ws_pae_nvm_store.c + ws/ws_pae_supp.c + ws/ws_pae_time.c + ws/ws_pae_timers.c + ws/ws_phy.c + ws/ws_stats.c + ws/ws_test_api.c +) diff --git a/source/6LoWPAN/ND/nd_router_object.c b/source/6LoWPAN/ND/nd_router_object.c index 40aa092de5..380a2413b1 100644 --- a/source/6LoWPAN/ND/nd_router_object.c +++ b/source/6LoWPAN/ND/nd_router_object.c @@ -849,6 +849,7 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac /* Register with 2 seconds off the lifetime - don't want the NCE to expire before the route */ ipv6_route_add_metric(neigh->ip_address, 128, cur_interface->id, neigh->ip_address, ROUTE_ARO, NULL, 0, neigh->lifetime - 2, 32); +#ifdef HAVE_RPL /* We need to know peer is a host before publishing - this needs MLE. Not yet established * what to do without MLE - might need special external/non-external prioritisation at root. * This "publish for RFD" rule comes from ZigBee IP. @@ -861,6 +862,7 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac rpl_control_publish_host_address(protocol_6lowpan_rpl_domain, neigh->ip_address, neigh->lifetime); } } +#endif // HAVE_RPL protocol_6lowpan_neighbor_address_state_synch(cur_interface, aro->eui64, neigh->ip_address + 8); } else { @@ -870,10 +872,13 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac neigh->lifetime = 2; ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE); ipv6_route_add_metric(neigh->ip_address, 128, cur_interface->id, neigh->ip_address, ROUTE_ARO, NULL, 0, 4, 32); +#ifdef HAVE_RPL rpl_control_unpublish_address(protocol_6lowpan_rpl_domain, neigh->ip_address); +#endif } } +#ifdef HAVE_RPL void nd_remove_registration(protocol_interface_info_entry_t *cur_interface, addrtype_t ll_type, const uint8_t *ll_address) { ns_list_foreach_safe(ipv6_neighbour_t, cur, &cur_interface->ipv6_neighbour_cache.list) { @@ -888,7 +893,9 @@ void nd_remove_registration(protocol_interface_info_entry_t *cur_interface, addr } } } +#endif // HAVE_RPL +#ifdef HAVE_RPL /* Process ICMP Neighbor Solicitation (RFC 4861 + RFC 6775) ARO. */ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uint8_t *aro_opt, const uint8_t *slla_opt, const uint8_t *src_addr, aro_t *aro_out) { @@ -1032,6 +1039,7 @@ RESPONSE: return false; /* Tell ns_handler to not transmit now */ } } +#endif //HAVE_RPL buffer_t *nd_dac_handler(buffer_t *buf, protocol_interface_info_entry_t *cur) { @@ -1304,6 +1312,7 @@ void nd_ra_process_lowpan_context_option(protocol_interface_info_entry_t *cur, c lowpan_context_update(&cur->lowpan_contexts, cid_flags, lifetime, opt + 8, ctx_len, true); } #ifdef HAVE_6LOWPAN_ROUTER +#ifdef HAVE_RPL static void nd_ra_build(nd_router_t *cur, const uint8_t *address, protocol_interface_info_entry_t *cur_interface) { if (!(cur_interface->lowpan_info & INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY) || !icmp_nd_router_prefix_valid(cur)) { @@ -1393,7 +1402,6 @@ void nd_ra_build_by_abro(const uint8_t *abro, const uint8_t *dest, protocol_inte } } - void nd_trigger_ras_from_rs(const uint8_t *unicast_adr, protocol_interface_info_entry_t *cur_interface) { ns_list_foreach(nd_router_t, cur, &nd_router_list) { @@ -1470,7 +1478,7 @@ static nd_router_t *nd_router_object_scan_by_prefix(const uint8_t *ptr, nwk_inte return NULL; } - +#endif //HAVE_RPL #endif void gp_address_add_to_end(gp_ipv6_address_list_t *list, const uint8_t address[static 16]) diff --git a/source/6LoWPAN/adaptation_interface.c b/source/6LoWPAN/adaptation_interface.c index 6e0b296b1b..55904778f0 100644 --- a/source/6LoWPAN/adaptation_interface.c +++ b/source/6LoWPAN/adaptation_interface.c @@ -1747,6 +1747,9 @@ static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status) case MLME_SUCCESS: socket_event = SOCKET_TX_DONE; break; + case MLME_BUSY_CHAN: + socket_event = SOCKET_BUSY; + break; case MLME_TX_NO_ACK: case MLME_SECURITY_FAIL: case MLME_TRANSACTION_EXPIRED: diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 0e9fe10b8b..db4bf5e2de 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -31,6 +31,7 @@ #include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" +#include "6LoWPAN/ws/ws_bootstrap_ffn.h" #include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_pae_key_storage.h" #include "6LoWPAN/ws/ws_pae_nvm_store.h" @@ -1209,6 +1210,94 @@ int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validatio return -1; #endif } +int ws_bbr_configuration_set(int8_t interface_id, bbr_configuration_t *configuration_ptr) +{ +#ifdef HAVE_WS_BORDER_ROUTER + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + + ws_bbr_cfg_t cfg; + if (!configuration_ptr || ws_cfg_bbr_get(&cfg) < 0) { + return -1; + } + + cfg.dio_interval_min = configuration_ptr->dio_interval_min; + cfg.dio_interval_doublings = configuration_ptr->dio_interval_doublings; + cfg.dio_redundancy_constant = configuration_ptr->dio_redundancy_constant; + cfg.dag_max_rank_increase = configuration_ptr->dag_max_rank_increase; + cfg.min_hop_rank_increase = configuration_ptr->min_hop_rank_increase; + cfg.dhcp_address_lifetime = configuration_ptr->dhcp_address_lifetime; + cfg.rpl_default_lifetime = configuration_ptr->rpl_default_lifetime; + + /* Configuration change is different from settings change as it changes + * PAN version instead of RPL version. + */ + ws_bbr_configure(interface_id, configuration_ptr->options); + + if (ws_cfg_bbr_set(cur, &cfg, 0) < 0) { + return -2; + } + + return 0; +#else + (void) interface_id; + (void) configuration_ptr; + return -1; +#endif +} + +int ws_bbr_configuration_get(int8_t interface_id, bbr_configuration_t *configuration_ptr) +{ +#ifdef HAVE_WS_BORDER_ROUTER + (void) interface_id; + ws_bbr_cfg_t cfg; + if (!configuration_ptr || ws_cfg_bbr_get(&cfg) < 0) { + return -1; + } + + configuration_ptr->dio_interval_min = cfg.dio_interval_min; + configuration_ptr->dio_interval_doublings = cfg.dio_interval_doublings; + configuration_ptr->dio_redundancy_constant = cfg.dio_redundancy_constant; + configuration_ptr->dag_max_rank_increase = cfg.dag_max_rank_increase; + configuration_ptr->min_hop_rank_increase = cfg.min_hop_rank_increase; + configuration_ptr->dhcp_address_lifetime = cfg.dhcp_address_lifetime; + configuration_ptr->rpl_default_lifetime = cfg.rpl_default_lifetime; + configuration_ptr->options = configuration; + return 0; +#else + (void) interface_id; + (void) configuration_ptr; + return -1; +#endif +} + +int ws_bbr_configuration_validate(int8_t interface_id, bbr_configuration_t *configuration_ptr) +{ +#ifdef HAVE_WS_BORDER_ROUTER + (void) interface_id; + ws_bbr_cfg_t cfg; + if (!configuration_ptr || ws_cfg_bbr_get(&cfg) < 0) { + return -1; + } + + cfg.dio_interval_min = configuration_ptr->dio_interval_min; + cfg.dio_interval_doublings = configuration_ptr->dio_interval_doublings; + cfg.dio_redundancy_constant = configuration_ptr->dio_redundancy_constant; + cfg.dag_max_rank_increase = configuration_ptr->dag_max_rank_increase; + cfg.min_hop_rank_increase = configuration_ptr->min_hop_rank_increase; + cfg.dhcp_address_lifetime = configuration_ptr->dhcp_address_lifetime; + cfg.rpl_default_lifetime = configuration_ptr->rpl_default_lifetime; + + if (ws_cfg_bbr_validate(&cfg) < 0) { + return -3; + } + + return 0; +#else + (void) interface_id; + (void) configuration_ptr; + 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) { diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 253ec1d228..73473fe588 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -63,8 +63,9 @@ #include "6LoWPAN/ws/ws_stats.h" #include "6LoWPAN/ws/ws_cfg_settings.h" #include "6LoWPAN/ws/ws_bootstrap_6lbr.h" +#include "6LoWPAN/ws/ws_bootstrap_6lr.h" #include "6LoWPAN/ws/ws_bootstrap_ffn.h" -#include "6LoWPAN/ws/ws_bootstrap_lfn.h" +#include "6LoWPAN/ws/ws_bootstrap_6ln.h" #include "6LoWPAN/ws/ws_phy.h" #include "6LoWPAN/lowpan_adaptation_interface.h" #include "Service_Libs/etx/etx.h" @@ -91,24 +92,17 @@ static void ws_bootstrap_event_handler(arm_event_s *event); static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data); static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entry_t *cur); -static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur); -static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur); static void ws_bootstrap_mac_security_enable(protocol_interface_info_entry_t *cur); static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t operation, uint8_t index, uint8_t *key); static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot); static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index); static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot); static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot); -static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name); static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64); static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id); -static bool ws_bootstrap_eapol_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); -static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur); static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor); 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_bootstrap_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t ll_addr[static 16]); -static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info); static void ws_bootstrap_test_procedure_trigger_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); uint16_t test_pan_version = 1; @@ -175,7 +169,7 @@ void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *inte mac_neighbor_table_neighbor_list_clean(mac_neighbor_info(interface)); } -static void ws_address_reregister_trig(struct protocol_interface_info_entry *interface) +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; @@ -195,7 +189,7 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_ //Trigger Address Registration only when Bootstrap is ready 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_bootstrap_6lr_address_registration_update(interface, addr->address); } ws_address_reregister_trig(interface); } @@ -654,7 +648,7 @@ void ws_bootstrap_fhss_configure_channel_masks(protocol_interface_info_entry_t * cur->ws_info->hopping_schdule.channel_plan = ws_bootstrap_generate_exluded_channel_list_from_active_channels(&cur->ws_info->hopping_schdule.excluded_channels, fhss_configuration->unicast_channel_mask, fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels); } -static int8_t ws_bootstrap_fhss_initialize(protocol_interface_info_entry_t *cur) +int8_t ws_bootstrap_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; @@ -784,7 +778,7 @@ void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur, } } -static void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entry *cur) +void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entry *cur) { // Configure EUI64 for MAC if missing uint8_t mac64[8]; @@ -884,7 +878,7 @@ bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neig // True means we skip the message sending return true; } -static void ws_bootstrap_memory_configuration() +void ws_bootstrap_memory_configuration() { /* Configure memory limits for garbage collection based on total memory size * Starting from these values @@ -908,118 +902,6 @@ static void ws_bootstrap_memory_configuration() return; } - -static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) -{ - int8_t ret_val = -1; - - if (!cur) { - return -1; - } - - if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) { - tr_error("Interface not yet fully configured"); - return -2; - } - if (ws_bootstrap_fhss_initialize(cur) != 0) { - tr_error("fhss initialization failed"); - return -3; - } - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - //BBR init like NVM read - ws_bbr_init(cur); - } - // Save FHSS api - cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); - - ws_bootstrap_ll_address_validate(cur); - - addr_interface_set_ll64(cur, NULL); - cur->nwk_nd_re_scan_count = 0; - // Trigger discovery for bootstrap - ret_val = nwk_6lowpan_up(cur); - if (ret_val) { - goto cleanup; - } - - /* Wi-sun will trig event for stamechine this timer must be zero on init */ - cur->bootsrap_state_machine_cnt = 0; - /* Disable SLLAO send/mandatory receive with the ARO */ - cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true; - /* Omit sending of NA if ARO SUCCESS */ - cur->ipv6_neighbour_cache.omit_na_aro_success = true; - /* Omit sending of NA and consider ACK to be success */ - cur->ipv6_neighbour_cache.omit_na = true; - // do not process AROs from NA. This is overriden by Wi-SUN specific failure handling - cur->ipv6_neighbour_cache.recv_na_aro = false; - /* Disable NUD Probes */ - cur->ipv6_neighbour_cache.send_nud_probes = false; - cur->ipv6_neighbour_cache.probe_avoided_routers = true; - /*Replace NS handler to disable multicast address queries */ - cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit; - - dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE); - dhcp_service_link_local_rx_cb_set(cur->id, ws_bootstrap_dhcp_neighbour_update_cb); - dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used. - - dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC, WS_DHCP_SOLICIT_MAX_DELAY); - dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_dhcp_info_notify_cb); - - // Configure memory limits and garbage collection values; - ws_bootstrap_memory_configuration(); - ws_nud_table_reset(cur); - - ws_bootstrap_candidate_table_reset(cur); - // Zero uptime counters - cur->ws_info->uptime = 0; - cur->ws_info->authentication_time = 0; - cur->ws_info->connected_time = 0; - - blacklist_params_set( - WS_BLACKLIST_ENTRY_LIFETIME, - WS_BLACKLIST_TIMER_MAX_TIMEOUT, - WS_BLACKLIST_TIMER_TIMEOUT, - WS_BLACKLIST_ENTRY_MAX_NBR, - WS_BLACKLIST_PURGE_NBR, - WS_BLACKLIST_PURGE_TIMER_TIMEOUT); - - ws_bootstrap_event_discovery_start(cur); - - return 0; -cleanup: - return ret_val; -} - -static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur) -{ - if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { - return -1; - } - - tr_info("Wi-SUN ifdown"); - // Reset MAC for safe upper layer memory free - protocol_mac_reset(cur); - ns_sw_mac_fhss_unregister(cur->mac_api); - ns_fhss_delete(cur->ws_info->fhss_api); - cur->ws_info->fhss_api = NULL; - // Reset WS information - ws_bootstrap_asynch_trickle_stop(cur); - ws_llc_reset(cur); - if (nd_proxy_downstream_interface_unregister(cur->id) != 0) { - tr_warn("nd proxy unregister failed"); - } - ws_nud_table_reset(cur); - dhcp_client_delete(cur->id); - ws_eapol_relay_delete(cur); - ws_eapol_auth_relay_delete(cur); - ws_pae_controller_stop(cur); - ws_bootstrap_candidate_table_reset(cur); - blacklist_clear(); - cur->if_common_forwarding_out_cb = NULL; - - return nwk_6lowpan_down(cur); -} - void ws_bootstrap_configuration_reset(protocol_interface_info_entry_t *cur) { // Configure IP stack to operate as Wi-SUN node @@ -1738,17 +1620,17 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) if (wisun_mode_host(cur)) { // Configure for LFN device #if defined(HAVE_WS) && defined(HAVE_WS_HOST) - ws_llc_create(cur, &ws_bootstrap_lfn_asynch_ind, &ws_bootstrap_lfn_asynch_confirm, &ws_bootstrap_neighbor_info_request); + ws_llc_create(cur, & ws_bootstrap_6ln_asynch_ind, & ws_bootstrap_6ln_asynch_confirm, &ws_bootstrap_neighbor_info_request, &ws_bootstrap_6ln_eapol_relay_state_active); #endif } else if (wisun_mode_router(cur)) { // Configure FFN device #if defined(HAVE_WS) && defined(HAVE_WS_ROUTER) - ws_llc_create(cur, &ws_bootstrap_ffn_asynch_ind, &ws_bootstrap_ffn_asynch_confirm, &ws_bootstrap_neighbor_info_request); + ws_llc_create(cur, &ws_bootstrap_6lr_asynch_ind, &ws_bootstrap_6lr_asynch_confirm, &ws_bootstrap_neighbor_info_request, &ws_bootstrap_6lr_eapol_relay_state_active); #endif } else if (wisun_mode_border_router(cur)) { // Configure as Border router #if defined(HAVE_WS) && defined(HAVE_WS_BORDER_ROUTER) - ws_llc_create(cur, &ws_bootstrap_6lbr_asynch_ind, &ws_bootstrap_6lbr_asynch_confirm, &ws_bootstrap_neighbor_info_request); + ws_llc_create(cur, &ws_bootstrap_6lbr_asynch_ind, &ws_bootstrap_6lbr_asynch_confirm, &ws_bootstrap_neighbor_info_request, &ws_bootstrap_6lbr_eapol_relay_state_active); #endif } @@ -1784,7 +1666,11 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) ret_val = -4; goto init_fail; } - if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_authentication_next_target, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment, &ws_bootstrap_nw_info_updated, &ws_bootstrap_eapol_congestion_get) < 0) { + if (ws_pae_controller_nw_key_cb_register(cur, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read) < 0) { + ret_val = -4; + goto init_fail; + } + if (ws_pae_controller_authentication_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_authentication_next_target) < 0) { ret_val = -4; goto init_fail; } @@ -1806,8 +1692,21 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode) cur->ipv6_neighbour_cache.link_mtu = cur->max_link_mtu = WS_MPX_MAX_MTU; - cur->if_up = ws_bootstrap_up; - cur->if_down = ws_bootstrap_down; + switch (bootstrap_mode) { + // case NET_6LOWPAN_SLEEPY_HOST: + case NET_6LOWPAN_HOST: + cur->if_up = ws_bootstrap_6ln_up; + cur->if_down = ws_bootstrap_6ln_down; + break; + case NET_6LOWPAN_ROUTER: + case NET_6LOWPAN_BORDER_ROUTER: + cur->if_up = ws_bootstrap_ffn_up; + cur->if_down = ws_bootstrap_ffn_down; + break; + default: + break; + } + cur->ws_info->neighbor_storage = neigh_info; cur->etx_read_override = ws_etx_read; @@ -1939,8 +1838,13 @@ static int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_ set_request.value_pointer = &multi_csma_params; set_request.value_size = sizeof(mlme_multi_csma_ca_param_t); cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request); - // Start automatic CCA threshold - mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, CCA_DEFAULT_DBM, CCA_HIGH_LIMIT, CCA_LOW_LIMIT); + if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_JP) { + // For Japan regulatory domain, use static CCA threshold -80dBm as defined by Wi-SUN FAN specification + mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, -80, -80, -80); + } else { + // Start automatic CCA threshold + mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, CCA_DEFAULT_DBM, CCA_HIGH_LIMIT, CCA_LOW_LIMIT); + } // Enable MAC mode switch when base PHY mode ID could be found, otherwise disable the feature uint8_t phy_mode_id = cur->ws_info->hopping_schdule.phy_mode_id; if (phy_mode_id == 255) { @@ -2053,527 +1957,6 @@ void ws_bootstrap_ip_stack_activate(protocol_interface_info_entry_t *cur) ws_bootstrap_ip_stack_reset(cur); } -static void ws_bootstrap_set_fhss_hop(protocol_interface_info_entry_t *cur) -{ - uint16_t own_rank = ws_bootstrap_rank_get(cur); - uint16_t rank_inc = ws_bootstrap_min_rank_inc_get(cur); - if (own_rank == 0xffff || rank_inc == 0xffff) { - return; - } - // Calculate own hop count. This method gets inaccurate when hop count increases. - uint8_t own_hop = (own_rank - rank_inc) / rank_inc; - ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, own_hop); - if (own_hop == 1) { - // Allow transmitting unicast frames only on TX slots in normal mode and always in expedited forwarding mode for first hop - ns_fhss_ws_set_tx_allowance_level(cur->ws_info->fhss_api, WS_TX_SLOT, WS_TX_ALWAYS); - } else { - // Allow transmitting unicast frames only on TX slots in normal and expedited forwarding mode for other hops - ns_fhss_ws_set_tx_allowance_level(cur->ws_info->fhss_api, WS_TX_SLOT, WS_TX_SLOT); - } - tr_debug("own hop: %u, own rank: %u, rank inc: %u", own_hop, own_rank, rank_inc); -} - -static void ws_bootstrap_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t ll_addr[static 16]) -{ - if (memcmp(ll_addr, ADDR_LINK_LOCAL_PREFIX, 8)) { - return; - } - - protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); - if (!cur) { - return; - } - - uint8_t mac64[8]; - memcpy(mac64, ll_addr + 8, 8); - mac64[0] ^= 2; - ws_bootstrap_mac_neighbor_short_time_set(cur, mac64, WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME); -} - -static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info) -{ - protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); - if (!cur) { - return; - } - uint8_t server_ll64[16]; - memcpy(server_ll64, ADDR_LINK_LOCAL_PREFIX, 8); - - if (server_info->duid_length == 8) { - memcpy(server_ll64 + 8, server_info->duid, 8); - } else { - server_ll64[8] = server_info->duid[0]; - server_ll64[9] = server_info->duid[1]; - server_ll64[10] = server_info->duid[2]; - server_ll64[11] = 0xff; - server_ll64[12] = 0xfe; - server_ll64[13] = server_info->duid[3]; - server_ll64[14] = server_info->duid[4]; - server_ll64[15] = server_info->duid[5]; - } - server_ll64[8] ^= 2; - - switch (options->option_type) { - case DHCPV6_OPTION_VENDOR_SPECIFIC_INFO: - if (options->option.vendor_spesific.enterprise_number != ARM_ENTERPRISE_NUMBER) { - break; - } - while (options->option.vendor_spesific.data_length) { - uint16_t option_type; - char *domain; - uint8_t *address; - uint16_t option_len; - option_len = net_dns_option_vendor_option_data_get_next(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &option_type); - tr_debug("DHCP vendor specific data type:%u length %d", option_type, option_len); - //tr_debug("DHCP vendor specific data %s", trace_array(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length)); - - if (option_len == 0) { - // Option fields were corrupted - break; - } - if (option_type == ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT) { - // Process ARM DNS query result - domain = NULL; - address = NULL; - if (net_dns_option_vendor_option_data_dns_query_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &address, &domain) > 0 || - domain || address) { - // Valid ARM DNS query entry - net_dns_query_result_set(interface, address, domain, server_info->life_time); - } - } - if (option_type == ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION) { - timezone_info_t time_configuration; - if (net_vendor_option_time_configuration_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &time_configuration.timestamp, &time_configuration.timezone, &time_configuration.deviation, &time_configuration.status)) { - int ret = ns_time_system_timezone_info_notify(&time_configuration); - tr_info("Network Time configuration %s status:%"PRIu16" time stamp: %"PRIu64" deviation: %"PRId16" Time Zone: %"PRId16, ret == 0 ? "notified" : "notify FAILED", time_configuration.status, time_configuration.timestamp, time_configuration.deviation, time_configuration.timezone); - } - } - if (option_type == ARM_DHCP_VENDOR_DATA_NETWORK_TIME) { - // Process ARM Network Time - // Get Current time - // Get Round trip time of the DHCP request - // Estimated error is elapsed time of request - // If current time difference is larger than estimated error update current time - // set the time for server time + *.5 RTT - int32_t era; - uint32_t offset; - if (net_vendor_option_current_time_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &era, &offset, NULL)) { - uint64_t current_time; - uint64_t network_time = (era * (uint64_t)(4294967296)) + offset - 2208988800; //Convert to First day of Unix (1 Jan 1970) - - tr_debug("Network Time option Era:%"PRId32" Offset:%"PRIu32" rtt: %"PRId32" time: %"PRIu64, era, offset, server_info->rtt, network_time); - if (0 == ns_time_system_time_read(¤t_time)) { - uint64_t difference; - // We only adjust clock if time has drifted more than 10 seconds to avoid constant changing of time - // If Round trip time is very high the accuracy is reduced. - uint32_t estimated_error = 10 + server_info->rtt / 10; - // Take into account the round trip time it took the response to arrive from the time server Write the time. - network_time += server_info->rtt / 20; - - if (current_time > network_time) { - difference = current_time - network_time; - } else { - difference = network_time - current_time; - } - if (difference > estimated_error) { - // Larger than 10 second difference update the time - int ret = ns_time_system_time_write(network_time); - tr_info("Network Time %s: Era:%"PRId32" Offset:%"PRIu32" old time: %"PRIu64" time: %"PRIu64, ret == 0 ? "updated" : "update FAILED", era, offset, current_time, network_time); - } - // System time has been acquired - ns_time_system_time_acquired_set(); - } - } - } - - options->option.vendor_spesific.data_length -= option_len; - options->option.vendor_spesific.data += option_len; - } - break; - - case DHCPV6_OPTION_DNS_SERVERS: - while (options->option.generic.data_length && options->option.generic.data_length >= 16 && options->option.generic.data_length % 16 == 0) { - // Validate payload to have full 16 byte length addresses without any extra bytes - net_dns_server_address_set(interface, server_ll64, options->option.generic.data, server_info->life_time); - options->option.generic.data_length -= 16; - options->option.generic.data += 16; - } - break; - case DHCPV6_OPTION_DOMAIN_LIST: - net_dns_server_search_list_set(interface, server_ll64, options->option.generic.data, options->option.generic.data_length, server_info->life_time); - break; - default: - break; - } - -} - -static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status) -{ - (void)prefix; - (void)interface; - //TODO add handler for negative status - tr_debug("DHCPv6 %s status %u with link %s", trace_ipv6(prefix), register_status, trace_ipv6(dhcp_addr)); - if (register_status) { - protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); - if (cur) { - ws_address_reregister_trig(cur); - } - } else { - //Delete dhcpv6 client - dhcp_client_global_address_delete(interface, dhcp_addr, prefix); - } -} - - -void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local) -{ - if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, ws_dhcp_client_global_adress_cb) != 0) { - tr_error("DHCPp client request fail"); - } -} - -void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix) -{ - dhcp_client_global_address_delete(cur->id, NULL, prefix); -} - -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) -{ - tr_info("RPL parent update ... register ARO"); - ws_address_registration_update(interface, NULL); -} - -void ws_bootstrap_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) -{ - /* Possible problem with the parent connection - * Give some time for parent to rejoin and confirm the connection with ARO and DAO - */ - const rpl_dodag_conf_t *config = NULL; - uint32_t Imin_secs = 0; - - if (!ws_bootstrap_state_active(cur)) { - // If we are not in Active state no need to confirm parent - return; - } - - tr_info("RPL parent confirm"); - - if (!instance) { - // If we dont have instance we take any available to get reference - instance = rpl_control_enumerate_instances(cur->rpl_domain, NULL); - } - - if (instance) { - config = rpl_control_get_dodag_config(instance); - } - - if (config) { - //dio imin Period caluclate in seconds - uint32_t Imin_ms = config->dio_interval_min < 32 ? (1ul << config->dio_interval_min) : 0xfffffffful; - //Covert to seconds and multiple by 2 so we give time to recovery so divide by 500 do that operation - Imin_secs = (Imin_ms + 499) / 500; - - if (Imin_secs > 0xffff) { - Imin_secs = 0xffff; - } - } - if (Imin_secs == 0) { - // If we dont have RPL configuration we assume conservative value - Imin_secs = 60; - } - - /*Speed up the ARO registration*/ - if (cur->ws_info->aro_registration_timer > Imin_secs) { - cur->ws_info->aro_registration_timer = Imin_secs; - } -} - -static void ws_rpl_parent_dis_callback(const uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance) -{ - (void) ll_parent_address; - protocol_interface_info_entry_t *cur = handle; - if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { - return; - } - //Multicast DIS from parent indicate that Parent is not valid in short time window possible - ws_bootstrap_parent_confirm(cur, instance); -} - - -static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle) -{ - - protocol_interface_info_entry_t *cur = handle; - if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { - return; - } - - if (event == RPL_EVENT_POISON_FINISHED) { - //If we are waiting poison we will trig Discovery after couple seconds - if (cur->nwk_bootstrap_state == ER_RPL_NETWORK_LEAVING) { - cur->bootsrap_state_machine_cnt = 80; //Give 8 seconds time to send Poison - } - return; - } - - // if waiting for RPL and - if (event == RPL_EVENT_DAO_DONE) { - // Trigger statemachine check - cur->bootsrap_state_machine_cnt = 1; - rpl_dodag_info_t dodag_info; - struct rpl_instance *instance = rpl_control_enumerate_instances(cur->rpl_domain, NULL); - - if (instance && rpl_control_read_dodag_info(instance, &dodag_info)) { - tr_debug("Enable DHCPv6 relay"); - dhcp_relay_agent_enable(cur->id, dodag_info.dodag_id); - - tr_debug("Start EAPOL relay"); - // 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->pan_information.pan_version, cur->ws_info->cfg->gen.network_name); - // Network key is valid, indicate border router IID to controller - ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]); - //Update here Suplikant target by validated Primary Parent - if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_priority(mac_neighbor_info(cur)); - if (mac_neighbor) { - ws_pae_controller_set_target(cur, cur->ws_info->network_pan_id, mac_neighbor->mac64); - } - } - - // After successful DAO ACK connection to border router is verified - ws_common_border_router_alive_update(cur); - } - - if (!cur->ws_info->trickle_pa_running || !cur->ws_info->trickle_pc_running) { - //Enable wi-sun asynch adverisment - ws_bootstrap_advertise_start(cur); - } - - ws_bootstrap_set_fhss_hop(cur); - // Set retry configuration for bootstrap ready state - ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES); - // Set TX failure request restart configuration - ws_bootstrap_configure_data_request_restart(cur, WS_CCA_REQUEST_RESTART_MAX, WS_TX_REQUEST_RESTART_MAX, WS_REQUEST_RESTART_BLACKLIST_MIN, WS_REQUEST_RESTART_BLACKLIST_MAX); - } else if (event == RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS) { - /* - * RPL goes to passive mode, but does not require any extra changed - * - * We could remove our current addresses learned from RPL - * We could send solicit for configuration and then select new parent when those arrive - * - */ - - } else if (event == RPL_EVENT_LOCAL_REPAIR_START) { - tr_debug("RPL local repair start"); - //Disable Async and go to state 4 to confirm parent connection - ws_bootstrap_parent_confirm(cur, NULL); - // Move to state 4 if we see issues with primary parent - if (ws_bootstrap_state_active(cur)) { - tr_info("Move state 4 to wait parent connection confirmation"); - ws_bootstrap_rpl_scan_start(cur); - ws_bootstrap_network_down(cur); - } - } else if (event == RPL_EVENT_DAO_PARENT_ADD) { - ws_address_parent_update(cur); - } - cur->ws_info->rpl_state = event; - tr_info("RPL event %d", event); -} - -bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur) -{ - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) { - return true; - } - - return false; -} - -static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local) -{ - protocol_interface_info_entry_t *cur = (protocol_interface_info_entry_t *) handle; - /* Check if A-Flag. - * A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC) - * from a prefix advertised by a parent. - */ - if (prefix->options & PIO_A) { - - if (parent_link_local) { - if (icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime) != 0) { - ipv6_interface_slaac_handler(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime); - /* - * Give SLAAC addresses a different label and low precedence to indicate that - * they probably shouldn't be used for external traffic. SLAAC use in Wi-SUN is non-standard, - * and we use it for mesh-local traffic we should prefer any DHCP-assigned addresses - * for talking to the outside world - * - */ - addr_policy_table_add_entry(prefix->prefix, prefix->prefix_len, 2, WS_NON_PREFFRED_LABEL); - } - } else { - icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, 0, 0); - } - } else if (prefix->prefix_len) { - // Create new address using DHCP - if (parent_link_local) { - ws_dhcp_client_address_request(cur, prefix->prefix, parent_link_local); - } else { - /* Deprecate address and remove client */ - tr_debug("Prefix invalidation %s", trace_ipv6(prefix->prefix)); - dhcp_client_global_address_delete(cur->id, NULL, prefix->prefix); - } - } -} - -static bool ws_rpl_candidate_soft_filtering(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) -{ - //Already many candidates - uint16_t candidate_list_size = rpl_control_candidate_list_size(cur, instance); - if (candidate_list_size >= cur->ws_info->cfg->gen.rpl_parent_candidate_max) { - return false; - } - - uint16_t selected_parents = rpl_control_selected_parent_count(cur, instance); - - //Already enough selected candidates - if (selected_parents >= cur->ws_info->cfg->gen.rpl_selected_parent_max) { - candidate_list_size -= selected_parents; - if (candidate_list_size >= 2) { - //We have more candidates than selected - return false; - } - } - - return true; -} - -static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank) -{ - - protocol_interface_info_entry_t *cur = handle; - if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { - return false; - } - - if (blacklist_reject(ll_parent_address)) { - // Rejected by blacklist - return false; - } - - uint8_t mac64[10]; - //bool replace_ok = false; - //bool create_ok = false; - llc_neighbour_req_t neigh_buffer; - - //Discover neigh ready here for possible ETX validate - memcpy(mac64, ll_parent_address + 8, 8); - mac64[0] ^= 2; - - - ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false); - //Discover Multicast temporary entry for create neighbour table entry for new candidate - ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); - - if (!ws_rpl_candidate_soft_filtering(cur, instance)) { - - //Acept only better than own rank here - if (candidate_rank >= rpl_control_current_rank(instance)) { - //Do not accept no more siblings - return false; - } - - uint16_t candidate_list_size = rpl_control_candidate_list_size(cur, instance); - if (candidate_list_size > cur->ws_info->cfg->gen.rpl_parent_candidate_max + 1) { - //Accept only 1 better 1 time - return false; - } - - if (!neigh_buffer.neighbor) { - //Do not accept any new in that Place - return false; - } - - uint8_t replacing[16]; - //Accept Know neighbour if it is enough good - if (!rpl_control_find_worst_neighbor(cur, instance, replacing)) { - return false; - } - // +2 Is for PAN ID space - memcpy(mac64, replacing + 8, 8); - mac64[0] ^= 2; - - if (ws_local_etx_read(cur, ADDR_802_15_4_LONG, mac64) == 0xffff) { - //Not probed yet because ETX is 0xffff - return false; - } - - uint16_t etx = 0; - if (neigh_buffer.neighbor) { - etx = ws_local_etx_read(cur, ADDR_802_15_4_LONG, neigh_buffer.neighbor->mac64); - } - - // Accept now only better one's when max candidates selected and max candidate list size is reached - return rpl_possible_better_candidate(cur, instance, replacing, candidate_rank, etx); - } - - //Neighbour allready - if (neigh_buffer.neighbor) { - return true; - } - - if (!entry) { - //No Multicast Entry Available - return false; - } - - //Create entry - bool create_ok = ws_bootstrap_neighbor_info_request(cur, entry->mac64, &neigh_buffer, true); - if (create_ok) { - ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; - ws_bootstrap_neighbor_set_stable(cur, entry->mac64); - //Copy fhss temporary data - *ws_neigh = entry->neigh_info_list; - mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true); - } - ws_llc_free_multicast_temp_entry(cur, entry); - -#if 0 -neigh_create_ok: - - if (create_ok && replace_ok) { - //Try remove here when accepted new better one possible - tr_debug("Remove %s by %s", trace_ipv6(replacing), trace_ipv6(ll_parent_address)); - rpl_control_neighbor_delete_from_instance(cur, instance, replacing); - } -#endif - return create_ok; -} static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entry_t *cur) { mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_priority(mac_neighbor_info(cur)); @@ -2600,92 +1983,6 @@ static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entr return ws_neighbor->routing_cost + etx; } -static struct rpl_instance *ws_bootstrap_get_rpl_instance(protocol_interface_info_entry_t *cur) -{ - if (!cur || !cur->rpl_domain) { - return NULL; - } - struct rpl_instance *best_instance = NULL; - ns_list_foreach(struct rpl_instance, instance, &cur->rpl_domain->instances) { - best_instance = instance; - // Select best grounded and lowest rank? But there should be only one really - } - return best_instance; -} - -static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur) -{ - struct rpl_instance *rpl_instance = ws_bootstrap_get_rpl_instance(cur); - if (!rpl_instance) { - return 0xffff; - } - return rpl_control_current_rank(rpl_instance); -} - - -static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur) -{ - struct rpl_instance *rpl_instance = ws_bootstrap_get_rpl_instance(cur); - if (!rpl_instance) { - return 0xffff; - } - struct rpl_dodag_info_t dodag_info; - if (!rpl_control_read_dodag_info(rpl_instance, &dodag_info)) { - return 0xffff; - } - return dodag_info.dag_min_hop_rank_inc; -} - -void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur) -{ - tr_debug("Start RPL learn"); - // Stop Trickle timers - ws_bootstrap_asynch_trickle_stop(cur); - - // routers wait until RPL root is contacted - ws_bootstrap_state_change(cur, ER_RPL_SCAN); - // Change state as the state is checked in state machine - cur->ws_info->rpl_state = RPL_EVENT_LOCAL_REPAIR_START; - //For Large network and medium should do passive scan - if (ws_cfg_network_config_get(cur) > CONFIG_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); - } -} - -void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) -{ - tr_debug("RPL Activate"); - bool downstream = true; - bool leaf = false; - - addr_add_router_groups(cur); - rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, downstream); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback, ws_rpl_parent_dis_callback, cur); - // If i am router I Do this - rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); - 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); - rpl_control_set_force_tunnel(true); - 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 -} - void ws_bootstrap_network_start(protocol_interface_info_entry_t *cur) { //Set Network names, Pan information configure, hopping schedule & GTKHash @@ -2702,12 +1999,6 @@ void ws_bootstrap_advertise_start(protocol_interface_info_entry_t *cur) 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) -{ - (void)cur; - ws_bbr_pan_version_increase(cur); -} - // Start authentication void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur) { @@ -2760,36 +2051,6 @@ static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t * mac_helper_key_link_frame_counter_read(cur->id, counter, slot); } -static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *cur, uint16_t pan_id, uint16_t pan_version, char *network_name) -{ - /* For border router, the PAE controller reads PAN ID, PAN version and network name from storage. - * If they are set, takes them into use here. - */ - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - // Get network name - ws_gen_cfg_t gen_cfg; - if (ws_cfg_gen_get(&gen_cfg) < 0) { - return; - } - - // If PAN ID has not been set, set it - if (cur->ws_info->network_pan_id == 0xffff) { - cur->ws_info->network_pan_id = pan_id; - // Sets PAN version - cur->ws_info->pan_information.pan_version = pan_version; - cur->ws_info->pan_information.pan_version_set = true; - } - - // If network name has not been set, set it - if (strlen(gen_cfg.network_name) == 0) { - strncpy(gen_cfg.network_name, network_name, 32); - } - - // Stores the settings - ws_cfg_gen_set(cur, &gen_cfg, 0); - } -} - static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64) { if (result == AUTH_RESULT_OK) { @@ -2841,79 +2102,6 @@ static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface return previous_eui_64; } -static bool ws_bootstrap_eapol_congestion_get(protocol_interface_info_entry_t *cur, uint16_t active_supp) -{ - if (cur == NULL || cur->random_early_detection == NULL || cur->llc_random_early_detection == NULL || cur->llc_eapol_random_early_detection == NULL) { - return false; - } - - bool return_value = false; - static struct red_info_s *red_info = NULL; - uint16_t adaptation_average = 0; - uint16_t llc_average = 0; - uint16_t llc_eapol_average = 0; - uint16_t average_sum = 0; - uint8_t active_max = 0; - - //TODO implement API for HEAP info request - uint32_t heap_size; - const mem_stat_t *mem_stats = ns_dyn_mem_get_mem_stat(); - if (mem_stats) { - heap_size = mem_stats->heap_sector_size; - } else { - heap_size = 0; - } - - /* - * For different memory sizes the max simultaneous authentications will be - * 32k: (32k / 50k) * 2 + 1 = 1 - * 65k: (65k / 50k) * 2 + 1 = 3 - * 250k: (250k / 50k) * 2 + 1 = 11 - * 1000k: (1000k / 50k) * 2 + 1 = 41 - * 2000k: (2000k / 50k) * 2 + 1 = 50 (upper limit) - */ - active_max = (heap_size / 50000) * 2 + 1; - if (active_max > 50) { - active_max = 50; - } - - // Read the values for adaptation and LLC queues - adaptation_average = random_early_detetction_aq_read(cur->random_early_detection); - llc_average = random_early_detetction_aq_read(cur->llc_random_early_detection); - llc_eapol_average = random_early_detetction_aq_read(cur->llc_eapol_random_early_detection); - // Calculate combined average - average_sum = adaptation_average + llc_average + llc_eapol_average; - - // Maximum for active supplicants based on memory reached, fail - if (active_supp >= active_max) { - return_value = true; - goto congestion_get_end; - } - - // Always allow at least five negotiations (if memory does not limit) - if (active_supp < 5) { - goto congestion_get_end; - } - - if (red_info == NULL) { - red_info = random_early_detection_create( - cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_min, - cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_max, - 100, RED_AVERAGE_WEIGHT_DISABLED); - } - if (red_info == NULL) { - goto congestion_get_end; - } - - // Check drop probability - average_sum = random_early_detetction_aq_calc(red_info, average_sum); - return_value = random_early_detection_congestion_check(red_info); - -congestion_get_end: - tr_info("Active supplicant limit, active: %i max: %i summed averageQ: %i adapt averageQ: %i LLC averageQ: %i LLC EAPOL averageQ: %i drop: %s", active_supp, active_max, average_sum, adaptation_average, llc_average, llc_eapol_average, return_value ? "T" : "F"); - - return return_value; -} /* * Event transitions @@ -3079,9 +2267,9 @@ static void ws_bootstrap_event_handler(arm_event_s *event) } if (wisun_mode_host(cur)) { - ws_bootstrap_lfn_event_handler(cur, event); + ws_bootstrap_6ln_event_handler(cur, event); } else if (wisun_mode_router(cur)) { - ws_bootstrap_ffn_event_handler(cur, event); + ws_bootstrap_6lr_event_handler(cur, event); } else if (wisun_mode_border_router(cur)) { ws_bootstrap_6lbr_event_handler(cur, event); } @@ -3298,32 +2486,6 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s ws_bootstrap_test_procedure_trigger_timer(cur, seconds); } -void ws_bootstrap_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) -{ - if (interface->ws_info) { - llc_neighbour_req_t neighbor_info; - neighbor_info.neighbor = neighbor; - neighbor_info.ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor->index); - ws_bootstrap_primary_parent_set(interface, &neighbor_info, WS_PARENT_HARD_SYNCH); - uint8_t link_local_address[16]; - ws_common_create_ll_address(link_local_address, neighbor->mac64); - dhcp_client_server_address_update(interface->id, NULL, link_local_address); - - ws_bootstrap_secondary_parent_update(interface); - } -} - -void ws_bootstrap_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_parent_update(interface); - } - } - } -} - int ws_bootstrap_stack_info_get(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr) { diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index 8c08a43978..b114ee9146 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -18,7 +18,6 @@ #ifndef WS_BOOTSTRAP_H_ #define WS_BOOTSTRAP_H_ - typedef enum { WS_INIT_EVENT = 0, /**< tasklet initializion event*/ WS_DISCOVERY_START, /**< discovery start*/ @@ -76,8 +75,6 @@ extern uint16_t test_pan_version; int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode); -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); @@ -92,22 +89,20 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); -void ws_bootstrap_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor); - -void ws_bootstrap_secondary_parent_update(protocol_interface_info_entry_t *interface); - void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor); void ws_nud_active_timer(protocol_interface_info_entry_t *cur, uint16_t ticks); -void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local); - -void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix); - -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); +void ws_bootstrap_ll_address_validate(struct protocol_interface_info_entry *cur); + +uint16_t ws_local_etx_read(protocol_interface_info_entry_t *interface, addrtype_t addr_type, const uint8_t *mac_adddress); + +bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neighbour_t *entry, bool unicast, uint8_t seq); + +void ws_bootstrap_memory_configuration(); + bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_interface_info_entry *cur); bool ws_bootstrap_validate_channel_function(struct ws_us_ie *ws_us, struct ws_bs_ie *ws_bs); @@ -166,16 +161,15 @@ void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cu parent_info_t *ws_bootstrap_candidate_parent_get_best(protocol_interface_info_entry_t *cur); void ws_bootstrap_primary_parent_set(struct protocol_interface_info_entry *cur, struct llc_neighbour_req *neighbor_info, ws_parent_synch_e synch_req); -void ws_bootstrap_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance); bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, struct llc_neighbour_req *neighbor_buffer, bool request_new); void ws_bootstrap_neighbor_list_clean(struct protocol_interface_info_entry *interface); int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr, bool clear_list); +void ws_address_reregister_trig(struct protocol_interface_info_entry *interface); void ws_nud_table_reset(protocol_interface_info_entry_t *cur); -void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]); - void ws_bootstrap_configure_csma_ca_backoffs(protocol_interface_info_entry_t *cur, uint8_t max_backoffs, uint8_t min_be, uint8_t max_be); void ws_bootstrap_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration); +int8_t ws_bootstrap_fhss_initialize(protocol_interface_info_entry_t *cur); int8_t ws_bootstrap_fhss_set_defaults(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration); void ws_bootstrap_fhss_activate(protocol_interface_info_entry_t *cur); uint16_t ws_bootstrap_randomize_fixed_channel(uint16_t configured_fixed_channel, uint8_t number_of_channels, uint32_t *channel_mask); @@ -186,9 +180,6 @@ void ws_bootstrap_configure_data_request_restart(protocol_interface_info_entry_t void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry *cur, const fhss_ws_configuration_t *fhss_configuration); -void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur); -void ws_bootstrap_rpl_scan_start(protocol_interface_info_entry_t *cur); - void ws_bootstrap_ip_stack_reset(protocol_interface_info_entry_t *cur); void ws_bootstrap_ip_stack_activate(protocol_interface_info_entry_t *cur); @@ -201,13 +192,10 @@ void ws_bootstrap_network_start(protocol_interface_info_entry_t *cur); #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) -#define ws_bootstrap_state_machine(cur) #define ws_bootstrap_restart(cur) #define ws_bootstrap_neighbor_remove(cur, ll_address) #define ws_bootstrap_aro_failure(cur, ll_address) #define ws_bootstrap_neighbor_set_stable(interface, src64) -#define ws_bootstrap_primary_parent_update(interface, neighbor) -#define ws_bootstrap_secondary_parent_update(interface) #define ws_bootstrap_stack_info_get(cur, info_ptr) #define ws_bootstrap_neighbor_info_get(cur, neighbor_ptr, count) #define ws_bootstrap_test_procedure_trigger(cur, procedure); diff --git a/source/6LoWPAN/ws/ws_bootstrap_6lbr.c b/source/6LoWPAN/ws/ws_bootstrap_6lbr.c index a5e9ac3037..34139e44a4 100644 --- a/source/6LoWPAN/ws/ws_bootstrap_6lbr.c +++ b/source/6LoWPAN/ws/ws_bootstrap_6lbr.c @@ -54,6 +54,7 @@ #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_config.h" #include "6LoWPAN/ws/ws_common.h" +#include "6LoWPAN/ws/ws_bootstrap_ffn.h" #include "6LoWPAN/ws/ws_bootstrap.h" #include "6LoWPAN/ws/ws_bbr_api_internal.h" #include "6LoWPAN/ws/ws_common_defines.h" @@ -271,6 +272,123 @@ void ws_bootstrap_6lbr_asynch_confirm(struct protocol_interface_info_entry *inte } } +bool ws_bootstrap_6lbr_eapol_relay_state_active(protocol_interface_info_entry_t *cur) +{ + (void) cur; + + return true; +} + +static void ws_bootstrap_6lbr_pan_version_increment(protocol_interface_info_entry_t *cur) +{ + (void)cur; + ws_bbr_pan_version_increase(cur); +} + +static void ws_bootstrap_6lbr_nw_info_updated(protocol_interface_info_entry_t *cur, uint16_t pan_id, uint16_t pan_version, char *network_name) +{ + /* For border router, the PAE controller reads PAN ID, PAN version and network name from storage. + * If they are set, takes them into use here. + */ + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + // Get network name + ws_gen_cfg_t gen_cfg; + if (ws_cfg_gen_get(&gen_cfg) < 0) { + return; + } + + // If PAN ID has not been set, set it + if (cur->ws_info->network_pan_id == 0xffff) { + cur->ws_info->network_pan_id = pan_id; + // Sets PAN version + cur->ws_info->pan_information.pan_version = pan_version; + cur->ws_info->pan_information.pan_version_set = true; + } + + // If network name has not been set, set it + if (strlen(gen_cfg.network_name) == 0) { + strncpy(gen_cfg.network_name, network_name, 32); + } + + // Stores the settings + ws_cfg_gen_set(cur, &gen_cfg, 0); + } +} + +static bool ws_bootstrap_6lbr_eapol_congestion_get(protocol_interface_info_entry_t *cur, uint16_t active_supp) +{ + if (cur == NULL || cur->random_early_detection == NULL || cur->llc_random_early_detection == NULL || cur->llc_eapol_random_early_detection == NULL) { + return false; + } + + bool return_value = false; + static struct red_info_s *red_info = NULL; + uint16_t adaptation_average = 0; + uint16_t llc_average = 0; + uint16_t llc_eapol_average = 0; + uint16_t average_sum = 0; + uint8_t active_max = 0; + + //TODO implement API for HEAP info request + uint32_t heap_size; + const mem_stat_t *mem_stats = ns_dyn_mem_get_mem_stat(); + if (mem_stats) { + heap_size = mem_stats->heap_sector_size; + } else { + heap_size = 0; + } + + /* + * For different memory sizes the max simultaneous authentications will be + * 32k: (32k / 50k) * 2 + 1 = 1 + * 65k: (65k / 50k) * 2 + 1 = 3 + * 250k: (250k / 50k) * 2 + 1 = 11 + * 1000k: (1000k / 50k) * 2 + 1 = 41 + * 2000k: (2000k / 50k) * 2 + 1 = 50 (upper limit) + */ + active_max = (heap_size / 50000) * 2 + 1; + if (active_max > 50) { + active_max = 50; + } + + // Read the values for adaptation and LLC queues + adaptation_average = random_early_detetction_aq_read(cur->random_early_detection); + llc_average = random_early_detetction_aq_read(cur->llc_random_early_detection); + llc_eapol_average = random_early_detetction_aq_read(cur->llc_eapol_random_early_detection); + // Calculate combined average + average_sum = adaptation_average + llc_average + llc_eapol_average; + + // Maximum for active supplicants based on memory reached, fail + if (active_supp >= active_max) { + return_value = true; + goto congestion_get_end; + } + + // Always allow at least five negotiations (if memory does not limit) + if (active_supp < 5) { + goto congestion_get_end; + } + + if (red_info == NULL) { + red_info = random_early_detection_create( + cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_min, + cur->ws_info->cfg->sec_prot.max_simult_sec_neg_tx_queue_max, + 100, RED_AVERAGE_WEIGHT_DISABLED); + } + if (red_info == NULL) { + goto congestion_get_end; + } + + // Check drop probability + average_sum = random_early_detetction_aq_calc(red_info, average_sum); + return_value = random_early_detection_congestion_check(red_info); + +congestion_get_end: + tr_info("Active supplicant limit, active: %i max: %i summed averageQ: %i adapt averageQ: %i LLC averageQ: %i LLC EAPOL averageQ: %i drop: %s", active_supp, active_max, average_sum, adaptation_average, llc_average, llc_eapol_average, return_value ? "T" : "F"); + + return return_value; +} + void ws_bootstrap_6lbr_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event) { ws_bootsrap_event_type_e event_type; @@ -371,8 +489,11 @@ void ws_bootstrap_6lbr_event_handler(protocol_interface_info_entry_t *cur, arm_e // Set PAN ID and network name to controller ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name); - // Set backbone IP address get callback - ws_pae_controller_auth_cb_register(cur, ws_bootstrap_6lbr_backbone_ip_addr_get); + // Set information callbacks (backbone IP address get callback, network information, congestion) + ws_pae_controller_information_cb_register(cur, ws_bootstrap_6lbr_backbone_ip_addr_get, &ws_bootstrap_6lbr_nw_info_updated, &ws_bootstrap_6lbr_eapol_congestion_get); + + // Set PAN version control callbacks + ws_pae_controller_pan_version_cb_register(cur, &ws_bootstrap_6lbr_pan_version_increment); // 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); @@ -402,7 +523,7 @@ void ws_bootstrap_6lbr_event_handler(protocol_interface_info_entry_t *cur, arm_e // Activate RPL // Activate IPv6 stack ws_bootstrap_ip_stack_activate(cur); - ws_bootstrap_rpl_activate(cur); + ws_bootstrap_ffn_rpl_configure(cur); ws_bootstrap_network_start(cur); // Wait for RPL start ws_bootstrap_event_routing_ready(cur); diff --git a/source/6LoWPAN/ws/ws_bootstrap_6lbr.h b/source/6LoWPAN/ws/ws_bootstrap_6lbr.h index 5517793fb5..716454484e 100644 --- a/source/6LoWPAN/ws/ws_bootstrap_6lbr.h +++ b/source/6LoWPAN/ws/ws_bootstrap_6lbr.h @@ -22,6 +22,7 @@ void ws_bootstrap_6lbr_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); void ws_bootstrap_6lbr_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message); +bool ws_bootstrap_6lbr_eapol_relay_state_active(protocol_interface_info_entry_t *cur); void ws_bootstrap_6lbr_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event); void ws_bootstrap_6lbr_state_machine(protocol_interface_info_entry_t *cur); void ws_bootstrap_6lbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); @@ -32,6 +33,7 @@ void ws_bootstrap_6lbr_seconds_timer(protocol_interface_info_entry_t *cur, uint3 #define ws_bootstrap_6lbr_asynch_ind(cur, data, ie_ext, message_type) ((void) 0) #define ws_bootstrap_6lbr_asynch_confirm(interface, asynch_message) ((void) 0) +#define ws_bootstrap_6lbr_eapol_relay_state_active(cur) false #define ws_bootstrap_6lbr_event_handler(cur, event) ((void) 0) #define ws_bootstrap_6lbr_state_machine(cur) ((void) 0) #define ws_bootstrap_6lbr_seconds_timer(cur, seconds) ((void) 0) diff --git a/source/6LoWPAN/ws/ws_bootstrap_lfn.c b/source/6LoWPAN/ws/ws_bootstrap_6ln.c similarity index 57% rename from source/6LoWPAN/ws/ws_bootstrap_lfn.c rename to source/6LoWPAN/ws/ws_bootstrap_6ln.c index 7e0a46cc49..824cb19646 100644 --- a/source/6LoWPAN/ws/ws_bootstrap_lfn.c +++ b/source/6LoWPAN/ws/ws_bootstrap_6ln.c @@ -85,7 +85,7 @@ #define TRACE_GROUP "wsbs" -void ws_bootstrap_lfn_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) +void ws_bootstrap_6ln_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) { (void)ie_ext; // Store weakest heard packet RSSI @@ -101,13 +101,20 @@ void ws_bootstrap_lfn_asynch_ind(struct protocol_interface_info_entry *cur, cons tr_warn("Wi-SUN LFN Mode received message id: %x", message_type); } -void ws_bootstrap_lfn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message) +void ws_bootstrap_6ln_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message) { (void)asynch_message; ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1); } -void ws_bootstrap_lfn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event) +bool ws_bootstrap_6ln_eapol_relay_state_active(protocol_interface_info_entry_t *cur) +{ + (void) cur; + + return false; +} + +void ws_bootstrap_6ln_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event) { (void)cur; ws_bootsrap_event_type_e event_type; @@ -130,7 +137,7 @@ void ws_bootstrap_lfn_event_handler(protocol_interface_info_entry_t *cur, arm_ev } } -void ws_bootstrap_lfn_state_machine(protocol_interface_info_entry_t *cur) +void ws_bootstrap_6ln_state_machine(protocol_interface_info_entry_t *cur) { switch (cur->nwk_bootstrap_state) { @@ -162,11 +169,111 @@ void ws_bootstrap_lfn_state_machine(protocol_interface_info_entry_t *cur) } } -void ws_bootstrap_lfn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) +void ws_bootstrap_6ln_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) { (void)cur; (void)seconds; } +int8_t ws_bootstrap_6ln_up(protocol_interface_info_entry_t *cur) +{ + int8_t ret_val = -1; + + if (!cur) { + return -1; + } + + if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) { + tr_error("Interface not yet fully configured"); + return -2; + } + if (ws_bootstrap_fhss_initialize(cur) != 0) { + tr_error("fhss initialization failed"); + return -3; + } + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //BBR init like NVM read + ws_bbr_init(cur); + } + // Save FHSS api + cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); + + ws_bootstrap_ll_address_validate(cur); + + addr_interface_set_ll64(cur, NULL); + cur->nwk_nd_re_scan_count = 0; + // Trigger discovery for bootstrap + ret_val = nwk_6lowpan_up(cur); + if (ret_val) { + goto cleanup; + } + + /* Wi-sun will trig event for stamechine this timer must be zero on init */ + cur->bootsrap_state_machine_cnt = 0; + /* Disable SLLAO send/mandatory receive with the ARO */ + cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true; + /* Omit sending of NA if ARO SUCCESS */ + cur->ipv6_neighbour_cache.omit_na_aro_success = true; + /* Omit sending of NA and consider ACK to be success */ + cur->ipv6_neighbour_cache.omit_na = true; + // do not process AROs from NA. This is overriden by Wi-SUN specific failure handling + cur->ipv6_neighbour_cache.recv_na_aro = false; + /* Disable NUD Probes */ + cur->ipv6_neighbour_cache.send_nud_probes = false; + cur->ipv6_neighbour_cache.probe_avoided_routers = true; + /*Replace NS handler to disable multicast address queries */ + cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit; + + // Configure memory limits and garbage collection values; + ws_bootstrap_memory_configuration(); + ws_nud_table_reset(cur); + + ws_bootstrap_candidate_table_reset(cur); + // Zero uptime counters + cur->ws_info->uptime = 0; + cur->ws_info->authentication_time = 0; + cur->ws_info->connected_time = 0; + + blacklist_params_set( + WS_BLACKLIST_ENTRY_LIFETIME, + WS_BLACKLIST_TIMER_MAX_TIMEOUT, + WS_BLACKLIST_TIMER_TIMEOUT, + WS_BLACKLIST_ENTRY_MAX_NBR, + WS_BLACKLIST_PURGE_NBR, + WS_BLACKLIST_PURGE_TIMER_TIMEOUT); + + ws_bootstrap_event_discovery_start(cur); + + return 0; +cleanup: + return ret_val; +} + +int8_t ws_bootstrap_6ln_down(protocol_interface_info_entry_t *cur) +{ + if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { + return -1; + } + + tr_info("Wi-SUN ifdown"); + // Reset MAC for safe upper layer memory free + protocol_mac_reset(cur); + ns_sw_mac_fhss_unregister(cur->mac_api); + ns_fhss_delete(cur->ws_info->fhss_api); + cur->ws_info->fhss_api = NULL; + // Reset WS information + ws_bootstrap_asynch_trickle_stop(cur); + ws_llc_reset(cur); + if (nd_proxy_downstream_interface_unregister(cur->id) != 0) { + tr_warn("nd proxy unregister failed"); + } + ws_nud_table_reset(cur); + ws_pae_controller_stop(cur); + ws_bootstrap_candidate_table_reset(cur); + blacklist_clear(); + cur->if_common_forwarding_out_cb = NULL; + + return nwk_6lowpan_down(cur); +} #endif //HAVE_WS_BORDER_ROUTER && HAVE_WS diff --git a/source/6LoWPAN/ws/ws_bootstrap_6ln.h b/source/6LoWPAN/ws/ws_bootstrap_6ln.h new file mode 100644 index 0000000000..0b9edeffdc --- /dev/null +++ b/source/6LoWPAN/ws/ws_bootstrap_6ln.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021, Pelion 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_BOOTSTRAP_6LN_H_ +#define WS_BOOTSTRAP_6LN_H_ + +#if defined(HAVE_WS) && defined(HAVE_WS_HOST) + +void ws_bootstrap_6ln_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); +void ws_bootstrap_6ln_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message); +bool ws_bootstrap_6ln_eapol_relay_state_active(protocol_interface_info_entry_t *cur); +void ws_bootstrap_6ln_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event); +void ws_bootstrap_6ln_state_machine(protocol_interface_info_entry_t *cur); +void ws_bootstrap_6ln_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); + +int8_t ws_bootstrap_6ln_up(protocol_interface_info_entry_t *cur); +int8_t ws_bootstrap_6ln_down(protocol_interface_info_entry_t *cur); + +#define wisun_mode_host(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST) + +#else + +#define ws_bootstrap_6lr_asynch_ind(cur, data, ie_ext, message_type) ((void) 0) +#define ws_bootstrap_6lr_asynch_confirm(interface, asynch_message) ((void) 0) +#define ws_bootstrap_6ln_eapol_relay_state_active(false) false +#define ws_bootstrap_6lr_event_handler(cur, event) ((void) 0) +#define ws_bootstrap_6ln_state_machine(cur) ((void) 0) +#define ws_bootstrap_6ln_seconds_timer(cur, seconds) ((void) 0) + +#define ws_bootstrap_6ln_up(cur) +#define ws_bootstrap_6ln_down(cur) + +#define wisun_mode_host(cur) (false) + +#endif //HAVE_WS + +#endif /* WS_BOOTSTRAP_6LN_H_ */ diff --git a/source/6LoWPAN/ws/ws_bootstrap_6lr.c b/source/6LoWPAN/ws/ws_bootstrap_6lr.c new file mode 100644 index 0000000000..d7a5cf8d81 --- /dev/null +++ b/source/6LoWPAN/ws/ws_bootstrap_6lr.c @@ -0,0 +1,1477 @@ +/* + * Copyright (c) 2021, Pelion 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" +#if defined(HAVE_WS) && defined(HAVE_WS_ROUTER) +#include "ns_types.h" +#include "ns_trace.h" +#include "nsdynmemLIB.h" +#include "net_interface.h" +#include "eventOS_event.h" +#include "randLIB.h" +#include "common_functions.h" +#include "mac_common_defines.h" +#include "sw_mac.h" +#include "ccmLIB.h" +#include "Core/include/ns_monitor.h" +#include "NWK_INTERFACE/Include/protocol.h" +#include "6LoWPAN/Bootstraps/protocol_6lowpan.h" +#include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h" +#include "ipv6_stack/protocol_ipv6.h" +#include "ipv6_stack/ipv6_routing_table.h" +#include "6LoWPAN/MAC/mac_helper.h" +#include "6LoWPAN/MAC/mac_data_poll.h" +#include "6LoWPAN/MAC/mpx_api.h" +#include "6LoWPAN/MAC/mac_ie_lib.h" +#include "MPL/mpl.h" +#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" +#include "Common_Protocols/ip.h" +#include "Service_Libs/Trickle/trickle.h" +#include "Service_Libs/fhss/channel_list.h" +#include "Service_Libs/utils/ns_time.h" +#include "6LoWPAN/ws/ws_common_defines.h" +#include "6LoWPAN/ws/ws_common_defines.h" +#include "6LoWPAN/ws/ws_config.h" +#include "6LoWPAN/ws/ws_common.h" +#include "6LoWPAN/ws/ws_bootstrap.h" +#include "6LoWPAN/ws/ws_bootstrap_6lr.h" +#include "6LoWPAN/ws/ws_bootstrap_ffn.h" +#include "6LoWPAN/ws/ws_bbr_api_internal.h" +#include "6LoWPAN/ws/ws_common_defines.h" +#include "6LoWPAN/ws/ws_llc.h" +#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" +#include "Service_Libs/nd_proxy/nd_proxy.h" +#include "Service_Libs/blacklist/blacklist.h" +#include "platform/topo_trace.h" +#include "dhcp_service_api.h" +#include "libDHCPv6/libDHCPv6.h" +#include "libDHCPv6/libDHCPv6_vendordata.h" +#include "DHCPv6_client/dhcpv6_client_api.h" +#include "ws_management_api.h" +#include "net_rpl.h" +#include "mac_api.h" +#include "6LoWPAN/ws/ws_pae_controller.h" +#include "6LoWPAN/ws/ws_eapol_pdu.h" +#include "6LoWPAN/ws/ws_eapol_auth_relay.h" +#include "6LoWPAN/ws/ws_eapol_relay.h" +#include "libNET/src/net_dns_internal.h" +#include "Service_Libs/random_early_detection/random_early_detection_api.h" + +#define TRACE_GROUP "wsbs" + +static void ws_bootstrap_6lr_address_update(protocol_interface_info_entry_t *interface); +static void ws_bootstrap_6lr_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance); +static struct rpl_instance *ws_bootstrap_6lr_get_rpl_instance(protocol_interface_info_entry_t *cur); +static uint16_t ws_bootstrap_6lr_rank_get(protocol_interface_info_entry_t *cur); +static uint16_t ws_bootstrap_6lr_min_rank_inc_get(protocol_interface_info_entry_t *cur); + + +static void ws_bootstrap_6lr_set_fhss_hop(protocol_interface_info_entry_t *cur) +{ + uint16_t own_rank = ws_bootstrap_6lr_rank_get(cur); + uint16_t rank_inc = ws_bootstrap_6lr_min_rank_inc_get(cur); + if (own_rank == 0xffff || rank_inc == 0xffff) { + return; + } + // Calculate own hop count. This method gets inaccurate when hop count increases. + uint8_t own_hop = (own_rank - rank_inc) / rank_inc; + ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, own_hop); + if (own_hop == 1) { + // Allow transmitting unicast frames only on TX slots in normal mode and always in expedited forwarding mode for first hop + ns_fhss_ws_set_tx_allowance_level(cur->ws_info->fhss_api, WS_TX_SLOT, WS_TX_ALWAYS); + } else { + // Allow transmitting unicast frames only on TX slots in normal and expedited forwarding mode for other hops + ns_fhss_ws_set_tx_allowance_level(cur->ws_info->fhss_api, WS_TX_SLOT, WS_TX_SLOT); + } + tr_debug("own hop: %u, own rank: %u, rank inc: %u", own_hop, own_rank, rank_inc); +} + +static void ws_bootstrap_6lr_ip_stack_addr_clear(protocol_interface_info_entry_t *cur) +{ + tr_debug("ip stack address clear"); + ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { + if (addr->source != ADDR_SOURCE_STATIC && + addr_ipv6_scope(addr->address, cur) > IPV6_SCOPE_LINK_LOCAL) { + // Remove all exept User set address + addr_delete_entry(cur, addr); + } + } +} + +static void ws_bootstrap_6lr_pan_information_store(struct protocol_interface_info_entry *cur, 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_info_t *new_entry; + /* Have List of 20 heard neighbours + * Order those as best based on pan cost + * In single pan order based on signal quality + * in single PAN limit the amount of devices to 5 + * If there is no advertisement heard for last hour Clear the neigbour. + */ + + // Discovery state processing + //tr_info("neighbour: addr:%s panid:%x signal:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm); + + // Clean old entries + ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY, protocol_core_monotonic_time, data->SrcPANId); + + new_entry = ws_bootstrap_candidate_parent_get(cur, data->SrcAddr, true); + if (!new_entry) { + tr_warn("neighbour creation fail"); + return; + } + // Safe the information + ws_bootstrap_candidate_parent_store(new_entry, data, ws_utt, ws_us, pan_information); + if (!new_entry->link_acceptable) { + // This entry is either poor quality or changed to poor quality link so we will remove this + // Todo in future possibility to try poor link parents if we have not found any good link parents + tr_info("neighbour not accepted: addr:%s panid:%x rsl:%d device_min_sens: %d", trace_array(new_entry->addr, 8), new_entry->pan_id, ws_neighbor_class_rsl_from_dbm_calculate(new_entry->signal_dbm), DEVICE_MIN_SENS); + ns_list_remove(&cur->ws_info->parent_list_reserved, new_entry); + ns_list_add_to_end(&cur->ws_info->parent_list_free, new_entry); + return; + } + // set to the correct place in list + ws_bootstrap_candidate_parent_sort(cur, new_entry); + + return; +} + +static int8_t ws_bootstrap_6lr_fhss_configure(protocol_interface_info_entry_t *cur, bool discovery) +{ + // Read configuration of existing FHSS and start using the default values for any network + fhss_ws_configuration_t fhss_configuration = ws_common_get_current_fhss_configuration(cur); + ws_bootstrap_fhss_set_defaults(cur, &fhss_configuration); + ws_bootstrap_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->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_bootstrap_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels, fhss_configuration.channel_mask); + uint8_t tmp_bc_fixed_channel = ws_bootstrap_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels, fhss_configuration.channel_mask); + 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); + ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff); + ws_bootstrap_llc_hopping_update(cur, &fhss_configuration); + + return 0; +} + +void ws_bootstrap_6lr_network_discovery_configure(protocol_interface_info_entry_t *cur) +{ + // Reset information to defaults + cur->ws_info->network_pan_id = 0xffff; + + ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule); + ws_bootstrap_set_domain_rf_config(cur); + ws_bootstrap_6lr_fhss_configure(cur, true); + + //Set Network names, Pan information configure, hopping schedule & GTKHash + ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->cfg->gen.network_name, strlen(cur->ws_info->cfg->gen.network_name)); +} + +// Start network scan +static void ws_bootstrap_6lr_start_discovery(protocol_interface_info_entry_t *cur) +{ + tr_debug("router discovery start"); + // Remove network keys from MAC + ws_pae_controller_nw_keys_remove(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_timeout_timer = 0; + cur->ws_info->weakest_received_rssi = 0; + + // Clear learned candidate parents + ws_bootstrap_candidate_table_reset(cur); + + // Clear RPL information + rpl_control_free_domain_instances_from_interface(cur); + // Clear EAPOL relay address + ws_eapol_relay_delete(cur); + + // Clear ip stack from old information + ws_bootstrap_ip_stack_reset(cur); + // New network scan started old addresses not assumed valid anymore + ws_bootstrap_6lr_ip_stack_addr_clear(cur); + + if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) != INTERFACE_NWK_BOOTSRAP_ACTIVE) { + // we have sent bootstrap ready event and now + // restarted discovery so bootstrap down event is sent + cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; + ws_bootstrap_network_down(cur); + } + + // Start advertisement solicit trickle and calculate when we are checking the status + cur->ws_info->trickle_pas_running = true; + if (cur->ws_info->trickle_pan_advertisement_solicit.I != cur->ws_info->trickle_params_pan_discovery.Imin) { + // Trickle not reseted so starting a new interval + trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); + } + + // Discovery statemachine is checkked after we have sent the Solicit + uint32_t time_to_solicit = 0; + if (cur->ws_info->trickle_pan_advertisement_solicit.t > cur->ws_info->trickle_pan_advertisement_solicit.now) { + time_to_solicit = cur->ws_info->trickle_pan_advertisement_solicit.t - cur->ws_info->trickle_pan_advertisement_solicit.now; + } + + tr_debug("Disc params imin %u, imax %u, expirations %u, k %u PAS Trickle I %u t %u, now %u, c %u", + cur->ws_info->trickle_params_pan_discovery.Imin, cur->ws_info->trickle_params_pan_discovery.Imax, cur->ws_info->trickle_params_pan_discovery.TimerExpirations, cur->ws_info->trickle_params_pan_discovery.k, + cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c); + + time_to_solicit += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); + + if (time_to_solicit > 0xffff) { + time_to_solicit = 0xffff; + } + cur->bootsrap_state_machine_cnt = time_to_solicit; + + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); +} + +// Start configuration learning +static void ws_bootstrap_6lr_start_configuration_learn(protocol_interface_info_entry_t *cur) +{ + tr_debug("router configuration learn start"); + ws_bootstrap_state_change(cur, ER_SCAN); + + cur->ws_info->configuration_learned = false; + + // Clear all temporary information + ws_bootstrap_ip_stack_reset(cur); + + cur->ws_info->pas_requests = 0; + //Calculate max time for config learn state + cur->ws_info->pan_config_sol_max_timeout = trickle_timer_max(&cur->ws_info->trickle_params_pan_discovery, PCS_MAX); + // Reset advertisement solicit trickle to start discovering network + cur->ws_info->trickle_pcs_running = true; + trickle_start(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); +} + +static void ws_bootstrap_6lr_network_configuration_learn(protocol_interface_info_entry_t *cur) +{ + tr_debug("Start using PAN configuration"); + + // Timing information can be modified here + ws_llc_set_pan_information_pointer(cur, &cur->ws_info->pan_information); + uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur); + ws_llc_set_gtkhash(cur, gtkhash); + // TODO update own fhss schedules we are starting to follow first parent + + return; +} + +static void ws_bootstrap_6lr_pan_advertisement_analyse_active(struct protocol_interface_info_entry *cur, ws_pan_information_t *pan_information) +{ + /* In Active state + * + * A consistent transmission is defined as a PAN Advertisement received by a node with PAN ID and + * NETNAME-IE / Network Name matching that of the receiving node, and with a PAN-IE / Routing Cost + * the same or worse than (bigger than or equal to) that of the receiving node. + * + * Inconsistent: + * + * Received Routing Cost is smaller than stored one + * + * A PAN Advertisement received by a node with PAN ID and NETNAME-IE / Network name matching + * that of the receiving node, and PAN-IE / Routing Cost better than (smaller than) that of the receiving node. + * + */ + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //Border router never set consistent that will guarantee that BR will send advertisment + return; + } +#ifdef WISUN_1_0_ERRATA_FIX + if (pan_information->pan_size == cur->ws_info->pan_information.pan_size) { + //If same pan size information then set consistent value + trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); + } +#else + // Wi-SUN 1.0 specified functionality, causes extra inconsistencies when we hear higher rank advertisements + if (pan_information->routing_cost >= ws_bootstrap_routing_cost_calculate(cur)) { + trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); + } else { + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); + } +#endif +} + +static void ws_bootstrap_6lr_pan_advertisement_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) +{ + + //Validate Pan Conrfirmation is at packet + ws_pan_information_t pan_information; + if (!ws_wp_nested_pan_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &pan_information)) { + // Corrupted + tr_error("No pan information"); + 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 + //tr_warn("Not supported routing"); + return; + } + + // Store heard pans and possible candidate parents + ws_bootstrap_6lr_pan_information_store(cur, data, ws_utt, ws_us, &pan_information); + + if (!(ws_bootstrap_state_active(cur) || + ws_bootstrap_state_wait_rpl(cur))) { + // During discovery/eapol/config learn we dont do further processing for advertisements + return; + } + // Active state processing + //tr_debug("Advertisement active"); + + // In active operation less neighbours per pan is allowed + ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_ACTIVE, protocol_core_monotonic_time, data->SrcPANId); + + // Check if valid PAN + if (data->SrcPANId != cur->ws_info->network_pan_id) { + return; + } + + // Save route cost for all known neighbors + llc_neighbour_req_t neighbor_info; + neighbor_info.neighbor = NULL; + if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { + neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost; + //Store and search neighbour PCAP info + if (ws_version_1_1(cur)) { + ws_neighbor_class_pcap_ie_store(neighbor_info.ws_neighbor, ie_ext); + } + } + + ws_bootstrap_6lr_pan_advertisement_analyse_active(cur, &pan_information); + + // Learn latest network information + if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && neighbor_info.neighbor) { + uint8_t ll_address[16]; + ws_common_create_ll_address(ll_address, neighbor_info.neighbor->mac64); + + if (rpl_control_is_dodag_parent(cur, ll_address)) { + cur->ws_info->pan_information.pan_size = pan_information.pan_size; + cur->ws_info->pan_information.routing_cost = pan_information.routing_cost; + cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method; + cur->ws_info->pan_information.use_parent_bs = pan_information.use_parent_bs; + } + } +} + +static void ws_bootstrap_6lr_pan_advertisement_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) +{ + + (void)data; + (void)ws_utt; + (void)ws_us; + /* + * An inconsistent transmission is defined as: + * A PAN Advertisement Solicit with NETNAME-IE matching that of the receiving node. + */ + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); + /* + * A consistent transmission is defined as + * a PAN Advertisement Solicit with NETNAME-IE / Network Name matching that configured on the receiving node. + */ + trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit); + /* + * Optimized PAN discovery to select the parent faster if we hear solicit from someone else + */ + + if (ws_bootstrap_state_discovery(cur) && ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM && + cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin * 2) { + + cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); + + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); + } + + if (ws_bootstrap_state_active(cur) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), data->SrcAddr, ADDR_802_15_4_LONG); + if (neighbor && neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { + ws_bootstrap_6lr_parent_confirm(cur, NULL); + } + } +} +#ifdef HAVE_WS_VERSION_1_1 +static void ws_bootstrap_6lr_pan_config_lfn_analyze(struct protocol_interface_info_entry *cur, const struct mcps_data_ie_list *ie_ext) +{ + if (!ws_version_1_1(cur) || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + return; + } + + ws_lfnver_ie_t lfn_version; + if (!ws_wp_nested_lfn_version_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &lfn_version)) { + return; // LFN version + } + + //Read LFNGTKHASH + ws_lgtkhash_ie_t ws_lgtkhash; + if (!ws_wp_nested_lgtk_hash_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_lgtkhash)) { + return; + } + + if (!cur->ws_info->lfngtk.lfn_version_learned) { + if (!cur->ws_info->configuration_learned) { + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); + } + } else { + if (cur->ws_info->lfngtk.lfn_version == lfn_version.lfn_version) { + return; + } + + if (common_serial_number_greater_16(cur->ws_info->lfngtk.lfn_version, lfn_version.lfn_version)) { + // older version heard ignoring the message + return; + } + } + + cur->ws_info->lfngtk.lfn_version = lfn_version.lfn_version; + + //Clear HASH allways at new first or for first leaned one's + memset(cur->ws_info->lfngtk.lgtkhash, 0, 24); + cur->ws_info->lfngtk.lfn_version_learned = true; + + //Set Active key index and hash inline bits + cur->ws_info->lfngtk.active_key_index = ws_lgtkhash.active_lgtk_index; + cur->ws_info->lfngtk.active_hash_1 = ws_lgtkhash.lgtk0; + cur->ws_info->lfngtk.active_hash_2 = ws_lgtkhash.lgtk1; + cur->ws_info->lfngtk.active_hash_3 = ws_lgtkhash.lgtk2; + + if (cur->ws_info->lfngtk.active_hash_1) { + memcpy(cur->ws_info->lfngtk.lgtkhash, ws_lgtkhash.lgtk0_hash, 8); + } + + if (cur->ws_info->lfngtk.active_hash_2) { + memcpy(cur->ws_info->lfngtk.lgtkhash + 8, ws_lgtkhash.lgtk1_hash, 8); + } + + if (cur->ws_info->lfngtk.active_hash_3) { + memcpy(cur->ws_info->lfngtk.lgtkhash + 16, ws_lgtkhash.lgtk2_hash, 8); + } + //TODO Analyze HASH's and set LFN group key index +} +#endif + + +static void ws_bootstrap_6lr_pan_config_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) +{ + + uint16_t pan_version; + ws_bs_ie_t ws_bs_ie; + uint8_t *gtkhash_ptr; + + if (data->SrcPANId != cur->ws_info->network_pan_id) { + return; + } + ws_bt_ie_t ws_bt_ie; + if (!ws_wh_bt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_bt_ie)) { + tr_warn("BT-IE"); + return; + } + + /* + * A consistent transmission is defined as a PAN Configuration with a PAN-ID matching that of the receiving node and + * a PANVER-IE / PAN Version greater than or equal to the receiving node’s current PAN version. + * + * A inconsistent transmission is defined as: + * + * A PAN Configuration with PAN-ID matching that of the receiving node and a + * PANVER-IE / PAN Version that is less than the receiving node’s current PAN version. + */ + + // TODO Add this to neighbor table + // TODO save all information from config message if version number has changed + + if (!ws_wp_nested_pan_version_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &pan_version)) { + // Corrupted + tr_warn("no version"); + return; + } + + gtkhash_ptr = ws_wp_nested_gtkhash_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength); + + if (!gtkhash_ptr) { + // Corrupted + tr_error("No gtk hash"); + return; + } + + if (!ws_wp_nested_bs_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_bs_ie)) { + // Corrupted + tr_error("No broadcast schedule"); + return; + } + + llc_neighbour_req_t neighbor_info; + bool neighbour_pointer_valid; + + //Validate BSI + if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + + if (cur->ws_info->ws_bsi_block.block_time && cur->ws_info->ws_bsi_block.old_bsi == ws_bs_ie.broadcast_schedule_identifier) { + tr_debug("Do not accept a old BSI: %u in time %"PRIu32, cur->ws_info->ws_bsi_block.old_bsi, cur->ws_info->ws_bsi_block.block_time); + //Refresh Block time when hear a old BSI + cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; + return; + } + + //When Config is learned and USE Parent BS is enabled compare is this new BSI + if (cur->ws_info->configuration_learned && cur->ws_info->pan_information.use_parent_bs && ws_bs_ie.broadcast_schedule_identifier != cur->ws_info->hopping_schdule.fhss_bsi) { + //Accept only next possible BSI number + if ((cur->ws_info->hopping_schdule.fhss_bsi + 1) != ws_bs_ie.broadcast_schedule_identifier) { + tr_debug("Do not accept a unknown BSI: %u", ws_bs_ie.broadcast_schedule_identifier); + } else { + tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier); + cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; + cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi; + ws_bootstrap_event_disconnect(cur, WS_NORMAL_DISCONNECT); + } + return; + } + } + + + if (cur->ws_info->configuration_learned || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //If we are border router or learned configuration we only update already learned neighbours. + neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false); + + } else { + neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true); + if (!neighbour_pointer_valid) { + return; + } + ws_bootstrap_neighbor_set_stable(cur, data->SrcAddr); + } + + if (neighbour_pointer_valid) { + //Update Neighbor Broadcast and Unicast Parameters + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); + ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); + ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp); + ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); + } + + 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) { + //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); + } + // no need to process more +#ifdef HAVE_WS_VERSION_1_1 + ws_bootstrap_6lr_pan_config_lfn_analyze(cur, ie_ext); +#endif + return; + } else { + // received version is different so we need to reset the trickle + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); + if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { + ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH); + } + if (common_serial_number_greater_16(cur->ws_info->pan_information.pan_version, pan_version)) { + // older version heard ignoring the message + return; + } + cur->ws_info->trickle_pc_consistency_block_period = WS_CONFIG_CONSISTENT_FILTER_PERIOD; + } + } + + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //Border router does not learn network information + return; + } + + /* + * Learn new information from neighbor + */ + tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); + + // restart PAN version timer + //Check Here Do we have a selected Primary parent + if (!cur->ws_info->configuration_learned || cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { + ws_common_border_router_alive_update(cur); + } + + cur->ws_info->pan_information.pan_version = pan_version; + + ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr); + + ws_pae_controller_nw_key_index_update(cur, data->Key.KeyIndex - 1); + +#ifdef HAVE_WS_VERSION_1_1 + ws_bootstrap_6lr_pan_config_lfn_analyze(cur, ie_ext); +#endif + + if (!cur->ws_info->configuration_learned) { + // Generate own hopping schedules Follow first parent broadcast and plans and also use same unicast dwell + tr_info("learn network configuration"); + cur->ws_info->configuration_learned = true; + // return to state machine after 1-2 s + cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, 20); + // enable frequency hopping for unicast channel and start listening first neighbour + ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH); + // set neighbor as priority parent clear if there is others + protocol_6lowpan_neighbor_priority_clear_all(cur->id, PRIORITY_1ST); + neighbor_info.neighbor->link_role = PRIORITY_PARENT_NEIGHBOUR; + } +} + +static void ws_bootstrap_6lr_pan_config_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) +{ + if (data->SrcPANId != cur->ws_info->network_pan_id) { + return; + } + + /* TODO smart neighbour process + * + * Unsecure packet we cant trust the device? + * + * Question mark in specification also present, now we create neighbour. + * this is moved in future to NS/ND processing triggered by RPL + * + */ + + llc_neighbour_req_t neighbor_info; + if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); + ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); + } + + if (ws_bootstrap_state_active(cur) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), data->SrcAddr, ADDR_802_15_4_LONG); + if (neighbor && neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { + ws_bootstrap_6lr_parent_confirm(cur, NULL); + } + } + + /* + * A consistent transmission is defined as a PAN Configuration Solicit with + * a PAN-ID matching that of the receiving node and a NETNAME-IE / Network Name + * matching that configured on the receiving node. + */ + trickle_consistent_heard(&cur->ws_info->trickle_pan_config_solicit); + /* + * inconsistent transmission is defined as either: + * A PAN Configuration Solicit with a PAN-ID matching that of the receiving node and + * a NETNAME-IE / Network Name matching the network name configured on the receiving + */ + trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); +} + + +void ws_bootstrap_6lr_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) +{ + // Store weakest heard packet RSSI + if (cur->ws_info->weakest_received_rssi > data->signal_dbm) { + cur->ws_info->weakest_received_rssi = data->signal_dbm; + } + + if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) { + // Not from long address + return; + } + ws_stats_update(cur, STATS_WS_ASYNCH_RX, 1); + //Validate network name + switch (message_type) { + case WS_FT_PAN_ADVERT: + 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->cfg->gen.network_name)) { + // Not in our network + return; + } + break; + case WS_FT_PAN_CONF: + break; + default: + return; + } + //UTT-IE and US-IE are mandatory for all Asynch Messages + ws_utt_ie_t ws_utt; + if (!ws_wh_utt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_utt)) { + // Corrupted + return; + } + + ws_us_ie_t ws_us; + if (!ws_wp_nested_us_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_us)) { + // Corrupted + return; + } + + if (!ws_bootstrap_validate_channel_plan(&ws_us, cur) || + !ws_bootstrap_validate_channel_function(&ws_us, NULL)) { + return; + } + + //Handle Message's + switch (message_type) { + case WS_FT_PAN_ADVERT: + // Analyse Advertisement + ws_stats_update(cur, STATS_WS_ASYNCH_RX_PA, 1); + tr_info("received ADVERT Src:%s panid:%x rssi:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm); + ws_bootstrap_6lr_pan_advertisement_analyse(cur, data, ie_ext, &ws_utt, &ws_us); + break; + case WS_FT_PAN_ADVERT_SOL: + ws_stats_update(cur, STATS_WS_ASYNCH_RX_PAS, 1); + tr_info("received ADVERT SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); + ws_bootstrap_6lr_pan_advertisement_solicit_analyse(cur, data, &ws_utt, &ws_us); + break; + case WS_FT_PAN_CONF: + ws_stats_update(cur, STATS_WS_ASYNCH_RX_PC, 1); + tr_info("received CONFIG Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); + ws_bootstrap_6lr_pan_config_analyse(cur, data, ie_ext, &ws_utt, &ws_us); + break; + case WS_FT_PAN_CONF_SOL: + ws_stats_update(cur, STATS_WS_ASYNCH_RX_PCS, 1); + tr_info("received CONFIG SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); + ws_bootstrap_6lr_pan_config_solicit_analyse(cur, data, &ws_utt, &ws_us); + default: + // Unknown message do not process + break; + } +} + +void ws_bootstrap_6lr_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message) +{ + (void)asynch_message; + ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1); +} + +bool ws_bootstrap_6lr_eapol_relay_state_active(protocol_interface_info_entry_t *cur) +{ + if (cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) { + return true; + } + + return false; +} + +static struct rpl_instance *ws_bootstrap_6lr_get_rpl_instance(protocol_interface_info_entry_t *cur) +{ + if (!cur || !cur->rpl_domain) { + return NULL; + } + struct rpl_instance *best_instance = NULL; + ns_list_foreach(struct rpl_instance, instance, &cur->rpl_domain->instances) { + best_instance = instance; + // Select best grounded and lowest rank? But there should be only one really + } + return best_instance; +} + +static uint16_t ws_bootstrap_6lr_rank_get(protocol_interface_info_entry_t *cur) +{ + struct rpl_instance *rpl_instance = ws_bootstrap_6lr_get_rpl_instance(cur); + if (!rpl_instance) { + return 0xffff; + } + return rpl_control_current_rank(rpl_instance); +} + +static uint16_t ws_bootstrap_6lr_min_rank_inc_get(protocol_interface_info_entry_t *cur) +{ + struct rpl_instance *rpl_instance = ws_bootstrap_6lr_get_rpl_instance(cur); + if (!rpl_instance) { + return 0xffff; + } + struct rpl_dodag_info_t dodag_info; + if (!rpl_control_read_dodag_info(rpl_instance, &dodag_info)) { + return 0xffff; + } + return dodag_info.dag_min_hop_rank_inc; +} + +void ws_bootstrap_6lr_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_bootstrap_6lr_address_update(protocol_interface_info_entry_t *interface) +{ + tr_info("RPL parent update ... register ARO"); + ws_bootstrap_6lr_address_registration_update(interface, NULL); +} + +static void ws_bootstrap_6lr_parent_confirm(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) +{ + /* Possible problem with the parent connection + * Give some time for parent to rejoin and confirm the connection with ARO and DAO + */ + const rpl_dodag_conf_int_t *config = NULL; + uint32_t Imin_secs = 0; + + if (!ws_bootstrap_state_active(cur)) { + // If we are not in Active state no need to confirm parent + return; + } + + tr_info("RPL parent confirm"); + + if (!instance) { + // If we dont have instance we take any available to get reference + instance = rpl_control_enumerate_instances(cur->rpl_domain, NULL); + } + + if (instance) { + config = rpl_control_get_dodag_config(instance); + } + + if (config) { + //dio imin Period caluclate in seconds + uint32_t Imin_ms = config->dio_interval_min < 32 ? (1ul << config->dio_interval_min) : 0xfffffffful; + //Covert to seconds and multiple by 2 so we give time to recovery so divide by 500 do that operation + Imin_secs = (Imin_ms + 499) / 500; + + if (Imin_secs > 0xffff) { + Imin_secs = 0xffff; + } + } + if (Imin_secs == 0) { + // If we dont have RPL configuration we assume conservative value + Imin_secs = 60; + } + + /*Speed up the ARO registration*/ + if (cur->ws_info->aro_registration_timer > Imin_secs) { + cur->ws_info->aro_registration_timer = Imin_secs; + } +} + + +void ws_bootstrap_6lr_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) +{ + if (interface->ws_info) { + llc_neighbour_req_t neighbor_info; + neighbor_info.neighbor = neighbor; + neighbor_info.ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor->index); + ws_bootstrap_primary_parent_set(interface, &neighbor_info, WS_PARENT_HARD_SYNCH); + uint8_t link_local_address[16]; + ws_common_create_ll_address(link_local_address, neighbor->mac64); + dhcp_client_server_address_update(interface->id, NULL, link_local_address); + + ws_bootstrap_6lr_secondary_parent_update(interface); + } +} + +void ws_bootstrap_6lr_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_bootstrap_6lr_address_update(interface); + } + } + } +} + +static void ws_bootstrap_6lr_rpl_scan_start(protocol_interface_info_entry_t *cur) +{ + tr_debug("Start RPL learn"); + // Stop Trickle timers + ws_bootstrap_asynch_trickle_stop(cur); + + // routers wait until RPL root is contacted + ws_bootstrap_state_change(cur, ER_RPL_SCAN); + // Change state as the state is checked in state machine + cur->ws_info->rpl_state = RPL_EVENT_LOCAL_REPAIR_START; + //For Large network and medium should do passive scan + if (ws_cfg_network_config_get(cur) > CONFIG_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); + } +} + + +static void ws_bootstrap_6lr_rpl_callback(rpl_event_t event, void *handle) +{ + + protocol_interface_info_entry_t *cur = handle; + if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { + return; + } + + if (event == RPL_EVENT_POISON_FINISHED) { + //If we are waiting poison we will trig Discovery after couple seconds + if (cur->nwk_bootstrap_state == ER_RPL_NETWORK_LEAVING) { + cur->bootsrap_state_machine_cnt = 80; //Give 8 seconds time to send Poison + } + return; + } + + // if waiting for RPL and + if (event == RPL_EVENT_DAO_DONE) { + // Trigger statemachine check + cur->bootsrap_state_machine_cnt = 1; + rpl_dodag_info_t dodag_info; + struct rpl_instance *instance = rpl_control_enumerate_instances(cur->rpl_domain, NULL); + + if (instance && rpl_control_read_dodag_info(instance, &dodag_info)) { + tr_debug("Enable DHCPv6 relay"); + dhcp_relay_agent_enable(cur->id, dodag_info.dodag_id); + + tr_debug("Start EAPOL relay"); + // 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->pan_information.pan_version, cur->ws_info->cfg->gen.network_name); + // Network key is valid, indicate border router IID to controller + ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]); + //Update here Suplikant target by validated Primary Parent + if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_priority(mac_neighbor_info(cur)); + if (mac_neighbor) { + ws_pae_controller_set_target(cur, cur->ws_info->network_pan_id, mac_neighbor->mac64); + } + } + + // After successful DAO ACK connection to border router is verified + ws_common_border_router_alive_update(cur); + } + + if (!cur->ws_info->trickle_pa_running || !cur->ws_info->trickle_pc_running) { + //Enable wi-sun asynch adverisment + ws_bootstrap_advertise_start(cur); + } + + ws_bootstrap_6lr_set_fhss_hop(cur); + // Set retry configuration for bootstrap ready state + ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES); + // Set TX failure request restart configuration + ws_bootstrap_configure_data_request_restart(cur, WS_CCA_REQUEST_RESTART_MAX, WS_TX_REQUEST_RESTART_MAX, WS_REQUEST_RESTART_BLACKLIST_MIN, WS_REQUEST_RESTART_BLACKLIST_MAX); + } else if (event == RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS) { + /* + * RPL goes to passive mode, but does not require any extra changed + * + * We could remove our current addresses learned from RPL + * We could send solicit for configuration and then select new parent when those arrive + * + */ + + } else if (event == RPL_EVENT_LOCAL_REPAIR_START) { + tr_debug("RPL local repair start"); + //Disable Async and go to state 4 to confirm parent connection + ws_bootstrap_6lr_parent_confirm(cur, NULL); + // Move to state 4 if we see issues with primary parent + if (ws_bootstrap_state_active(cur)) { + tr_info("Move state 4 to wait parent connection confirmation"); + ws_bootstrap_6lr_rpl_scan_start(cur); + ws_bootstrap_network_down(cur); + } + } else if (event == RPL_EVENT_DAO_PARENT_ADD) { + ws_bootstrap_6lr_address_update(cur); + } + cur->ws_info->rpl_state = event; + tr_info("RPL event %d", event); +} + +static void ws_bootstrap_6lr_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local) +{ + protocol_interface_info_entry_t *cur = (protocol_interface_info_entry_t *) handle; + /* Check if A-Flag. + * A RPL node may use this option for the purpose of Stateless Address Autoconfiguration (SLAAC) + * from a prefix advertised by a parent. + */ + if (prefix->options & PIO_A) { + + if (parent_link_local) { + if (icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime) != 0) { + ipv6_interface_slaac_handler(cur, prefix->prefix, prefix->prefix_len, prefix->lifetime, prefix->preftime); + /* + * Give SLAAC addresses a different label and low precedence to indicate that + * they probably shouldn't be used for external traffic. SLAAC use in Wi-SUN is non-standard, + * and we use it for mesh-local traffic we should prefer any DHCP-assigned addresses + * for talking to the outside world + * + */ + addr_policy_table_add_entry(prefix->prefix, prefix->prefix_len, 2, WS_NON_PREFFRED_LABEL); + } + } else { + icmpv6_slaac_prefix_update(cur, prefix->prefix, prefix->prefix_len, 0, 0); + } + } else if (prefix->prefix_len) { + // Create new address using DHCP + if (parent_link_local) { + ws_dhcp_client_address_request(cur, prefix->prefix, parent_link_local); + } else { + /* Deprecate address and remove client */ + tr_debug("Prefix invalidation %s", trace_ipv6(prefix->prefix)); + dhcp_client_global_address_delete(cur->id, NULL, prefix->prefix); + } + } +} + +static bool ws_bootstrap_6lr_rpl_candidate_soft_filtering(protocol_interface_info_entry_t *cur, struct rpl_instance *instance) +{ + //Already many candidates + uint16_t candidate_list_size = rpl_control_candidate_list_size(cur, instance); + if (candidate_list_size >= cur->ws_info->cfg->gen.rpl_parent_candidate_max) { + return false; + } + + uint16_t selected_parents = rpl_control_selected_parent_count(cur, instance); + + //Already enough selected candidates + if (selected_parents >= cur->ws_info->cfg->gen.rpl_selected_parent_max) { + candidate_list_size -= selected_parents; + if (candidate_list_size >= 2) { + //We have more candidates than selected + return false; + } + } + + return true; +} + +static bool ws_bootstrap_6lr_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance, uint16_t candidate_rank) +{ + + protocol_interface_info_entry_t *cur = handle; + if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { + return false; + } + + if (blacklist_reject(ll_parent_address)) { + // Rejected by blacklist + return false; + } + + uint8_t mac64[10]; + //bool replace_ok = false; + //bool create_ok = false; + llc_neighbour_req_t neigh_buffer; + + //Discover neigh ready here for possible ETX validate + memcpy(mac64, ll_parent_address + 8, 8); + mac64[0] ^= 2; + + + ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false); + //Discover Multicast temporary entry for create neighbour table entry for new candidate + ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); + + if (!ws_bootstrap_6lr_rpl_candidate_soft_filtering(cur, instance)) { + + //Acept only better than own rank here + if (candidate_rank >= rpl_control_current_rank(instance)) { + //Do not accept no more siblings + return false; + } + + uint16_t candidate_list_size = rpl_control_candidate_list_size(cur, instance); + if (candidate_list_size > cur->ws_info->cfg->gen.rpl_parent_candidate_max + 1) { + //Accept only 1 better 1 time + return false; + } + + if (!neigh_buffer.neighbor) { + //Do not accept any new in that Place + return false; + } + + uint8_t replacing[16]; + //Accept Know neighbour if it is enough good + if (!rpl_control_find_worst_neighbor(cur, instance, replacing)) { + return false; + } + // +2 Is for PAN ID space + memcpy(mac64, replacing + 8, 8); + mac64[0] ^= 2; + + if (ws_local_etx_read(cur, ADDR_802_15_4_LONG, mac64) == 0xffff) { + //Not probed yet because ETX is 0xffff + return false; + } + + uint16_t etx = 0; + if (neigh_buffer.neighbor) { + etx = ws_local_etx_read(cur, ADDR_802_15_4_LONG, neigh_buffer.neighbor->mac64); + } + + // Accept now only better one's when max candidates selected and max candidate list size is reached + return rpl_possible_better_candidate(cur, instance, replacing, candidate_rank, etx); + } + + //Neighbour allready + if (neigh_buffer.neighbor) { + return true; + } + + if (!entry) { + //No Multicast Entry Available + return false; + } + + //Create entry + bool create_ok = ws_bootstrap_neighbor_info_request(cur, entry->mac64, &neigh_buffer, true); + if (create_ok) { + ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; + ws_bootstrap_neighbor_set_stable(cur, entry->mac64); + //Copy fhss temporary data + *ws_neigh = entry->neigh_info_list; + mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true); + } + ws_llc_free_multicast_temp_entry(cur, entry); + +#if 0 +neigh_create_ok: + + if (create_ok && replace_ok) { + //Try remove here when accepted new better one possible + tr_debug("Remove %s by %s", trace_ipv6(replacing), trace_ipv6(ll_parent_address)); + rpl_control_neighbor_delete_from_instance(cur, instance, replacing); + } +#endif + return create_ok; +} + +static void ws_bootstrap_6lr_rpl_parent_dis_callback(const uint8_t *ll_parent_address, void *handle, struct rpl_instance *instance) +{ + (void) ll_parent_address; + protocol_interface_info_entry_t *cur = handle; + if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { + return; + } + //Multicast DIS from parent indicate that Parent is not valid in short time window possible + ws_bootstrap_6lr_parent_confirm(cur, instance); +} + + +void ws_bootstrap_6lr_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event) +{ + ws_bootsrap_event_type_e event_type; + event_type = (ws_bootsrap_event_type_e)event->event_type; + + switch (event_type) { + case WS_INIT_EVENT: + tr_debug("tasklet init"); + break; + case WS_DISCOVERY_START: + tr_info("Discovery start"); + protocol_mac_reset(cur); + ws_llc_reset(cur); + lowpan_adaptation_interface_reset(cur->id); + //Clear Pending Key Index State + cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; + cur->mac_parameters->mac_default_key_index = 0; + + ipv6_destination_cache_clean(cur->id); + + // Clear parent blacklist + blacklist_clear(); + + // All trickle timers stopped to allow entry from any state + ws_bootstrap_asynch_trickle_stop(cur); + //Init Packet congestion + ws_bootstrap_packet_congestion_init(cur); + + ws_pae_controller_supp_init(cur); + // Clear learned neighbours + ws_bootstrap_neighbor_list_clean(cur); + // Configure LLC for network discovery + ws_bootstrap_6lr_network_discovery_configure(cur); + ws_bootstrap_fhss_activate(cur); + // Set retry configuration for discovery state + ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES_BOOTSTRAP); + // Set TX failure request restart configuration for discovery state + ws_bootstrap_configure_data_request_restart(cur, WS_CCA_REQUEST_RESTART_MAX, WS_TX_REQUEST_RESTART_MAX_BOOTSTRAP, WS_REQUEST_RESTART_BLACKLIST_MIN, WS_REQUEST_RESTART_BLACKLIST_MAX); + // Set CSMA-CA backoff configuration + ws_bootstrap_configure_csma_ca_backoffs(cur, WS_MAX_CSMA_BACKOFFS, WS_MAC_MIN_BE, WS_MAC_MAX_BE); + // Start network scan + ws_bootstrap_6lr_start_discovery(cur); + break; + + case WS_CONFIGURATION_START: + tr_info("Configuration start"); + // Old configuration is considered invalid stopping all + ws_bootstrap_asynch_trickle_stop(cur); + + // Build list of possible neighbours and learn first broadcast schedule + + ws_bootstrap_6lr_start_configuration_learn(cur); + break; + case WS_OPERATION_START: + tr_info("operation start"); + // Advertisements stopped during the RPL scan + ws_bootstrap_asynch_trickle_stop(cur); + // Activate RPL + // Activate IPv6 stack + ws_bootstrap_ip_stack_activate(cur); + ws_bootstrap_ffn_rpl_configure(cur); + // Configure RPL for Node. + rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_6lr_rpl_callback, ws_bootstrap_6lr_rpl_prefix_callback, ws_bootstrap_6lr_rpl_new_parent_callback, ws_bootstrap_6lr_rpl_parent_dis_callback, cur); + rpl_control_set_memory_limits(WS_NODE_RPL_SOFT_MEM_LIMIT, WS_NODE_RPL_HARD_MEM_LIMIT); + + ws_bootstrap_network_start(cur); + // Wait for RPL start + ws_bootstrap_6lr_rpl_scan_start(cur); + /* 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 + */ + ws_common_border_router_alive_update(cur); + break; + case WS_ROUTING_READY: + tr_info("Routing ready"); + // stopped all to make sure we can enter here from any state + ws_bootstrap_asynch_trickle_stop(cur); + + // Indicate PAE controller that bootstrap is ready + ws_pae_controller_bootstrap_done(cur); + + ws_bootstrap_advertise_start(cur); + ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE); + break; + case WS_FAST_DISCONNECT: + ws_bootstrap_state_disconnect(cur, WS_FAST_DISCONNECT); + break; + case WS_NORMAL_DISCONNECT: + ws_bootstrap_state_disconnect(cur, WS_NORMAL_DISCONNECT); + break; + + case WS_TEST_PROC_TRIGGER: + ws_bootstrap_test_procedure_trigger_exec(cur, (ws_bootsrap_procedure_t) event->data_ptr); + break; + + default: + tr_err("Invalid event received"); + break; + } +} + +/* + * Statemachine state functions + * */ + +static void ws_bootstrap_6lr_network_scan_process(protocol_interface_info_entry_t *cur) +{ + + parent_info_t *selected_parent_ptr; + + tr_debug("analyze network discovery result"); + +select_best_candidate: + selected_parent_ptr = ws_bootstrap_candidate_parent_get_best(cur); + + if (!selected_parent_ptr) { + // Configure LLC for network discovery + ws_bootstrap_6lr_network_discovery_configure(cur); + // randomize new channel and start MAC + ws_bootstrap_fhss_activate(cur); + // Next check will be after one trickle + uint32_t random_start = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); + if (random_start > 0xffff) { + random_start = 0xffff; + } + cur->bootsrap_state_machine_cnt = random_start; + + tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); + return; + } + tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id); + + if (ws_bootstrap_neighbor_set(cur, selected_parent_ptr, false) < 0) { + goto select_best_candidate; + } + + ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth + ws_bootstrap_event_authentication_start(cur); + return; +} + +static void ws_bootstrap_6lr_configure_process(protocol_interface_info_entry_t *cur) +{ + + if (cur->ws_info->configuration_learned) { + ws_bootstrap_6lr_network_configuration_learn(cur); + ws_bootstrap_event_operation_start(cur); + return; + } + return; +} + +void ws_bootstrap_6lr_rpl_wait_process(protocol_interface_info_entry_t *cur) +{ + + if (cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { + // RPL routing is ready + cur->ws_info->connected_time = cur->ws_info->uptime; + ws_bootstrap_event_routing_ready(cur); + } else if (!rpl_control_have_dodag(cur->rpl_domain)) { + // RPL not ready send DIS message if possible + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) { + // TODO Multicast DIS should be sent only if no DIO heard for some time + rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, ADDR_LINK_LOCAL_ALL_RPL_NODES); + } + // set timer for next DIS + cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_TIMEOUT / 2, WS_RPL_DIS_TIMEOUT); + } + return; +} + + +/* + * State machine + */ + +void ws_bootstrap_6lr_state_machine(protocol_interface_info_entry_t *cur) +{ + + switch (cur->nwk_bootstrap_state) { + case ER_WAIT_RESTART: + tr_debug("WS SM:Wait for startup"); + ws_bootstrap_event_discovery_start(cur); + break; + case ER_ACTIVE_SCAN: + tr_debug("WS SM:Active Scan"); + ws_bootstrap_6lr_network_scan_process(cur); + break; + case ER_SCAN: + tr_debug("WS SM:configuration Scan"); + ws_bootstrap_6lr_configure_process(cur); + break; + case ER_PANA_AUTH: + tr_info("authentication start"); + // Advertisements stopped during the EAPOL + ws_bootstrap_asynch_trickle_stop(cur); + ws_bootstrap_6lr_fhss_configure(cur, false); + int8_t new_default = cur->ws_info->weakest_received_rssi - 1; + if ((new_default < CCA_DEFAULT_DBM) && (new_default >= CCA_LOW_LIMIT) && (new_default <= CCA_HIGH_LIMIT)) { + // Restart automatic CCA threshold using weakest received RSSI as new default + mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->weakest_received_rssi - 1, CCA_HIGH_LIMIT, CCA_LOW_LIMIT); + } + ws_bootstrap_start_authentication(cur); + break; + case ER_RPL_SCAN: + tr_debug("WS SM:Wait RPL to contact DODAG root"); + ws_bootstrap_6lr_rpl_wait_process(cur); + break; + case ER_BOOTSRAP_DONE: + tr_info("WS SM:Bootstrap Done"); + // Bootstrap_done event to application + nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur); + break; + case ER_RPL_NETWORK_LEAVING: + tr_debug("WS SM:RPL Leaving ready trigger discovery"); + ws_bootstrap_event_discovery_start(cur); + break; + default: + tr_warn("WS SM:Invalid state %d", cur->nwk_bootstrap_state); + } +} + +void ws_bootstrap_6lr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) +{ + /* Border router keep alive check + */ + if (cur->ws_info->pan_timeout_timer) { + // PAN version timer running + 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 + //Clear Timeout timer + cur->ws_info->pan_timeout_timer = 0; + tr_warn("Border router has timed out"); + ws_bootstrap_event_disconnect(cur, WS_FAST_DISCONNECT); + } + } + 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_bootstrap_6lr_address_registration_update(cur, NULL); + } + } + + if (cur->ws_info->ws_bsi_block.block_time) { + if (cur->ws_info->ws_bsi_block.block_time > seconds) { + cur->ws_info->ws_bsi_block.block_time -= seconds; + } else { + //Clear A BSI blokker + cur->ws_info->ws_bsi_block.block_time = 0; + cur->ws_info->ws_bsi_block.old_bsi = 0; + } + } +} + + +#endif //HAVE_WS_BORDER_ROUTER && HAVE_WS diff --git a/source/6LoWPAN/ws/ws_bootstrap_6lr.h b/source/6LoWPAN/ws/ws_bootstrap_6lr.h new file mode 100644 index 0000000000..0facfa3d35 --- /dev/null +++ b/source/6LoWPAN/ws/ws_bootstrap_6lr.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021, Pelion 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_BOOTSTRAP_6LR_H_ +#define WS_BOOTSTRAP_6LR_H_ + +#if defined(HAVE_WS) && defined(HAVE_WS_ROUTER) + +void ws_bootstrap_6lr_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); +void ws_bootstrap_6lr_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message); +bool ws_bootstrap_6lr_eapol_relay_state_active(protocol_interface_info_entry_t *cur); +void ws_bootstrap_6lr_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event); +void ws_bootstrap_6lr_state_machine(protocol_interface_info_entry_t *cur); +void ws_bootstrap_6lr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); + +void ws_bootstrap_6lr_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor); +void ws_bootstrap_6lr_secondary_parent_update(protocol_interface_info_entry_t *interface); +void ws_bootstrap_6lr_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]); + +#define wisun_mode_router(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) + +#else + +#define ws_bootstrap_6lr_asynch_ind(cur, data, ie_ext, message_type) ((void) 0) +#define ws_bootstrap_6lr_asynch_confirm(interface, asynch_message) ((void) 0) +#define ws_bootstrap_6lr_eapol_relay_state_active false +#define ws_bootstrap_6lr_event_handler(cur, event) ((void) 0) +#define ws_bootstrap_6lr_state_machine(cur) ((void) 0) +#define ws_bootstrap_6lr_seconds_timer(cur, seconds) ((void) 0) +#define ws_bootstrap_6lr_primary_parent_update(interface, neighbor) ((void) 0) +#define ws_bootstrap_6lr_secondary_parent_update(interface) ((void) 0) +#define ws_bootstrap_6lr_address_registration_update(interface, addr) ((void) 0) + +#define wisun_mode_router(cur) (false) + +#endif //HAVE_WS + +#endif /* WS_BOOTSTRAP_6LR_H_ */ diff --git a/source/6LoWPAN/ws/ws_bootstrap_ffn.c b/source/6LoWPAN/ws/ws_bootstrap_ffn.c index 489039abff..ae9dd1315f 100644 --- a/source/6LoWPAN/ws/ws_bootstrap_ffn.c +++ b/source/6LoWPAN/ws/ws_bootstrap_ffn.c @@ -17,7 +17,7 @@ #include #include "nsconfig.h" -#if defined(HAVE_WS) && defined(HAVE_WS_ROUTER) +#ifdef HAVE_WS #include "ns_types.h" #include "ns_trace.h" #include "nsdynmemLIB.h" @@ -62,6 +62,11 @@ #include "6LoWPAN/ws/ws_ie_lib.h" #include "6LoWPAN/ws/ws_stats.h" #include "6LoWPAN/ws/ws_cfg_settings.h" +#include "6LoWPAN/ws/ws_bootstrap_ffn.h" +#include "6LoWPAN/ws/ws_bootstrap_6lbr.h" +#include "6LoWPAN/ws/ws_bootstrap_6lr.h" +#include "6LoWPAN/ws/ws_bootstrap_6ln.h" +#include "6LoWPAN/ws/ws_phy.h" #include "6LoWPAN/lowpan_adaptation_interface.h" #include "Service_Libs/etx/etx.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" @@ -84,944 +89,315 @@ #define TRACE_GROUP "wsbs" -static void ws_bootstrap_ffn_ip_stack_addr_clear(protocol_interface_info_entry_t *cur) +static void ws_bootstrap_ffn_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t ll_addr[static 16]); +static void ws_bootstrap_ffn_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info); + +int8_t ws_bootstrap_ffn_up(protocol_interface_info_entry_t *cur) { - tr_debug("ip stack address clear"); - ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) { - if (addr->source != ADDR_SOURCE_STATIC && - addr_ipv6_scope(addr->address, cur) > IPV6_SCOPE_LINK_LOCAL) { - // Remove all exept User set address - addr_delete_entry(cur, addr); - } + int8_t ret_val = -1; + + if (!cur) { + return -1; } -} -static void ws_bootstrap_ffn_pan_information_store(struct protocol_interface_info_entry *cur, 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_info_t *new_entry; - /* Have List of 20 heard neighbours - * Order those as best based on pan cost - * In single pan order based on signal quality - * in single PAN limit the amount of devices to 5 - * If there is no advertisement heard for last hour Clear the neigbour. - */ - - // Discovery state processing - //tr_info("neighbour: addr:%s panid:%x signal:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm); - - // Clean old entries - ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY, protocol_core_monotonic_time, data->SrcPANId); - - new_entry = ws_bootstrap_candidate_parent_get(cur, data->SrcAddr, true); - if (!new_entry) { - tr_warn("neighbour creation fail"); - return; + if ((cur->configure_flags & INTERFACE_SETUP_MASK) != INTERFACE_SETUP_READY) { + tr_error("Interface not yet fully configured"); + return -2; } - // Safe the information - ws_bootstrap_candidate_parent_store(new_entry, data, ws_utt, ws_us, pan_information); - if (!new_entry->link_acceptable) { - // This entry is either poor quality or changed to poor quality link so we will remove this - // Todo in future possibility to try poor link parents if we have not found any good link parents - tr_info("neighbour not accepted: addr:%s panid:%x rsl:%d device_min_sens: %d", trace_array(new_entry->addr, 8), new_entry->pan_id, ws_neighbor_class_rsl_from_dbm_calculate(new_entry->signal_dbm), DEVICE_MIN_SENS); - ns_list_remove(&cur->ws_info->parent_list_reserved, new_entry); - ns_list_add_to_end(&cur->ws_info->parent_list_free, new_entry); - return; + if (ws_bootstrap_fhss_initialize(cur) != 0) { + tr_error("fhss initialization failed"); + return -3; } - // set to the correct place in list - ws_bootstrap_candidate_parent_sort(cur, new_entry); - - return; -} - -static int8_t ws_bootstrap_ffn_fhss_configure(protocol_interface_info_entry_t *cur, bool discovery) -{ - // Read configuration of existing FHSS and start using the default values for any network - fhss_ws_configuration_t fhss_configuration = ws_common_get_current_fhss_configuration(cur); - ws_bootstrap_fhss_set_defaults(cur, &fhss_configuration); - ws_bootstrap_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->cfg->fhss.fhss_uc_channel_function; + if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { + //BBR init like NVM read + ws_bbr_init(cur); } - fhss_configuration.ws_bc_channel_function = WS_FIXED_CHANNEL; - fhss_configuration.fhss_broadcast_interval = 0; - uint8_t tmp_uc_fixed_channel = ws_bootstrap_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels, fhss_configuration.channel_mask); - uint8_t tmp_bc_fixed_channel = ws_bootstrap_randomize_fixed_channel(cur->ws_info->cfg->fhss.fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels, fhss_configuration.channel_mask); - 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); - ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff); - ws_bootstrap_llc_hopping_update(cur, &fhss_configuration); + // Save FHSS api + cur->ws_info->fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api); + + ws_bootstrap_ll_address_validate(cur); + + addr_interface_set_ll64(cur, NULL); + cur->nwk_nd_re_scan_count = 0; + // Trigger discovery for bootstrap + ret_val = nwk_6lowpan_up(cur); + if (ret_val) { + goto cleanup; + } + + /* Wi-sun will trig event for stamechine this timer must be zero on init */ + cur->bootsrap_state_machine_cnt = 0; + /* Disable SLLAO send/mandatory receive with the ARO */ + cur->ipv6_neighbour_cache.use_eui64_as_slla_in_aro = true; + /* Omit sending of NA if ARO SUCCESS */ + cur->ipv6_neighbour_cache.omit_na_aro_success = true; + /* Omit sending of NA and consider ACK to be success */ + cur->ipv6_neighbour_cache.omit_na = true; + // do not process AROs from NA. This is overriden by Wi-SUN specific failure handling + cur->ipv6_neighbour_cache.recv_na_aro = false; + /* Disable NUD Probes */ + cur->ipv6_neighbour_cache.send_nud_probes = false; + cur->ipv6_neighbour_cache.probe_avoided_routers = true; + /*Replace NS handler to disable multicast address queries */ + cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit; + + dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE); + dhcp_service_link_local_rx_cb_set(cur->id, ws_bootstrap_ffn_dhcp_neighbour_update_cb); + dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used. + + dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC, WS_DHCP_SOLICIT_MAX_DELAY); + dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_ffn_dhcp_info_notify_cb); + + // Configure memory limits and garbage collection values; + ws_bootstrap_memory_configuration(); + ws_nud_table_reset(cur); + + ws_bootstrap_candidate_table_reset(cur); + // Zero uptime counters + cur->ws_info->uptime = 0; + cur->ws_info->authentication_time = 0; + cur->ws_info->connected_time = 0; + + blacklist_params_set( + WS_BLACKLIST_ENTRY_LIFETIME, + WS_BLACKLIST_TIMER_MAX_TIMEOUT, + WS_BLACKLIST_TIMER_TIMEOUT, + WS_BLACKLIST_ENTRY_MAX_NBR, + WS_BLACKLIST_PURGE_NBR, + WS_BLACKLIST_PURGE_TIMER_TIMEOUT); + + ws_bootstrap_event_discovery_start(cur); return 0; +cleanup: + return ret_val; } -void ws_bootstrap_ffn_network_discovery_configure(protocol_interface_info_entry_t *cur) +int8_t ws_bootstrap_ffn_down(protocol_interface_info_entry_t *cur) { - // Reset information to defaults - cur->ws_info->network_pan_id = 0xffff; + if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) { + return -1; + } - ws_common_regulatory_domain_config(cur, &cur->ws_info->hopping_schdule); - ws_bootstrap_set_domain_rf_config(cur); - ws_bootstrap_ffn_fhss_configure(cur, true); - - //Set Network names, Pan information configure, hopping schedule & GTKHash - ws_llc_set_network_name(cur, (uint8_t *)cur->ws_info->cfg->gen.network_name, strlen(cur->ws_info->cfg->gen.network_name)); -} - -// Start network scan -static void ws_bootstrap_ffn_start_discovery(protocol_interface_info_entry_t *cur) -{ - tr_debug("router discovery start"); - // Remove network keys from MAC - ws_pae_controller_nw_keys_remove(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_timeout_timer = 0; - cur->ws_info->weakest_received_rssi = 0; - - // Clear learned candidate parents - ws_bootstrap_candidate_table_reset(cur); - - // Clear RPL information - rpl_control_free_domain_instances_from_interface(cur); - // Clear EAPOL relay address + tr_info("Wi-SUN ifdown"); + // Reset MAC for safe upper layer memory free + protocol_mac_reset(cur); + ns_sw_mac_fhss_unregister(cur->mac_api); + ns_fhss_delete(cur->ws_info->fhss_api); + cur->ws_info->fhss_api = NULL; + // Reset WS information + ws_bootstrap_asynch_trickle_stop(cur); + ws_llc_reset(cur); + if (nd_proxy_downstream_interface_unregister(cur->id) != 0) { + tr_warn("nd proxy unregister failed"); + } + ws_nud_table_reset(cur); + dhcp_client_delete(cur->id); ws_eapol_relay_delete(cur); + ws_eapol_auth_relay_delete(cur); + ws_pae_controller_stop(cur); + ws_bootstrap_candidate_table_reset(cur); + blacklist_clear(); + cur->if_common_forwarding_out_cb = NULL; - // Clear ip stack from old information - ws_bootstrap_ip_stack_reset(cur); - // New network scan started old addresses not assumed valid anymore - ws_bootstrap_ffn_ip_stack_addr_clear(cur); - - if ((cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_ACTIVE) != INTERFACE_NWK_BOOTSRAP_ACTIVE) { - // we have sent bootstrap ready event and now - // restarted discovery so bootstrap down event is sent - cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; - ws_bootstrap_network_down(cur); - } - - // Start advertisement solicit trickle and calculate when we are checking the status - cur->ws_info->trickle_pas_running = true; - if (cur->ws_info->trickle_pan_advertisement_solicit.I != cur->ws_info->trickle_params_pan_discovery.Imin) { - // Trickle not reseted so starting a new interval - trickle_start(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery); - } - - // Discovery statemachine is checkked after we have sent the Solicit - uint32_t time_to_solicit = 0; - if (cur->ws_info->trickle_pan_advertisement_solicit.t > cur->ws_info->trickle_pan_advertisement_solicit.now) { - time_to_solicit = cur->ws_info->trickle_pan_advertisement_solicit.t - cur->ws_info->trickle_pan_advertisement_solicit.now; - } - - tr_debug("Disc params imin %u, imax %u, expirations %u, k %u PAS Trickle I %u t %u, now %u, c %u", - cur->ws_info->trickle_params_pan_discovery.Imin, cur->ws_info->trickle_params_pan_discovery.Imax, cur->ws_info->trickle_params_pan_discovery.TimerExpirations, cur->ws_info->trickle_params_pan_discovery.k, - cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c); - - time_to_solicit += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); - - if (time_to_solicit > 0xffff) { - time_to_solicit = 0xffff; - } - cur->bootsrap_state_machine_cnt = time_to_solicit; - - tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); + return nwk_6lowpan_down(cur); } -// Start configuration learning -static void ws_bootstrap_ffn_start_configuration_learn(protocol_interface_info_entry_t *cur) +static void ws_bootstrap_ffn_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t ll_addr[static 16]) { - tr_debug("router configuration learn start"); - ws_bootstrap_state_change(cur, ER_SCAN); - - cur->ws_info->configuration_learned = false; - - // Clear all temporary information - ws_bootstrap_ip_stack_reset(cur); - - cur->ws_info->pas_requests = 0; - //Calculate max time for config learn state - cur->ws_info->pan_config_sol_max_timeout = trickle_timer_max(&cur->ws_info->trickle_params_pan_discovery, PCS_MAX); - // Reset advertisement solicit trickle to start discovering network - cur->ws_info->trickle_pcs_running = true; - trickle_start(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config_solicit, &cur->ws_info->trickle_params_pan_discovery); -} - -static void ws_bootstrap_ffn_network_configuration_learn(protocol_interface_info_entry_t *cur) -{ - tr_debug("Start using PAN configuration"); - - // Timing information can be modified here - ws_llc_set_pan_information_pointer(cur, &cur->ws_info->pan_information); - uint8_t *gtkhash = ws_pae_controller_gtk_hash_ptr_get(cur); - ws_llc_set_gtkhash(cur, gtkhash); - // TODO update own fhss schedules we are starting to follow first parent - - return; -} - -static void ws_bootstrap_ffn_pan_advertisement_analyse_active(struct protocol_interface_info_entry *cur, ws_pan_information_t *pan_information) -{ - /* In Active state - * - * A consistent transmission is defined as a PAN Advertisement received by a node with PAN ID and - * NETNAME-IE / Network Name matching that of the receiving node, and with a PAN-IE / Routing Cost - * the same or worse than (bigger than or equal to) that of the receiving node. - * - * Inconsistent: - * - * Received Routing Cost is smaller than stored one - * - * A PAN Advertisement received by a node with PAN ID and NETNAME-IE / Network name matching - * that of the receiving node, and PAN-IE / Routing Cost better than (smaller than) that of the receiving node. - * - */ - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - //Border router never set consistent that will guarantee that BR will send advertisment + if (memcmp(ll_addr, ADDR_LINK_LOCAL_PREFIX, 8)) { return; } -#ifdef WISUN_1_0_ERRATA_FIX - if (pan_information->pan_size == cur->ws_info->pan_information.pan_size) { - //If same pan size information then set consistent value - trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); + + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur) { + return; } -#else - // Wi-SUN 1.0 specified functionality, causes extra inconsistencies when we hear higher rank advertisements - if (pan_information->routing_cost >= ws_bootstrap_routing_cost_calculate(cur)) { - trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement); + + uint8_t mac64[8]; + memcpy(mac64, ll_addr + 8, 8); + mac64[0] ^= 2; + ws_bootstrap_mac_neighbor_short_time_set(cur, mac64, WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME); +} + +static void ws_bootstrap_ffn_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info) +{ + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); + if (!cur) { + return; + } + uint8_t server_ll64[16]; + memcpy(server_ll64, ADDR_LINK_LOCAL_PREFIX, 8); + + if (server_info->duid_length == 8) { + memcpy(server_ll64 + 8, server_info->duid, 8); } else { - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); + server_ll64[8] = server_info->duid[0]; + server_ll64[9] = server_info->duid[1]; + server_ll64[10] = server_info->duid[2]; + server_ll64[11] = 0xff; + server_ll64[12] = 0xfe; + server_ll64[13] = server_info->duid[3]; + server_ll64[14] = server_info->duid[4]; + server_ll64[15] = server_info->duid[5]; } -#endif + server_ll64[8] ^= 2; + + switch (options->option_type) { + case DHCPV6_OPTION_VENDOR_SPECIFIC_INFO: + if (options->option.vendor_spesific.enterprise_number != ARM_ENTERPRISE_NUMBER) { + break; + } + while (options->option.vendor_spesific.data_length) { + uint16_t option_type; + char *domain; + uint8_t *address; + uint16_t option_len; + option_len = net_dns_option_vendor_option_data_get_next(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &option_type); + tr_debug("DHCP vendor specific data type:%u length %d", option_type, option_len); + //tr_debug("DHCP vendor specific data %s", trace_array(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length)); + + if (option_len == 0) { + // Option fields were corrupted + break; + } + if (option_type == ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT) { + // Process ARM DNS query result + domain = NULL; + address = NULL; + if (net_dns_option_vendor_option_data_dns_query_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &address, &domain) > 0 || + domain || address) { + // Valid ARM DNS query entry + net_dns_query_result_set(interface, address, domain, server_info->life_time); + } + } + if (option_type == ARM_DHCP_VENDOR_DATA_TIME_CONFIGURATION) { + timezone_info_t time_configuration; + if (net_vendor_option_time_configuration_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &time_configuration.timestamp, &time_configuration.timezone, &time_configuration.deviation, &time_configuration.status)) { + int ret = ns_time_system_timezone_info_notify(&time_configuration); + tr_info("Network Time configuration %s status:%"PRIu16" time stamp: %"PRIu64" deviation: %"PRId16" Time Zone: %"PRId16, ret == 0 ? "notified" : "notify FAILED", time_configuration.status, time_configuration.timestamp, time_configuration.deviation, time_configuration.timezone); + } + } + if (option_type == ARM_DHCP_VENDOR_DATA_NETWORK_TIME) { + // Process ARM Network Time + // Get Current time + // Get Round trip time of the DHCP request + // Estimated error is elapsed time of request + // If current time difference is larger than estimated error update current time + // set the time for server time + *.5 RTT + int32_t era; + uint32_t offset; + if (net_vendor_option_current_time_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &era, &offset, NULL)) { + uint64_t current_time; + uint64_t network_time = (era * (uint64_t)(4294967296)) + offset - 2208988800; //Convert to First day of Unix (1 Jan 1970) + + tr_debug("Network Time option Era:%"PRId32" Offset:%"PRIu32" rtt: %"PRId32" time: %"PRIu64, era, offset, server_info->rtt, network_time); + if (0 == ns_time_system_time_read(¤t_time)) { + uint64_t difference; + // We only adjust clock if time has drifted more than 10 seconds to avoid constant changing of time + // If Round trip time is very high the accuracy is reduced. + uint32_t estimated_error = 10 + server_info->rtt / 10; + // Take into account the round trip time it took the response to arrive from the time server Write the time. + network_time += server_info->rtt / 20; + + if (current_time > network_time) { + difference = current_time - network_time; + } else { + difference = network_time - current_time; + } + if (difference > estimated_error) { + // Larger than 10 second difference update the time + int ret = ns_time_system_time_write(network_time); + tr_info("Network Time %s: Era:%"PRId32" Offset:%"PRIu32" old time: %"PRIu64" time: %"PRIu64, ret == 0 ? "updated" : "update FAILED", era, offset, current_time, network_time); + } + // System time has been acquired + ns_time_system_time_acquired_set(); + } + } + } + + options->option.vendor_spesific.data_length -= option_len; + options->option.vendor_spesific.data += option_len; + } + break; + + case DHCPV6_OPTION_DNS_SERVERS: + while (options->option.generic.data_length && options->option.generic.data_length >= 16 && options->option.generic.data_length % 16 == 0) { + // Validate payload to have full 16 byte length addresses without any extra bytes + net_dns_server_address_set(interface, server_ll64, options->option.generic.data, server_info->life_time); + options->option.generic.data_length -= 16; + options->option.generic.data += 16; + } + break; + case DHCPV6_OPTION_DOMAIN_LIST: + net_dns_server_search_list_set(interface, server_ll64, options->option.generic.data, options->option.generic.data_length, server_info->life_time); + break; + default: + break; + } + } -static void ws_bootstrap_ffn_pan_advertisement_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) +static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status) { - - //Validate Pan Conrfirmation is at packet - ws_pan_information_t pan_information; - if (!ws_wp_nested_pan_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &pan_information)) { - // Corrupted - tr_error("No pan information"); - 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 - //tr_warn("Not supported routing"); - return; - } - - // Store heard pans and possible candidate parents - ws_bootstrap_ffn_pan_information_store(cur, data, ws_utt, ws_us, &pan_information); - - if (!(ws_bootstrap_state_active(cur) || - ws_bootstrap_state_wait_rpl(cur))) { - // During discovery/eapol/config learn we dont do further processing for advertisements - return; - } - // Active state processing - //tr_debug("Advertisement active"); - - // In active operation less neighbours per pan is allowed - ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_ACTIVE, protocol_core_monotonic_time, data->SrcPANId); - - // Check if valid PAN - if (data->SrcPANId != cur->ws_info->network_pan_id) { - return; - } - - // Save route cost for all known neighbors - llc_neighbour_req_t neighbor_info; - neighbor_info.neighbor = NULL; - if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { - neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost; - //Store and search neighbour PCAP info - if (ws_version_1_1(cur)) { - ws_neighbor_class_pcap_ie_store(neighbor_info.ws_neighbor, ie_ext); - } - } - - ws_bootstrap_ffn_pan_advertisement_analyse_active(cur, &pan_information); - - // Learn latest network information - if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && neighbor_info.neighbor) { - uint8_t ll_address[16]; - ws_common_create_ll_address(ll_address, neighbor_info.neighbor->mac64); - - if (rpl_control_is_dodag_parent(cur, ll_address)) { - cur->ws_info->pan_information.pan_size = pan_information.pan_size; - cur->ws_info->pan_information.routing_cost = pan_information.routing_cost; - cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method; - cur->ws_info->pan_information.use_parent_bs = pan_information.use_parent_bs; - } - } -} - -static void ws_bootstrap_ffn_pan_advertisement_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) -{ - - (void)data; - (void)ws_utt; - (void)ws_us; - /* - * An inconsistent transmission is defined as: - * A PAN Advertisement Solicit with NETNAME-IE matching that of the receiving node. - */ - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery); - /* - * A consistent transmission is defined as - * a PAN Advertisement Solicit with NETNAME-IE / Network Name matching that configured on the receiving node. - */ - trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit); - /* - * Optimized PAN discovery to select the parent faster if we hear solicit from someone else - */ - - if (ws_bootstrap_state_discovery(cur) && ws_cfg_network_config_get(cur) <= CONFIG_MEDIUM && - cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin * 2) { - - cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); - - tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); - } - - if (ws_bootstrap_state_active(cur) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), data->SrcAddr, ADDR_802_15_4_LONG); - if (neighbor && neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { - ws_bootstrap_parent_confirm(cur, NULL); - } - } -} -#ifdef HAVE_WS_VERSION_1_1 -static void ws_bootstrap_ffn_pan_config_lfn_analyze(struct protocol_interface_info_entry *cur, const struct mcps_data_ie_list *ie_ext) -{ - if (!ws_version_1_1(cur) || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - return; - } - - ws_lfnver_ie_t lfn_version; - if (!ws_wp_nested_lfn_version_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &lfn_version)) { - return; // LFN version - } - - //Read LFNGTKHASH - ws_lgtkhash_ie_t ws_lgtkhash; - if (!ws_wp_nested_lgtk_hash_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_lgtkhash)) { - return; - } - - if (!cur->ws_info->lfngtk.lfn_version_learned) { - if (!cur->ws_info->configuration_learned) { - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); + (void)prefix; + (void)interface; + //TODO add handler for negative status + tr_debug("DHCPv6 %s status %u with link %s", trace_ipv6(prefix), register_status, trace_ipv6(dhcp_addr)); + if (register_status) { + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); + if (cur) { + ws_address_reregister_trig(cur); } } else { - if (cur->ws_info->lfngtk.lfn_version == lfn_version.lfn_version) { - return; - } - - if (common_serial_number_greater_16(cur->ws_info->lfngtk.lfn_version, lfn_version.lfn_version)) { - // older version heard ignoring the message - return; - } + //Delete dhcpv6 client + dhcp_client_global_address_delete(interface, dhcp_addr, prefix); } - - cur->ws_info->lfngtk.lfn_version = lfn_version.lfn_version; - - //Clear HASH allways at new first or for first leaned one's - memset(cur->ws_info->lfngtk.lgtkhash, 0, 24); - cur->ws_info->lfngtk.lfn_version_learned = true; - - //Set Active key index and hash inline bits - cur->ws_info->lfngtk.active_key_index = ws_lgtkhash.active_lgtk_index; - cur->ws_info->lfngtk.active_hash_1 = ws_lgtkhash.lgtk0; - cur->ws_info->lfngtk.active_hash_2 = ws_lgtkhash.lgtk1; - cur->ws_info->lfngtk.active_hash_3 = ws_lgtkhash.lgtk2; - - if (cur->ws_info->lfngtk.active_hash_1) { - memcpy(cur->ws_info->lfngtk.lgtkhash, ws_lgtkhash.lgtk0_hash, 8); - } - - if (cur->ws_info->lfngtk.active_hash_2) { - memcpy(cur->ws_info->lfngtk.lgtkhash + 8, ws_lgtkhash.lgtk1_hash, 8); - } - - if (cur->ws_info->lfngtk.active_hash_3) { - memcpy(cur->ws_info->lfngtk.lgtkhash + 16, ws_lgtkhash.lgtk2_hash, 8); - } - //TODO Analyze HASH's and set LFN group key index } + + +void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local) +{ + if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, ws_dhcp_client_global_adress_cb) != 0) { + tr_error("DHCPp client request fail"); + } +} + +void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix) +{ + dhcp_client_global_address_delete(cur->id, NULL, prefix); +} + +void ws_bootstrap_ffn_rpl_configure(protocol_interface_info_entry_t *cur) +{ + tr_debug("RPL Activate"); +#ifdef HAVE_RPL + bool downstream = true; + bool leaf = false; #endif + addr_add_router_groups(cur); +#ifdef HAVE_RPL + rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, downstream); + // If i am router I Do this + rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); + 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); + rpl_control_set_force_tunnel(true); + // 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); -static void ws_bootstrap_ffn_pan_config_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) -{ + // Set the minimum target refresh to sen DAO registrations before pan timeout + rpl_control_set_minimum_dao_target_refresh(WS_RPL_DAO_MAX_TIMOUT); +#endif // HAVE_RPL - uint16_t pan_version; - ws_bs_ie_t ws_bs_ie; - uint8_t *gtkhash_ptr; - - if (data->SrcPANId != cur->ws_info->network_pan_id) { - return; - } - ws_bt_ie_t ws_bt_ie; - if (!ws_wh_bt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_bt_ie)) { - tr_warn("BT-IE"); - return; - } - - /* - * A consistent transmission is defined as a PAN Configuration with a PAN-ID matching that of the receiving node and - * a PANVER-IE / PAN Version greater than or equal to the receiving node’s current PAN version. - * - * A inconsistent transmission is defined as: - * - * A PAN Configuration with PAN-ID matching that of the receiving node and a - * PANVER-IE / PAN Version that is less than the receiving node’s current PAN version. - */ - - // TODO Add this to neighbor table - // TODO save all information from config message if version number has changed - - if (!ws_wp_nested_pan_version_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &pan_version)) { - // Corrupted - tr_warn("no version"); - return; - } - - gtkhash_ptr = ws_wp_nested_gtkhash_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength); - - if (!gtkhash_ptr) { - // Corrupted - tr_error("No gtk hash"); - return; - } - - if (!ws_wp_nested_bs_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_bs_ie)) { - // Corrupted - tr_error("No broadcast schedule"); - return; - } - - llc_neighbour_req_t neighbor_info; - bool neighbour_pointer_valid; - - //Validate BSI - if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - - if (cur->ws_info->ws_bsi_block.block_time && cur->ws_info->ws_bsi_block.old_bsi == ws_bs_ie.broadcast_schedule_identifier) { - tr_debug("Do not accept a old BSI: %u in time %"PRIu32, cur->ws_info->ws_bsi_block.old_bsi, cur->ws_info->ws_bsi_block.block_time); - //Refresh Block time when hear a old BSI - cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; - return; - } - - //When Config is learned and USE Parent BS is enabled compare is this new BSI - if (cur->ws_info->configuration_learned && cur->ws_info->pan_information.use_parent_bs && ws_bs_ie.broadcast_schedule_identifier != cur->ws_info->hopping_schdule.fhss_bsi) { - //Accept only next possible BSI number - if ((cur->ws_info->hopping_schdule.fhss_bsi + 1) != ws_bs_ie.broadcast_schedule_identifier) { - tr_debug("Do not accept a unknown BSI: %u", ws_bs_ie.broadcast_schedule_identifier); - } else { - tr_debug("NEW Brodcast Schedule %u...BR rebooted", ws_bs_ie.broadcast_schedule_identifier); - cur->ws_info->ws_bsi_block.block_time = cur->ws_info->cfg->timing.pan_timeout; - cur->ws_info->ws_bsi_block.old_bsi = cur->ws_info->hopping_schdule.fhss_bsi; - ws_bootstrap_event_disconnect(cur, WS_NORMAL_DISCONNECT); - } - return; - } - } - - - if (cur->ws_info->configuration_learned || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - //If we are border router or learned configuration we only update already learned neighbours. - neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false); - - } else { - neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true); - if (!neighbour_pointer_valid) { - return; - } - ws_bootstrap_neighbor_set_stable(cur, data->SrcAddr); - } - - if (neighbour_pointer_valid) { - //Update Neighbor Broadcast and Unicast Parameters - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); - ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); - ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp); - ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); - } - - 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) { - //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); - } - // no need to process more -#ifdef HAVE_WS_VERSION_1_1 - ws_bootstrap_ffn_pan_config_lfn_analyze(cur, ie_ext); -#endif - return; - } else { - // received version is different so we need to reset the trickle - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); - if (neighbour_pointer_valid && neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { - ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH); - } - if (common_serial_number_greater_16(cur->ws_info->pan_information.pan_version, pan_version)) { - // older version heard ignoring the message - return; - } - cur->ws_info->trickle_pc_consistency_block_period = WS_CONFIG_CONSISTENT_FILTER_PERIOD; - } - } - - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - //Border router does not learn network information - return; - } - - /* - * Learn new information from neighbor - */ - tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); - - // restart PAN version timer - //Check Here Do we have a selected Primary parent - if (!cur->ws_info->configuration_learned || cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { - ws_common_border_router_alive_update(cur); - } - - cur->ws_info->pan_information.pan_version = pan_version; - - ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr); - - ws_pae_controller_nw_key_index_update(cur, data->Key.KeyIndex - 1); - -#ifdef HAVE_WS_VERSION_1_1 - ws_bootstrap_ffn_pan_config_lfn_analyze(cur, ie_ext); -#endif - - if (!cur->ws_info->configuration_learned) { - // Generate own hopping schedules Follow first parent broadcast and plans and also use same unicast dwell - tr_info("learn network configuration"); - cur->ws_info->configuration_learned = true; - // return to state machine after 1-2 s - cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, 20); - // enable frequency hopping for unicast channel and start listening first neighbour - ws_bootstrap_primary_parent_set(cur, &neighbor_info, WS_PARENT_HARD_SYNCH); - // set neighbor as priority parent clear if there is others - protocol_6lowpan_neighbor_priority_clear_all(cur->id, PRIORITY_1ST); - neighbor_info.neighbor->link_role = PRIORITY_PARENT_NEIGHBOUR; - } + cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event } - -static void ws_bootstrap_ffn_pan_config_solicit_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us) -{ - if (data->SrcPANId != cur->ws_info->network_pan_id) { - return; - } - - /* TODO smart neighbour process - * - * Unsecure packet we cant trust the device? - * - * Question mark in specification also present, now we create neighbour. - * this is moved in future to NS/ND processing triggered by RPL - * - */ - - llc_neighbour_req_t neighbor_info; - if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); - ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); - } - - if (ws_bootstrap_state_active(cur) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), data->SrcAddr, ADDR_802_15_4_LONG); - if (neighbor && neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { - ws_bootstrap_parent_confirm(cur, NULL); - } - } - - /* - * A consistent transmission is defined as a PAN Configuration Solicit with - * a PAN-ID matching that of the receiving node and a NETNAME-IE / Network Name - * matching that configured on the receiving node. - */ - trickle_consistent_heard(&cur->ws_info->trickle_pan_config_solicit); - /* - * inconsistent transmission is defined as either: - * A PAN Configuration Solicit with a PAN-ID matching that of the receiving node and - * a NETNAME-IE / Network Name matching the network name configured on the receiving - */ - trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery); -} - - -void ws_bootstrap_ffn_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) -{ - // Store weakest heard packet RSSI - if (cur->ws_info->weakest_received_rssi > data->signal_dbm) { - cur->ws_info->weakest_received_rssi = data->signal_dbm; - } - - if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) { - // Not from long address - return; - } - ws_stats_update(cur, STATS_WS_ASYNCH_RX, 1); - //Validate network name - switch (message_type) { - case WS_FT_PAN_ADVERT: - 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->cfg->gen.network_name)) { - // Not in our network - return; - } - break; - case WS_FT_PAN_CONF: - break; - default: - return; - } - //UTT-IE and US-IE are mandatory for all Asynch Messages - ws_utt_ie_t ws_utt; - if (!ws_wh_utt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_utt)) { - // Corrupted - return; - } - - ws_us_ie_t ws_us; - if (!ws_wp_nested_us_read(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_us)) { - // Corrupted - return; - } - - if (!ws_bootstrap_validate_channel_plan(&ws_us, cur) || - !ws_bootstrap_validate_channel_function(&ws_us, NULL)) { - return; - } - - //Handle Message's - switch (message_type) { - case WS_FT_PAN_ADVERT: - // Analyse Advertisement - ws_stats_update(cur, STATS_WS_ASYNCH_RX_PA, 1); - tr_info("received ADVERT Src:%s panid:%x rssi:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm); - ws_bootstrap_ffn_pan_advertisement_analyse(cur, data, ie_ext, &ws_utt, &ws_us); - break; - case WS_FT_PAN_ADVERT_SOL: - ws_stats_update(cur, STATS_WS_ASYNCH_RX_PAS, 1); - tr_info("received ADVERT SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); - ws_bootstrap_ffn_pan_advertisement_solicit_analyse(cur, data, &ws_utt, &ws_us); - break; - case WS_FT_PAN_CONF: - ws_stats_update(cur, STATS_WS_ASYNCH_RX_PC, 1); - tr_info("received CONFIG Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); - ws_bootstrap_ffn_pan_config_analyse(cur, data, ie_ext, &ws_utt, &ws_us); - break; - case WS_FT_PAN_CONF_SOL: - ws_stats_update(cur, STATS_WS_ASYNCH_RX_PCS, 1); - tr_info("received CONFIG SOL Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm); - ws_bootstrap_ffn_pan_config_solicit_analyse(cur, data, &ws_utt, &ws_us); - default: - // Unknown message do not process - break; - } -} - -void ws_bootstrap_ffn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message) -{ - (void)asynch_message; - ws_stats_update(interface, STATS_WS_ASYNCH_TX, 1); -} - -void ws_bootstrap_ffn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event) -{ - ws_bootsrap_event_type_e event_type; - event_type = (ws_bootsrap_event_type_e)event->event_type; - - switch (event_type) { - case WS_INIT_EVENT: - tr_debug("tasklet init"); - break; - case WS_DISCOVERY_START: - tr_info("Discovery start"); - protocol_mac_reset(cur); - ws_llc_reset(cur); - lowpan_adaptation_interface_reset(cur->id); - //Clear Pending Key Index State - cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS; - cur->mac_parameters->mac_default_key_index = 0; - - ipv6_destination_cache_clean(cur->id); - - // Clear parent blacklist - blacklist_clear(); - - // All trickle timers stopped to allow entry from any state - ws_bootstrap_asynch_trickle_stop(cur); - //Init Packet congestion - ws_bootstrap_packet_congestion_init(cur); - - ws_pae_controller_supp_init(cur); - // Clear learned neighbours - ws_bootstrap_neighbor_list_clean(cur); - // Configure LLC for network discovery - ws_bootstrap_ffn_network_discovery_configure(cur); - ws_bootstrap_fhss_activate(cur); - // Set retry configuration for discovery state - ws_bootstrap_configure_max_retries(cur, WS_MAX_FRAME_RETRIES_BOOTSTRAP); - // Set TX failure request restart configuration for discovery state - ws_bootstrap_configure_data_request_restart(cur, WS_CCA_REQUEST_RESTART_MAX, WS_TX_REQUEST_RESTART_MAX_BOOTSTRAP, WS_REQUEST_RESTART_BLACKLIST_MIN, WS_REQUEST_RESTART_BLACKLIST_MAX); - // Set CSMA-CA backoff configuration - ws_bootstrap_configure_csma_ca_backoffs(cur, WS_MAX_CSMA_BACKOFFS, WS_MAC_MIN_BE, WS_MAC_MAX_BE); - // Start network scan - ws_bootstrap_ffn_start_discovery(cur); - break; - - case WS_CONFIGURATION_START: - tr_info("Configuration start"); - // Old configuration is considered invalid stopping all - ws_bootstrap_asynch_trickle_stop(cur); - - // Build list of possible neighbours and learn first broadcast schedule - - ws_bootstrap_ffn_start_configuration_learn(cur); - break; - case WS_OPERATION_START: - tr_info("operation start"); - // Advertisements stopped during the RPL scan - ws_bootstrap_asynch_trickle_stop(cur); - // Activate RPL - // Activate IPv6 stack - ws_bootstrap_ip_stack_activate(cur); - ws_bootstrap_rpl_activate(cur); - ws_bootstrap_network_start(cur); - // Wait for RPL start - ws_bootstrap_rpl_scan_start(cur); - /* 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 - */ - ws_common_border_router_alive_update(cur); - break; - case WS_ROUTING_READY: - tr_info("Routing ready"); - // stopped all to make sure we can enter here from any state - ws_bootstrap_asynch_trickle_stop(cur); - - // Indicate PAE controller that bootstrap is ready - ws_pae_controller_bootstrap_done(cur); - - ws_bootstrap_advertise_start(cur); - ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE); - break; - case WS_FAST_DISCONNECT: - ws_bootstrap_state_disconnect(cur, WS_FAST_DISCONNECT); - break; - case WS_NORMAL_DISCONNECT: - ws_bootstrap_state_disconnect(cur, WS_NORMAL_DISCONNECT); - break; - - case WS_TEST_PROC_TRIGGER: - ws_bootstrap_test_procedure_trigger_exec(cur, (ws_bootsrap_procedure_t) event->data_ptr); - break; - - default: - tr_err("Invalid event received"); - break; - } -} - -/* - * Statemachine state functions - * */ - -static void ws_bootstrap_ffn_network_scan_process(protocol_interface_info_entry_t *cur) -{ - - parent_info_t *selected_parent_ptr; - - tr_debug("analyze network discovery result"); - -select_best_candidate: - selected_parent_ptr = ws_bootstrap_candidate_parent_get_best(cur); - - if (!selected_parent_ptr) { - // Configure LLC for network discovery - ws_bootstrap_ffn_network_discovery_configure(cur); - // randomize new channel and start MAC - ws_bootstrap_fhss_activate(cur); - // Next check will be after one trickle - uint32_t random_start = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_random_in_range(0, cur->ws_info->trickle_params_pan_discovery.Imin); - if (random_start > 0xffff) { - random_start = 0xffff; - } - cur->bootsrap_state_machine_cnt = random_start; - - tr_info("Making parent selection in %u s", (cur->bootsrap_state_machine_cnt / 10)); - return; - } - tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id); - - if (ws_bootstrap_neighbor_set(cur, selected_parent_ptr, false) < 0) { - goto select_best_candidate; - } - - ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth - ws_bootstrap_event_authentication_start(cur); - return; -} - -static void ws_bootstrap_ffn_configure_process(protocol_interface_info_entry_t *cur) -{ - - if (cur->ws_info->configuration_learned) { - ws_bootstrap_ffn_network_configuration_learn(cur); - ws_bootstrap_event_operation_start(cur); - return; - } - return; -} - -void ws_bootstrap_ffn_rpl_wait_process(protocol_interface_info_entry_t *cur) -{ - - if (cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { - // RPL routing is ready - cur->ws_info->connected_time = cur->ws_info->uptime; - ws_bootstrap_event_routing_ready(cur); - } else if (!rpl_control_have_dodag(cur->rpl_domain)) { - // RPL not ready send DIS message if possible - if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) { - // TODO Multicast DIS should be sent only if no DIO heard for some time - rpl_control_transmit_dis(cur->rpl_domain, cur, 0, 0, NULL, 0, ADDR_LINK_LOCAL_ALL_RPL_NODES); - } - // set timer for next DIS - cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(WS_RPL_DIS_TIMEOUT / 2, WS_RPL_DIS_TIMEOUT); - } - return; -} - - -/* - * State machine - */ - -void ws_bootstrap_ffn_state_machine(protocol_interface_info_entry_t *cur) -{ - - switch (cur->nwk_bootstrap_state) { - case ER_WAIT_RESTART: - tr_debug("WS SM:Wait for startup"); - ws_bootstrap_event_discovery_start(cur); - break; - case ER_ACTIVE_SCAN: - tr_debug("WS SM:Active Scan"); - ws_bootstrap_ffn_network_scan_process(cur); - break; - case ER_SCAN: - tr_debug("WS SM:configuration Scan"); - ws_bootstrap_ffn_configure_process(cur); - break; - case ER_PANA_AUTH: - tr_info("authentication start"); - // Advertisements stopped during the EAPOL - ws_bootstrap_asynch_trickle_stop(cur); - ws_bootstrap_ffn_fhss_configure(cur, false); - int8_t new_default = cur->ws_info->weakest_received_rssi - 1; - if ((new_default < CCA_DEFAULT_DBM) && (new_default >= CCA_LOW_LIMIT) && (new_default <= CCA_HIGH_LIMIT)) { - // Restart automatic CCA threshold using weakest received RSSI as new default - mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->weakest_received_rssi - 1, CCA_HIGH_LIMIT, CCA_LOW_LIMIT); - } - ws_bootstrap_start_authentication(cur); - break; - case ER_RPL_SCAN: - tr_debug("WS SM:Wait RPL to contact DODAG root"); - ws_bootstrap_ffn_rpl_wait_process(cur); - break; - case ER_BOOTSRAP_DONE: - tr_info("WS SM:Bootstrap Done"); - // Bootstrap_done event to application - nwk_bootsrap_state_update(ARM_NWK_BOOTSTRAP_READY, cur); - break; - case ER_RPL_NETWORK_LEAVING: - tr_debug("WS SM:RPL Leaving ready trigger discovery"); - ws_bootstrap_event_discovery_start(cur); - break; - default: - tr_warn("WS SM:Invalid state %d", cur->nwk_bootstrap_state); - } -} - -void ws_bootstrap_ffn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds) -{ - /* Border router keep alive check - */ - if (cur->ws_info->pan_timeout_timer) { - // PAN version timer running - 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 - //Clear Timeout timer - cur->ws_info->pan_timeout_timer = 0; - tr_warn("Border router has timed out"); - ws_bootstrap_event_disconnect(cur, WS_FAST_DISCONNECT); - } - } - 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); - } - } - - if (cur->ws_info->ws_bsi_block.block_time) { - if (cur->ws_info->ws_bsi_block.block_time > seconds) { - cur->ws_info->ws_bsi_block.block_time -= seconds; - } else { - //Clear A BSI blokker - cur->ws_info->ws_bsi_block.block_time = 0; - cur->ws_info->ws_bsi_block.old_bsi = 0; - } - } -} - - -#endif //HAVE_WS_BORDER_ROUTER && HAVE_WS +#endif //HAVE_WS diff --git a/source/6LoWPAN/ws/ws_bootstrap_ffn.h b/source/6LoWPAN/ws/ws_bootstrap_ffn.h index fcc9dd25d6..b598b81479 100644 --- a/source/6LoWPAN/ws/ws_bootstrap_ffn.h +++ b/source/6LoWPAN/ws/ws_bootstrap_ffn.h @@ -18,26 +18,15 @@ #ifndef WS_BOOTSTRAP_FFN_H_ #define WS_BOOTSTRAP_FFN_H_ -#if defined(HAVE_WS) && defined(HAVE_WS_ROUTER) +#ifdef HAVE_WS -void ws_bootstrap_ffn_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); -void ws_bootstrap_ffn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message); -void ws_bootstrap_ffn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event); -void ws_bootstrap_ffn_state_machine(protocol_interface_info_entry_t *cur); -void ws_bootstrap_ffn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); +int8_t ws_bootstrap_ffn_up(protocol_interface_info_entry_t *cur); +int8_t ws_bootstrap_ffn_down(protocol_interface_info_entry_t *cur); -#define wisun_mode_router(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) +void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local); -#else +void ws_bootstrap_ffn_rpl_configure(protocol_interface_info_entry_t *cur); -#define ws_bootstrap_ffn_asynch_ind(cur, data, ie_ext, message_type) ((void) 0) -#define ws_bootstrap_ffn_asynch_confirm(interface, asynch_message) ((void) 0) -#define ws_bootstrap_ffn_event_handler(cur, event) ((void) 0) -#define ws_bootstrap_ffn_state_machine(cur) ((void) 0) -#define ws_bootstrap_ffn_seconds_timer(cur, seconds) ((void) 0) +#endif -#define wisun_mode_router(cur) (false) - -#endif //HAVE_WS - -#endif /* WS_BOOTSTRAP_H_ */ +#endif /* WS_BOOTSTRAP_FFN_H_ */ diff --git a/source/6LoWPAN/ws/ws_bootstrap_lfn.h b/source/6LoWPAN/ws/ws_bootstrap_lfn.h deleted file mode 100644 index 84a0cf8101..0000000000 --- a/source/6LoWPAN/ws/ws_bootstrap_lfn.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2021, Pelion 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_BOOTSTRAP_LFN_H_ -#define WS_BOOTSTRAP_LFN_H_ - -#if defined(HAVE_WS) && defined(HAVE_WS_HOST) - -void ws_bootstrap_lfn_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); -void ws_bootstrap_lfn_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message); -void ws_bootstrap_lfn_event_handler(protocol_interface_info_entry_t *cur, arm_event_s *event); -void ws_bootstrap_lfn_state_machine(protocol_interface_info_entry_t *cur); -void ws_bootstrap_lfn_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds); - -#define wisun_mode_host(cur) (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST) - -#else - -#define ws_bootstrap_ffn_asynch_ind(cur, data, ie_ext, message_type) ((void) 0) -#define ws_bootstrap_ffn_asynch_confirm(interface, asynch_message) ((void) 0) -#define ws_bootstrap_ffn_event_handler(cur, event) ((void) 0) -#define ws_bootstrap_lfn_state_machine(cur) ((void) 0) -#define ws_bootstrap_lfn_seconds_timer(cur, seconds) ((void) 0) - -#define wisun_mode_host(cur) (false) - -#endif //HAVE_WS - -#endif /* WS_BOOTSTRAP_H_ */ diff --git a/source/6LoWPAN/ws/ws_cfg_settings.c b/source/6LoWPAN/ws/ws_cfg_settings.c index 2d70df180a..312d41263a 100644 --- a/source/6LoWPAN/ws/ws_cfg_settings.c +++ b/source/6LoWPAN/ws/ws_cfg_settings.c @@ -792,6 +792,13 @@ int8_t ws_cfg_bbr_validate(ws_bbr_cfg_t *new_cfg) return CFG_SETTINGS_CHANGED; } + if (cfg->dio_interval_min == 0 || + cfg->min_hop_rank_increase < 32 || + cfg->dhcp_address_lifetime < 60 || + cfg->rpl_default_lifetime < 60) { + return CFG_SETTINGS_ERROR_GEN_CONF; + } + return CFG_SETTINGS_OK; } diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index e6274c2e4f..f9c258aefd 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -33,9 +33,10 @@ #include "6LoWPAN/ws/ws_llc.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" +#include "6LoWPAN/ws/ws_bootstrap_6ln.h" +#include "6LoWPAN/ws/ws_bootstrap_6lr.h" #include "6LoWPAN/ws/ws_bootstrap_6lbr.h" #include "6LoWPAN/ws/ws_bootstrap_ffn.h" -#include "6LoWPAN/ws/ws_bootstrap_lfn.h" #include "6LoWPAN/ws/ws_bbr_api_internal.h" #include "6LoWPAN/ws/ws_pae_controller.h" #include "6LoWPAN/ws/ws_cfg_settings.h" @@ -419,10 +420,10 @@ void ws_common_state_machine(protocol_interface_info_entry_t *cur) { if (wisun_mode_host(cur)) { // Configure for LFN device - ws_bootstrap_lfn_state_machine(cur); + ws_bootstrap_6ln_state_machine(cur); } else if (wisun_mode_router(cur)) { // Configure FFN device - ws_bootstrap_ffn_state_machine(cur); + ws_bootstrap_6lr_state_machine(cur); } else if (wisun_mode_border_router(cur)) { // Configure as Border router ws_bootstrap_6lbr_state_machine(cur); @@ -435,8 +436,8 @@ void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seco ws_bbr_seconds_timer(cur, seconds); ws_bootstrap_seconds_timer(cur, seconds); ws_bootstrap_6lbr_seconds_timer(cur, seconds); - ws_bootstrap_ffn_seconds_timer(cur, seconds); - ws_bootstrap_lfn_seconds_timer(cur, seconds); + ws_bootstrap_6lr_seconds_timer(cur, seconds); + ws_bootstrap_6ln_seconds_timer(cur, seconds); blacklist_ttl_update(seconds); } @@ -661,12 +662,12 @@ uint32_t ws_common_authentication_time_get(protocol_interface_info_entry_t *cur) void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor) { - ws_bootstrap_primary_parent_update(interface, neighbor); + ws_bootstrap_6lr_primary_parent_update(interface, neighbor); } void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface) { - ws_bootstrap_secondary_parent_update(interface); + ws_bootstrap_6lr_secondary_parent_update(interface); } void ws_common_border_router_alive_update(protocol_interface_info_entry_t *interface) diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 9af23615d8..d2715783a3 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -246,15 +246,21 @@ extern uint8_t DEVICE_MIN_SENS; * * Trickle is reset on start (inconsistent heard is set) */ +#define SEC_PROT_TIMER_EXPIRATIONS 4 // Number of retries +#define SEC_PROT_END_DELAY 30 // 30 seconds delay + #define SEC_PROT_SMALL_IMIN 60 // Retries done in 60 seconds #define SEC_PROT_SMALL_IMAX 120 // Largest value 120 seconds -#define SEC_PROT_RETRY_TIMEOUT_SMALL 450 // Retry timeout for small network additional 30 seconds for authenticator delay +// Retry timeout for small network; additional 30 seconds for authenticator delay +#define SEC_PROT_RETRY_TIMEOUT_SMALL (SEC_PROT_SMALL_IMAX * SEC_PROT_TIMER_EXPIRATIONS + SEC_PROT_END_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 +// Retry timeout for large network; additional 30 seconds for authenticator delay +#define SEC_PROT_RETRY_TIMEOUT_LARGE (SEC_PROT_LARGE_IMAX * SEC_PROT_TIMER_EXPIRATIONS + SEC_PROT_END_DELAY) -#define SEC_PROT_TIMER_EXPIRATIONS 4 // Number of retries +// Timeout for retrying side of the protocol (runs when trickle not running) +#define SEC_PROT_RETRYING_PROTOCOL_TIMEOUT (5 * 60 * 10) // 5 minutes in ticks // Maximum number of simultaneous security negotiations #define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_TX_QUEUE_MIN 64 diff --git a/source/6LoWPAN/ws/ws_llc.h b/source/6LoWPAN/ws/ws_llc.h index da89a34959..9b8e55f380 100644 --- a/source/6LoWPAN/ws/ws_llc.h +++ b/source/6LoWPAN/ws/ws_llc.h @@ -117,7 +117,7 @@ typedef void ws_asynch_ind(struct protocol_interface_info_entry *interface, cons typedef void ws_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message); /** - * @brief ws_asynch_confirm ws asynch data confirmation to asynch message request + * @brief ws_neighbor_info_request neighbor info request * @param interface The interface pointer * @param mac_64 Neighbor 64-bit address * @param neighbor_buffer Buffer where neighbor infor is buffered @@ -128,15 +128,31 @@ typedef void ws_asynch_confirm(struct protocol_interface_info_entry *interface, */ typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, struct llc_neighbour_req *neighbor_buffer, bool request_new); +/** + * @brief ws_eapol_relay_active_check check if eapol relay is active + * @param interface The interface pointer + * + * @return true eapol relay is active + * @return false eapol relay is not active + */ +typedef bool ws_eapol_relay_active_check(struct protocol_interface_info_entry *cur); + /** * @brief ws_llc_create ws LLC module create * @param interface Interface pointer * @param asynch_ind_cb Asynch indication + * @param asynch_cnf_cb Asynch confirm + * @param ws_neighbor_info_request_cb neighbor info request + * @param eapol_relay_active_cb check if eapol relay is active + * * @param ie_ext Information element list * * Function allocate and init LLC class and init it 2 supported 2 API: ws asynch and MPX user are internally registered. + * + * @return 0 on success + * @return < 0 on failure */ -int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ind *asynch_ind_cb, ws_asynch_confirm *asynch_cnf_cb, ws_neighbor_info_request *ws_neighbor_info_request_cb); +int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ind *asynch_ind_cb, ws_asynch_confirm *asynch_cnf_cb, ws_neighbor_info_request *ws_neighbor_info_request_cb, ws_eapol_relay_active_check *eapol_relay_active_cb); /** * @brief ws_llc_reset Reset ws LLC parametrs and clean messages diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index 43794ba776..665a16b8c8 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -32,6 +32,7 @@ #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" +#include "6LoWPAN/ws/ws_bootstrap_ffn.h" #include "6LoWPAN/ws/ws_ie_lib.h" #include "6LoWPAN/ws/ws_llc.h" #include "6LoWPAN/ws/ws_neighbor_class.h" @@ -153,6 +154,7 @@ typedef struct { ws_asynch_ind *asynch_ind; /**< LLC Asynch data indication call back configured by user */ ws_asynch_confirm *asynch_confirm; /**< LLC Asynch data confirmation call back configured by user */ ws_neighbor_info_request *ws_neighbor_info_request_cb; /**< LLC Neighbour discover API*/ + ws_eapol_relay_active_check *eapol_relay_active_cb; /**< EAPOL relay active check callback */ uint8_t ws_enhanced_response_elements[ENHANCED_FRAME_RESPONSE]; ns_ie_iovec_t ws_header_vector; bool high_priority_mode; @@ -992,9 +994,9 @@ static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id) return header_size; } -static bool ws_eapol_handshake_first_msg(uint8_t *pdu, uint16_t length, protocol_interface_info_entry_t *cur) +static bool ws_eapol_handshake_first_msg(llc_data_base_t *base, uint8_t *pdu, uint16_t length, protocol_interface_info_entry_t *cur) { - if (!ws_eapol_relay_state_active(cur)) { + if (!base->eapol_relay_active_cb(cur)) { return false; } @@ -1246,8 +1248,8 @@ static void ws_llc_mpx_eapol_request(llc_data_base_t *base, mpx_user_t *user_cb, wp_nested_ie_sub_list_t nested_wp_id; memset(&nested_wp_id, 0, sizeof(wp_nested_ie_sub_list_t)); ie_header_mask.utt_ie = true; - ie_header_mask.bt_ie = ws_eapol_relay_state_active(base->interface_ptr); - ie_header_mask.ea_ie = ws_eapol_handshake_first_msg(data->msdu, data->msduLength, base->interface_ptr); + ie_header_mask.bt_ie = base->eapol_relay_active_cb(base->interface_ptr); /* Broadcast timing information */ + ie_header_mask.ea_ie = ws_eapol_handshake_first_msg(base, data->msdu, data->msduLength, base->interface_ptr); nested_wp_id.bs_ie = ie_header_mask.ea_ie; @@ -1746,7 +1748,7 @@ static uint16_t ws_llc_calculate_dynamic_entries_max(uint16_t min_entry, uint16_ } -int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ind *asynch_ind_cb, ws_asynch_confirm *asynch_cnf_cb, ws_neighbor_info_request *ws_neighbor_info_request_cb) +int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ind *asynch_ind_cb, ws_asynch_confirm *asynch_cnf_cb, ws_neighbor_info_request *ws_neighbor_info_request_cb, ws_eapol_relay_active_check eapol_relay_active_cb) { llc_data_base_t *base = ws_llc_discover_by_interface(interface); if (base) { @@ -1765,6 +1767,7 @@ int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ base->asynch_ind = asynch_ind_cb; base->asynch_confirm = asynch_cnf_cb; base->ws_neighbor_info_request_cb = ws_neighbor_info_request_cb; + base->eapol_relay_active_cb = eapol_relay_active_cb; //Register MAC Extensions base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, &ws_llc_mac_indication_cb, &ws_llc_mac_confirm_cb, &ws_llc_ack_data_req_ext); base->interface_ptr->mac_api->mac_mcps_edfe_enable(base->interface_ptr->mac_api, &ws_llc_mcps_edfe_handler); diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index c39f6bced0..92e280d1b1 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -327,9 +327,26 @@ int ws_management_regulatory_domain_get( return -3; } - *regulatory_domain = cfg.regulatory_domain; - *operating_class = cfg.operating_class; - *operating_mode = cfg.operating_mode; + if (regulatory_domain) { + *regulatory_domain = cfg.regulatory_domain; + } + + // If phy_mode_id is set the new configuration mode is used and class and mode return invalid value + if (operating_class) { + if (cfg.phy_mode_id == 0xff) { + *operating_class = cfg.operating_class; + } else { + *operating_class = 0xff; + } + } + + if (operating_mode) { + if (cfg.phy_mode_id == 0xff) { + *operating_mode = cfg.operating_mode; + } else { + *operating_mode = 0xff; + } + } return 0; } diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index 8abfe1e970..79df031586 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -295,7 +295,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #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 -#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get, nw_frame_cnt_read) {(void) hash_set;} +#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get, nw_frame_cnt_read) #define ws_pae_auth_start(interface_ptr) #define ws_pae_auth_gtks_updated NULL #define ws_pae_auth_nw_key_index_update NULL diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 6511616540..fdc0dbfd0a 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -64,11 +64,15 @@ typedef struct { typedef struct { ns_list_link_t link; /**< Link */ +#ifdef HAVE_PAE_SUPP uint8_t target_eui_64[8]; /**< EAPOL target */ uint16_t target_pan_id; /**< EAPOL target PAN ID */ +#endif uint8_t br_eui_64[8]; /**< Border router EUI-64 */ sec_prot_gtk_keys_t gtks; /**< GTKs */ +#ifdef HAVE_PAE_AUTH sec_prot_gtk_keys_t next_gtks; /**< Next GTKs */ +#endif sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */ int8_t gtk_index; /**< GTK index */ uint8_t gtkhash[32]; /**< GTK hashes */ @@ -80,17 +84,21 @@ typedef struct { sec_cfg_t sec_cfg; /**< Security configuration (configuration set values) */ uint32_t restart_cnt; /**< Re-start counter */ 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 */ ws_pae_controller_nw_key_clear *nw_key_clear; /**< Key clear callback */ ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set; /**< Send key index set callback */ ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set; /**< Frame counter set callback */ ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read; /**< Frame counter read callback */ +#ifdef HAVE_PAE_SUPP + ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */ + ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */ +#endif +#ifdef HAVE_PAE_AUTH ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */ ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */ - ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */ ws_pae_controller_congestion_get *congestion_get; /**< Congestion get callback */ ws_pae_controller_ip_addr_get *ip_addr_get; /**< IP address get callback */ +#endif ws_pae_delete *pae_delete; /**< PAE delete callback */ ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */ ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */ @@ -128,10 +136,14 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool static void ws_pae_controller_nvm_frame_counter_write(frame_cnt_nvm_tlv_t *tlv_entry); static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters); static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id); +#ifdef HAVE_PAE_AUTH static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash); +#endif static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, bool force_install); static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key); +#ifdef HAVE_PAE_SUPP static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index); +#endif static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name); static void ws_pae_controller_frame_counter_store_and_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr, pae_controller_t *controller, bool use_threshold); #ifdef HAVE_PAE_AUTH @@ -250,7 +262,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in return 0; } -int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get) +int8_t ws_pae_controller_nw_key_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read) { if (!interface_ptr) { return -1; @@ -261,21 +273,40 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ return -1; } + controller->nw_key_set = nw_key_set; + controller->nw_key_clear = nw_key_clear; + controller->nw_send_key_index_set = nw_send_key_index_set; + controller->nw_frame_counter_set = nw_frame_counter_set; + controller->nw_frame_counter_read = nw_frame_counter_read; + return 0; +} + +int8_t ws_pae_controller_authentication_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target) +{ +#ifdef HAVE_PAE_SUPP + if (!interface_ptr) { + return -1; + } + + pae_controller_t *controller = ws_pae_controller_get(interface_ptr); + if (!controller) { + return -1; + } + controller->auth_completed = completed; - controller->nw_key_set = nw_key_set; - controller->nw_key_clear = nw_key_clear; - controller->nw_send_key_index_set = nw_send_key_index_set; - controller->nw_frame_counter_set = nw_frame_counter_set; - controller->nw_frame_counter_read = nw_frame_counter_read; - controller->pan_ver_increment = pan_ver_increment; - controller->nw_info_updated = nw_info_updated; controller->auth_next_target = auth_next_target; - controller->congestion_get = congestion_get; return 0; +#else + (void) interface_ptr; + (void) completed; + (void) auth_next_target; + return 0; +#endif } -int8_t ws_pae_controller_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_ip_addr_get *ip_addr_get) +int8_t ws_pae_controller_information_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_ip_addr_get *ip_addr_get, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get) { +#ifdef HAVE_PAE_AUTH if (!interface_ptr) { return -1; } @@ -286,11 +317,42 @@ int8_t ws_pae_controller_auth_cb_register(protocol_interface_info_entry_t *inter } controller->ip_addr_get = ip_addr_get; + controller->nw_info_updated = nw_info_updated; + controller->congestion_get = congestion_get; return 0; +#else + (void) interface_ptr; + (void) ip_addr_get; + (void) nw_info_updated; + (void) congestion_get; + return 0; +#endif +} + +int8_t ws_pae_controller_pan_version_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_pan_ver_increment *pan_ver_increment) +{ +#ifdef HAVE_PAE_AUTH + if (!interface_ptr) { + return -1; + } + + pae_controller_t *controller = ws_pae_controller_get(interface_ptr); + if (!controller) { + return -1; + } + + controller->pan_ver_increment = pan_ver_increment; + return 0; +#else + (void) interface_ptr; + (void) pan_ver_increment; + return 0; +#endif } int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_ptr, uint16_t target_pan_id, uint8_t *target_eui_64) { +#ifdef HAVE_PAE_SUPP if (!interface_ptr) { return -1; } @@ -304,6 +366,12 @@ int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_p memcpy(controller->target_eui_64, target_eui_64, 8); return 0; +#else + (void) interface_ptr; + (void) target_pan_id; + (void) target_eui_64; + return -1; +#endif } static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks) @@ -432,6 +500,8 @@ static int8_t ws_pae_controller_auth_nw_frame_counter_read(protocol_interface_in int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid) { + (void) br_iid; + if (!interface_ptr) { return -1; } @@ -683,6 +753,7 @@ static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info } #endif +#ifdef HAVE_PAE_SUPP static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index) { pae_controller_t *controller = ws_pae_controller_get(cur); @@ -701,6 +772,7 @@ static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t } } +#endif int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr) { @@ -720,15 +792,21 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr) } controller->interface_ptr = interface_ptr; - controller->auth_completed = NULL; controller->nw_key_set = NULL; controller->nw_key_clear = NULL; controller->nw_send_key_index_set = NULL; controller->nw_frame_counter_set = NULL; + controller->nw_frame_counter_read = NULL; +#ifdef HAVE_PAE_SUPP + controller->auth_completed = NULL; + controller->auth_next_target = NULL; +#endif +#ifdef HAVE_PAE_AUTH controller->pan_ver_increment = NULL; controller->nw_info_updated = NULL; - controller->auth_next_target = NULL; controller->congestion_get = NULL; + controller->ip_addr_get = NULL; +#endif memset(&controller->sec_cfg, 0, sizeof(sec_cfg_t)); @@ -773,7 +851,9 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt static void ws_pae_controller_data_init(pae_controller_t *controller) { +#ifdef HAVE_PAE_SUPP memset(controller->target_eui_64, 0, 8); +#endif memset(controller->br_eui_64, 0, 8); memset(controller->gtkhash, 0, 32); @@ -782,7 +862,9 @@ static void ws_pae_controller_data_init(pae_controller_t *controller) ws_pae_controller_active_nw_key_clear(&controller->nw_key[2]); ws_pae_controller_active_nw_key_clear(&controller->nw_key[3]); +#ifdef HAVE_PAE_SUPP controller->target_pan_id = 0xffff; +#endif controller->pae_delete = NULL; controller->pae_fast_timer = NULL; controller->pae_slow_timer = NULL; @@ -803,7 +885,9 @@ static void ws_pae_controller_data_init(pae_controller_t *controller) controller->auth_started = false; ws_pae_controller_frame_counter_reset(&controller->frame_counters); sec_prot_keys_gtks_init(&controller->gtks); +#ifdef HAVE_PAE_AUTH sec_prot_keys_gtks_init(&controller->next_gtks); +#endif sec_prot_certs_init(&controller->certs); sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled); ws_pae_controller_keys_nw_info_init(&controller->sec_keys_nw_info, &controller->gtks); @@ -1006,7 +1090,6 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt } sec_prot_keys_gtks_updated_reset(&controller->gtks); } -#endif if (read_gtks_to && ws_pae_controller_nw_info_read(controller, read_gtks_to) >= 0) { /* If network information i.e pan_id and network name exists updates bootstrap with it, (in case already configured by application then no changes are made) */ @@ -1020,6 +1103,7 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt ws_pae_controller_nvm_nw_info_write(controller->interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, NULL, system_time, controller->sec_keys_nw_info.system_time_changed); } } +#endif ws_pae_key_storage_init(); if (read_gtks_to) { @@ -1539,6 +1623,7 @@ int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM]) int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM]) { +#ifdef HAVE_PAE_AUTH if (!gtk) { return -1; } @@ -1558,6 +1643,11 @@ int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_N } return 0; +#else + (void) interface_id; + (void) gtk; + return -1; +#endif } int8_t ws_pae_controller_active_key_update(int8_t interface_id, uint8_t index) @@ -1657,6 +1747,7 @@ void ws_pae_controller_forced_gc(bool full_gc) } } +#ifdef HAVE_PAE_AUTH static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash) { pae_controller_t *controller = ws_pae_controller_get(interface_ptr); @@ -1681,6 +1772,7 @@ static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *inte controller->gtkhash_set = true; } } +#endif uint8_t *ws_pae_controller_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr) { diff --git a/source/6LoWPAN/ws/ws_pae_controller.h b/source/6LoWPAN/ws/ws_pae_controller.h index 40cd01fb0b..ab31a7c75a 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.h +++ b/source/6LoWPAN/ws/ws_pae_controller.h @@ -573,6 +573,22 @@ typedef void ws_pae_controller_nw_frame_counter_set(protocol_interface_info_entr */ typedef void ws_pae_controller_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t slot); +/** + * ws_pae_controller_nw_key_cb_register register network key control callbacks + * + * \param interface_ptr interface + * \param nw_key_set network key set callback + * \param nw_key_clear network key clear callback + * \param nw_send_key_index_set network send key index set callback + * \param nw_frame_counter_set network frame counter set callback + * \param nw_frame_counter_read network frame counter read callback + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_nw_key_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read); + /** * ws_pae_controller_auth_completed authentication completed callback * @@ -596,12 +612,29 @@ typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *i typedef const uint8_t *ws_pae_controller_auth_next_target(protocol_interface_info_entry_t *interface_ptr, const uint8_t *previous_eui_64, uint16_t *pan_id); /** - * ws_pae_controller_pan_ver_increment PAN version increment callback + * ws_pae_controller_authentication_cb_register register supplicant authentication control callbacks * * \param interface_ptr interface + * \param completed authentication completed callback + * \param next_target authentication next target callback + * + * \return < 0 failure + * \return >= 0 success * */ -typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t *interface_ptr); +int8_t ws_pae_controller_authentication_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target); + +/** + * ws_pae_controller_ip_addr_get gets IP addressing information + * + * \param interface_ptr interface + * \param address IP address + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t ws_pae_controller_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address); /** * ws_pae_controller_nw_info_updated network information is updated (read from memory) @@ -626,17 +659,10 @@ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t * typedef bool ws_pae_controller_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); /** - * ws_pae_controller_cb_register register controller callbacks + * ws_pae_controller_information_cb_register register information callbacks * * \param interface_ptr interface - * \param completed authentication completed callback - * \param next_target authentication next target callback - * \param nw_key_set network key set callback - * \param nw_key_clear network key clear callback - * \param nw_send_key_index_set network send key index set callback - * \param nw_frame_counter_set network frame counter set callback - * \param nw_frame_counter_read network frame counter read callback - * \param pan_ver_increment PAN version increment callback + * \param ip_addr_get IP address get callback * \param nw_info_updated network information updated callback * \param congestion_get congestion get callback * @@ -644,31 +670,27 @@ typedef bool ws_pae_controller_congestion_get(protocol_interface_info_entry_t *i * \return >= 0 success * */ -int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get); +int8_t ws_pae_controller_information_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_ip_addr_get *ip_addr_get, ws_pae_controller_nw_info_updated *nw_info_updated, ws_pae_controller_congestion_get *congestion_get); /** - * ws_pae_controller_ip_addr_get gets IP addressing information + * ws_pae_controller_pan_ver_increment PAN version increment callback * * \param interface_ptr interface - * \param address IP address + * + */ +typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t *interface_ptr); + +/** + * ws_pae_controller_bbr_control_cb_register register PAN version control callbacks + * + * \param interface_ptr interface + * \param pan_ver_increment PAN version increment callback * * \return < 0 failure * \return >= 0 success * */ -typedef int8_t ws_pae_controller_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address); - -/** - * ws_pae_controller_auth_cb_register register authenticator callbacks - * - * \param interface_ptr interface - * \param ip_addr_get IP address get callback - * - * \return < 0 failure - * \return >= 0 success - * - */ -int8_t ws_pae_controller_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_ip_addr_get *ip_addr_get); +int8_t ws_pae_controller_pan_version_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_pan_ver_increment *pan_ver_increment); /** * ws_pae_controller_fast_timer PAE controller fast timer call diff --git a/source/6LoWPAN/ws/ws_pae_key_storage.c b/source/6LoWPAN/ws/ws_pae_key_storage.c index 398c9ac0cd..04fd4d4757 100644 --- a/source/6LoWPAN/ws/ws_pae_key_storage.c +++ b/source/6LoWPAN/ws/ws_pae_key_storage.c @@ -42,6 +42,7 @@ #include "6LoWPAN/ws/ws_pae_key_storage.h" #ifdef HAVE_WS +#ifdef HAVE_PAE_AUTH #define TRACE_GROUP "wsks" @@ -1081,5 +1082,6 @@ static void ws_pae_key_storage_array_ptk_invalid(sec_prot_keys_storage_t *storag storage_array->ptk_lifetime = 0; } +#endif /* HAVE_PAE_AUTH */ #endif /* HAVE_WS */ diff --git a/source/6LoWPAN/ws/ws_pae_key_storage.h b/source/6LoWPAN/ws/ws_pae_key_storage.h index 39e6df60e0..7c170b6331 100644 --- a/source/6LoWPAN/ws/ws_pae_key_storage.h +++ b/source/6LoWPAN/ws/ws_pae_key_storage.h @@ -18,6 +18,8 @@ #ifndef WS_PAE_KEY_STORAGE_H_ #define WS_PAE_KEY_STORAGE_H_ +#ifdef HAVE_PAE_AUTH + /* * Port access entity key storage functions. * @@ -169,4 +171,22 @@ void ws_pae_key_storage_fast_timer(uint16_t ticks); */ uint16_t ws_pae_key_storage_storing_interval_get(void); +#else + +#define ws_pae_key_storage_memory_set(key_storages_number, key_storage_size, key_storages) +#define ws_pae_key_storage_settings_set(alloc_max_number, alloc_size, storing_interval) +#define ws_pae_key_storage_init() +#define ws_pae_key_storage_delete() +#define ws_pae_key_storage_store() +#define ws_pae_key_storage_read(restart_cnt) +#define ws_pae_key_storage_remove() +#define ws_pae_key_storage_supp_write(instance, pae_supp) +#define ws_pae_key_storage_supp_read(instance, eui_64, gtks, certs) +#define ws_pae_key_storage_supp_delete(instance, eui64) +#define ws_pae_key_storage_timer(seconds) +#define ws_pae_key_storage_fast_timer(ticks) +#define ws_pae_key_storage_storing_interval_get() 0 + +#endif + #endif /* WS_PAE_KEY_STORAGE_H_ */ diff --git a/source/6LoWPAN/ws/ws_pae_lib.c b/source/6LoWPAN/ws/ws_pae_lib.c index bc14ba93ab..e833dc3019 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.c +++ b/source/6LoWPAN/ws/ws_pae_lib.c @@ -374,9 +374,6 @@ void ws_pae_lib_supp_list_to_inactive(void *instance, supp_list_t *active_supp_l // Remove supplicant entry ws_pae_lib_supp_list_remove(instance, active_supp_list, entry, supp_deleted); - if (supp_deleted) { - supp_deleted(instance); - } } void ws_pae_lib_supp_list_purge(void *instance, supp_list_t *active_supp_list, uint16_t max_number, uint8_t max_purge, ws_pae_lib_supp_deleted supp_deleted) diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 7e518c465b..8c6cefdb78 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -1007,6 +1007,7 @@ static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_ static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64) { rpl_dodag_info_t dodag_info; + (void) dodag_info; // avoid unused warning in ws_host mode if (!interface_ptr->rpl_domain) { return -1; } diff --git a/source/6LoWPAN/ws/ws_pae_supp.h b/source/6LoWPAN/ws/ws_pae_supp.h index c991d65062..377c78ec76 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.h +++ b/source/6LoWPAN/ws/ws_pae_supp.h @@ -265,8 +265,8 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #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) -#define ws_pae_supp_nw_key_valid(interface_ptr) -1 +#define ws_pae_supp_cb_register(interface_ptr, completed, auth_next_target,nw_key_insert, nw_key_index_set, gtk_hash_ptr_get, nw_info_updated) +#define ws_pae_supp_nw_key_valid(interface_ptr, br_iid) -1 #define ws_pae_supp_fast_timer NULL #define ws_pae_supp_slow_timer NULL #define ws_pae_supp_authenticate(interface_ptr, dest_pan_id, dest_eui_64) PAE_SUPP_NOT_ENABLED @@ -276,6 +276,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #define ws_pae_supp_nw_key_index_update NULL #define ws_pae_supp_gtks_set(interface_ptr, gtks) #define ws_pae_supp_eapol_target_remove(interface_ptr) +#define ws_pae_supp_nw_info_set NULL #endif diff --git a/source/6LoWPAN/ws/ws_test_api.c b/source/6LoWPAN/ws/ws_test_api.c index 4dc5d394b1..902cc352b6 100644 --- a/source/6LoWPAN/ws/ws_test_api.c +++ b/source/6LoWPAN/ws/ws_test_api.c @@ -218,7 +218,7 @@ int ws_test_procedure_trigger(int8_t interface_id, ws_test_proc_t procedure, voi } } - return ws_bootstrap_test_procedure_trigger(cur, procedure); + return ws_bootstrap_test_procedure_trigger(cur, (ws_bootsrap_procedure_t) procedure); } #endif // HAVE_WS diff --git a/source/BorderRouter/CMakeLists.txt b/source/BorderRouter/CMakeLists.txt new file mode 100644 index 0000000000..3f0d5fafce --- /dev/null +++ b/source/BorderRouter/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + border_router.c +) diff --git a/source/Common_Protocols/CMakeLists.txt b/source/Common_Protocols/CMakeLists.txt new file mode 100644 index 0000000000..31bcdffc22 --- /dev/null +++ b/source/Common_Protocols/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + icmpv6.c + icmpv6_prefix.c + icmpv6_radv.c + ipv6.c + ipv6_flow.c + ipv6_fragmentation.c + ipv6_resolution.c + mld.c + tcp.c + udp.c +) diff --git a/source/Common_Protocols/icmpv6_radv.c b/source/Common_Protocols/icmpv6_radv.c index 9ad0544322..f49f7303bb 100644 --- a/source/Common_Protocols/icmpv6_radv.c +++ b/source/Common_Protocols/icmpv6_radv.c @@ -326,6 +326,7 @@ void icmpv6_stop_router_advertisements(protocol_interface_info_entry_t *cur, con static void icmpv6_send_ra(protocol_interface_info_entry_t *cur, const uint8_t *dest, const uint8_t *abro) { #ifndef HAVE_RPL + (void) dest; (void) abro; #endif if (cur->nwk_id == IF_6LoWPAN) { diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt new file mode 100644 index 0000000000..ae8903fe3f --- /dev/null +++ b/source/Core/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./include +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + buffer_dyn.c + ns_address_internal.c + ns_monitor.c + ns_socket.c + sockbuf.c +) diff --git a/source/Core/ns_socket.c b/source/Core/ns_socket.c index d91c03d0d3..c520c20279 100644 --- a/source/Core/ns_socket.c +++ b/source/Core/ns_socket.c @@ -1438,6 +1438,10 @@ buffer_t *socket_tx_buffer_event(buffer_t *buf, uint8_t status) if (buf->ack_receive_cb) { buf->ack_receive_cb(buf, status); } + if (status == SOCKET_BUSY) { + //SOCKET_BUSY shuold not be forward further and switched back orginal behaviour + status = SOCKET_TX_FAIL; + } /* Suppress events once socket orphaned */ if (!buf->socket || (buf->socket->flags & (SOCKET_FLAG_PENDING | SOCKET_FLAG_CLOSED))) { diff --git a/source/DHCPv6_Server/CMakeLists.txt b/source/DHCPv6_Server/CMakeLists.txt new file mode 100644 index 0000000000..f62037f121 --- /dev/null +++ b/source/DHCPv6_Server/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + DHCPv6_Server_service.c +) diff --git a/source/DHCPv6_client/CMakeLists.txt b/source/DHCPv6_client/CMakeLists.txt new file mode 100644 index 0000000000..1838ab0153 --- /dev/null +++ b/source/DHCPv6_client/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + dhcpv6_client_service.c +) diff --git a/source/MAC/CMakeLists.txt b/source/MAC/CMakeLists.txt new file mode 100644 index 0000000000..6dec6f74a7 --- /dev/null +++ b/source/MAC/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./IEEE802_15_4 + ./virtual_rf +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + rf_driver_storage.c + + IEEE802_15_4/mac_cca_threshold.c + IEEE802_15_4/mac_fhss_callbacks.c + IEEE802_15_4/mac_filter.c + IEEE802_15_4/mac_header_helper_functions.c + IEEE802_15_4/mac_indirect_data.c + IEEE802_15_4/mac_mcps_sap.c + IEEE802_15_4/mac_mlme.c + IEEE802_15_4/mac_mode_switch.c + IEEE802_15_4/mac_pd_sap.c + IEEE802_15_4/mac_security_mib.c + IEEE802_15_4/mac_timer.c + IEEE802_15_4/sw_mac.c + + ethernet/ethernet_mac_api.c + + serial/serial_mac_api.c + + virtual_rf/virtual_rf_client.c + virtual_rf/virtual_rf_driver.c +) diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index cbc6682020..0e6e7c6c50 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -71,6 +71,7 @@ static void mac_mlme_start_confirm_handler(protocol_interface_rf_mac_setup_s *rf 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 int mac_mlme_allocate_beacon_payload_buffer(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t mtu_size); static void mac_mlme_energy_scan_start(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t channel) { @@ -1133,7 +1134,6 @@ static int mac_mlme_set_symbol_rate(protocol_interface_rf_mac_setup_s *rf_mac_se 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; @@ -1142,15 +1142,26 @@ static int mac_mlme_allocate_tx_buffers(protocol_interface_rf_mac_setup_s *rf_ma 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); + + return 0; +} + +static int mac_mlme_allocate_beacon_payload_buffer(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t mtu_size) +{ + + rf_mac_setup->mac_beacon_payload = ns_dyn_mem_alloc(mtu_size); if (!rf_mac_setup->mac_beacon_payload) { return -1; } + + rf_mac_setup->max_beacon_payload_length = mtu_size; + rf_mac_setup->mac_beacon_payload_size = 0; + memset(rf_mac_setup->mac_beacon_payload, 0, rf_mac_setup->max_beacon_payload_length); 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 @@ -1191,6 +1202,11 @@ protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, a mac_mlme_data_base_deallocate(entry); return NULL; } + //Allocate Default Beacon pyload data + if (mac_mlme_allocate_beacon_payload_buffer(entry, MAC_IEEE_802_15_4_MAX_BEACON_PAYLOAD_LENGTH)) { + mac_mlme_data_base_deallocate(entry); + return NULL; + } entry->mac_tasklet_id = mac_mcps_sap_tasklet_init(); if (entry->mac_tasklet_id < 0) { @@ -1213,7 +1229,6 @@ protocol_interface_rf_mac_setup_s *mac_mlme_data_base_allocate(uint8_t *mac64, a entry->mac_mlme_retry_max = MAC_DEFAULT_MAX_FRAME_RETRIES; memset(entry->mac_default_key_source, 0xff, 8); memset(entry->mac_auto_request.Keysource, 0xff, 8); - memset(entry->mac_beacon_payload, 0, entry->max_beacon_payload_length); entry->mac_auto_request.SecurityLevel = 6; entry->mac_auto_request.KeyIndex = 0xff; mac_pd_sap_rf_low_level_function_set(entry, entry->dev_driver); diff --git a/source/MLE/CMakeLists.txt b/source/MLE/CMakeLists.txt new file mode 100644 index 0000000000..da8a5f3d37 --- /dev/null +++ b/source/MLE/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + mle.c + mle_tlv.c +) diff --git a/source/MPL/CMakeLists.txt b/source/MPL/CMakeLists.txt new file mode 100644 index 0000000000..805ae78d20 --- /dev/null +++ b/source/MPL/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + mpl.c +) diff --git a/source/NWK_INTERFACE/CMakeLists.txt b/source/NWK_INTERFACE/CMakeLists.txt new file mode 100644 index 0000000000..50445aeffe --- /dev/null +++ b/source/NWK_INTERFACE/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./Include +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + protocol_core.c + protocol_core_sleep.c + protocol_stats.c + protocol_timer.c +) diff --git a/source/NWK_INTERFACE/Include/protocol.h b/source/NWK_INTERFACE/Include/protocol.h index a3a845ffba..e2a71fee20 100644 --- a/source/NWK_INTERFACE/Include/protocol.h +++ b/source/NWK_INTERFACE/Include/protocol.h @@ -91,12 +91,10 @@ typedef enum icmp_state { ER_SCAN = 2, ER_ADDRESS_REQ = 3, ER_BIND_COMP = 4, -#ifdef HAVE_RPL ER_RPL_MC = 5, ER_RPL_SCAN = 6, ER_RPL_UNICAST = 7, ER_DAO_TX = 8, -#endif ER_PANA_AUTH = 9, ER_PANA_AUTH_DONE = 10, ER_PANA_AUTH_ERROR = 11, @@ -104,9 +102,7 @@ typedef enum icmp_state { ER_MLE_LINK_REQ = 13, ER_MLE_LINK_SHORT_SYNCH = 14, ER_MLE_LINK_ADDRESS_SYNCH = 15, -#ifdef HAVE_RPL ER_ROUTER_SYNCH = 17, -#endif ER_PANA_PING = 18, ER_PARENT_SYNCH_LOST = 19, ER_MLE_SCAN = 20, diff --git a/source/RPL/CMakeLists.txt b/source/RPL/CMakeLists.txt new file mode 100644 index 0000000000..98616d90be --- /dev/null +++ b/source/RPL/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + rpl_control.c + rpl_data.c + rpl_downward.c + rpl_mrhof.c + rpl_objective.c + rpl_of0.c + rpl_policy.c + rpl_upward.c +) diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index fb77ea064e..59f573a087 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -132,6 +132,19 @@ void rpl_control_event(struct rpl_domain *domain, rpl_event_t event) } } +static void rpl_control_convert_internal_config(rpl_dodag_conf_int_t *conf, const rpl_dodag_conf_t *external_conf) +{ + conf->dio_interval_min = external_conf->dio_interval_min; + conf->dio_interval_doublings = external_conf->dio_interval_doublings; + conf->dio_redundancy_constant = external_conf->dio_redundancy_constant; + conf->default_lifetime = external_conf->default_lifetime; + conf->dag_max_rank_increase = external_conf->dag_max_rank_increase; + conf->min_hop_rank_increase = external_conf->min_hop_rank_increase; + conf->objective_code_point = external_conf->objective_code_point; + conf->lifetime_unit = external_conf->lifetime_unit; + conf->options = rpl_conf_options(external_conf->authentication, external_conf->path_control_size); + conf->reserved = 0; +} /* When we join a new instance, we need to publish existing addresses. * Later addresses additions/removals are handled by rpl_control_addr_notifier. @@ -660,7 +673,9 @@ rpl_dodag_t *rpl_control_create_dodag_root(rpl_domain_t *domain, uint8_t instanc return NULL; } - rpl_dodag_update_config(dodag, conf, NULL, NULL); + rpl_dodag_conf_int_t internal_conf; + rpl_control_convert_internal_config(&internal_conf, conf); + rpl_dodag_update_config(dodag, &internal_conf, NULL, NULL); rpl_dodag_set_root(dodag, true); rpl_dodag_version_t *version = rpl_create_dodag_version(dodag, rpl_seq_init()); if (!version) { @@ -717,11 +732,12 @@ void rpl_control_update_dodag_config(struct rpl_dodag *dodag, const rpl_dodag_co { if (rpl_dodag_am_root(dodag)) { - rpl_dodag_update_config(dodag, conf, NULL, NULL); + rpl_dodag_conf_int_t internal_conf; + rpl_control_convert_internal_config(&internal_conf, conf); + rpl_dodag_update_config(dodag, &internal_conf, NULL, NULL); } } - void rpl_control_set_dodag_pref(rpl_dodag_t *dodag, uint8_t pref) { if (rpl_dodag_am_root(dodag)) { @@ -839,34 +855,33 @@ static const uint8_t *rpl_control_find_option_in_buffer(const buffer_t *buf, uin * * Figure 24: Format of the DODAG Configuration Option */ -static const uint8_t *rpl_control_read_conf(rpl_dodag_conf_t *conf_out, const uint8_t *opt) +static const uint8_t *rpl_control_read_conf(rpl_dodag_conf_int_t *conf_out, const uint8_t *opt) { - conf_out->authentication = opt[2] & 0x08; - conf_out->path_control_size = opt[2] & 0x07; + conf_out->options = opt[2]; conf_out->dio_interval_doublings = opt[3]; conf_out->dio_interval_min = opt[4]; conf_out->dio_redundancy_constant = opt[5]; conf_out->dag_max_rank_increase = common_read_16_bit(opt + 6); conf_out->min_hop_rank_increase = common_read_16_bit(opt + 8); conf_out->objective_code_point = common_read_16_bit(opt + 10); + conf_out->reserved = opt[12]; conf_out->default_lifetime = opt[13]; conf_out->lifetime_unit = common_read_16_bit(opt + 14); return opt + 16; } -static uint8_t *rpl_control_write_conf(uint8_t *opt_out, const rpl_dodag_conf_t *conf) +static uint8_t *rpl_control_write_conf(uint8_t *opt_out, const rpl_dodag_conf_int_t *conf) { opt_out[0] = RPL_DODAG_CONF_OPTION; opt_out[1] = 14; - opt_out[2] = conf->authentication ? RPL_CONF_FLAG_AUTH : 0; - opt_out[2] |= conf->path_control_size; + opt_out[2] = conf->options; opt_out[3] = conf->dio_interval_doublings; opt_out[4] = conf->dio_interval_min; opt_out[5] = conf->dio_redundancy_constant; common_write_16_bit(conf->dag_max_rank_increase, opt_out + 6); common_write_16_bit(conf->min_hop_rank_increase, opt_out + 8); common_write_16_bit(conf->objective_code_point, opt_out + 10); - opt_out[12] = 0; // reserved + opt_out[12] = conf->reserved; opt_out[13] = conf->default_lifetime; common_write_16_bit(conf->lifetime_unit, opt_out + 14); return opt_out + 16; @@ -1174,7 +1189,7 @@ malformed: /* Update DODAG config information, if option present, and either we don't have it or version is newer */ const uint8_t *dodag_conf_ptr = rpl_control_find_option_in_buffer(buf, 24, RPL_DODAG_CONF_OPTION, 14); if (dodag_conf_ptr) { - rpl_dodag_conf_t conf_buf; + rpl_dodag_conf_int_t conf_buf; rpl_control_read_conf(&conf_buf, dodag_conf_ptr); if (!rpl_dodag_update_config(dodag, &conf_buf, buf->src_sa.address, &become_leaf)) { goto invalid_parent; @@ -1182,7 +1197,7 @@ malformed: } /* If we don't have any DODAG config information, ask by unicast DIS */ - const rpl_dodag_conf_t *conf = rpl_dodag_get_config(dodag); + const rpl_dodag_conf_int_t *conf = rpl_dodag_get_config(dodag); if (!conf) { /* TODO - rate limit DIS? */ if (domain->new_parent_add && !domain->new_parent_add(buf->src_sa.address, domain->cb_handle, instance, rank)) { @@ -1361,7 +1376,7 @@ void rpl_control_transmit(rpl_domain_t *domain, protocol_interface_info_entry_t /* Transmit a DIO (unicast or multicast); cur may be NULL if multicast */ -void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entry_t *cur, uint8_t instance_id, uint8_t dodag_version, uint16_t rank, uint8_t g_mop_prf, uint8_t dtsn, rpl_dodag_t *dodag, const uint8_t dodagid[16], const rpl_dodag_conf_t *conf, const uint8_t *dst) +void rpl_control_transmit_dio(rpl_domain_t *domain, protocol_interface_info_entry_t *cur, uint8_t instance_id, uint8_t dodag_version, uint16_t rank, uint8_t g_mop_prf, uint8_t dtsn, rpl_dodag_t *dodag, const uint8_t dodagid[16], const rpl_dodag_conf_int_t *conf, const uint8_t *dst) { uint16_t length; @@ -1931,7 +1946,7 @@ bool rpl_control_read_dodag_info(const rpl_instance_t *instance, rpl_dodag_info_ return rpl_upward_read_dodag_info(instance, dodag_info); } -const rpl_dodag_conf_t *rpl_control_get_dodag_config(const rpl_instance_t *instance) +const rpl_dodag_conf_int_t *rpl_control_get_dodag_config(const rpl_instance_t *instance) { rpl_dodag_t *dodag = rpl_instance_current_dodag(instance); if (!dodag) { diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index c1cd578828..ce8a1d1665 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -18,8 +18,6 @@ #ifndef RPL_CONTROL_H_ #define RPL_CONTROL_H_ -#ifdef HAVE_RPL - #include "ns_list.h" #include "ipv6_stack/ipv6_routing_table.h" @@ -85,6 +83,29 @@ typedef struct rpl_dodag_conf { uint16_t lifetime_unit; /* seconds */ } rpl_dodag_conf_t; +/* Internally used configuration parameters for a DODAG, obtained through DIO DODAG Configuration options + * + * This structure has all the fields that are in the configuration + * to allow forwarding new bits that are added in future specifications. + */ +typedef struct rpl_dodag_conf_int { + uint8_t options; /* Flags|A|PCS */ + uint8_t reserved; /* Reserved fields in options (byte 12)*/ + uint8_t dio_interval_min; /* log2 milliseconds */ + uint8_t dio_interval_doublings; + uint8_t dio_redundancy_constant; + uint8_t default_lifetime; /* lifetime units */ + uint16_t dag_max_rank_increase; + uint16_t min_hop_rank_increase; + uint16_t objective_code_point; + uint16_t lifetime_unit; /* seconds */ +} rpl_dodag_conf_int_t; + +/* Helpers to handle configuration option bits*/ +#define rpl_conf_options(security, path_control_size) ((security ? 1:0) << 4) | (path_control_size & 0x07) +#define rpl_conf_option_security(conf) (bool)((conf)->options & 0x08) +#define rpl_conf_option_path_control_size(conf) ((conf)->options & 0x07) + /* Descriptor for a route from a DIO Route Information option. * Used to hold the "master copy" in the DODAG structure - the table for the * current DODAG is used to populate routes in our system routing table, and to @@ -104,6 +125,8 @@ typedef struct rpl_dio_route { uint8_t prefix[]; /* Variable-length prefix */ } rpl_dio_route_t; +#ifdef HAVE_RPL + typedef NS_LIST_HEAD(rpl_dio_route_t, link) rpl_dio_route_list_t; /******************************* RPL internal API ****************************/ @@ -112,7 +135,7 @@ void *rpl_realloc(void *p, uint16_t old_size, uint16_t new_size); void rpl_free(void *p, uint16_t size); void rpl_control_transmit(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, uint8_t code, struct buffer *buf, const uint8_t *dst); void rpl_control_transmit_multicast_dio(struct rpl_domain *domain, struct rpl_instance *instance, uint8_t instance_id, uint8_t dodag_version, uint16_t rank, uint8_t g_mop_prf, uint8_t dtsn, const uint8_t dodagid[16], const struct rpl_dodag_conf *conf); -void rpl_control_transmit_dio(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, uint8_t instance_id, uint8_t dodag_version, uint16_t rank, uint8_t g_mop_prf, uint8_t dtsn, struct rpl_dodag *dodag, const uint8_t dodagid[16], const struct rpl_dodag_conf *conf, const uint8_t *dst); +void rpl_control_transmit_dio(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, uint8_t instance_id, uint8_t dodag_version, uint16_t rank, uint8_t g_mop_prf, uint8_t dtsn, struct rpl_dodag *dodag, const uint8_t dodagid[16], const struct rpl_dodag_conf_int *conf, const uint8_t *dst); bool rpl_control_transmit_dao(struct rpl_domain *domain, struct protocol_interface_info_entry *cur, struct rpl_instance *instance, uint8_t instance_id, uint8_t dao_sequence, const uint8_t dodagid[16], const uint8_t *opts, uint16_t opts_size, const uint8_t *dst); void rpl_control_disable_ra_routes(struct rpl_domain *domain); void rpl_control_event(struct rpl_domain *domain, rpl_event_t event); @@ -207,7 +230,7 @@ struct rpl_instance *rpl_control_enumerate_instances(rpl_domain_t *domain, struc struct rpl_instance *rpl_control_lookup_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid); bool rpl_control_get_instance_dao_target_count(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid, const uint8_t *prefix, uint16_t *target_count); bool rpl_control_read_dodag_info(const struct rpl_instance *instance, struct rpl_dodag_info_t *dodag_info); -const rpl_dodag_conf_t *rpl_control_get_dodag_config(const struct rpl_instance *instance); +const rpl_dodag_conf_int_t *rpl_control_get_dodag_config(const struct rpl_instance *instance); const uint8_t *rpl_control_preferred_parent_addr(const struct rpl_instance *instance, bool global); uint16_t rpl_control_current_rank(const struct rpl_instance *instance); uint8_t rpl_policy_mrhof_parent_set_size_get(const rpl_domain_t *domain); @@ -215,15 +238,39 @@ void rpl_control_instant_poison(struct protocol_interface_info_entry *cur, rpl_d #else /* HAVE_RPL */ +#define rpl_control_set_memory_limits(soft_limit, hard_limit) #define rpl_control_fast_timer(ticks) ((void) 0) #define rpl_control_slow_timer(seconds) ((void) 0) +#define rpl_control_transmit_dis(domain, cur, pred, instance_id, dodagid, version, dst) ((void) 0) +#define rpl_control_transmit_dio_trigger(cur, domain) ((void) 0) +#define rpl_control_parent_selection_trigger(domain) ((void) 0) +#define rpl_control_force_leaf(domain, leaf) ((void) 0) +#define rpl_control_poison(domain, poison_count) ((void) 0) +#define rpl_control_dao_timeout(domain, seconds) ((void) 0) +#define rpl_control_set_domain_on_interface(cur, domain, downstream) ((void) 0) #define rpl_control_remove_domain_from_interface(cur) ((void) 0) #define rpl_control_free_domain_instances_from_interface(cur) ((void) 0) +#define rpl_control_set_callback(domain, callback, prefix_learn_cb, new_parent_add, parent_dis, cb_handle) ((void) 0) +#define rpl_control_is_dodag_parent(interface, ll_addr) (false) +#define rpl_control_is_dodag_parent_candidate(interface, ll_addr, candidate_cmp_limiter) (false) +#define rpl_control_probe_parent_candidate(interface, ll_addr) (false) +#define rpl_control_neighbor_info_get(interface, ll_addr, global_address) (0xffff) +#define rpl_possible_better_candidate(interface, rpl_instance, ll_addr, candidate_rank, etx) (false) +#define rpl_control_parent_candidate_list_size(interface, parent_list) (0) +#define rpl_control_candidate_list_size(interface, rpl_instance) (0) +#define rpl_control_selected_parent_count(interface, rpl_instance) (0) +#define rpl_control_neighbor_delete(interface, ll_addr) ((void) 0) +#define rpl_control_find_worst_neighbor(interface, rpl_instance, ll_addr) (false) #define rpl_control_register_address(interface, addr) ((void) 0) #define rpl_control_address_register_done(interface, ll_addr, status) (false) +#define rpl_control_enumerate_instances(domain, instance) (NULL) +#define rpl_control_read_dodag_info(instance, dodag_info) (false) +#define rpl_control_get_dodag_config(instance) (NULL) +#define rpl_control_preferred_parent_addr(instance, global) (NULL) +#define rpl_control_current_rank(instance) (RPL_RANK_INFINITE) #define rpl_policy_mrhof_parent_set_size_get(domain) (0) -#define rpl_control_set_mrhof_parent_set_size(parent_set_size) #define rpl_control_instant_poison(cur, domain) ((void) 0) + #endif /* HAVE_RPL */ #endif /* RPL_CONTROL_H_ */ diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 984c24953e..628b344052 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -134,7 +134,7 @@ void rpl_downward_convert_dodag_preferences_to_dao_path_control(rpl_dodag_t *dod } rpl_instance_t *instance = dodag->instance; - uint8_t pcs = dodag->config.path_control_size; + uint8_t pcs = rpl_conf_option_path_control_size(&dodag->config); uint_fast8_t bit = 0; rpl_neighbour_t *last = NULL; @@ -477,14 +477,14 @@ static uint8_t *rpl_downward_write_target(uint8_t *ptr, rpl_dao_target_t *target * Figure 26: Format of the Transit Information Option * */ -static uint8_t *rpl_downward_write_transit(uint8_t *ptr, rpl_dao_target_t *target, uint8_t path_control, const uint8_t *parent, bool no_path) +static uint8_t *rpl_downward_write_transit(uint8_t *ptr, rpl_dao_target_t *target, uint8_t path_control, const uint8_t *parent, uint8_t path_lifetime) { *ptr++ = RPL_TRANSIT_OPTION; *ptr++ = parent ? 16 + 4 : 4; *ptr++ = target->external ? TRANSIT_FLAG_EXTERNAL : 0; *ptr++ = path_control; *ptr++ = target->path_sequence; - *ptr++ = no_path ? 0 : target->info.non_root.path_lifetime; + *ptr++ = path_lifetime; if (parent) { ptr = (uint8_t *) memcpy(ptr, parent, 16) + 16; } @@ -770,7 +770,11 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance) * (^ Repeat if more targets with different transit info/parents) */ - + const rpl_dodag_conf_int_t *conf = rpl_dodag_get_config(dodag); + if (!conf) { + rpl_instance_dao_trigger(instance, 0); + return; + } uint8_t *opts = ns_dyn_mem_temporary_alloc(1280); if (!opts) { rpl_instance_dao_trigger(instance, 0); @@ -778,13 +782,13 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance) } uint8_t *ptr = opts; - rpl_downward_reset_assigning(instance, PCSMASK(dodag->config.path_control_size)); + rpl_downward_reset_assigning(instance, PCSMASK(rpl_conf_option_path_control_size(&dodag->config))); ns_list_foreach(rpl_dao_target_t, t, &instance->dao_targets) { /* Self-published targets can defer path lifetime choice */ if (t->info.non_root.path_lifetime == 0) { uint32_t lifetime = t->lifetime; - const rpl_dodag_conf_t *conf = rpl_dodag_get_config(dodag); + uint16_t unit = conf->lifetime_unit; uint8_t def = conf->default_lifetime; if (lifetime != 0xFFFFFFFF) { @@ -835,20 +839,31 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance) ptr = rpl_downward_write_target(ptr, t2); } + + uint8_t path_lifetime; + uint8_t path_life_adjust_t_default = conf->default_lifetime - (conf->default_lifetime / 8); + if (target->info.non_root.path_lifetime < path_life_adjust_t_default || target->info.non_root.path_lifetime >= conf->default_lifetime) { + path_lifetime = target->info.non_root.path_lifetime; + } else { + //Adjust from 7/8-0.99 to 1*default + //to pass conformance tests that expect to see exactly the default lifetime in a smoothly-running system + path_lifetime = conf->default_lifetime; + } + /* Then output the transit information for the original target */ if (storing) { /* Just one transit info */ - ptr = rpl_downward_write_transit(ptr, target, path_control, NULL, false); + ptr = rpl_downward_write_transit(ptr, target, path_control, NULL, path_lifetime); } else if (target->own) { /* One transit info for each DAO parent */ ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) { if (neighbour->dao_path_control & path_control) { - ptr = rpl_downward_write_transit(ptr, target, neighbour->dao_path_control & path_control, neighbour->global_address, false); + ptr = rpl_downward_write_transit(ptr, target, neighbour->dao_path_control & path_control, neighbour->global_address, path_lifetime); } } } else { /* Attached host - single transit is us */ - ptr = rpl_downward_write_transit(ptr, target, path_control, our_addr, false); + ptr = rpl_downward_write_transit(ptr, target, path_control, our_addr, path_lifetime); } } @@ -1601,7 +1616,7 @@ void rpl_instance_dao_acked(rpl_instance_t *instance, const uint8_t src[16], int } rpl_dodag_t *dodag = rpl_instance_current_dodag(instance); - const rpl_dodag_conf_t *conf = dodag ? rpl_dodag_get_config(dodag) : NULL; + const rpl_dodag_conf_int_t *conf = dodag ? rpl_dodag_get_config(dodag) : NULL; instance->dao_in_transit = false; instance->dao_retry_timer = 0; if (!retry) { @@ -1917,11 +1932,11 @@ static void rpl_instance_address_registration_cancel(rpl_instance_t *instance) instance->pending_neighbour_confirmation = false; } -static void rpl_instance_address_registration_retry(rpl_dao_target_t *dao_target) +static void rpl_instance_address_registration_retry(rpl_dao_target_t *dao_target, uint8_t response_wait_time) { 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 + dao_target->response_wait_time = response_wait_time; // Wait 20 seconds before retry } void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint16_t seconds) @@ -2003,28 +2018,36 @@ bool rpl_instance_address_registration_done(protocol_interface_info_entry_t *int tr_debug("Address %s register to %s", trace_ipv6(dao_target->prefix), trace_ipv6(neighbour->ll_address)); - 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; + 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); } - tr_warn("Address registration ACK fail retry selection"); - neighbour->addr_reg_failures++; - rpl_instance_address_registration_retry(dao_target); + neighbour->addr_reg_failures = 0; + neighbour->confirmed = true; + dao_target->response_wait_time = 6; 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); + + if (status == SOCKET_BUSY) { + tr_warn("Address registration CCA fail retry selection"); + rpl_instance_address_registration_retry(dao_target, 4); + return false; } - neighbour->addr_reg_failures = 0; - neighbour->confirmed = true; - dao_target->response_wait_time = 6; + + 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; + } + tr_warn("Address registration ACK fail retry selection"); + neighbour->addr_reg_failures++; + rpl_instance_address_registration_retry(dao_target, 20); return false; + } #endif /* HAVE_RPL */ diff --git a/source/RPL/rpl_policy.c b/source/RPL/rpl_policy.c index 5f669c591c..c0ee117117 100644 --- a/source/RPL/rpl_policy.c +++ b/source/RPL/rpl_policy.c @@ -87,7 +87,7 @@ bool rpl_policy_join_dodag(rpl_domain_t *domain, uint8_t g_mop_prf, uint8_t inst return true; } -bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf, bool *leaf_only) +bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_int_t *conf, bool *leaf_only) { (void)domain; (void)conf; @@ -99,7 +99,7 @@ bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf, } /* We don't support authentication */ - if (conf->authentication) { + if (rpl_conf_option_security(conf)) { return false; } diff --git a/source/RPL/rpl_policy.h b/source/RPL/rpl_policy.h index b80e0e9f2a..4b59432595 100644 --- a/source/RPL/rpl_policy.h +++ b/source/RPL/rpl_policy.h @@ -26,7 +26,7 @@ void rpl_policy_force_tunnel_set(bool enable); bool rpl_policy_join_instance(rpl_domain_t *domain, uint8_t instance_id, const uint8_t *dodagid); bool rpl_policy_join_dodag(rpl_domain_t *domain, uint8_t g_mop_prf, uint8_t instance_id, const uint8_t *dodagid); -bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf, bool *leaf_only); +bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_int_t *conf, bool *leaf_only); 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); diff --git a/source/RPL/rpl_structures.h b/source/RPL/rpl_structures.h index 0adeaacbf9..d43dea4a20 100644 --- a/source/RPL/rpl_structures.h +++ b/source/RPL/rpl_structures.h @@ -81,7 +81,7 @@ struct rpl_dodag { uint32_t timestamp; /* How long since we heard a DIO */ uint8_t id[16]; /* Root identifier */ uint8_t g_mop_prf; /* Grounded, Mode, Preference */ - rpl_dodag_conf_t config; /* Configuration from DIO */ + rpl_dodag_conf_int_t config; /* Configuration from DIO */ uint8_t info_version; /* Version for g_mop_prf and config */ bool root: 1; /* We are the root of this DODAG */ bool was_root: 1; /* If we have ever been a root in this DODAG */ diff --git a/source/RPL/rpl_upward.c b/source/RPL/rpl_upward.c index 283dff2b9c..c4347fc76d 100644 --- a/source/RPL/rpl_upward.c +++ b/source/RPL/rpl_upward.c @@ -729,7 +729,7 @@ void rpl_delete_dodag_root(rpl_dodag_t *dodag) /* Convert RPL configuration to generic trickle parameters. Returns true if * the value in the generic object has changed. */ -static bool rpl_dodag_conf_convert_trickle_parameters(trickle_params_t *params_out, const rpl_dodag_conf_t *conf) +static bool rpl_dodag_conf_convert_trickle_parameters(trickle_params_t *params_out, const rpl_dodag_conf_int_t *conf) { /* Convert trickle parameters into 100ms ticks */ uint32_t Imin_ms = conf->dio_interval_min < 32 ? (1ul << conf->dio_interval_min) : 0xfffffffful; @@ -756,7 +756,7 @@ uint8_t rpl_dodag_mop(const rpl_dodag_t *dodag) return dodag->g_mop_prf & RPL_MODE_MASK; } -bool rpl_dodag_update_config(rpl_dodag_t *dodag, const rpl_dodag_conf_t *conf, const uint8_t *src, bool *become_leaf) +bool rpl_dodag_update_config(rpl_dodag_t *dodag, const rpl_dodag_conf_int_t *conf, const uint8_t *src, bool *become_leaf) { /* If already have config, don't update unless it's coming from preferred parent */ if (dodag->have_config) { @@ -863,7 +863,7 @@ bool rpl_dodag_is_current(const rpl_dodag_t *dodag) return dodag->instance->current_dodag_version && dodag->instance->current_dodag_version->dodag == dodag; } -const rpl_dodag_conf_t *rpl_dodag_get_config(const rpl_dodag_t *dodag) +const rpl_dodag_conf_int_t *rpl_dodag_get_config(const rpl_dodag_t *dodag) { return dodag->have_config ? &dodag->config : NULL; } @@ -1677,7 +1677,7 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_ } // Always send config in unicasts (as required), never in multicasts (optional) - rpl_dodag_conf_t *conf; + rpl_dodag_conf_int_t *conf; if (addr) { conf = &dodag->config; //Unicast diff --git a/source/RPL/rpl_upward.h b/source/RPL/rpl_upward.h index 3a3cb183c2..b15e65f438 100644 --- a/source/RPL/rpl_upward.h +++ b/source/RPL/rpl_upward.h @@ -108,7 +108,7 @@ uint8_t rpl_dodag_get_version_number_as_root(const rpl_dodag_t *dodag); void rpl_dodag_set_version_number_as_root(rpl_dodag_t *dodag, uint8_t number); void rpl_dodag_set_leaf(rpl_dodag_t *dodag, bool leaf); bool rpl_dodag_am_leaf(const rpl_dodag_t *dodag); -const rpl_dodag_conf_t *rpl_dodag_get_config(const rpl_dodag_t *dodag); +const rpl_dodag_conf_int_t *rpl_dodag_get_config(const rpl_dodag_t *dodag); void rpl_dodag_inconsistency(rpl_dodag_t *dodag); void rpl_dodag_increment_dtsn(rpl_dodag_t *dodag); rpl_cmp_t rpl_dodag_pref_compare(const rpl_dodag_t *a, const rpl_dodag_t *b); @@ -138,7 +138,7 @@ rpl_neighbour_t *rpl_lookup_neighbour_by_ll_address(const rpl_instance_t *instan rpl_neighbour_t *rpl_lookup_last_candidate_from_list(const rpl_instance_t *instance); rpl_neighbour_t *rpl_create_neighbour(rpl_dodag_version_t *instance, const uint8_t *ll_addr, int8_t if_id, uint8_t g_mop_prf, uint8_t dtsn); void rpl_delete_neighbour(rpl_instance_t *instance, rpl_neighbour_t *neighbour); -bool rpl_dodag_update_config(rpl_dodag_t *dodag, const rpl_dodag_conf_t *conf, const uint8_t *src, bool *become_leaf); +bool rpl_dodag_update_config(rpl_dodag_t *dodag, const rpl_dodag_conf_int_t *conf, const uint8_t *src, bool *become_leaf); const uint8_t *rpl_neighbour_ll_address(const rpl_neighbour_t *neighbour); const uint8_t *rpl_neighbour_global_address(const rpl_neighbour_t *neighbour); void rpl_neighbour_update_global_address(rpl_neighbour_t *neighbour, const uint8_t *addr); diff --git a/source/Security/CMakeLists.txt b/source/Security/CMakeLists.txt new file mode 100644 index 0000000000..63aaf0653a --- /dev/null +++ b/source/Security/CMakeLists.txt @@ -0,0 +1,69 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./Common + ./PANA + ./TLS + ./eapol + ./kmp + ./protocols + ./protocols/eap_tls_sec_prot + ./protocols/fwh_sec_prot + ./protocols/gkh_sec_prot + ./protocols/key_sec_prot + ./protocols/radius_sec_prot + ./protocols/tls_sec_prot +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + Common/security_lib.c + + PANA/eap_protocol.c + PANA/pana.c + PANA/pana_avp.c + PANA/pana_client.c + PANA/pana_eap_header.c + PANA/pana_header.c + PANA/pana_relay_table.c + PANA/pana_server.c + + TLS/tls_ccm_crypt.c + TLS/tls_lib.c + + eapol/eapol_helper.c + eapol/kde_helper.c + + kmp/kmp_addr.c + kmp/kmp_api.c + kmp/kmp_eapol_pdu_if.c + kmp/kmp_socket_if.c + + protocols/sec_prot_certs.c + protocols/sec_prot_keys.c + protocols/sec_prot_lib.c + + protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c + protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c + protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c + protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c + + protocols/fwh_sec_prot/auth_fwh_sec_prot.c + protocols/fwh_sec_prot/supp_fwh_sec_prot.c + + protocols/gkh_sec_prot/auth_gkh_sec_prot.c + protocols/gkh_sec_prot/supp_gkh_sec_prot.c + + protocols/key_sec_prot/key_sec_prot.c + + protocols/msg_sec_prot/msg_sec_prot.c + + protocols/radius_sec_prot/avp_helper.c + protocols/radius_sec_prot/radius_client_sec_prot.c + + protocols/tls_sec_prot/tls_sec_prot.c + protocols/tls_sec_prot/tls_sec_prot_lib.c +) 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 4f1d3a725b..d4a7c476e8 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 @@ -411,7 +411,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot) tr_info("EAP-TLS start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, SEC_PROT_RETRYING_PROTOCOL_TIMEOUT); // KMP-CREATE.confirm prot->create_conf(prot, SEC_RESULT_OK); diff --git a/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c index 09944249d9..1591df9cac 100644 --- a/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c @@ -436,7 +436,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) tr_info("EAP-TLS: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, SEC_PROT_RETRYING_PROTOCOL_TIMEOUT); // KMP-CREATE.confirm prot->create_conf(prot, SEC_RESULT_OK); @@ -482,7 +482,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) sec_prot_timer_trickle_stop(&data->common); // Set timeout to wait for RADIUS client to continue - data->common.ticks = RADIUS_EAP_TLS_CLIENT_TIMEOUT; + sec_prot_timeout_set(&data->common, RADIUS_EAP_TLS_CLIENT_TIMEOUT); // Send to radius client data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length); @@ -547,7 +547,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) sec_prot_timer_trickle_stop(&data->common); // Set timeout to wait for RADIUS client to continue - data->common.ticks = RADIUS_EAP_TLS_CLIENT_TIMEOUT; + sec_prot_timeout_set(&data->common, RADIUS_EAP_TLS_CLIENT_TIMEOUT); // Send to radius client data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length); 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 aa296c39d1..a80a3ea258 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 @@ -406,7 +406,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) } // Set retry timeout based on network size - data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); // Store sequence ID supp_eap_tls_sec_prot_seq_id_update(prot); @@ -451,7 +451,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 = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); // Initialize TLS protocol if (supp_eap_tls_sec_prot_init_tls(prot) < 0) { @@ -485,7 +485,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 = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); } // All fragments received for a message 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 8138fe8ed4..cae5869127 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 @@ -120,7 +120,7 @@ static int8_t auth_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 = 15 * 10; // 15 seconds + sec_prot_timeout_set(&data->common, 15 * 10); // 15 seconds uint8_t eui64[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; sec_prot_lib_nonce_init(data->nonce, eui64, 1000); @@ -348,7 +348,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot) tr_info("4WH: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, SEC_PROT_RETRYING_PROTOCOL_TIMEOUT); uint8_t *pmk = sec_prot_keys_pmk_get(prot->sec_keys); if (!pmk) { // If PMK is not set fails 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 84e91e61ca..1f98e8c92f 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 @@ -139,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 = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); data->msg3_received = false; data->msg3_retry_wait = false; data->recv_replay_cnt = 0; @@ -314,7 +314,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) } // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); tr_info("4WH: start"); @@ -337,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 = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3); } else { // Ready to be deleted @@ -365,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 = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); return; } else if (data->recv_msg != FWH_MESSAGE_3) { return; @@ -392,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 = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH); break; @@ -412,7 +412,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->sec_cfg->timer_cfg.ptk_lifetime); sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64); - data->common.ticks = 60 * 10; // 60 seconds + sec_prot_timeout_set(&data->common, 60 * 10); // 60 seconds // KMP-FINISHED.indication prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys); sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3_RETRY_WAIT); 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 b01d60c824..416a0797b1 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 @@ -295,7 +295,7 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot) tr_info("GKH start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, SEC_PROT_RETRYING_PROTOCOL_TIMEOUT); // KMP-CREATE.confirm prot->create_conf(prot, SEC_RESULT_OK); 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 a836e5870b..cffe5f704e 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 @@ -247,7 +247,7 @@ static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot) } // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); supp_gkh_sec_prot_security_replay_counter_update(prot); 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 540ed35c71..817f3c43e9 100644 --- a/source/Security/protocols/key_sec_prot/key_sec_prot.c +++ b/source/Security/protocols/key_sec_prot/key_sec_prot.c @@ -370,7 +370,7 @@ static void supp_key_sec_prot_state_machine(sec_prot_t *prot) // KMP-FINISHED.indication, prot->finished_ind(prot, sec_prot_result_get(&data->common), 0); sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED); - data->common.ticks = KEY_SEC_FINISHED_TIMEOUT; + sec_prot_timeout_set(&data->common, KEY_SEC_FINISHED_TIMEOUT); break; case KEY_STATE_FINISHED: @@ -416,7 +416,7 @@ static void auth_key_sec_prot_state_machine(sec_prot_t *prot) // KMP-FINISHED.indication, prot->finished_ind(prot, sec_prot_result_get(&data->common), 0); sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED); - data->common.ticks = KEY_SEC_FINISHED_TIMEOUT; + sec_prot_timeout_set(&data->common, KEY_SEC_FINISHED_TIMEOUT); break; case KEY_STATE_FINISHED: { diff --git a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c index 8f3371f621..c646b24cd2 100644 --- a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c +++ b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c @@ -1089,7 +1089,7 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) tr_info("Radius: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, SEC_PROT_RETRYING_PROTOCOL_TIMEOUT); sec_prot_state_set(prot, &data->common, RADIUS_STATE_CREATE_RESP); @@ -1148,7 +1148,7 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) sec_prot_timer_trickle_stop(&data->common); // Set timeout to wait for EAP-TLS to continue - data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); // Send to radius EAP-TLS if (data->radius_eap_tls_send && data->radius_eap_tls_prot && data->recv_eap_msg && data->recv_eap_msg_len > 0) { diff --git a/source/Security/protocols/sec_prot_lib.c b/source/Security/protocols/sec_prot_lib.c index 88577b3157..09495a817c 100644 --- a/source/Security/protocols/sec_prot_lib.c +++ b/source/Security/protocols/sec_prot_lib.c @@ -174,9 +174,9 @@ bool sec_prot_result_ok_check(sec_prot_common_t *data) return false; } -void sec_prot_default_timeout_set(sec_prot_common_t *data) +void sec_prot_timeout_set(sec_prot_common_t *data, uint16_t ticks) { - data->ticks = SEC_TOTAL_TIMEOUT; + data->ticks = ticks; } void sec_prot_lib_nonce_generate(uint8_t *nonce) diff --git a/source/Security/protocols/sec_prot_lib.h b/source/Security/protocols/sec_prot_lib.h index 83a01879c2..cc04b141a7 100644 --- a/source/Security/protocols/sec_prot_lib.h +++ b/source/Security/protocols/sec_prot_lib.h @@ -26,7 +26,6 @@ */ #define EUI64_LEN 8 -#define SEC_TOTAL_TIMEOUT 30 * 60 * 10 // 30 minutes #define SEC_FINISHED_TIMEOUT 5 * 10 // 5 seconds #define FWH_NONCE_LENGTH 32 @@ -299,11 +298,12 @@ bool sec_prot_result_timeout_check(sec_prot_common_t *data); bool sec_prot_result_ok_check(sec_prot_common_t *data); /** - * sec_prot_default_timeout_set sets default timeout for protocol + * sec_prot_timeout_set sets timeout for protocol * * \param data common data + * \param ticks ticks * */ -void sec_prot_default_timeout_set(sec_prot_common_t *data); +void sec_prot_timeout_set(sec_prot_common_t *data, uint16_t ticks); #endif /* SEC_PROT_LIB_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 e194301e4d..a7cb9b163f 100644 --- a/source/Security/protocols/tls_sec_prot/tls_sec_prot.c +++ b/source/Security/protocols/tls_sec_prot/tls_sec_prot.c @@ -320,7 +320,7 @@ static void client_tls_sec_prot_state_machine(sec_prot_t *prot) sec_prot_state_set(prot, &data->common, TLS_STATE_CREATE_REQ); prot->timer_start(prot); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); break; // Wait KMP-CREATE.request @@ -355,6 +355,8 @@ static void client_tls_sec_prot_state_machine(sec_prot_t *prot) data->calculating = false; } + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); + if (data->tls_send.data) { prot->send(prot, data->tls_send.data, data->tls_send.handled_len); eap_tls_sec_prot_lib_message_init(&data->tls_send); @@ -415,7 +417,7 @@ static void server_tls_sec_prot_state_machine(sec_prot_t *prot) sec_prot_state_set(prot, &data->common, TLS_STATE_CLIENT_HELLO); prot->timer_start(prot); // Set default timeout for the total maximum length of the negotiation - sec_prot_default_timeout_set(&data->common); + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); break; // Wait EAP request, Identity (starts handshake on supplicant) @@ -474,6 +476,8 @@ static void server_tls_sec_prot_state_machine(sec_prot_t *prot) data->calculating = false; } + sec_prot_timeout_set(&data->common, prot->sec_cfg->prot_cfg.sec_prot_retry_timeout); + if (data->tls_send.data) { prot->send(prot, data->tls_send.data, data->tls_send.handled_len); eap_tls_sec_prot_lib_message_init(&data->tls_send); diff --git a/source/Service_Libs/CMakeLists.txt b/source/Service_Libs/CMakeLists.txt new file mode 100644 index 0000000000..846fc8cb05 --- /dev/null +++ b/source/Service_Libs/CMakeLists.txt @@ -0,0 +1,107 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./Neighbor_cache + ./Trickle + ./blacklist + ./etx + ./fhss + ./fnv_hash + ./hmac + ./ieee_802_11 + ./load_balance + ./mac_neighbor_table + ./mdns + ./mdns/fnet + ./mdns/fnet/fnet_stack + ./mdns/fnet/fnet_stack/port + ./mdns/fnet/fnet_stack/port/compiler + ./mdns/fnet/fnet_stack/port/cpu + ./mdns/fnet/fnet_stack/services + ./mdns/fnet/fnet_stack/services/dns + ./mdns/fnet/fnet_stack/services/mdns + ./mdns/fnet/fnet_stack/services/poll + ./mdns/fnet/fnet_stack/services/serial + ./mdns/fnet/fnet_stack/stack + ./mle_service + ./nd_proxy + ./nist_aes_kw + ./pan_blacklist + ./random_early_detection + ./utils + ./whiteboard +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + CCM_lib/ccm_security.c + + CCM_lib/mbedOS/aes_mbedtls_adapter.c + + Neighbor_cache/neighbor_cache.c + + SHA256_Lib/ns_sha256.c + SHA256_Lib/shalib.c + + Trickle/trickle.c + + blacklist/blacklist.c + + etx/etx.c + + fhss/channel_functions.c + fhss/channel_list.c + fhss/fhss.c + fhss/fhss_channel.c + fhss/fhss_common.c + fhss/fhss_configuration_interface.c + fhss/fhss_statistics.c + fhss/fhss_test_api.c + fhss/fhss_ws.c + fhss/fhss_ws_empty_functions.c + + fnv_hash/fnv_hash.c + + hmac/hmac_md.c + + ieee_802_11/ieee_802_11.c + + load_balance/load_balance.c + + mac_neighbor_table/mac_neighbor_table.c + + mdns/ns_fnet_events.c + mdns/ns_fnet_port.c + mdns/ns_mdns_api.c + + mdns/fnet/fnet_stack/services/mdns/fnet_mdns.c + + mdns/fnet/fnet_stack/services/poll/fnet_poll.c + + mdns/fnet/fnet_stack/stack/fnet_stdlib.c + + mle_service/mle_service.c + mle_service/mle_service_buffer.c + mle_service/mle_service_frame_counter_table.c + mle_service/mle_service_interface.c + mle_service/mle_service_security.c + + nd_proxy/nd_proxy.c + + nist_aes_kw/nist_aes_kw.c + + pan_blacklist/pan_blacklist.c + + random_early_detection/random_early_detection.c + + utils/isqrt.c + utils/ns_conf.c + utils/ns_crc.c + utils/ns_file_system.c + utils/ns_time.c + + whiteboard/whiteboard.c +) diff --git a/source/configs/CMakeLists.txt b/source/configs/CMakeLists.txt new file mode 100644 index 0000000000..232128a026 --- /dev/null +++ b/source/configs/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./base +) diff --git a/source/configs/base/cfg_ws_full.h b/source/configs/base/cfg_ws_full.h new file mode 100644 index 0000000000..798f3c88a0 --- /dev/null +++ b/source/configs/base/cfg_ws_full.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Pelion 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 "cfg_ws_border_router.h" + +#define HAVE_PAE_SUPP diff --git a/source/configs/base/cfg_ws_host.h b/source/configs/base/cfg_ws_host.h index 49122b9da6..aec86edcd3 100644 --- a/source/configs/base/cfg_ws_host.h +++ b/source/configs/base/cfg_ws_host.h @@ -18,9 +18,7 @@ #define HAVE_WS #define HAVE_WS_HOST #define HAVE_WS_VERSION_1_1 -#define HAVE_RPL #define HAVE_MPL #define HAVE_6LOWPAN_ND #define HAVE_IPV6_ND -#define HAVE_PAE_SUPP -#define HAVE_6LOWPAN_ROUTER \ No newline at end of file +#define HAVE_6LOWPAN_ROUTER diff --git a/source/configs/base/cfg_ws_router.h b/source/configs/base/cfg_ws_router.h index 78f3537941..5e36562036 100644 --- a/source/configs/base/cfg_ws_router.h +++ b/source/configs/base/cfg_ws_router.h @@ -17,5 +17,6 @@ #include "cfg_ws_host.h" +#define HAVE_RPL #define HAVE_WS_ROUTER #define HAVE_EAPOL_RELAY diff --git a/source/configs/cfg_generic.h b/source/configs/cfg_generic.h index c7a27d4c2d..49ccb5ee99 100644 --- a/source/configs/cfg_generic.h +++ b/source/configs/cfg_generic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016-2019, Pelion and affiliates. + * Copyright (c) 2014, 2016-2021, Pelion and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ #include "base/cfg_lowpan_border_router.h" #include "base/cfg_local_socket.h" #include "base/cfg_rf_tunnel.h" -#include "base/cfg_ws_border_router.h" +#include "base/cfg_ws_full.h" #define FEA_TRACE_SUPPORT #define EXTRA_CONSISTENCY_CHECKS diff --git a/source/configs/cfg_ws_full.h b/source/configs/cfg_ws_full.h new file mode 100644 index 0000000000..798f3c88a0 --- /dev/null +++ b/source/configs/cfg_ws_full.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Pelion 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 "cfg_ws_border_router.h" + +#define HAVE_PAE_SUPP diff --git a/source/configs/cfg_ws_host.h b/source/configs/cfg_ws_host.h index 74b3113c48..debfeb2c87 100644 --- a/source/configs/cfg_ws_host.h +++ b/source/configs/cfg_ws_host.h @@ -20,4 +20,5 @@ #define FEA_TRACE_SUPPORT #define EXTRA_CONSISTENCY_CHECKS +#define HAVE_PAE_SUPP diff --git a/source/configs/cfg_ws_router.h b/source/configs/cfg_ws_router.h index a4cf952501..da740e5c69 100644 --- a/source/configs/cfg_ws_router.h +++ b/source/configs/cfg_ws_router.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Pelion and affiliates. + * Copyright (c) 2019-2021, Pelion and affiliates. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,4 +20,5 @@ #define FEA_TRACE_SUPPORT #define EXTRA_CONSISTENCY_CHECKS +#define HAVE_PAE_SUPP diff --git a/source/ipv6_stack/CMakeLists.txt b/source/ipv6_stack/CMakeLists.txt new file mode 100644 index 0000000000..6ef7fbb31c --- /dev/null +++ b/source/ipv6_stack/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + ipv6_routing_table.c + protocol_ipv6.c +) diff --git a/source/libDHCPv6/CMakeLists.txt b/source/libDHCPv6/CMakeLists.txt new file mode 100644 index 0000000000..f922d6e437 --- /dev/null +++ b/source/libDHCPv6/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + dhcp_service_api.c + libDHCPv6.c + libDHCPv6_server.c + libDHCPv6_vendordata.c +) diff --git a/source/libNET/CMakeLists.txt b/source/libNET/CMakeLists.txt new file mode 100644 index 0000000000..8d2a977d72 --- /dev/null +++ b/source/libNET/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) 2020-2021, Pelion and affiliates. +# SPDX-License-Identifier: Apache-2.0 + +target_include_directories(mbed-nanostack-sal_stack + INTERFACE + . + ./src +) + +target_sources(mbed-nanostack-sal_stack + INTERFACE + src/multicast_api.c + src/net_6lowpan_parameter_api.c + src/net_dns.c + src/net_dns_internal.h + src/net_ipv6.c + src/net_load_balance.c + src/net_load_balance_internal.h + src/net_mle.c + src/net_rpl.c + src/net_short_address_extension.c + src/net_test.c + src/ns_net.c + src/socket_api.c +) diff --git a/source/libNET/src/net_load_balance.c b/source/libNET/src/net_load_balance.c index 7dbbe1ae29..34fb9bf32d 100644 --- a/source/libNET/src/net_load_balance.c +++ b/source/libNET/src/net_load_balance.c @@ -248,7 +248,7 @@ void net_load_balance_internal_state_activate(protocol_interface_info_entry_t *i if (state && interface_ptr->rpl_domain) { struct rpl_instance *instance = rpl_control_lookup_instance(interface_ptr->rpl_domain, 1, NULL); if (instance) { - const rpl_dodag_conf_t *dodag_config = rpl_control_get_dodag_config(instance); + const rpl_dodag_conf_int_t *dodag_config = rpl_control_get_dodag_config(instance); if (dodag_config) { //dio max Period caluclate in seconds uint32_t Imax_ms = (dodag_config->dio_interval_min + dodag_config->dio_interval_doublings) < 32 ? diff --git a/sources.mk b/sources.mk index 1b6916f4b7..417d2d63f4 100644 --- a/sources.mk +++ b/sources.mk @@ -24,8 +24,9 @@ SRCS += \ source/6LoWPAN/ws/ws_neighbor_class.c \ source/6LoWPAN/ws/ws_bootstrap.c \ source/6LoWPAN/ws/ws_bootstrap_6lbr.c \ + source/6LoWPAN/ws/ws_bootstrap_6lr.c \ + source/6LoWPAN/ws/ws_bootstrap_6ln.c \ source/6LoWPAN/ws/ws_bootstrap_ffn.c \ - source/6LoWPAN/ws/ws_bootstrap_lfn.c \ source/6LoWPAN/ws/ws_common.c \ source/6LoWPAN/ws/ws_management_api.c \ source/6LoWPAN/ws/ws_bbr_api.c \